xref: /onnv-gate/usr/src/uts/common/io/softmac/softmac_ctl.c (revision 8275:7c223a798022)
15895Syz147064 /*
25895Syz147064  * CDDL HEADER START
35895Syz147064  *
45895Syz147064  * The contents of this file are subject to the terms of the
55895Syz147064  * Common Development and Distribution License (the "License").
65895Syz147064  * You may not use this file except in compliance with the License.
75895Syz147064  *
85895Syz147064  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95895Syz147064  * or http://www.opensolaris.org/os/licensing.
105895Syz147064  * See the License for the specific language governing permissions
115895Syz147064  * and limitations under the License.
125895Syz147064  *
135895Syz147064  * When distributing Covered Code, include this CDDL HEADER in each
145895Syz147064  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155895Syz147064  * If applicable, add the following below this CDDL HEADER, with the
165895Syz147064  * fields enclosed by brackets "[]" replaced with your own identifying
175895Syz147064  * information: Portions Copyright [yyyy] [name of copyright owner]
185895Syz147064  *
195895Syz147064  * CDDL HEADER END
205895Syz147064  */
215895Syz147064 /*
225895Syz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235895Syz147064  * Use is subject to license terms.
245895Syz147064  */
255895Syz147064 
265895Syz147064 #include <sys/stropts.h>
27*8275SEric Cheng #include <sys/strsubr.h>
28*8275SEric Cheng #include <sys/callb.h>
295895Syz147064 #include <sys/softmac_impl.h>
305895Syz147064 
315895Syz147064 int
325895Syz147064 softmac_send_notify_req(softmac_lower_t *slp, uint32_t notifications)
335895Syz147064 {
345895Syz147064 	mblk_t		*reqmp;
355895Syz147064 
365895Syz147064 	/*
375895Syz147064 	 * create notify req message and send it down
385895Syz147064 	 */
395895Syz147064 	reqmp = mexchange(NULL, NULL, DL_NOTIFY_REQ_SIZE, M_PROTO,
405895Syz147064 	    DL_NOTIFY_REQ);
415895Syz147064 	if (reqmp == NULL)
425895Syz147064 		return (ENOMEM);
435895Syz147064 
445895Syz147064 	((dl_notify_req_t *)reqmp->b_rptr)->dl_notifications = notifications;
455895Syz147064 
465895Syz147064 	return (softmac_proto_tx(slp, reqmp, NULL));
475895Syz147064 }
485895Syz147064 
495895Syz147064 int
505895Syz147064 softmac_send_bind_req(softmac_lower_t *slp, uint_t sap)
515895Syz147064 {
525895Syz147064 	dl_bind_req_t	*bind;
535895Syz147064 	mblk_t		*reqmp;
545895Syz147064 
555895Syz147064 	/*
565895Syz147064 	 * create bind req message and send it down
575895Syz147064 	 */
585895Syz147064 	reqmp = mexchange(NULL, NULL, DL_BIND_REQ_SIZE, M_PROTO, DL_BIND_REQ);
595895Syz147064 	if (reqmp == NULL)
605895Syz147064 		return (ENOMEM);
615895Syz147064 
625895Syz147064 	bind = (dl_bind_req_t *)reqmp->b_rptr;
635895Syz147064 	bind->dl_sap = sap;
645895Syz147064 	bind->dl_conn_mgmt = 0;
655895Syz147064 	bind->dl_max_conind = 0;
665895Syz147064 	bind->dl_xidtest_flg = 0;
675895Syz147064 	bind->dl_service_mode = DL_CLDLS;
685895Syz147064 
695895Syz147064 	return (softmac_proto_tx(slp, reqmp, NULL));
705895Syz147064 }
715895Syz147064 
725895Syz147064 int
735895Syz147064 softmac_send_promisc_req(softmac_lower_t *slp, t_uscalar_t level, boolean_t on)
745895Syz147064 {
755895Syz147064 	mblk_t		*reqmp;
765895Syz147064 	size_t		size;
775895Syz147064 	t_uscalar_t	dl_prim;
785895Syz147064 
795895Syz147064 	/*
805895Syz147064 	 * create promisc message and send it down
815895Syz147064 	 */
825895Syz147064 	if (on) {
835895Syz147064 		dl_prim = DL_PROMISCON_REQ;
845895Syz147064 		size = DL_PROMISCON_REQ_SIZE;
855895Syz147064 	} else {
865895Syz147064 		dl_prim = DL_PROMISCOFF_REQ;
875895Syz147064 		size = DL_PROMISCOFF_REQ_SIZE;
885895Syz147064 	}
895895Syz147064 
905895Syz147064 	reqmp = mexchange(NULL, NULL, size, M_PROTO, dl_prim);
915895Syz147064 	if (reqmp == NULL)
925895Syz147064 		return (ENOMEM);
935895Syz147064 
945895Syz147064 	if (on)
955895Syz147064 		((dl_promiscon_req_t *)reqmp->b_rptr)->dl_level = level;
965895Syz147064 	else
975895Syz147064 		((dl_promiscoff_req_t *)reqmp->b_rptr)->dl_level = level;
985895Syz147064 
995895Syz147064 	return (softmac_proto_tx(slp, reqmp, NULL));
1005895Syz147064 }
1015895Syz147064 
1025895Syz147064 int
1035895Syz147064 softmac_m_promisc(void *arg, boolean_t on)
1045895Syz147064 {
1055895Syz147064 	softmac_t		*softmac = arg;
1065895Syz147064 	softmac_lower_t		*slp = softmac->smac_lower;
1075895Syz147064 
1085895Syz147064 	ASSERT(slp != NULL);
1095895Syz147064 	return (softmac_send_promisc_req(slp, DL_PROMISC_PHYS, on));
1105895Syz147064 }
1115895Syz147064 
1125895Syz147064 int
1135895Syz147064 softmac_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
1145895Syz147064 {
1155895Syz147064 	softmac_t		*softmac = arg;
1165895Syz147064 	softmac_lower_t		*slp;
1175895Syz147064 	dl_enabmulti_req_t	*enabmulti;
1185895Syz147064 	dl_disabmulti_req_t	*disabmulti;
1195895Syz147064 	mblk_t			*reqmp;
1205895Syz147064 	t_uscalar_t		dl_prim;
1215895Syz147064 	uint32_t		size, addr_length;
1225895Syz147064 
1235895Syz147064 	/*
1245895Syz147064 	 * create multicst message and send it down
1255895Syz147064 	 */
1265895Syz147064 	addr_length = softmac->smac_addrlen;
1275895Syz147064 	if (add) {
1285895Syz147064 		size = sizeof (dl_enabmulti_req_t) + addr_length;
1295895Syz147064 		dl_prim = DL_ENABMULTI_REQ;
1305895Syz147064 	} else {
1315895Syz147064 		size = sizeof (dl_disabmulti_req_t) + addr_length;
1325895Syz147064 		dl_prim = DL_DISABMULTI_REQ;
1335895Syz147064 	}
1345895Syz147064 
1355895Syz147064 	reqmp = mexchange(NULL, NULL, size, M_PROTO, dl_prim);
1365895Syz147064 	if (reqmp == NULL)
1375895Syz147064 		return (ENOMEM);
1385895Syz147064 
1395895Syz147064 	if (add) {
1405895Syz147064 		enabmulti = (dl_enabmulti_req_t *)reqmp->b_rptr;
1415895Syz147064 		enabmulti->dl_addr_offset = sizeof (dl_enabmulti_req_t);
1425895Syz147064 		enabmulti->dl_addr_length = addr_length;
1435895Syz147064 		(void) memcpy(&enabmulti[1], mca, addr_length);
1445895Syz147064 	} else {
1455895Syz147064 		disabmulti = (dl_disabmulti_req_t *)reqmp->b_rptr;
1465895Syz147064 		disabmulti->dl_addr_offset = sizeof (dl_disabmulti_req_t);
1475895Syz147064 		disabmulti->dl_addr_length = addr_length;
1485895Syz147064 		(void) memcpy(&disabmulti[1], mca, addr_length);
1495895Syz147064 	}
1505895Syz147064 
1515895Syz147064 	slp = softmac->smac_lower;
1525895Syz147064 	ASSERT(slp != NULL);
1535895Syz147064 	return (softmac_proto_tx(slp, reqmp, NULL));
1545895Syz147064 }
1555895Syz147064 
1565895Syz147064 int
1575895Syz147064 softmac_m_unicst(void *arg, const uint8_t *macaddr)
1585895Syz147064 {
1595895Syz147064 	softmac_t		*softmac = arg;
1605895Syz147064 	softmac_lower_t		*slp;
1615895Syz147064 	dl_set_phys_addr_req_t	*phyaddr;
1625895Syz147064 	mblk_t			*reqmp;
1635895Syz147064 	size_t			size;
1645895Syz147064 
1655895Syz147064 	/*
1665895Syz147064 	 * create set_phys_addr message and send it down
1675895Syz147064 	 */
1685895Syz147064 	size = DL_SET_PHYS_ADDR_REQ_SIZE + softmac->smac_addrlen;
1695895Syz147064 	reqmp = mexchange(NULL, NULL, size, M_PROTO, DL_SET_PHYS_ADDR_REQ);
1705895Syz147064 	if (reqmp == NULL)
1715895Syz147064 		return (ENOMEM);
1725895Syz147064 
1735895Syz147064 	phyaddr = (dl_set_phys_addr_req_t *)reqmp->b_rptr;
1745895Syz147064 	phyaddr->dl_addr_offset = sizeof (dl_set_phys_addr_req_t);
1755895Syz147064 	phyaddr->dl_addr_length = softmac->smac_addrlen;
1765895Syz147064 	(void) memcpy(&phyaddr[1], macaddr, softmac->smac_addrlen);
1775895Syz147064 
1785895Syz147064 	slp = softmac->smac_lower;
1795895Syz147064 	ASSERT(slp != NULL);
1805895Syz147064 	return (softmac_proto_tx(slp, reqmp, NULL));
1815895Syz147064 }
1825895Syz147064 
1835895Syz147064 void
1845895Syz147064 softmac_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1855895Syz147064 {
1865895Syz147064 	softmac_lower_t *slp = ((softmac_t *)arg)->smac_lower;
1875895Syz147064 	mblk_t *ackmp;
1885895Syz147064 
1895895Syz147064 	ASSERT(slp != NULL);
1905895Syz147064 	softmac_ioctl_tx(slp, mp, &ackmp);
1915895Syz147064 	qreply(wq, ackmp);
1925895Syz147064 }
1935895Syz147064 
1945895Syz147064 static void
195*8275SEric Cheng softmac_process_notify_ind(softmac_t *softmac, mblk_t *mp)
1965895Syz147064 {
1975895Syz147064 	dl_notify_ind_t	*dlnip = (dl_notify_ind_t *)mp->b_rptr;
1985895Syz147064 	uint_t		addroff, addrlen;
1995895Syz147064 
2005895Syz147064 	ASSERT(dlnip->dl_primitive == DL_NOTIFY_IND);
2015895Syz147064 
2025895Syz147064 	switch (dlnip->dl_notification) {
2035895Syz147064 	case DL_NOTE_PHYS_ADDR:
2045895Syz147064 		if (dlnip->dl_data != DL_CURR_PHYS_ADDR)
2055895Syz147064 			break;
2065895Syz147064 
2075895Syz147064 		addroff = dlnip->dl_addr_offset;
2085895Syz147064 		addrlen = dlnip->dl_addr_length - softmac->smac_saplen;
2095895Syz147064 		if (addroff == 0 || addrlen != softmac->smac_addrlen ||
2105895Syz147064 		    !MBLKIN(mp, addroff, addrlen)) {
2115895Syz147064 			cmn_err(CE_NOTE, "softmac: got malformed "
2125895Syz147064 			    "DL_NOTIFY_IND; length/offset %d/%d",
2135895Syz147064 			    addrlen, addroff);
2145895Syz147064 			break;
2155895Syz147064 		}
2165895Syz147064 
2175895Syz147064 		mac_unicst_update(softmac->smac_mh, mp->b_rptr + addroff);
2185895Syz147064 		break;
2195895Syz147064 
2205895Syz147064 	case DL_NOTE_LINK_UP:
2215895Syz147064 		mac_link_update(softmac->smac_mh, LINK_STATE_UP);
2225895Syz147064 		break;
2235895Syz147064 
2245895Syz147064 	case DL_NOTE_LINK_DOWN:
2255895Syz147064 		mac_link_update(softmac->smac_mh, LINK_STATE_DOWN);
2265895Syz147064 		break;
2275895Syz147064 	}
2285895Syz147064 
2295895Syz147064 	freemsg(mp);
2305895Syz147064 }
2315895Syz147064 
232*8275SEric Cheng void
233*8275SEric Cheng softmac_notify_thread(void *arg)
234*8275SEric Cheng {
235*8275SEric Cheng 	softmac_t	*softmac = arg;
236*8275SEric Cheng 	callb_cpr_t	cprinfo;
237*8275SEric Cheng 
238*8275SEric Cheng 	CALLB_CPR_INIT(&cprinfo, &softmac->smac_mutex, callb_generic_cpr,
239*8275SEric Cheng 	    "softmac_notify_thread");
240*8275SEric Cheng 
241*8275SEric Cheng 	mutex_enter(&softmac->smac_mutex);
242*8275SEric Cheng 
243*8275SEric Cheng 	/*
244*8275SEric Cheng 	 * Quit the thread if smac_mh is unregistered.
245*8275SEric Cheng 	 */
246*8275SEric Cheng 	while (softmac->smac_mh != NULL &&
247*8275SEric Cheng 	    !(softmac->smac_flags & SOFTMAC_NOTIFY_QUIT)) {
248*8275SEric Cheng 		mblk_t		*mp, *nextmp;
249*8275SEric Cheng 
250*8275SEric Cheng 		if ((mp = softmac->smac_notify_head) == NULL) {
251*8275SEric Cheng 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
252*8275SEric Cheng 			cv_wait(&softmac->smac_cv, &softmac->smac_mutex);
253*8275SEric Cheng 			CALLB_CPR_SAFE_END(&cprinfo, &softmac->smac_mutex);
254*8275SEric Cheng 			continue;
255*8275SEric Cheng 		}
256*8275SEric Cheng 
257*8275SEric Cheng 		softmac->smac_notify_head = softmac->smac_notify_tail = NULL;
258*8275SEric Cheng 		mutex_exit(&softmac->smac_mutex);
259*8275SEric Cheng 
260*8275SEric Cheng 		while (mp != NULL) {
261*8275SEric Cheng 			nextmp = mp->b_next;
262*8275SEric Cheng 			mp->b_next = NULL;
263*8275SEric Cheng 			softmac_process_notify_ind(softmac, mp);
264*8275SEric Cheng 			mp = nextmp;
265*8275SEric Cheng 		}
266*8275SEric Cheng 		mutex_enter(&softmac->smac_mutex);
267*8275SEric Cheng 	}
268*8275SEric Cheng 
269*8275SEric Cheng 	/*
270*8275SEric Cheng 	 * The softmac is being destroyed, simply free all of the DL_NOTIFY_IND
271*8275SEric Cheng 	 * messages left in the queue which did not have the chance to be
272*8275SEric Cheng 	 * processed.
273*8275SEric Cheng 	 */
274*8275SEric Cheng 	freemsgchain(softmac->smac_notify_head);
275*8275SEric Cheng 	softmac->smac_notify_head = softmac->smac_notify_tail = NULL;
276*8275SEric Cheng 	softmac->smac_notify_thread = NULL;
277*8275SEric Cheng 	cv_broadcast(&softmac->smac_cv);
278*8275SEric Cheng 	CALLB_CPR_EXIT(&cprinfo);
279*8275SEric Cheng 	thread_exit();
280*8275SEric Cheng }
281*8275SEric Cheng 
282*8275SEric Cheng static void
283*8275SEric Cheng softmac_enqueue_notify_ind(queue_t *rq, mblk_t *mp)
284*8275SEric Cheng {
285*8275SEric Cheng 	softmac_lower_t	*slp = rq->q_ptr;
286*8275SEric Cheng 	softmac_t	*softmac = slp->sl_softmac;
287*8275SEric Cheng 
288*8275SEric Cheng 	mutex_enter(&softmac->smac_mutex);
289*8275SEric Cheng 	if (softmac->smac_notify_tail == NULL) {
290*8275SEric Cheng 		softmac->smac_notify_head = softmac->smac_notify_tail = mp;
291*8275SEric Cheng 	} else {
292*8275SEric Cheng 		softmac->smac_notify_tail->b_next = mp;
293*8275SEric Cheng 		softmac->smac_notify_tail = mp;
294*8275SEric Cheng 	}
295*8275SEric Cheng 	cv_broadcast(&softmac->smac_cv);
296*8275SEric Cheng 	mutex_exit(&softmac->smac_mutex);
297*8275SEric Cheng }
298*8275SEric Cheng 
2995895Syz147064 static void
3005895Syz147064 softmac_process_dlpi(softmac_lower_t *slp, mblk_t *mp, uint_t minlen,
3015895Syz147064     t_uscalar_t reqprim)
3025895Syz147064 {
3035895Syz147064 	const char *ackname;
3045895Syz147064 
3055895Syz147064 	ackname = dl_primstr(((union DL_primitives *)mp->b_rptr)->dl_primitive);
3065895Syz147064 
3075895Syz147064 	if (MBLKL(mp) < minlen) {
3085895Syz147064 		cmn_err(CE_WARN, "softmac: got short %s", ackname);
3095895Syz147064 		freemsg(mp);
3105895Syz147064 		return;
3115895Syz147064 	}
3125895Syz147064 
3135895Syz147064 	mutex_enter(&slp->sl_mutex);
3145895Syz147064 	if (slp->sl_pending_prim != reqprim) {
3155895Syz147064 		cmn_err(CE_NOTE, "softmac: got unexpected %s", ackname);
3165895Syz147064 		mutex_exit(&slp->sl_mutex);
3175895Syz147064 		freemsg(mp);
3185895Syz147064 		return;
3195895Syz147064 	}
3205895Syz147064 
3215895Syz147064 	slp->sl_pending_prim = DL_PRIM_INVAL;
3225895Syz147064 	slp->sl_ack_mp = mp;
3235895Syz147064 	cv_signal(&slp->sl_cv);
3245895Syz147064 	mutex_exit(&slp->sl_mutex);
3255895Syz147064 }
3265895Syz147064 
3275895Syz147064 void
3285895Syz147064 softmac_rput_process_proto(queue_t *rq, mblk_t *mp)
3295895Syz147064 {
3305895Syz147064 	softmac_lower_t		*slp = rq->q_ptr;
3315895Syz147064 	union DL_primitives	*dlp = (union DL_primitives *)mp->b_rptr;
3325895Syz147064 	ssize_t			len = MBLKL(mp);
3335895Syz147064 	const char		*primstr;
3345895Syz147064 
3355895Syz147064 	if (len < sizeof (t_uscalar_t)) {
3365895Syz147064 		cmn_err(CE_WARN, "softmac: got runt DLPI message");
3375895Syz147064 		goto exit;
3385895Syz147064 	}
3395895Syz147064 
3405895Syz147064 	primstr = dl_primstr(dlp->dl_primitive);
3415895Syz147064 
3425895Syz147064 	switch (dlp->dl_primitive) {
3435895Syz147064 	case DL_OK_ACK:
3445895Syz147064 		if (len < DL_OK_ACK_SIZE)
3455895Syz147064 			goto runt;
3465895Syz147064 
3475895Syz147064 		softmac_process_dlpi(slp, mp, DL_OK_ACK_SIZE,
3485895Syz147064 		    dlp->ok_ack.dl_correct_primitive);
3495895Syz147064 		return;
3505895Syz147064 
3515895Syz147064 	case DL_ERROR_ACK:
3525895Syz147064 		if (len < DL_ERROR_ACK_SIZE)
3535895Syz147064 			goto runt;
3545895Syz147064 
3555895Syz147064 		softmac_process_dlpi(slp, mp, DL_ERROR_ACK_SIZE,
3565895Syz147064 		    dlp->error_ack.dl_error_primitive);
3575895Syz147064 		return;
3585895Syz147064 
3595895Syz147064 	case DL_NOTIFY_IND:
3605895Syz147064 		if (len < DL_NOTIFY_IND_SIZE)
3615895Syz147064 			goto runt;
3625895Syz147064 
363*8275SEric Cheng 		/*
364*8275SEric Cheng 		 * Enqueue all the DL_NOTIFY_IND messages and process them
365*8275SEric Cheng 		 * in another separate thread to avoid deadlock. Here is an
366*8275SEric Cheng 		 * example of the deadlock scenario:
367*8275SEric Cheng 		 *
368*8275SEric Cheng 		 * Thread A: mac_promisc_set()->softmac_m_promisc()
369*8275SEric Cheng 		 *
370*8275SEric Cheng 		 *   The softmac driver waits for the ACK of the
371*8275SEric Cheng 		 *   DL_PROMISC_PHYS request with the MAC perimeter;
372*8275SEric Cheng 		 *
373*8275SEric Cheng 		 * Thread B:
374*8275SEric Cheng 		 *
375*8275SEric Cheng 		 *   The driver handles the DL_PROMISC_PHYS request. Before
376*8275SEric Cheng 		 *   it sends back the ACK, it could first send a
377*8275SEric Cheng 		 *   DL_NOTE_PROMISC_ON_PHYS notification.
378*8275SEric Cheng 		 *
379*8275SEric Cheng 		 * Since DL_NOTIFY_IND could eventually cause softmac to call
380*8275SEric Cheng 		 * mac_xxx_update(), which requires MAC perimeter, this would
381*8275SEric Cheng 		 * cause deadlock between the two threads. Enqueuing the
382*8275SEric Cheng 		 * DL_NOTIFY_IND message and defer its processing would
383*8275SEric Cheng 		 * avoid the potential deadlock.
384*8275SEric Cheng 		 */
385*8275SEric Cheng 		softmac_enqueue_notify_ind(rq, mp);
3865895Syz147064 		return;
3875895Syz147064 
3885895Syz147064 	case DL_NOTIFY_ACK:
3895895Syz147064 		softmac_process_dlpi(slp, mp, DL_NOTIFY_ACK_SIZE,
3905895Syz147064 		    DL_NOTIFY_REQ);
3915895Syz147064 		return;
3925895Syz147064 
3935895Syz147064 	case DL_CAPABILITY_ACK:
3945895Syz147064 		softmac_process_dlpi(slp, mp, DL_CAPABILITY_ACK_SIZE,
3955895Syz147064 		    DL_CAPABILITY_REQ);
3965895Syz147064 		return;
3975895Syz147064 
3985895Syz147064 	case DL_BIND_ACK:
3995895Syz147064 		softmac_process_dlpi(slp, mp, DL_BIND_ACK_SIZE, DL_BIND_REQ);
4005895Syz147064 		return;
4015895Syz147064 
4025895Syz147064 	case DL_CONTROL_ACK:
4035895Syz147064 		softmac_process_dlpi(slp, mp, DL_CONTROL_ACK_SIZE,
4045895Syz147064 		    DL_CONTROL_REQ);
4055895Syz147064 		return;
4065895Syz147064 
4075895Syz147064 	case DL_UNITDATA_IND:
4085895Syz147064 	case DL_PHYS_ADDR_ACK:
4095895Syz147064 		/*
4105895Syz147064 		 * a. Because the stream is in DLIOCRAW mode,
4115895Syz147064 		 *    DL_UNITDATA_IND messages are not expected.
4125895Syz147064 		 * b. The lower stream should not receive DL_PHYS_ADDR_REQ,
4135895Syz147064 		 *    so DL_PHYS_ADDR_ACK messages are also unexpected.
4145895Syz147064 		 */
4155895Syz147064 	default:
4165895Syz147064 		cmn_err(CE_WARN, "softmac: got unexpected %s", primstr);
4175895Syz147064 		break;
4185895Syz147064 	}
4195895Syz147064 exit:
4205895Syz147064 	freemsg(mp);
4215895Syz147064 	return;
4225895Syz147064 runt:
4235895Syz147064 	cmn_err(CE_WARN, "softmac: got runt %s", primstr);
4245895Syz147064 	freemsg(mp);
4255895Syz147064 }
4265895Syz147064 
4275895Syz147064 void
4285895Syz147064 softmac_rput_process_notdata(queue_t *rq, mblk_t *mp)
4295895Syz147064 {
4305895Syz147064 	softmac_lower_t	*slp = rq->q_ptr;
4315895Syz147064 
4325895Syz147064 	switch (DB_TYPE(mp)) {
4335895Syz147064 	case M_PROTO:
4345895Syz147064 	case M_PCPROTO:
4355895Syz147064 		softmac_rput_process_proto(rq, mp);
4365895Syz147064 		break;
4375895Syz147064 
4385895Syz147064 	case M_FLUSH:
4395895Syz147064 		if (*mp->b_rptr & FLUSHR)
4405895Syz147064 			flushq(rq, FLUSHDATA);
4415895Syz147064 		if (*mp->b_rptr & FLUSHW)
4425895Syz147064 			flushq(OTHERQ(rq), FLUSHDATA);
4435895Syz147064 		putnext(rq, mp);
4445895Syz147064 		break;
4455895Syz147064 
4465895Syz147064 	case M_IOCACK:
4475895Syz147064 	case M_IOCNAK:
4485895Syz147064 	case M_COPYIN:
4495895Syz147064 	case M_COPYOUT:
4505895Syz147064 		mutex_enter(&slp->sl_mutex);
4515895Syz147064 		if (!slp->sl_pending_ioctl) {
4525895Syz147064 			mutex_exit(&slp->sl_mutex);
4535895Syz147064 			cmn_err(CE_NOTE, "softmac: got unexpected mblk "
4545895Syz147064 			    "type 0x%x", DB_TYPE(mp));
4555895Syz147064 			freemsg(mp);
4565895Syz147064 			break;
4575895Syz147064 		}
4585895Syz147064 
4595895Syz147064 		slp->sl_pending_ioctl = B_FALSE;
4605895Syz147064 		slp->sl_ack_mp = mp;
4615895Syz147064 		cv_broadcast(&slp->sl_cv);
4625895Syz147064 		mutex_exit(&slp->sl_mutex);
4635895Syz147064 		return;
4645895Syz147064 
4655895Syz147064 	default:
4665895Syz147064 		cmn_err(CE_NOTE, "softmac: got unsupported mblk type 0x%x",
4675895Syz147064 		    DB_TYPE(mp));
4685895Syz147064 		freemsg(mp);
4695895Syz147064 		break;
4705895Syz147064 	}
4715895Syz147064 }
472