svn commit: r259456 - stable/9/sys/dev/usb/wlan

Hans Petter Selasky hselasky at FreeBSD.org
Mon Dec 16 08:56:49 UTC 2013


Author: hselasky
Date: Mon Dec 16 08:56:45 2013
New Revision: 259456
URL: http://svnweb.freebsd.org/changeset/base/259456

Log:
  MFC r246614:
  - Streamline detach logic in wlan drivers, so that
    freed memory cannot be used during detach.
  - Remove all panic() calls from the urtw driver because
    panic() is not appropriate here.
  - Remove redundant checks for device detached in
    device detach callbacks.
  - Use DEVMETHOD_END to mark end of device methods.

Modified:
  stable/9/sys/dev/usb/wlan/if_rum.c
  stable/9/sys/dev/usb/wlan/if_rumvar.h
  stable/9/sys/dev/usb/wlan/if_run.c
  stable/9/sys/dev/usb/wlan/if_runvar.h
  stable/9/sys/dev/usb/wlan/if_uath.c
  stable/9/sys/dev/usb/wlan/if_upgt.c
  stable/9/sys/dev/usb/wlan/if_upgtvar.h
  stable/9/sys/dev/usb/wlan/if_ural.c
  stable/9/sys/dev/usb/wlan/if_uralvar.h
  stable/9/sys/dev/usb/wlan/if_urtw.c
  stable/9/sys/dev/usb/wlan/if_urtwvar.h
  stable/9/sys/dev/usb/wlan/if_zyd.c
  stable/9/sys/dev/usb/wlan/if_zydreg.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/usb/wlan/if_rum.c
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_rum.c	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_rum.c	Mon Dec 16 08:56:45 2013	(r259456)
@@ -543,6 +543,11 @@ rum_detach(device_t self)
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic;
 
+	/* Prevent further ioctls */
+	RUM_LOCK(sc);
+	sc->sc_detached = 1;
+	RUM_UNLOCK(sc);
+
 	/* stop all USB transfers */
 	usbd_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER);
 
@@ -557,7 +562,6 @@ rum_detach(device_t self)
 		if_free(ifp);
 	}
 	mtx_destroy(&sc->sc_mtx);
-
 	return (0);
 }
 
