From owner-svn-src-all@FreeBSD.ORG Sun Feb 10 10:36:19 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id DF7CBFC2; Sun, 10 Feb 2013 10:36:19 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id C32F7315; Sun, 10 Feb 2013 10:36:19 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r1AAaJB7022050; Sun, 10 Feb 2013 10:36:19 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r1AAaHs1022034; Sun, 10 Feb 2013 10:36:17 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201302101036.r1AAaHs1022034@svn.freebsd.org> From: Hans Petter Selasky Date: Sun, 10 Feb 2013 10:36:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r246614 - head/sys/dev/usb/wlan X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 10 Feb 2013 10:36:19 -0000 Author: hselasky Date: Sun Feb 10 10:36:16 2013 New Revision: 246614 URL: http://svnweb.freebsd.org/changeset/base/246614 Log: - 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. MFC after: 2 weeks Modified: head/sys/dev/usb/wlan/if_rum.c head/sys/dev/usb/wlan/if_rumvar.h head/sys/dev/usb/wlan/if_run.c head/sys/dev/usb/wlan/if_runvar.h head/sys/dev/usb/wlan/if_uath.c head/sys/dev/usb/wlan/if_upgt.c head/sys/dev/usb/wlan/if_upgtvar.h head/sys/dev/usb/wlan/if_ural.c head/sys/dev/usb/wlan/if_uralvar.h head/sys/dev/usb/wlan/if_urtw.c head/sys/dev/usb/wlan/if_urtwvar.h head/sys/dev/usb/wlan/if_zyd.c head/sys/dev/usb/wlan/if_zydreg.h Modified: head/sys/dev/usb/wlan/if_rum.c ============================================================================== --- head/sys/dev/usb/wlan/if_rum.c Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_rum.c Sun Feb 10 10:36:16 2013 (r246614) @@ -542,6 +542,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); @@ -556,7 +561,6 @@ rum_detach(device_t self) if_free(ifp); } mtx_destroy(&sc->sc_mtx); - return (0); } @@ -1321,7 +1325,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: @@ -2365,8 +2376,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: head/sys/dev/usb/wlan/if_rumvar.h ============================================================================== --- head/sys/dev/usb/wlan/if_rumvar.h Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_rumvar.h Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_run.c ============================================================================== --- head/sys/dev/usb/wlan/if_run.c Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_run.c Sun Feb 10 10:36:16 2013 (r246614) @@ -716,11 +716,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; @@ -3441,7 +3444,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: @@ -4963,8 +4972,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: head/sys/dev/usb/wlan/if_runvar.h ============================================================================== --- head/sys/dev/usb/wlan/if_runvar.h Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_runvar.h Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_uath.c ============================================================================== --- head/sys/dev/usb/wlan/if_uath.c Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_uath.c Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_upgt.c ============================================================================== --- head/sys/dev/usb/wlan/if_upgt.c Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_upgt.c Sun Feb 10 10:36:16 2013 (r246614) @@ -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: @@ -1976,7 +1983,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); } @@ -1986,22 +1992,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); @@ -2029,6 +2055,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: head/sys/dev/usb/wlan/if_upgtvar.h ============================================================================== --- head/sys/dev/usb/wlan/if_upgtvar.h Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_upgtvar.h Sun Feb 10 10:36:16 2013 (r246614) @@ -429,6 +429,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: head/sys/dev/usb/wlan/if_ural.c ============================================================================== --- head/sys/dev/usb/wlan/if_ural.c Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_ural.c Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_uralvar.h ============================================================================== --- head/sys/dev/usb/wlan/if_uralvar.h Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_uralvar.h Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_urtw.c ============================================================================== --- head/sys/dev/usb/wlan/if_urtw.c Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_urtw.c Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_urtwvar.h ============================================================================== --- head/sys/dev/usb/wlan/if_urtwvar.h Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_urtwvar.h Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_zyd.c ============================================================================== --- head/sys/dev/usb/wlan/if_zyd.c Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_zyd.c Sun Feb 10 10:36:16 2013 (r246614) @@ -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: head/sys/dev/usb/wlan/if_zydreg.h ============================================================================== --- head/sys/dev/usb/wlan/if_zydreg.h Sun Feb 10 10:17:41 2013 (r246613) +++ head/sys/dev/usb/wlan/if_zydreg.h Sun Feb 10 10:36:16 2013 (r246614) @@ -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;