1d62bc4baSyz147064 /*
2d62bc4baSyz147064 * CDDL HEADER START
3d62bc4baSyz147064 *
4d62bc4baSyz147064 * The contents of this file are subject to the terms of the
5d62bc4baSyz147064 * Common Development and Distribution License (the "License").
6d62bc4baSyz147064 * You may not use this file except in compliance with the License.
7d62bc4baSyz147064 *
8d62bc4baSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d62bc4baSyz147064 * or http://www.opensolaris.org/os/licensing.
10d62bc4baSyz147064 * See the License for the specific language governing permissions
11d62bc4baSyz147064 * and limitations under the License.
12d62bc4baSyz147064 *
13d62bc4baSyz147064 * When distributing Covered Code, include this CDDL HEADER in each
14d62bc4baSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d62bc4baSyz147064 * If applicable, add the following below this CDDL HEADER, with the
16d62bc4baSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying
17d62bc4baSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner]
18d62bc4baSyz147064 *
19d62bc4baSyz147064 * CDDL HEADER END
20d62bc4baSyz147064 */
21d62bc4baSyz147064 /*
22*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23d62bc4baSyz147064 * Use is subject to license terms.
24d62bc4baSyz147064 */
25d62bc4baSyz147064
26d62bc4baSyz147064 #include <sys/strsubr.h>
27d62bc4baSyz147064 #include <inet/led.h>
28d62bc4baSyz147064 #include <sys/softmac_impl.h>
29d62bc4baSyz147064
30d62bc4baSyz147064 mblk_t *
softmac_m_tx(void * arg,mblk_t * mp)31d62bc4baSyz147064 softmac_m_tx(void *arg, mblk_t *mp)
32d62bc4baSyz147064 {
33d62bc4baSyz147064 queue_t *wq = ((softmac_t *)arg)->smac_lower->sl_wq;
34d62bc4baSyz147064
35d62bc4baSyz147064 /*
36d62bc4baSyz147064 * Optimize for the most common case.
37d62bc4baSyz147064 */
38d81b850fSyz147064 if (mp->b_next == NULL) {
395d460eafSCathy Zhou if (!SOFTMAC_CANPUTNEXT(wq))
40d62bc4baSyz147064 return (mp);
41d62bc4baSyz147064
42d62bc4baSyz147064 mp->b_flag |= MSGNOLOOP;
43d62bc4baSyz147064 putnext(wq, mp);
44d62bc4baSyz147064 return (NULL);
45d62bc4baSyz147064 }
46d62bc4baSyz147064
47d62bc4baSyz147064 while (mp != NULL) {
48d62bc4baSyz147064 mblk_t *next = mp->b_next;
49d62bc4baSyz147064
505d460eafSCathy Zhou if (!SOFTMAC_CANPUTNEXT(wq))
51d62bc4baSyz147064 break;
52d62bc4baSyz147064 mp->b_next = NULL;
53d62bc4baSyz147064 mp->b_flag |= MSGNOLOOP;
54d62bc4baSyz147064 putnext(wq, mp);
55d62bc4baSyz147064 mp = next;
56d62bc4baSyz147064 }
57d62bc4baSyz147064 return (mp);
58d62bc4baSyz147064 }
59d62bc4baSyz147064
60d62bc4baSyz147064 void
softmac_rput_process_data(softmac_lower_t * slp,mblk_t * mp)61d62bc4baSyz147064 softmac_rput_process_data(softmac_lower_t *slp, mblk_t *mp)
62d62bc4baSyz147064 {
63d62bc4baSyz147064 /*
64d62bc4baSyz147064 * When packets arrive, the softmac might not be fully started.
65d62bc4baSyz147064 */
66d62bc4baSyz147064 ASSERT((slp->sl_softmac != NULL));
67d62bc4baSyz147064 ASSERT((mp->b_next == NULL) && (mp->b_prev == NULL));
68d62bc4baSyz147064
69d62bc4baSyz147064 if (DB_REF(mp) > 1) {
70d62bc4baSyz147064 mblk_t *tmp;
7110972ddeSCathy Zhou uint32_t start, stuff, end, value, flags;
72d62bc4baSyz147064
73d62bc4baSyz147064 if ((tmp = copymsg(mp)) == NULL) {
74d62bc4baSyz147064 cmn_err(CE_WARN, "softmac_rput_process_data: "
75d62bc4baSyz147064 "copymsg failed");
76d62bc4baSyz147064 goto failed;
77d62bc4baSyz147064 }
78*0dc2366fSVenugopal Iyer mac_hcksum_get(mp, &start, &stuff, &end, &value, &flags);
79*0dc2366fSVenugopal Iyer mac_hcksum_set(tmp, start, stuff, end, value, flags);
80d62bc4baSyz147064 freemsg(mp);
81d62bc4baSyz147064 mp = tmp;
82d62bc4baSyz147064 }
83d62bc4baSyz147064
84da14cebeSEric Cheng mac_rx(slp->sl_softmac->smac_mh, NULL, mp);
85d62bc4baSyz147064 return;
86d62bc4baSyz147064
87d62bc4baSyz147064 failed:
88d62bc4baSyz147064 freemsg(mp);
89d62bc4baSyz147064 }
90d62bc4baSyz147064
91d62bc4baSyz147064 #define ACKTIMEOUT (10 * hz)
92d62bc4baSyz147064
93d62bc4baSyz147064 static int
dlpi_get_errno(t_uscalar_t error,t_uscalar_t unix_errno)94d62bc4baSyz147064 dlpi_get_errno(t_uscalar_t error, t_uscalar_t unix_errno)
95d62bc4baSyz147064 {
96d62bc4baSyz147064 return (error == DL_SYSERR ? unix_errno : EINVAL);
97d62bc4baSyz147064 }
98d62bc4baSyz147064
995d460eafSCathy Zhou int
softmac_output(softmac_lower_t * slp,mblk_t * mp,t_uscalar_t dl_prim,t_uscalar_t ack,mblk_t ** mpp)100d62bc4baSyz147064 softmac_output(softmac_lower_t *slp, mblk_t *mp, t_uscalar_t dl_prim,
101d62bc4baSyz147064 t_uscalar_t ack, mblk_t **mpp)
102d62bc4baSyz147064 {
103d62bc4baSyz147064 union DL_primitives *dlp;
104f1956ffeSCathy Zhou mac_perim_handle_t mph;
105d62bc4baSyz147064 int err = 0;
106d62bc4baSyz147064
107f1956ffeSCathy Zhou mac_perim_enter_by_mh(slp->sl_softmac->smac_mh, &mph);
108f1956ffeSCathy Zhou
109f1956ffeSCathy Zhou ASSERT(!slp->sl_pending_ioctl);
110f1956ffeSCathy Zhou ASSERT(slp->sl_pending_prim == DL_PRIM_INVAL);
111d62bc4baSyz147064
112d62bc4baSyz147064 /*
113d62bc4baSyz147064 * Record the pending DLPI primitive.
114d62bc4baSyz147064 */
115d62bc4baSyz147064 mutex_enter(&slp->sl_mutex);
116d62bc4baSyz147064 slp->sl_pending_prim = dl_prim;
117d62bc4baSyz147064 mutex_exit(&slp->sl_mutex);
118d62bc4baSyz147064
119d62bc4baSyz147064 putnext(slp->sl_wq, mp);
120d62bc4baSyz147064
121d62bc4baSyz147064 mutex_enter(&slp->sl_mutex);
122d62bc4baSyz147064 while (slp->sl_pending_prim != DL_PRIM_INVAL) {
123d3d50737SRafael Vanoni if (cv_reltimedwait(&slp->sl_cv, &slp->sl_mutex, ACKTIMEOUT,
124d3d50737SRafael Vanoni TR_CLOCK_TICK) == -1)
125d62bc4baSyz147064 break;
126d62bc4baSyz147064 }
127d62bc4baSyz147064
128d62bc4baSyz147064 mp = slp->sl_ack_mp;
129d62bc4baSyz147064 slp->sl_ack_mp = NULL;
130d62bc4baSyz147064
131d62bc4baSyz147064 /*
132d62bc4baSyz147064 * If we timed out, sl_ack_mp will still be NULL, but sl_pending_prim
133d62bc4baSyz147064 * won't be set to DL_PRIM_INVAL.
134d62bc4baSyz147064 */
135d62bc4baSyz147064 ASSERT(mp != NULL || slp->sl_pending_prim != DL_PRIM_INVAL);
136d62bc4baSyz147064
137d62bc4baSyz147064 slp->sl_pending_prim = DL_PRIM_INVAL;
138d62bc4baSyz147064 mutex_exit(&slp->sl_mutex);
139d62bc4baSyz147064
140d62bc4baSyz147064 if (mp != NULL) {
141d62bc4baSyz147064 dlp = (union DL_primitives *)mp->b_rptr;
142d62bc4baSyz147064
143d62bc4baSyz147064 if (dlp->dl_primitive == DL_ERROR_ACK) {
144d62bc4baSyz147064 err = dlpi_get_errno(dlp->error_ack.dl_errno,
145d62bc4baSyz147064 dlp->error_ack.dl_unix_errno);
146d62bc4baSyz147064 } else {
147d62bc4baSyz147064 ASSERT(dlp->dl_primitive == ack);
148d62bc4baSyz147064 }
149d62bc4baSyz147064 } else {
150d62bc4baSyz147064 err = ENOMSG;
151d62bc4baSyz147064 }
152d62bc4baSyz147064
153d62bc4baSyz147064 if (mpp != NULL)
154d62bc4baSyz147064 *mpp = mp;
155d62bc4baSyz147064 else
156d62bc4baSyz147064 freemsg(mp);
157d62bc4baSyz147064
158f1956ffeSCathy Zhou mac_perim_exit(mph);
159d62bc4baSyz147064 return (err);
160d62bc4baSyz147064 }
161d62bc4baSyz147064
162d62bc4baSyz147064 void
softmac_ioctl_tx(softmac_lower_t * slp,mblk_t * mp,mblk_t ** mpp)163d62bc4baSyz147064 softmac_ioctl_tx(softmac_lower_t *slp, mblk_t *mp, mblk_t **mpp)
164d62bc4baSyz147064 {
165f1956ffeSCathy Zhou mac_perim_handle_t mph;
166f1956ffeSCathy Zhou
167f1956ffeSCathy Zhou mac_perim_enter_by_mh(slp->sl_softmac->smac_mh, &mph);
168d62bc4baSyz147064
169d62bc4baSyz147064 /*
170d62bc4baSyz147064 * Record that ioctl processing is currently in progress.
171d62bc4baSyz147064 */
172d62bc4baSyz147064 mutex_enter(&slp->sl_mutex);
173d62bc4baSyz147064 slp->sl_pending_ioctl = B_TRUE;
174d62bc4baSyz147064 mutex_exit(&slp->sl_mutex);
175d62bc4baSyz147064
176d62bc4baSyz147064 putnext(slp->sl_wq, mp);
177d62bc4baSyz147064
178d62bc4baSyz147064 mutex_enter(&slp->sl_mutex);
179d62bc4baSyz147064 while (slp->sl_pending_ioctl)
180d62bc4baSyz147064 cv_wait(&slp->sl_cv, &slp->sl_mutex);
181d62bc4baSyz147064 mp = slp->sl_ack_mp;
182d62bc4baSyz147064 slp->sl_ack_mp = NULL;
183d62bc4baSyz147064 mutex_exit(&slp->sl_mutex);
184d62bc4baSyz147064
185d62bc4baSyz147064 ASSERT(mpp != NULL && mp != NULL);
186d62bc4baSyz147064 *mpp = mp;
187d62bc4baSyz147064
188f1956ffeSCathy Zhou mac_perim_exit(mph);
189d62bc4baSyz147064 }
190d62bc4baSyz147064
1915d460eafSCathy Zhou int
softmac_mexchange_error_ack(mblk_t ** mpp,t_uscalar_t error_primitive,t_uscalar_t error,t_uscalar_t unix_errno)192d62bc4baSyz147064 softmac_mexchange_error_ack(mblk_t **mpp, t_uscalar_t error_primitive,
193d62bc4baSyz147064 t_uscalar_t error, t_uscalar_t unix_errno)
194d62bc4baSyz147064 {
195d62bc4baSyz147064 union DL_primitives *dlp;
196d62bc4baSyz147064
197d62bc4baSyz147064 if ((*mpp = mexchange(NULL, *mpp, sizeof (dl_error_ack_t), M_PCPROTO,
198d62bc4baSyz147064 DL_ERROR_ACK)) == NULL)
199d62bc4baSyz147064 return (ENOMEM);
200d62bc4baSyz147064
201d62bc4baSyz147064 dlp = (union DL_primitives *)(*mpp)->b_rptr;
202d62bc4baSyz147064 dlp->error_ack.dl_error_primitive = error_primitive;
203d62bc4baSyz147064 dlp->error_ack.dl_errno = error;
204d62bc4baSyz147064 dlp->error_ack.dl_unix_errno = unix_errno;
205d62bc4baSyz147064
206d62bc4baSyz147064 return (0);
207d62bc4baSyz147064 }
208d62bc4baSyz147064
209d62bc4baSyz147064 int
softmac_proto_tx(softmac_lower_t * slp,mblk_t * mp,mblk_t ** mpp)210d62bc4baSyz147064 softmac_proto_tx(softmac_lower_t *slp, mblk_t *mp, mblk_t **mpp)
211d62bc4baSyz147064 {
212d62bc4baSyz147064 int err = 0;
213d62bc4baSyz147064 t_uscalar_t dl_prim;
214d62bc4baSyz147064
215d62bc4baSyz147064 dl_prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive;
216d62bc4baSyz147064
217d62bc4baSyz147064 ASSERT(slp->sl_softmac != NULL);
218d62bc4baSyz147064
219d62bc4baSyz147064 switch (dl_prim) {
220d62bc4baSyz147064 case DL_ENABMULTI_REQ:
221d62bc4baSyz147064 case DL_DISABMULTI_REQ:
222d62bc4baSyz147064 case DL_SET_PHYS_ADDR_REQ:
223d62bc4baSyz147064 case DL_UNBIND_REQ:
224d62bc4baSyz147064 case DL_UDQOS_REQ:
225d62bc4baSyz147064 case DL_PROMISCON_REQ:
226d62bc4baSyz147064 case DL_PROMISCOFF_REQ:
227d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_OK_ACK, mpp);
228d62bc4baSyz147064 break;
229d62bc4baSyz147064 case DL_BIND_REQ:
230d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_BIND_ACK, mpp);
231d62bc4baSyz147064 break;
232d62bc4baSyz147064 case DL_NOTIFY_REQ:
233d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_NOTIFY_ACK, mpp);
234d62bc4baSyz147064 break;
235d62bc4baSyz147064 case DL_CONTROL_REQ:
236d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_CONTROL_ACK, mpp);
237d62bc4baSyz147064 break;
238d62bc4baSyz147064 case DL_CAPABILITY_REQ:
239d62bc4baSyz147064 err = softmac_output(slp, mp, dl_prim, DL_CAPABILITY_ACK, mpp);
240d62bc4baSyz147064 break;
241d62bc4baSyz147064 default:
242d62bc4baSyz147064 if (mpp != NULL) {
243d62bc4baSyz147064 *mpp = mp;
244d62bc4baSyz147064 err = softmac_mexchange_error_ack(mpp, dl_prim,
245d62bc4baSyz147064 DL_UNSUPPORTED, 0);
246d62bc4baSyz147064 }
247d62bc4baSyz147064 break;
248d62bc4baSyz147064 }
249d62bc4baSyz147064 return (err);
250d62bc4baSyz147064 }
251