@@ -1322,7 +1326,14 @@ rum_ioctl(struct ifnet *ifp, u_long cmd,
 	struct rum_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
+
+	RUM_LOCK(sc);
+	error = sc->sc_detached ? ENXIO : 0;
+	RUM_UNLOCK(sc);
+	if (error)
+		return (error);
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
@@ -2366,8 +2377,7 @@ static device_method_t rum_methods[] = {
 	DEVMETHOD(device_probe,		rum_match),
 	DEVMETHOD(device_attach,	rum_attach),
 	DEVMETHOD(device_detach,	rum_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t rum_driver = {

Modified: stable/9/sys/dev/usb/wlan/if_rumvar.h
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_rumvar.h	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_rumvar.h	Mon Dec 16 08:56:45 2013	(r259456)
@@ -106,6 +106,7 @@ struct rum_softc {
 	uint32_t			rf_regs[4];
 	uint8_t				txpow[44];
 	uint8_t				sc_bssid[6];
+	uint8_t				sc_detached;
 
 	struct {
 		uint8_t	val;

Modified: stable/9/sys/dev/usb/wlan/if_run.c
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_run.c	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_run.c	Mon Dec 16 08:56:45 2013	(r259456)
@@ -718,11 +718,14 @@ run_detach(device_t self)
 	struct ieee80211com *ic;
 	int i;
 
+	RUN_LOCK(sc);
+	sc->sc_detached = 1;
+	RUN_UNLOCK(sc);
+
 	/* stop all USB transfers */
 	usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER);
 
 	RUN_LOCK(sc);
-
 	sc->ratectl_run = RUN_RATECTL_OFF;
 	sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT;
 
@@ -3443,7 +3446,13 @@ run_ioctl(struct ifnet *ifp, u_long cmd,
 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
 	int startall = 0;
-	int error = 0;
+	int error;
+
+	RUN_LOCK(sc);
+	error = sc->sc_detached ? ENXIO : 0;
+	RUN_UNLOCK(sc);
+	if (error)
+		return (error);
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
@@ -4965,8 +4974,7 @@ static device_method_t run_methods[] = {
 	DEVMETHOD(device_probe,		run_match),
 	DEVMETHOD(device_attach,	run_attach),
 	DEVMETHOD(device_detach,	run_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t run_driver = {

Modified: stable/9/sys/dev/usb/wlan/if_runvar.h
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_runvar.h	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_runvar.h	Mon Dec 16 08:56:45 2013	(r259456)
@@ -239,6 +239,7 @@ struct run_softc {
 	uint8_t				sta_running;
 	uint8_t				rvp_cnt;
 	uint8_t				rvp_bmap;
+	uint8_t				sc_detached;
 
 	union {
 		struct run_rx_radiotap_header th;

Modified: stable/9/sys/dev/usb/wlan/if_uath.c
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_uath.c	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_uath.c	Mon Dec 16 08:56:45 2013	(r259456)
@@ -504,29 +504,48 @@ uath_detach(device_t dev)
 	struct uath_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
+	unsigned int x;
 
-	if (!device_is_attached(dev))
-		return (0);
-
+	/*
+	 * Prevent further allocations from RX/TX/CMD
+	 * data lists and ioctls
+	 */
 	UATH_LOCK(sc);
 	sc->sc_flags |= UATH_FLAG_INVALID;
+
+	STAILQ_INIT(&sc->sc_rx_active);
+	STAILQ_INIT(&sc->sc_rx_inactive);
+
+	STAILQ_INIT(&sc->sc_tx_active);
+	STAILQ_INIT(&sc->sc_tx_inactive);
+	STAILQ_INIT(&sc->sc_tx_pending);
+
+	STAILQ_INIT(&sc->sc_cmd_active);
+	STAILQ_INIT(&sc->sc_cmd_pending);
+	STAILQ_INIT(&sc->sc_cmd_waiting);
+	STAILQ_INIT(&sc->sc_cmd_inactive);
 	UATH_UNLOCK(sc);
 
-	ieee80211_ifdetach(ic);
 	uath_stop(ifp);
 
 	callout_drain(&sc->stat_ch);
 	callout_drain(&sc->watchdog_ch);
 
-	usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+	/* drain USB transfers */
+	for (x = 0; x != UATH_N_XFERS; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
 
-	/* free buffers */
+	/* free data buffers */
 	UATH_LOCK(sc);
 	uath_free_rx_data_list(sc);
 	uath_free_tx_data_list(sc);
 	uath_free_cmd_list(sc, sc->sc_cmd);
 	UATH_UNLOCK(sc);
 
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+
+	ieee80211_ifdetach(ic);
 	if_free(ifp);
 	mtx_destroy(&sc->sc_mtx);
 	return (0);
@@ -934,10 +953,10 @@ uath_free_data_list(struct uath_softc *s
 		} else {
 			dp->buf = NULL;
 		}
-#ifdef UATH_DEBUG
-		if (dp->ni != NULL)
-			device_printf(sc->sc_dev, "Node isn't NULL\n");
-#endif
+		if (dp->ni != NULL) {
+			ieee80211_free_node(dp->ni);
+			dp->ni = NULL;
+		}
 	}
 }
 
@@ -1025,10 +1044,6 @@ uath_alloc_tx_data_list(struct uath_soft
 static void
 uath_free_rx_data_list(struct uath_softc *sc)
 {
-
-	STAILQ_INIT(&sc->sc_rx_active);
-	STAILQ_INIT(&sc->sc_rx_inactive);
-
 	uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT,
 	    1 /* free mbufs */);
 }
@@ -1036,11 +1051,6 @@ uath_free_rx_data_list(struct uath_softc
 static void
 uath_free_tx_data_list(struct uath_softc *sc)
 {
-
-	STAILQ_INIT(&sc->sc_tx_active);
-	STAILQ_INIT(&sc->sc_tx_inactive);
-	STAILQ_INIT(&sc->sc_tx_pending);
-
 	uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT,
 	    0 /* no mbufs */);
 }
@@ -1543,7 +1553,15 @@ uath_ioctl(struct ifnet *ifp, u_long cmd
 {
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	struct uath_softc *sc = ifp->if_softc;
+	int error;
+	int startall = 0;
+
+	UATH_LOCK(sc);
+	error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0;
+	UATH_UNLOCK(sc);
+	if (error)
+		return (error);
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:

Modified: stable/9/sys/dev/usb/wlan/if_upgt.c
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_upgt.c	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_upgt.c	Mon Dec 16 08:56:45 2013	(r259456)
@@ -466,7 +466,14 @@ upgt_ioctl(struct ifnet *ifp, u_long cmd
 	struct upgt_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
+
+	UPGT_LOCK(sc);
+	error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0;
+	UPGT_UNLOCK(sc);
+	if (error)
+		return (error);
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
@@ -2001,7 +2008,6 @@ upgt_alloc_rx(struct upgt_softc *sc)
 		data->buf = ((uint8_t *)sc->sc_rx_dma_buf) + (i * MCLBYTES);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
 	}
-
 	return (0);
 }
 
@@ -2011,22 +2017,42 @@ upgt_detach(device_t dev)
 	struct upgt_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
+	unsigned int x;
 
-	if (!device_is_attached(dev))
-		return 0;
+	/*
+	 * Prevent further allocations from RX/TX/CMD
+	 * data lists and ioctls
+	 */
+	UPGT_LOCK(sc);
+	sc->sc_flags |= UPGT_FLAG_DETACHED;
+
+	STAILQ_INIT(&sc->sc_tx_active);
+	STAILQ_INIT(&sc->sc_tx_inactive);
+	STAILQ_INIT(&sc->sc_tx_pending);
+
+	STAILQ_INIT(&sc->sc_rx_active);
+	STAILQ_INIT(&sc->sc_rx_inactive);
+	UPGT_UNLOCK(sc);
 
 	upgt_stop(sc);
 
 	callout_drain(&sc->sc_led_ch);
 	callout_drain(&sc->sc_watchdog_ch);
 
-	ieee80211_ifdetach(ic);
-
-	usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
+	/* drain USB transfers */
+	for (x = 0; x != UPGT_N_XFERS; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
 
+	/* free data buffers */
+	UPGT_LOCK(sc);
 	upgt_free_rx(sc);
 	upgt_free_tx(sc);
+	UPGT_UNLOCK(sc);
+
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
 
+	ieee80211_ifdetach(ic);
 	if_free(ifp);
 	mtx_destroy(&sc->sc_mtx);
 
@@ -2054,6 +2080,9 @@ upgt_free_tx(struct upgt_softc *sc)
 	for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_tx_data[i];
 
+		if (data->ni != NULL)
+			ieee80211_free_node(data->ni);
+
 		data->buf = NULL;
 		data->ni = NULL;
 	}

Modified: stable/9/sys/dev/usb/wlan/if_upgtvar.h
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_upgtvar.h	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_upgtvar.h	Mon Dec 16 08:56:45 2013	(r259456)
@@ -428,6 +428,7 @@ struct upgt_softc {
 	int			 sc_flags;
 #define	UPGT_FLAG_FWLOADED	 (1 << 0)
 #define	UPGT_FLAG_INITDONE	 (1 << 1)
+#define	UPGT_FLAG_DETACHED	 (1 << 2)
 	int			 sc_if_flags;
 	int			 sc_debug;
 

Modified: stable/9/sys/dev/usb/wlan/if_ural.c
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_ural.c	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_ural.c	Mon Dec 16 08:56:45 2013	(r259456)
@@ -385,8 +385,7 @@ static device_method_t ural_methods[] = 
 	DEVMETHOD(device_probe,		ural_match),
 	DEVMETHOD(device_attach,	ural_attach),
 	DEVMETHOD(device_detach,	ural_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t ural_driver = {
@@ -528,6 +527,11 @@ ural_detach(device_t self)
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic;
 
+	/* prevent further ioctls */
+	RAL_LOCK(sc);
+	sc->sc_detached = 1;
+	RAL_UNLOCK(sc);
+
 	/* stop all USB transfers */
 	usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
 
@@ -1371,7 +1375,14 @@ ural_ioctl(struct ifnet *ifp, u_long cmd
 	struct ural_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
+
+	RAL_LOCK(sc);
+	error = sc->sc_detached ? ENXIO : 0;
+	RAL_UNLOCK(sc);
+	if (error)
+		return (error);
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:

Modified: stable/9/sys/dev/usb/wlan/if_uralvar.h
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_uralvar.h	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_uralvar.h	Mon Dec 16 08:56:45 2013	(r259456)
@@ -110,6 +110,7 @@ struct ural_softc {
 	uint32_t			rf_regs[4];
 	uint8_t				txpow[14];
 	uint8_t				sc_bssid[6];
+	uint8_t				sc_detached;
 
 	struct {
 		uint8_t			val;

Modified: stable/9/sys/dev/usb/wlan/if_urtw.c
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_urtw.c	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_urtw.c	Mon Dec 16 08:56:45 2013	(r259456)
@@ -651,8 +651,8 @@ static struct ieee80211vap *urtw_vap_cre
 			    const uint8_t [IEEE80211_ADDR_LEN]);
 static void		urtw_vap_delete(struct ieee80211vap *);
 static void		urtw_init(void *);
-static void		urtw_stop(struct ifnet *, int);
-static void		urtw_stop_locked(struct ifnet *, int);
+static void		urtw_stop(struct ifnet *);
+static void		urtw_stop_locked(struct ifnet *);
 static int		urtw_ioctl(struct ifnet *, u_long, caddr_t);
 static void		urtw_start(struct ifnet *);
 static int		urtw_alloc_rx_data_list(struct urtw_softc *);
@@ -933,42 +933,63 @@ urtw_detach(device_t dev)
 	struct urtw_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
+	unsigned int x;
+	unsigned int n_xfers;
 
-	if (!device_is_attached(dev))
-		return (0);
+	/* Prevent further ioctls */
+	URTW_LOCK(sc);
+	sc->sc_flags |= URTW_DETACHED;
+	URTW_UNLOCK(sc);
+
+	urtw_stop(ifp);
 
-	urtw_stop(ifp, 1);
 	ieee80211_draintask(ic, &sc->sc_updateslot_task);
 	ieee80211_draintask(ic, &sc->sc_led_task);
 
 	usb_callout_drain(&sc->sc_led_ch);
 	callout_drain(&sc->sc_watchdog_ch);
 
-	ieee80211_ifdetach(ic);
+	n_xfers = (sc->sc_flags & URTW_RTL8187B) ?
+	    URTW_8187B_N_XFERS : URTW_8187L_N_XFERS;
 
-	usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
-	    URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
+	/* prevent further allocations from RX/TX data lists */
+	URTW_LOCK(sc);
+	STAILQ_INIT(&sc->sc_tx_active);
+	STAILQ_INIT(&sc->sc_tx_inactive);
+	STAILQ_INIT(&sc->sc_tx_pending);
 
+	STAILQ_INIT(&sc->sc_rx_active);
+	STAILQ_INIT(&sc->sc_rx_inactive);
+	URTW_UNLOCK(sc);
+
+	/* drain USB transfers */
+	for (x = 0; x != n_xfers; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
+
+	/* free data buffers */
+	URTW_LOCK(sc);
 	urtw_free_tx_data_list(sc);
 	urtw_free_rx_data_list(sc);
+	URTW_UNLOCK(sc);
+
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, n_xfers);
 
+	ieee80211_ifdetach(ic);
 	if_free(ifp);
 	mtx_destroy(&sc->sc_mtx);
-
 	return (0);
 }
 
 static void
 urtw_free_tx_data_list(struct urtw_softc *sc)
 {
-
 	urtw_free_data_list(sc, sc->sc_tx, URTW_TX_DATA_LIST_COUNT, 0);
 }
 
 static void
 urtw_free_rx_data_list(struct urtw_softc *sc)
 {
-
 	urtw_free_data_list(sc, sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 1);
 }
 
@@ -1046,7 +1067,7 @@ urtw_init_locked(void *arg)
 	usb_error_t error;
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-		urtw_stop_locked(ifp, 0);
+		urtw_stop_locked(ifp);
 
 	error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
 	    urtw_adapter_start(sc);
@@ -1309,13 +1330,12 @@ urtw_do_request(struct urtw_softc *sc,
 }
 
 static void
-urtw_stop_locked(struct ifnet *ifp, int disable)
+urtw_stop_locked(struct ifnet *ifp)
 {
 	struct urtw_softc *sc = ifp->if_softc;
 	uint8_t data8;
 	usb_error_t error;
 
-	(void)disable;
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
 	error = urtw_intr_disable(sc);
@@ -1349,12 +1369,12 @@ fail:
 }
 
 static void
-urtw_stop(struct ifnet *ifp, int disable)
+urtw_stop(struct ifnet *ifp)
 {
 	struct urtw_softc *sc = ifp->if_softc;
 
 	URTW_LOCK(sc);
-	urtw_stop_locked(ifp, disable);
+	urtw_stop_locked(ifp);
 	URTW_UNLOCK(sc);
 }
 
@@ -1379,7 +1399,14 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd
 	struct urtw_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
+
+	URTW_LOCK(sc);
+	error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0;
+	URTW_UNLOCK(sc);
+	if (error)
+		return (error);
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
@@ -1394,7 +1421,7 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd
 			}
 		} else {
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-				urtw_stop(ifp, 1);
+				urtw_stop(ifp);
 		}
 		sc->sc_if_flags = ifp->if_flags;
 		if (startall)
@@ -1410,7 +1437,6 @@ urtw_ioctl(struct ifnet *ifp, u_long cmd
 		error = EINVAL;
 		break;
 	}
-
 	return (error);
 }
 
@@ -1991,9 +2017,11 @@ urtw_update_msr(struct urtw_softc *sc)
 			data |= URTW_MSR_LINK_HOSTAP;
 			break;
 		default:
-			panic("unsupported operation mode 0x%x\n",
+			DPRINTF(sc, URTW_DEBUG_STATE,
+			    "unsupported operation mode 0x%x\n",
 			    ic->ic_opmode);
-			/* never reach  */
+			error = USB_ERR_INVAL;
+			goto fail;
 		}
 	} else
 		data |= URTW_MSR_LINK_NONE;
@@ -2424,8 +2452,10 @@ urtw_get_rfchip(struct urtw_softc *sc)
 		sc->sc_rf_stop = urtw_8225_rf_stop;
 		break;
 	default:
-		panic("unsupported RF chip %d\n", data & 0xff);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported RF chip %d\n", data & 0xff);
+		error = USB_ERR_INVAL;
+		goto fail;
 	}
 
 	device_printf(sc->sc_dev, "%s rf %s hwrev %s\n",
@@ -3605,8 +3635,10 @@ urtw_led_ctl(struct urtw_softc *sc, int 
 		error = urtw_led_mode3(sc, mode);
 		break;
 	default:
-		panic("unsupported LED mode %d\n", sc->sc_strategy);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED mode %d\n", sc->sc_strategy);
+		error = USB_ERR_INVAL;
+		break;
 	}
 
 	return (error);
@@ -3631,8 +3663,9 @@ urtw_led_mode0(struct urtw_softc *sc, in
 		sc->sc_gpio_ledstate = URTW_LED_ON;
 		break;
 	default:
-		panic("unsupported LED mode 0x%x", mode);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED mode 0x%x", mode);
+		return (USB_ERR_INVAL);
 	}
 
 	switch (sc->sc_gpio_ledstate) {
@@ -3655,8 +3688,9 @@ urtw_led_mode0(struct urtw_softc *sc, in
 		urtw_led_off(sc, URTW_LED_GPIO);
 		break;
 	default:
-		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unknown LED status 0x%x", sc->sc_gpio_ledstate);
+		return (USB_ERR_INVAL);
 	}
 	return (0);
 }
@@ -3664,21 +3698,18 @@ urtw_led_mode0(struct urtw_softc *sc, in
 static usb_error_t
 urtw_led_mode1(struct urtw_softc *sc, int mode)
 {
-
 	return (USB_ERR_INVAL);
 }
 
 static usb_error_t
 urtw_led_mode2(struct urtw_softc *sc, int mode)
 {
-
 	return (USB_ERR_INVAL);
 }
 
 static usb_error_t
 urtw_led_mode3(struct urtw_softc *sc, int mode)
 {
-
 	return (USB_ERR_INVAL);
 }
 
@@ -3694,13 +3725,17 @@ urtw_led_on(struct urtw_softc *sc, int t
 			urtw_write8_m(sc, URTW_GP_ENABLE, 0x00);
 			break;
 		default:
-			panic("unsupported LED PIN type 0x%x",
+			DPRINTF(sc, URTW_DEBUG_STATE,
+			    "unsupported LED PIN type 0x%x",
 			    sc->sc_gpio_ledpin);
-			/* never reach  */
+			error = USB_ERR_INVAL;
+			goto fail;
 		}
 	} else {
-		panic("unsupported LED type 0x%x", type);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED type 0x%x", type);
+		error = USB_ERR_INVAL;
+		goto fail;
 	}
 
 	sc->sc_gpio_ledon = 1;
@@ -3721,13 +3756,17 @@ urtw_led_off(struct urtw_softc *sc, int 
 			    URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1);
 			break;
 		default:
-			panic("unsupported LED PIN type 0x%x",
+			DPRINTF(sc, URTW_DEBUG_STATE,
+			    "unsupported LED PIN type 0x%x",
 			    sc->sc_gpio_ledpin);
-			/* never reach  */
+			error = USB_ERR_INVAL;
+			goto fail;
 		}
 	} else {
-		panic("unsupported LED type 0x%x", type);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED type 0x%x", type);
+		error = USB_ERR_INVAL;
+		goto fail;
 	}
 
 	sc->sc_gpio_ledon = 0;
@@ -3751,8 +3790,12 @@ urtw_ledtask(void *arg, int pending)
 {
 	struct urtw_softc *sc = arg;
 
-	if (sc->sc_strategy != URTW_SW_LED_MODE0)
-		panic("could not process a LED strategy 0x%x", sc->sc_strategy);
+	if (sc->sc_strategy != URTW_SW_LED_MODE0) {
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "could not process a LED strategy 0x%x",
+		    sc->sc_strategy);
+		return;
+	}
 
 	URTW_LOCK(sc);
 	urtw_led_blink(sc);
@@ -3799,8 +3842,10 @@ urtw_led_blink(struct urtw_softc *sc)
 		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
 		break;
 	default:
-		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unknown LED status 0x%x",
+		    sc->sc_gpio_ledstate);
+		return (USB_ERR_INVAL);
 	}
 	return (0);
 }

Modified: stable/9/sys/dev/usb/wlan/if_urtwvar.h
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_urtwvar.h	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_urtwvar.h	Mon Dec 16 08:56:45 2013	(r259456)
@@ -107,6 +107,7 @@ struct urtw_softc {
 #define	URTW_RTL8187B_REV_B		(1 << 3)
 #define	URTW_RTL8187B_REV_D		(1 << 4)
 #define	URTW_RTL8187B_REV_E		(1 << 5)
+#define	URTW_DETACHED			(1 << 6)
 	enum ieee80211_state		sc_state;
 
 	int				sc_epromtype;

Modified: stable/9/sys/dev/usb/wlan/if_zyd.c
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_zyd.c	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_zyd.c	Mon Dec 16 08:56:45 2013	(r259456)
@@ -438,12 +438,29 @@ zyd_detach(device_t dev)
 	struct zyd_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic;
+	unsigned int x;
 
-	/* stop all USB transfers */
-	usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
+	/*
+	 * Prevent further allocations from RX/TX data
+	 * lists and ioctls:
+	 */
+	ZYD_LOCK(sc);
+	sc->sc_flags |= ZYD_FLAG_DETACHED;
+	STAILQ_INIT(&sc->tx_q);
+	STAILQ_INIT(&sc->tx_free);
+	ZYD_UNLOCK(sc);
+
+	/* drain USB transfers */
+	for (x = 0; x != ZYD_N_TRANSFER; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
 
 	/* free TX list, if any */
+	ZYD_LOCK(sc);
 	zyd_unsetup_tx_list(sc);
+	ZYD_UNLOCK(sc);
+
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
 
 	if (ifp) {
 		ic = ifp->if_l2com;
@@ -2637,7 +2654,14 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd,
 	struct zyd_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
+
+	ZYD_LOCK(sc);
+	error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0;
+	ZYD_UNLOCK(sc);
+	if (error)
+		return (error);
 
 	switch (cmd) {
 	case SIOCSIFFLAGS:
@@ -2928,8 +2952,7 @@ static device_method_t zyd_methods[] = {
         DEVMETHOD(device_probe, zyd_match),
         DEVMETHOD(device_attach, zyd_attach),
         DEVMETHOD(device_detach, zyd_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t zyd_driver = {

Modified: stable/9/sys/dev/usb/wlan/if_zydreg.h
==============================================================================
--- stable/9/sys/dev/usb/wlan/if_zydreg.h	Mon Dec 16 08:54:24 2013	(r259455)
+++ stable/9/sys/dev/usb/wlan/if_zydreg.h	Mon Dec 16 08:56:45 2013	(r259456)
@@ -1259,6 +1259,7 @@ struct zyd_softc {
 #define	ZYD_FLAG_FWLOADED		(1 << 0)
 #define	ZYD_FLAG_INITONCE		(1 << 1)
 #define	ZYD_FLAG_INITDONE		(1 << 2)
+#define	ZYD_FLAG_DETACHED		(1 << 3)
 
 	struct zyd_rf		sc_rf;
 


More information about the svn-src-stable-9 mailing list