From 1b216d36262f8644608cef36b96a43aca2478e28 Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Mon, 9 Feb 2009 22:14:38 +0000 Subject: [PATCH] Correct sources for r188417 MFp4 //depot/projects/usb; 157412 Sync from svn.freebsd.org/base/user/thompsa/usb which is a minimal changeset from oldUSB (no config_td). This excludes the taskqueue changes (for the moment) as requested. --- sys/dev/usb2/wlan/if_rum2.c | 245 +++++++++++++++++---------------- sys/dev/usb2/wlan/if_rumvar.h | 10 +- sys/dev/usb2/wlan/if_ural2.c | 230 +++++++++++++++---------------- sys/dev/usb2/wlan/if_uralvar.h | 7 +- sys/dev/usb2/wlan/if_zyd2.c | 219 ++++++++++++++--------------- sys/dev/usb2/wlan/if_zydreg.h | 13 +- 6 files changed, 360 insertions(+), 364 deletions(-) diff --git a/sys/dev/usb2/wlan/if_rum2.c b/sys/dev/usb2/wlan/if_rum2.c index 4e78c37cb8b0..4e7db6d5245f 100644 --- a/sys/dev/usb2/wlan/if_rum2.c +++ b/sys/dev/usb2/wlan/if_rum2.c @@ -54,9 +54,6 @@ SYSCTL_INT(_hw_usb2_rum, OID_AUTO, debug, CTLFLAG_RW, &rum_debug, 0, "Debug level"); #endif -#define rum_do_request(sc,req,data) \ - usb2_do_request_proc((sc)->sc_udev, &(sc)->sc_tq, req, data, 0, NULL, 5000) - static const struct usb2_device_id rum_devs[] = { { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM) }, { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2) }, @@ -119,13 +116,10 @@ static device_detach_t rum_detach; static usb2_callback_t rum_bulk_read_callback; static usb2_callback_t rum_bulk_write_callback; -static usb2_proc_callback_t rum_attach_post; static usb2_proc_callback_t rum_task; static usb2_proc_callback_t rum_scantask; static usb2_proc_callback_t rum_promisctask; static usb2_proc_callback_t rum_amrr_task; -static usb2_proc_callback_t rum_init_task; -static usb2_proc_callback_t rum_stop_task; static struct ieee80211vap *rum_vap_create(struct ieee80211com *, const char name[IFNAMSIZ], int unit, int opmode, @@ -133,8 +127,8 @@ static struct ieee80211vap *rum_vap_create(struct ieee80211com *, const uint8_t mac[IEEE80211_ADDR_LEN]); static void rum_vap_delete(struct ieee80211vap *); static void rum_tx_free(struct rum_tx_data *, int); -static void rum_setup_tx_list(struct rum_softc *); -static void rum_unsetup_tx_list(struct rum_softc *); +static int rum_alloc_tx_list(struct rum_softc *); +static void rum_free_tx_list(struct rum_softc *); static int rum_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void rum_setup_tx_desc(struct rum_softc *, @@ -175,7 +169,9 @@ static void rum_set_macaddr(struct rum_softc *, const uint8_t *); static const char *rum_get_rf(int); static void rum_read_eeprom(struct rum_softc *); static int rum_bbp_init(struct rum_softc *); +static void rum_init_locked(struct rum_softc *); static void rum_init(void *); +static void rum_stop(void *); static int rum_load_microcode(struct rum_softc *, const u_char *, size_t); static int rum_prepare_beacon(struct rum_softc *, @@ -395,8 +391,12 @@ rum_attach(device_t self) { struct usb2_attach_arg *uaa = device_get_ivars(self); struct rum_softc *sc = device_get_softc(self); - uint8_t iface_index; - int error; + struct ieee80211com *ic; + struct ifnet *ifp; + const uint8_t *ucode = NULL; + uint8_t bands, iface_index; + uint32_t tmp; + int error, ntries, size; device_set_usb2_desc(self); sc->sc_udev = uaa->device; @@ -420,64 +420,42 @@ rum_attach(device_t self) goto detach; } - /* fork rest of the attach code */ + ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); + if (ifp == NULL) { + device_printf(sc->sc_dev, "can not if_alloc()\n"); + goto detach; + } + ic = ifp->if_l2com; + RUM_LOCK(sc); - rum_queue_command(sc, rum_attach_post, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); - RUM_UNLOCK(sc); - return (0); - -detach: - rum_detach(self); - return (ENXIO); /* failure */ -} - -static void -rum_attach_post(struct usb2_proc_msg *pm) -{ - struct rum_task *task = (struct rum_task *)pm; - struct rum_softc *sc = task->sc; - struct ifnet *ifp; - struct ieee80211com *ic; - unsigned int ntries; - int error; - uint32_t tmp; - uint8_t bands; - /* retrieve RT2573 rev. no */ - for (ntries = 0; ntries != 1000; ntries++) { + for (ntries = 0; ntries < 1000; ntries++) { if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0) break; - usb2_pause_mtx(&sc->sc_mtx, hz / 1000); + DELAY(1000); } if (ntries == 1000) { - device_printf(sc->sc_dev, "timeout waiting for chip to settle\n"); - return; + device_printf(self, "timeout waiting for chip to settle\n"); + RUM_UNLOCK(sc); + goto detach; } /* retrieve MAC address and various other things from EEPROM */ rum_read_eeprom(sc); - device_printf(sc->sc_dev, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n", + device_printf(self, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n", tmp, rum_get_rf(sc->rf_rev)); - error = rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode)); + ucode = rt2573_ucode; + size = sizeof rt2573_ucode; + error = rum_load_microcode(sc, ucode, size); if (error != 0) { + device_printf(self, "could not load 8051 microcode\n"); RUM_UNLOCK(sc); - device_printf(sc->sc_dev, "could not load 8051 microcode\n"); - return; + goto detach; } RUM_UNLOCK(sc); - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); - RUM_LOCK(sc); - return; - } - ic = ifp->if_l2com; - ifp->if_softc = sc; if_initname(ifp, "rum", device_get_unit(sc->sc_dev)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; @@ -490,7 +468,6 @@ rum_attach_post(struct usb2_proc_msg *pm) ic->ic_ifp = ifp; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid); /* set device capabilities */ ic->ic_caps = @@ -539,7 +516,10 @@ rum_attach_post(struct usb2_proc_msg *pm) if (bootverbose) ieee80211_announce(ic); - RUM_LOCK(sc); + return 0; +detach: + rum_detach(self); + return (ENXIO); /* failure */ } static int @@ -549,24 +529,20 @@ rum_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - /* wait for any post attach or other command to complete */ - usb2_proc_drain(&sc->sc_tq); + RUM_LOCK(sc); + sc->sc_flags |= RUM_FLAG_DETACH; + rum_stop(sc); + RUM_UNLOCK(sc); - /* stop all USB transfers */ + /* stop all USB transfers first */ usb2_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER); usb2_proc_free(&sc->sc_tq); - /* free TX list, if any */ - RUM_LOCK(sc); - rum_unsetup_tx_list(sc); - RUM_UNLOCK(sc); - if (ifp) { bpfdetach(ifp); ieee80211_ifdetach(ic); if_free(ifp); } - mtx_destroy(&sc->sc_mtx); return (0); @@ -614,8 +590,11 @@ static void rum_vap_delete(struct ieee80211vap *vap) { struct rum_vap *rvp = RUM_VAP(vap); + struct rum_softc *sc = rvp->sc; - usb2_callout_drain(&rvp->amrr_ch); + RUM_LOCK(sc); + usb2_callout_stop(&rvp->amrr_ch); + RUM_UNLOCK(sc); ieee80211_amrr_cleanup(&rvp->amrr); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); @@ -640,12 +619,17 @@ rum_tx_free(struct rum_tx_data *data, int txerr) sc->tx_nfree++; } -static void -rum_setup_tx_list(struct rum_softc *sc) +static int +rum_alloc_tx_list(struct rum_softc *sc) { struct rum_tx_data *data; int i; + sc->tx_data = malloc(sizeof(struct rum_tx_data) * RUM_TX_LIST_COUNT, + M_USB, M_NOWAIT|M_ZERO); + if (sc->tx_data == NULL) + return (ENOMEM); + sc->tx_nfree = 0; STAILQ_INIT(&sc->tx_q); STAILQ_INIT(&sc->tx_free); @@ -657,20 +641,18 @@ rum_setup_tx_list(struct rum_softc *sc) STAILQ_INSERT_TAIL(&sc->tx_free, data, next); sc->tx_nfree++; } + return 0; } static void -rum_unsetup_tx_list(struct rum_softc *sc) +rum_free_tx_list(struct rum_softc *sc) { struct rum_tx_data *data; int i; - /* make sure any subsequent use of the queues will fail */ - sc->tx_nfree = 0; - STAILQ_INIT(&sc->tx_q); - STAILQ_INIT(&sc->tx_free); + if (sc->tx_data == NULL) + return; - /* free up all node references and mbufs */ for (i = 0; i < RUM_TX_LIST_COUNT; i++) { data = &sc->tx_data[i]; @@ -683,6 +665,8 @@ rum_unsetup_tx_list(struct rum_softc *sc) data->ni = NULL; } } + free(sc->tx_data, M_USB); + sc->tx_data = NULL; } static void @@ -699,6 +683,9 @@ rum_task(struct usb2_proc_msg *pm) struct ieee80211_node *ni; uint32_t tmp; + if (sc->sc_flags & RUM_FLAG_DETACH) + return; + ostate = vap->iv_state; switch (sc->sc_state) { @@ -718,8 +705,7 @@ rum_task(struct usb2_proc_msg *pm) rum_enable_mrr(sc); rum_set_txpreamble(sc); rum_set_basicrates(sc); - IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); - rum_set_bssid(sc, sc->sc_bssid); + rum_set_bssid(sc, ni->ni_bssid); } if (vap->iv_opmode == IEEE80211_M_HOSTAP || @@ -787,7 +773,7 @@ rum_bulk_write_callback(struct usb2_xfer *xfer) struct ieee80211_channel *c = ic->ic_curchan; struct rum_tx_data *data; struct mbuf *m; - unsigned int len; + int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -804,6 +790,15 @@ rum_bulk_write_callback(struct usb2_xfer *xfer) /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: +#if 0 + if (sc->sc_flags & RUM_FLAG_WAIT_COMMAND) { + /* + * don't send anything while a command is pending ! + */ + break; + } +#endif + data = STAILQ_FIRST(&sc->tx_q); if (data) { STAILQ_REMOVE_HEAD(&sc->tx_q, next); @@ -850,13 +845,6 @@ rum_bulk_write_callback(struct usb2_xfer *xfer) DPRINTFN(11, "transfer error, %s\n", usb2_errstr(xfer->error)); - ifp->if_oerrors++; - data = xfer->priv_fifo; - if (data != NULL) { - rum_tx_free(data, xfer->error); - xfer->priv_fifo = NULL; - } - if (xfer->error == USB_ERR_STALLED) { /* try to clear stall first */ xfer->flags.stall_pipe = 1; @@ -864,6 +852,13 @@ rum_bulk_write_callback(struct usb2_xfer *xfer) } if (xfer->error == USB_ERR_TIMEOUT) device_printf(sc->sc_dev, "device timeout\n"); + + ifp->if_oerrors++; + data = xfer->priv_fifo; + if (data != NULL) { + rum_tx_free(data, xfer->error); + xfer->priv_fifo = NULL; + } break; } } @@ -878,7 +873,7 @@ rum_bulk_read_callback(struct usb2_xfer *xfer) struct mbuf *m = NULL; uint32_t flags; uint8_t rssi = 0; - unsigned int len; + int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -970,6 +965,7 @@ rum_bulk_read_callback(struct usb2_xfer *xfer) goto tr_setup; } return; + } } @@ -1337,20 +1333,15 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) RUM_LOCK(sc); if (ifp->if_flags & IFF_UP) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - rum_queue_command(sc, rum_init_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); + rum_init_locked(sc); startall = 1; } else rum_queue_command(sc, rum_promisctask, &sc->sc_promisctask[0].hdr, &sc->sc_promisctask[1].hdr); } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - rum_queue_command(sc, rum_stop_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); - } + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + rum_stop(sc); } RUM_UNLOCK(sc); if (startall) @@ -1381,7 +1372,7 @@ rum_eeprom_read(struct rum_softc *sc, uint16_t addr, void *buf, int len) USETW(req.wIndex, addr); USETW(req.wLength, len); - error = rum_do_request(sc, &req, buf); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not read EEPROM: %s\n", usb2_errstr(error)); @@ -1410,7 +1401,7 @@ rum_read_multi(struct rum_softc *sc, uint16_t reg, void *buf, int len) USETW(req.wIndex, reg); USETW(req.wLength, len); - error = rum_do_request(sc, &req, buf); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not multi read MAC register: %s\n", @@ -1438,7 +1429,7 @@ rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len) USETW(req.wIndex, reg); USETW(req.wLength, len); - error = rum_do_request(sc, &req, buf); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not multi write MAC register: %s\n", @@ -1796,6 +1787,9 @@ rum_promisctask(struct usb2_proc_msg *pm) struct ifnet *ifp = sc->sc_ifp; uint32_t tmp; + if (sc->sc_flags & RUM_FLAG_DETACH) + return; + tmp = rum_read(sc, RT2573_TXRX_CSR0); tmp &= ~RT2573_DROP_NOT_TO_ME; @@ -1823,13 +1817,15 @@ rum_get_rf(int rev) static void rum_read_eeprom(struct rum_softc *sc) { + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; uint16_t val; #ifdef RUM_DEBUG int i; #endif /* read MAC address */ - rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6); + rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, ic->ic_myaddr, 6); rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2); val = le16toh(val); @@ -1937,11 +1933,9 @@ rum_bbp_init(struct rum_softc *sc) } static void -rum_init_task(struct usb2_proc_msg *pm) +rum_init_locked(struct rum_softc *sc) { #define N(a) (sizeof (a) / sizeof ((a)[0])) - struct rum_task *task = (struct rum_task *)pm; - struct rum_softc *sc = task->sc; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; uint32_t tmp; @@ -1950,7 +1944,10 @@ rum_init_task(struct usb2_proc_msg *pm) RUM_LOCK_ASSERT(sc, MA_OWNED); - rum_stop_task(pm); + if (sc->sc_flags & RUM_FLAG_DETACH) + return; + + rum_stop(sc); /* initialize MAC registers to default values */ for (i = 0; i < N(rum_def_mac); i++) @@ -1993,7 +1990,11 @@ rum_init_task(struct usb2_proc_msg *pm) /* * Allocate Tx and Rx xfer queues. */ - rum_setup_tx_list(sc); + error = rum_alloc_tx_list(sc); + if (error != 0) { + device_printf(sc->sc_dev, "could not allocate Tx list\n"); + goto fail; + } /* update Rx filter */ tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff; @@ -2014,7 +2015,7 @@ rum_init_task(struct usb2_proc_msg *pm) usb2_transfer_start(sc->sc_xfer[RUM_BULK_RD]); return; -fail: rum_stop_task(pm); +fail: rum_stop(sc); #undef N } @@ -2026,9 +2027,7 @@ rum_init(void *priv) struct ieee80211com *ic = ifp->if_l2com; RUM_LOCK(sc); - rum_queue_command(sc, rum_init_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); + rum_init_locked(sc); RUM_UNLOCK(sc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -2036,10 +2035,9 @@ rum_init(void *priv) } static void -rum_stop_task(struct usb2_proc_msg *pm) +rum_stop(void *priv) { - struct rum_task *task = (struct rum_task *)pm; - struct rum_softc *sc = task->sc; + struct rum_softc *sc = priv; struct ifnet *ifp = sc->sc_ifp; uint32_t tmp; @@ -2047,17 +2045,17 @@ rum_stop_task(struct usb2_proc_msg *pm) ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - RUM_UNLOCK(sc); - /* - * Drain the USB transfers, if not already drained: + * stop all the transfers, if not already stopped: */ - usb2_transfer_drain(sc->sc_xfer[RUM_BULK_WR]); - usb2_transfer_drain(sc->sc_xfer[RUM_BULK_RD]); + usb2_transfer_stop(sc->sc_xfer[RUM_BULK_WR]); + usb2_transfer_stop(sc->sc_xfer[RUM_BULK_RD]); - RUM_LOCK(sc); + rum_free_tx_list(sc); - rum_unsetup_tx_list(sc); + /* Stop now if the device has vanished */ + if (sc->sc_flags & RUM_FLAG_DETACH) + return; /* disable Rx */ tmp = rum_read(sc, RT2573_TXRX_CSR0); @@ -2085,7 +2083,7 @@ rum_load_microcode(struct rum_softc *sc, const u_char *ucode, size_t size) USETW(req.wIndex, 0); USETW(req.wLength, 0); - error = rum_do_request(sc, &req, NULL); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL); if (error != 0) { device_printf(sc->sc_dev, "could not run firmware: %s\n", usb2_errstr(error)); @@ -2293,10 +2291,14 @@ rum_scantask(struct usb2_proc_msg *pm) struct rum_softc *sc = task->sc; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; RUM_LOCK_ASSERT(sc, MA_OWNED); + if (sc->sc_flags & RUM_FLAG_DETACH) + return; + switch (sc->sc_scan_action) { case RUM_SCAN_START: /* abort TSF synchronization */ @@ -2305,13 +2307,19 @@ rum_scantask(struct usb2_proc_msg *pm) rum_set_bssid(sc, ifp->if_broadcastaddr); break; + case RUM_SCAN_END: + rum_enable_tsf_sync(sc); + /* XXX keep local copy */ + rum_set_bssid(sc, vap->iv_bss->ni_bssid); + break; + case RUM_SET_CHANNEL: rum_set_chan(sc, ic->ic_curchan); break; - default: /* RUM_SCAN_END */ - rum_enable_tsf_sync(sc); - rum_set_bssid(sc, sc->sc_bssid); + default: + panic("unknown scan action %d\n", sc->sc_scan_action); + /* NEVER REACHED */ break; } } @@ -2387,11 +2395,6 @@ rum_queue_command(struct rum_softc *sc, usb2_proc_callback_t *fn, task->hdr.pm_callback = fn; task->sc = sc; - /* - * Init and stop must be synchronous! - */ - if ((fn == rum_init_task) || (fn == rum_stop_task)) - usb2_proc_mwait(&sc->sc_tq, t0, t1); } static device_method_t rum_methods[] = { diff --git a/sys/dev/usb2/wlan/if_rumvar.h b/sys/dev/usb2/wlan/if_rumvar.h index 1b58dc47b54f..1375565d3db7 100644 --- a/sys/dev/usb2/wlan/if_rumvar.h +++ b/sys/dev/usb2/wlan/if_rumvar.h @@ -100,14 +100,14 @@ struct rum_softc { struct usb2_process sc_tq; const struct ieee80211_rate_table *sc_rates; - struct usb2_xfer *sc_xfer[RUM_N_TRANSFER]; uint8_t rf_rev; uint8_t rffreq; + struct usb2_xfer *sc_xfer[RUM_N_TRANSFER]; + enum ieee80211_state sc_state; int sc_arg; - struct rum_task sc_synctask[2]; struct rum_task sc_task[2]; struct rum_task sc_promisctask[2]; struct rum_task sc_scantask[2]; @@ -116,7 +116,7 @@ struct rum_softc { #define RUM_SCAN_END 1 #define RUM_SET_CHANNEL 2 - struct rum_tx_data tx_data[RUM_TX_LIST_COUNT]; + struct rum_tx_data *tx_data; rum_txdhead tx_q; rum_txdhead tx_free; int tx_nfree; @@ -124,10 +124,12 @@ struct rum_softc { struct mtx sc_mtx; + int sc_flags; +#define RUM_FLAG_DETACH 0x0001 + uint32_t sta[6]; uint32_t rf_regs[4]; uint8_t txpow[44]; - uint8_t sc_bssid[6]; struct { uint8_t val; diff --git a/sys/dev/usb2/wlan/if_ural2.c b/sys/dev/usb2/wlan/if_ural2.c index 34bb1b37ac33..ebf6dca4f55a 100644 --- a/sys/dev/usb2/wlan/if_ural2.c +++ b/sys/dev/usb2/wlan/if_ural2.c @@ -55,9 +55,6 @@ SYSCTL_INT(_hw_usb2_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0, "Debug level"); #endif -#define ural_do_request(sc,req,data) \ - usb2_do_request_proc((sc)->sc_udev, &(sc)->sc_tq, req, data, 0, NULL, 5000) - #define URAL_RSSI(rssi) \ ((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ? \ ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0) @@ -98,13 +95,10 @@ static const struct usb2_device_id ural_devs[] = { static usb2_callback_t ural_bulk_read_callback; static usb2_callback_t ural_bulk_write_callback; -static usb2_proc_callback_t ural_attach_post; static usb2_proc_callback_t ural_task; static usb2_proc_callback_t ural_scantask; static usb2_proc_callback_t ural_promisctask; static usb2_proc_callback_t ural_amrr_task; -static usb2_proc_callback_t ural_init_task; -static usb2_proc_callback_t ural_stop_task; static struct ieee80211vap *ural_vap_create(struct ieee80211com *, const char name[IFNAMSIZ], int unit, int opmode, @@ -112,8 +106,8 @@ static struct ieee80211vap *ural_vap_create(struct ieee80211com *, const uint8_t mac[IEEE80211_ADDR_LEN]); static void ural_vap_delete(struct ieee80211vap *); static void ural_tx_free(struct ural_tx_data *, int); -static void ural_setup_tx_list(struct ural_softc *); -static void ural_unsetup_tx_list(struct ural_softc *); +static int ural_alloc_tx_list(struct ural_softc *); +static void ural_free_tx_list(struct ural_softc *); static int ural_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void ural_setup_tx_desc(struct ural_softc *, @@ -159,7 +153,9 @@ static void ural_read_eeprom(struct ural_softc *); static int ural_bbp_init(struct ural_softc *); static void ural_set_txantenna(struct ural_softc *, int); static void ural_set_rxantenna(struct ural_softc *, int); +static void ural_init_locked(struct ural_softc *); static void ural_init(void *); +static void ural_stop(void *); static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static void ural_amrr_start(struct ural_softc *, @@ -398,8 +394,10 @@ ural_attach(device_t self) { struct usb2_attach_arg *uaa = device_get_ivars(self); struct ural_softc *sc = device_get_softc(self); + struct ifnet *ifp; + struct ieee80211com *ic; int error; - uint8_t iface_index; + uint8_t bands, iface_index; device_set_usb2_desc(self); sc->sc_udev = uaa->device; @@ -424,28 +422,14 @@ ural_attach(device_t self) goto detach; } - /* fork rest of the attach code */ + ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); + if (ifp == NULL) { + device_printf(sc->sc_dev, "can not if_alloc()\n"); + goto detach; + } + ic = ifp->if_l2com; + RAL_LOCK(sc); - ural_queue_command(sc, ural_attach_post, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); - RAL_UNLOCK(sc); - return (0); - -detach: - ural_detach(self); - return (ENXIO); /* failure */ -} - -static void -ural_attach_post(struct usb2_proc_msg *pm) -{ - struct ural_task *task = (struct ural_task *)pm; - struct ural_softc *sc = task->sc; - struct ifnet *ifp; - struct ieee80211com *ic; - uint8_t bands; - /* retrieve RT2570 rev. no */ sc->asic_rev = ural_read(sc, RAL_MAC_CSR0); @@ -456,14 +440,6 @@ ural_attach_post(struct usb2_proc_msg *pm) device_printf(sc->sc_dev, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n", sc->asic_rev, ural_get_rf(sc->rf_rev)); - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); - RAL_LOCK(sc); - return; - } - ic = ifp->if_l2com; - ifp->if_softc = sc; if_initname(ifp, "ural", device_get_unit(sc->sc_dev)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; @@ -476,7 +452,6 @@ ural_attach_post(struct usb2_proc_msg *pm) ic->ic_ifp = ifp; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid); /* set device capabilities */ ic->ic_caps = @@ -525,7 +500,11 @@ ural_attach_post(struct usb2_proc_msg *pm) if (bootverbose) ieee80211_announce(ic); - RAL_LOCK(sc); + return (0); /* success */ + +detach: + ural_detach(self); + return (ENXIO); /* failure */ } static int @@ -535,24 +514,20 @@ ural_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - /* wait for any post attach or other command to complete */ - usb2_proc_drain(&sc->sc_tq); + RAL_LOCK(sc); + sc->sc_flags |= URAL_FLAG_DETACH; + ural_stop(sc); + RAL_UNLOCK(sc); - /* stop all USB transfers */ + /* stop all USB transfers first */ usb2_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER); usb2_proc_free(&sc->sc_tq); - /* free TX list, if any */ - RAL_LOCK(sc); - ural_unsetup_tx_list(sc); - RAL_UNLOCK(sc); - if (ifp) { bpfdetach(ifp); ieee80211_ifdetach(ic); if_free(ifp); } - mtx_destroy(&sc->sc_mtx); return (0); @@ -600,8 +575,11 @@ static void ural_vap_delete(struct ieee80211vap *vap) { struct ural_vap *uvp = URAL_VAP(vap); + struct ural_softc *sc = uvp->sc; - usb2_callout_drain(&uvp->amrr_ch); + RAL_LOCK(sc); + usb2_callout_stop(&uvp->amrr_ch); + RAL_UNLOCK(sc); ieee80211_amrr_cleanup(&uvp->amrr); ieee80211_vap_detach(vap); free(uvp, M_80211_VAP); @@ -626,12 +604,17 @@ ural_tx_free(struct ural_tx_data *data, int txerr) sc->tx_nfree++; } -static void -ural_setup_tx_list(struct ural_softc *sc) +static int +ural_alloc_tx_list(struct ural_softc *sc) { struct ural_tx_data *data; int i; + sc->tx_data = malloc(sizeof(struct ural_tx_data) * RAL_TX_LIST_COUNT, + M_USB, M_NOWAIT|M_ZERO); + if (sc->tx_data == NULL) + return (ENOMEM); + sc->tx_nfree = 0; STAILQ_INIT(&sc->tx_q); STAILQ_INIT(&sc->tx_free); @@ -643,20 +626,18 @@ ural_setup_tx_list(struct ural_softc *sc) STAILQ_INSERT_TAIL(&sc->tx_free, data, next); sc->tx_nfree++; } + return 0; } static void -ural_unsetup_tx_list(struct ural_softc *sc) +ural_free_tx_list(struct ural_softc *sc) { struct ural_tx_data *data; int i; - /* make sure any subsequent use of the queues will fail */ - sc->tx_nfree = 0; - STAILQ_INIT(&sc->tx_q); - STAILQ_INIT(&sc->tx_free); + if (sc->tx_data == NULL) + return; - /* free up all node references and mbufs */ for (i = 0; i < RAL_TX_LIST_COUNT; i++) { data = &sc->tx_data[i]; @@ -669,6 +650,8 @@ ural_unsetup_tx_list(struct ural_softc *sc) data->ni = NULL; } } + free(sc->tx_data, M_USB); + sc->tx_data = NULL; } static void @@ -685,6 +668,9 @@ ural_task(struct usb2_proc_msg *pm) struct ieee80211_node *ni; struct mbuf *m; + if (sc->sc_flags & URAL_FLAG_DETACH) + return; + ostate = vap->iv_state; switch (sc->sc_state) { @@ -705,8 +691,7 @@ ural_task(struct usb2_proc_msg *pm) ural_update_slot(ic->ic_ifp); ural_set_txpreamble(sc); ural_set_basicrates(sc, ic->ic_bsschan); - IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); - ural_set_bssid(sc, sc->sc_bssid); + ural_set_bssid(sc, ni->ni_bssid); } if (vap->iv_opmode == IEEE80211_M_HOSTAP || @@ -758,27 +743,26 @@ ural_scantask(struct usb2_proc_msg *pm) struct ural_softc *sc = task->sc; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); RAL_LOCK_ASSERT(sc, MA_OWNED); - switch (sc->sc_scan_action) { - case URAL_SCAN_START: + if (sc->sc_flags & URAL_FLAG_DETACH) + return; + + if (sc->sc_scan_action == URAL_SCAN_START) { /* abort TSF synchronization */ DPRINTF("starting scan\n"); ural_write(sc, RAL_TXRX_CSR19, 0); ural_set_bssid(sc, ifp->if_broadcastaddr); - break; - - case URAL_SET_CHANNEL: + } else if (sc->sc_scan_action == URAL_SET_CHANNEL) { ural_set_chan(sc, ic->ic_curchan); - break; - - default: /* URAL_SCAN_END */ + } else { DPRINTF("stopping scan\n"); ural_enable_tsf_sync(sc); - ural_set_bssid(sc, sc->sc_bssid); - break; - } + /* XXX keep local copy */ + ural_set_bssid(sc, vap->iv_bss->ni_bssid); + } } static int @@ -822,7 +806,7 @@ ural_bulk_write_callback(struct usb2_xfer *xfer) struct ieee80211_channel *c = ic->ic_curchan; struct ural_tx_data *data; struct mbuf *m; - unsigned int len; + int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -839,6 +823,15 @@ ural_bulk_write_callback(struct usb2_xfer *xfer) /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: +#if 0 + if (sc->sc_flags & URAL_FLAG_WAIT_COMMAND) { + /* + * don't send anything while a command is pending ! + */ + break; + } +#endif + data = STAILQ_FIRST(&sc->tx_q); if (data) { STAILQ_REMOVE_HEAD(&sc->tx_q, next); @@ -885,13 +878,6 @@ ural_bulk_write_callback(struct usb2_xfer *xfer) DPRINTFN(11, "transfer error, %s\n", usb2_errstr(xfer->error)); - ifp->if_oerrors++; - data = xfer->priv_fifo; - if (data != NULL) { - ural_tx_free(data, xfer->error); - xfer->priv_fifo = NULL; - } - if (xfer->error == USB_ERR_STALLED) { /* try to clear stall first */ xfer->flags.stall_pipe = 1; @@ -899,6 +885,13 @@ ural_bulk_write_callback(struct usb2_xfer *xfer) } if (xfer->error == USB_ERR_TIMEOUT) device_printf(sc->sc_dev, "device timeout\n"); + + ifp->if_oerrors++; + data = xfer->priv_fifo; + if (data != NULL) { + ural_tx_free(data, xfer->error); + xfer->priv_fifo = NULL; + } break; } } @@ -913,7 +906,7 @@ ural_bulk_read_callback(struct usb2_xfer *xfer) struct mbuf *m = NULL; uint32_t flags; uint8_t rssi = 0; - unsigned int len; + int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -1008,6 +1001,7 @@ ural_bulk_read_callback(struct usb2_xfer *xfer) goto tr_setup; } return; + } } @@ -1412,20 +1406,15 @@ ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) RAL_LOCK(sc); if (ifp->if_flags & IFF_UP) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - ural_queue_command(sc, ural_init_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); + ural_init_locked(sc); startall = 1; } else ural_queue_command(sc, ural_promisctask, &sc->sc_promisctask[0].hdr, &sc->sc_promisctask[1].hdr); } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - ural_queue_command(sc, ural_stop_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); - } + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + ural_stop(sc); } RAL_UNLOCK(sc); if (startall) @@ -1454,7 +1443,7 @@ ural_set_testmode(struct ural_softc *sc) USETW(req.wIndex, 1); USETW(req.wLength, 0); - error = ural_do_request(sc, &req, NULL); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL); if (error != 0) { device_printf(sc->sc_dev, "could not set test mode: %s\n", usb2_errstr(error)); @@ -1473,7 +1462,7 @@ ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len) USETW(req.wIndex, addr); USETW(req.wLength, len); - error = ural_do_request(sc, &req, buf); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not read EEPROM: %s\n", usb2_errstr(error)); @@ -1493,7 +1482,7 @@ ural_read(struct ural_softc *sc, uint16_t reg) USETW(req.wIndex, reg); USETW(req.wLength, sizeof (uint16_t)); - error = ural_do_request(sc, &req, &val); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, &val); if (error != 0) { device_printf(sc->sc_dev, "could not read MAC register: %s\n", usb2_errstr(error)); @@ -1515,7 +1504,7 @@ ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) USETW(req.wIndex, reg); USETW(req.wLength, len); - error = ural_do_request(sc, &req, buf); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not read MAC register: %s\n", usb2_errstr(error)); @@ -1534,7 +1523,7 @@ ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val) USETW(req.wIndex, reg); USETW(req.wLength, 0); - error = ural_do_request(sc, &req, NULL); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL); if (error != 0) { device_printf(sc->sc_dev, "could not write MAC register: %s\n", usb2_errstr(error)); @@ -1553,7 +1542,7 @@ ural_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) USETW(req.wIndex, reg); USETW(req.wLength, len); - error = ural_do_request(sc, &req, buf); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not write MAC register: %s\n", usb2_errstr(error)); @@ -1948,6 +1937,9 @@ ural_promisctask(struct usb2_proc_msg *pm) struct ifnet *ifp = sc->sc_ifp; uint32_t tmp; + if (sc->sc_flags & URAL_FLAG_DETACH) + return; + tmp = ural_read(sc, RAL_TXRX_CSR2); tmp &= ~RAL_DROP_NOT_TO_ME; @@ -1978,6 +1970,8 @@ ural_get_rf(int rev) static void ural_read_eeprom(struct ural_softc *sc) { + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; uint16_t val; ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2); @@ -1990,7 +1984,7 @@ ural_read_eeprom(struct ural_softc *sc) sc->nb_ant = val & 0x3; /* read MAC address */ - ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6); + ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_myaddr, 6); /* read default values for BBP registers */ ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); @@ -2083,22 +2077,24 @@ ural_set_rxantenna(struct ural_softc *sc, int antenna) } static void -ural_init_task(struct usb2_proc_msg *pm) +ural_init_locked(struct ural_softc *sc) { #define N(a) (sizeof (a) / sizeof ((a)[0])) - struct ural_task *task = (struct ural_task *)pm; - struct ural_softc *sc = task->sc; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; uint16_t tmp; + usb2_error_t error; int i, ntries; RAL_LOCK_ASSERT(sc, MA_OWNED); + if (sc->sc_flags & URAL_FLAG_DETACH) + return; + ural_set_testmode(sc); ural_write(sc, 0x308, 0x00f0); /* XXX magic */ - ural_stop_task(pm); + ural_stop(sc); /* initialize MAC registers to default values */ for (i = 0; i < N(ural_def_mac); i++) @@ -2141,7 +2137,11 @@ ural_init_task(struct usb2_proc_msg *pm) /* * Allocate Tx and Rx xfer queues. */ - ural_setup_tx_list(sc); + error = ural_alloc_tx_list(sc); + if (error != 0) { + device_printf(sc->sc_dev, "could not allocate Tx list\n"); + goto fail; + } /* kick Rx */ tmp = RAL_DROP_PHY | RAL_DROP_CRC; @@ -2159,7 +2159,7 @@ ural_init_task(struct usb2_proc_msg *pm) usb2_transfer_start(sc->sc_xfer[URAL_BULK_RD]); return; -fail: ural_stop_task(pm); +fail: ural_stop(sc); #undef N } @@ -2171,9 +2171,7 @@ ural_init(void *priv) struct ieee80211com *ic = ifp->if_l2com; RAL_LOCK(sc); - ural_queue_command(sc, ural_init_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); + ural_init_locked(sc); RAL_UNLOCK(sc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -2181,10 +2179,9 @@ ural_init(void *priv) } static void -ural_stop_task(struct usb2_proc_msg *pm) +ural_stop(void *priv) { - struct ural_task *task = (struct ural_task *)pm; - struct ural_softc *sc = task->sc; + struct ural_softc *sc = priv; struct ifnet *ifp = sc->sc_ifp; RAL_LOCK_ASSERT(sc, MA_OWNED); @@ -2192,14 +2189,16 @@ ural_stop_task(struct usb2_proc_msg *pm) ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); /* - * Drain all the transfers, if not already drained: + * stop all the transfers, if not already stopped: */ - RAL_UNLOCK(sc); - usb2_transfer_drain(sc->sc_xfer[URAL_BULK_WR]); - usb2_transfer_drain(sc->sc_xfer[URAL_BULK_RD]); - RAL_LOCK(sc); + usb2_transfer_stop(sc->sc_xfer[URAL_BULK_WR]); + usb2_transfer_stop(sc->sc_xfer[URAL_BULK_RD]); - ural_unsetup_tx_list(sc); + ural_free_tx_list(sc); + + /* Stop now if the device has vanished */ + if (sc->sc_flags & URAL_FLAG_DETACH) + return; /* disable Rx */ ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX); @@ -2334,10 +2333,5 @@ ural_queue_command(struct ural_softc *sc, usb2_proc_callback_t *fn, task->hdr.pm_callback = fn; task->sc = sc; - /* - * Init and stop must be synchronous! - */ - if ((fn == ural_init_task) || (fn == ural_stop_task)) - usb2_proc_mwait(&sc->sc_tq, t0, t1); } diff --git a/sys/dev/usb2/wlan/if_uralvar.h b/sys/dev/usb2/wlan/if_uralvar.h index c7e546951e87..1b335806a4cd 100644 --- a/sys/dev/usb2/wlan/if_uralvar.h +++ b/sys/dev/usb2/wlan/if_uralvar.h @@ -114,12 +114,11 @@ struct ural_softc { enum ieee80211_state sc_state; int sc_arg; int sc_scan_action; /* should be an enum */ - struct ural_task sc_synctask[2]; struct ural_task sc_task[2]; struct ural_task sc_promisctask[2]; struct ural_task sc_scantask[2]; - struct ural_tx_data tx_data[RAL_TX_LIST_COUNT]; + struct ural_tx_data *tx_data; ural_txdhead tx_q; ural_txdhead tx_free; int tx_nfree; @@ -127,10 +126,12 @@ struct ural_softc { struct mtx sc_mtx; + int sc_flags; +#define URAL_FLAG_DETACH 0x0001 + uint16_t sta[11]; uint32_t rf_regs[4]; uint8_t txpow[14]; - uint8_t sc_bssid[6]; struct { uint8_t val; diff --git a/sys/dev/usb2/wlan/if_zyd2.c b/sys/dev/usb2/wlan/if_zyd2.c index 0195bd8ea4ad..8f4fb838d2f5 100644 --- a/sys/dev/usb2/wlan/if_zyd2.c +++ b/sys/dev/usb2/wlan/if_zyd2.c @@ -64,7 +64,7 @@ enum { ZYD_DEBUG_ANY = 0xffffffff }; #define DPRINTF(sc, m, fmt, ...) do { \ - if (zyd_debug & (m)) \ + if (sc->sc_debug & (m)) \ printf("%s: " fmt, __func__, ## __VA_ARGS__); \ } while (0) #else @@ -73,9 +73,6 @@ enum { } while (0) #endif -#define zyd_do_request(sc,req,data) \ - usb2_do_request_proc((sc)->sc_udev, &(sc)->sc_tq, req, data, 0, NULL, 5000) - static device_probe_t zyd_match; static device_attach_t zyd_attach; static device_detach_t zyd_detach; @@ -85,12 +82,9 @@ static usb2_callback_t zyd_intr_write_callback; static usb2_callback_t zyd_bulk_read_callback; static usb2_callback_t zyd_bulk_write_callback; -static usb2_proc_callback_t zyd_attach_post; static usb2_proc_callback_t zyd_task; static usb2_proc_callback_t zyd_scantask; static usb2_proc_callback_t zyd_multitask; -static usb2_proc_callback_t zyd_init_task; -static usb2_proc_callback_t zyd_stop_task; static struct ieee80211vap *zyd_vap_create(struct ieee80211com *, const char name[IFNAMSIZ], int unit, int opmode, @@ -98,8 +92,8 @@ static struct ieee80211vap *zyd_vap_create(struct ieee80211com *, const uint8_t mac[IEEE80211_ADDR_LEN]); static void zyd_vap_delete(struct ieee80211vap *); static void zyd_tx_free(struct zyd_tx_data *, int); -static void zyd_setup_tx_list(struct zyd_softc *); -static void zyd_unsetup_tx_list(struct zyd_softc *); +static int zyd_alloc_tx_list(struct zyd_softc *); +static void zyd_free_tx_list(struct zyd_softc *); static struct ieee80211_node *zyd_node_alloc(struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN]); static int zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int); @@ -136,12 +130,15 @@ static void zyd_start(struct ifnet *); static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static int zyd_ioctl(struct ifnet *, u_long, caddr_t); +static void zyd_init_locked(struct zyd_softc *); static void zyd_init(void *); +static void zyd_stop(struct zyd_softc *); static int zyd_loadfirmware(struct zyd_softc *); static void zyd_newassoc(struct ieee80211_node *, int); static void zyd_scan_start(struct ieee80211com *); static void zyd_scan_end(struct ieee80211com *); static void zyd_set_channel(struct ieee80211com *); +static void zyd_wakeup(struct zyd_softc *); static int zyd_rfmd_init(struct zyd_rf *); static int zyd_rfmd_switch_radio(struct zyd_rf *, int); static int zyd_rfmd_set_channel(struct zyd_rf *, uint8_t); @@ -293,7 +290,7 @@ zyd_match(device_t dev) if (uaa->usb2_mode != USB_MODE_HOST) return (ENXIO); - if (uaa->info.bConfigIndex != ZYD_CONFIG_INDEX) + if (uaa->info.bConfigIndex != 0) return (ENXIO); if (uaa->info.bIfaceIndex != ZYD_IFACE_INDEX) return (ENXIO); @@ -304,10 +301,12 @@ zyd_match(device_t dev) static int zyd_attach(device_t dev) { + int error = ENXIO; + struct ieee80211com *ic; + struct ifnet *ifp; struct usb2_attach_arg *uaa = device_get_ivars(dev); struct zyd_softc *sc = device_get_softc(dev); - int error; - uint8_t iface_index; + uint8_t bands, iface_index; if (uaa->info.bcdDevice < 0x4330) { device_printf(dev, "device version mismatch: 0x%X " @@ -320,7 +319,9 @@ zyd_attach(device_t dev) sc->sc_dev = dev; sc->sc_udev = uaa->device; sc->sc_macrev = USB_GET_DRIVER_INFO(uaa); - +#ifdef USB_DEBUG + sc->sc_debug = zyd_debug; +#endif mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, MTX_DEF); @@ -333,50 +334,26 @@ zyd_attach(device_t dev) if (error) { device_printf(dev, "could not allocate USB transfers, " "err=%s\n", usb2_errstr(error)); - goto detach; + goto fail0; } error = usb2_proc_create(&sc->sc_tq, &sc->sc_mtx, device_get_nameunit(dev), USB_PRI_MED); if (error) { device_printf(dev, "could not setup config thread!\n"); - goto detach; + goto fail0; } - /* fork rest of the attach code */ - ZYD_LOCK(sc); - zyd_queue_command(sc, zyd_attach_post, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); - ZYD_UNLOCK(sc); - return (0); - -detach: - zyd_detach(dev); - return (ENXIO); /* failure */ -} - -static void -zyd_attach_post(struct usb2_proc_msg *pm) -{ - struct zyd_task *task = (struct zyd_task *)pm; - struct zyd_softc *sc = task->sc; - struct ifnet *ifp; - struct ieee80211com *ic; - int error; - uint8_t bands; - if ((error = zyd_get_macaddr(sc)) != 0) { device_printf(sc->sc_dev, "could not read EEPROM\n"); - return; + error = ENXIO; + goto fail0; } - ZYD_UNLOCK(sc); - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); - ZYD_LOCK(sc); - return; + device_printf(dev, "can not if_alloc()\n"); + error = ENXIO; + goto fail0; } ifp->if_softc = sc; if_initname(ifp, "zyd", device_get_unit(sc->sc_dev)); @@ -432,7 +409,10 @@ zyd_attach_post(struct usb2_proc_msg *pm) if (bootverbose) ieee80211_announce(ic); - ZYD_LOCK(sc); + return (0); + +fail0: mtx_destroy(&sc->sc_mtx); + return (error); } static int @@ -442,22 +422,21 @@ zyd_detach(device_t dev) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - /* wait for any post attach or other command to complete */ - usb2_proc_drain(&sc->sc_tq); + ZYD_LOCK(sc); + sc->sc_flags |= ZYD_FLAG_DETACHING; + zyd_stop(sc); + zyd_wakeup(sc); + ZYD_UNLOCK(sc); - /* stop all USB transfers */ + /* stop all USB transfers first */ usb2_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); usb2_proc_free(&sc->sc_tq); - /* free TX list, if any */ - zyd_unsetup_tx_list(sc); - if (ifp) { bpfdetach(ifp); ieee80211_ifdetach(ic); if_free(ifp); } - mtx_destroy(&sc->sc_mtx); return (0); @@ -528,12 +507,17 @@ zyd_tx_free(struct zyd_tx_data *data, int txerr) sc->tx_nfree++; } -static void -zyd_setup_tx_list(struct zyd_softc *sc) +static int +zyd_alloc_tx_list(struct zyd_softc *sc) { struct zyd_tx_data *data; int i; + sc->tx_data = malloc(sizeof(struct zyd_tx_data) * ZYD_TX_LIST_CNT, + M_USB, M_NOWAIT|M_ZERO); + if (sc->tx_data == NULL) + return (ENOMEM); + sc->tx_nfree = 0; STAILQ_INIT(&sc->tx_q); STAILQ_INIT(&sc->tx_free); @@ -545,20 +529,18 @@ zyd_setup_tx_list(struct zyd_softc *sc) STAILQ_INSERT_TAIL(&sc->tx_free, data, next); sc->tx_nfree++; } + return 0; } static void -zyd_unsetup_tx_list(struct zyd_softc *sc) +zyd_free_tx_list(struct zyd_softc *sc) { struct zyd_tx_data *data; int i; - /* make sure any subsequent use of the queues will fail */ - sc->tx_nfree = 0; - STAILQ_INIT(&sc->tx_q); - STAILQ_INIT(&sc->tx_free); + if (sc->tx_data == NULL) + return; - /* free up all node references and mbufs */ for (i = 0; i < ZYD_TX_LIST_CNT; i++) { data = &sc->tx_data[i]; @@ -571,6 +553,8 @@ zyd_unsetup_tx_list(struct zyd_softc *sc) data->ni = NULL; } } + free(sc->tx_data, M_USB); + sc->tx_data = NULL; } /* ARGUSED */ @@ -818,8 +802,7 @@ zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen, if (ilen > sizeof(cmd.data)) return (EINVAL); - - if (usb2_proc_is_gone(&sc->sc_tq)) + if (sc->sc_flags & ZYD_FLAG_DETACHING) return (ENXIO); cmd.code = htole16(code); @@ -1916,11 +1899,13 @@ zyd_get_macaddr(struct zyd_softc *sc) USETW(req.wIndex, 0); USETW(req.wLength, IEEE80211_ADDR_LEN); - error = zyd_do_request(sc, &req, sc->sc_bssid); + ZYD_LOCK(sc); + error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, sc->sc_bssid); if (error != 0) { device_printf(sc->sc_dev, "could not read EEPROM: %s\n", usb2_errstr(error)); } + ZYD_UNLOCK(sc); return (error); } @@ -2492,6 +2477,16 @@ zyd_bulk_write_callback(struct usb2_xfer *xfer) /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: +#if 0 + if (sc->sc_flags & ZYD_FLAG_WAIT_COMMAND) { + /* + * don't send anything while a command is pending ! + */ + DPRINTF(sc, ZYD_DEBUG_ANY, "wait command\n"); + break; + } +#endif + data = STAILQ_FIRST(&sc->tx_q); if (data) { STAILQ_REMOVE_HEAD(&sc->tx_q, next); @@ -2528,12 +2523,6 @@ zyd_bulk_write_callback(struct usb2_xfer *xfer) DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n", usb2_errstr(xfer->error)); - ifp->if_oerrors++; - data = xfer->priv_fifo; - xfer->priv_fifo = NULL; - if (data != NULL) - zyd_tx_free(data, xfer->error); - if (xfer->error == USB_ERR_STALLED) { /* try to clear stall first */ xfer->flags.stall_pipe = 1; @@ -2541,6 +2530,12 @@ zyd_bulk_write_callback(struct usb2_xfer *xfer) } if (xfer->error == USB_ERR_TIMEOUT) device_printf(sc->sc_dev, "device timeout\n"); + + ifp->if_oerrors++; + data = xfer->priv_fifo; + xfer->priv_fifo = NULL; + if (data != NULL && ifp->if_drv_flags & IFF_DRV_RUNNING) + zyd_tx_free(data, xfer->error); break; } } @@ -2734,17 +2729,12 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) (IFF_ALLMULTI | IFF_PROMISC)) zyd_set_multi(sc); } else { - zyd_queue_command(sc, zyd_init_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); + zyd_init_locked(sc); startall = 1; } } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - zyd_queue_command(sc, zyd_stop_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); - } + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + zyd_stop(sc); } sc->sc_if_flags = ifp->if_flags; ZYD_UNLOCK(sc); @@ -2765,18 +2755,19 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } static void -zyd_init_task(struct usb2_proc_msg *pm) +zyd_init_locked(struct zyd_softc *sc) { - struct zyd_task *task = (struct zyd_task *)pm; - struct zyd_softc *sc = task->sc; + int error; struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; struct usb2_config_descriptor *cd; - int error; uint32_t val; ZYD_LOCK_ASSERT(sc, MA_OWNED); + if (sc->sc_flags & ZYD_FLAG_DETACHING) + return; + if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) { error = zyd_loadfirmware(sc); if (error != 0) { @@ -2823,7 +2814,7 @@ zyd_init_task(struct usb2_proc_msg *pm) } if (ifp->if_drv_flags & IFF_DRV_RUNNING) - zyd_stop_task(pm); + zyd_stop(sc); IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %s\n", @@ -2859,7 +2850,10 @@ zyd_init_task(struct usb2_proc_msg *pm) /* * Allocate Tx and Rx xfer queues. */ - zyd_setup_tx_list(sc); + if ((error = zyd_alloc_tx_list(sc)) != 0) { + device_printf(sc->sc_dev, "could not allocate Tx list\n"); + goto fail; + } /* enable interrupts */ zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK); @@ -2871,7 +2865,7 @@ zyd_init_task(struct usb2_proc_msg *pm) return; -fail: zyd_stop_task(pm); +fail: zyd_stop(sc); return; } @@ -2883,9 +2877,7 @@ zyd_init(void *priv) struct ieee80211com *ic = ifp->if_l2com; ZYD_LOCK(sc); - zyd_queue_command(sc, zyd_init_task, - &sc->sc_synctask[0].hdr, - &sc->sc_synctask[1].hdr); + zyd_init_locked(sc); ZYD_UNLOCK(sc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -2893,10 +2885,8 @@ zyd_init(void *priv) } static void -zyd_stop_task(struct usb2_proc_msg *pm) +zyd_stop(struct zyd_softc *sc) { - struct zyd_task *task = (struct zyd_task *)pm; - struct zyd_softc *sc = task->sc; struct ifnet *ifp = sc->sc_ifp; int error; @@ -2905,17 +2895,16 @@ zyd_stop_task(struct usb2_proc_msg *pm) ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); /* - * Drain all the transfers, if not already drained: + * stop all the transfers, if not already stopped: */ - ZYD_UNLOCK(sc); - usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_WR]); - usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_RD]); - ZYD_LOCK(sc); + usb2_transfer_stop(sc->sc_xfer[ZYD_BULK_WR]); + usb2_transfer_stop(sc->sc_xfer[ZYD_BULK_RD]); - zyd_unsetup_tx_list(sc); + zyd_free_tx_list(sc); - /* Stop now if the device was never set up */ - if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) + /* Stop now if the device has vanished or was never set up */ + if (sc->sc_flags & ZYD_FLAG_DETACHING || + (sc->sc_flags & ZYD_FLAG_INITONCE) == 0) return; /* switch radio transmitter OFF */ @@ -2969,7 +2958,7 @@ zyd_loadfirmware(struct zyd_softc *sc) USETW(req.wValue, addr); USETW(req.wLength, mlen); - if (zyd_do_request(sc, &req, fw) != 0) + if (usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, fw) != 0) return (EIO); addr += mlen / 2; @@ -2983,7 +2972,7 @@ zyd_loadfirmware(struct zyd_softc *sc) USETW(req.wValue, 0); USETW(req.wIndex, 0); USETW(req.wLength, sizeof(stat)); - if (zyd_do_request(sc, &req, &stat) != 0) + if (usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, &stat) != 0) return (EIO); sc->sc_flags |= ZYD_FLAG_FWLOADED; @@ -3053,16 +3042,27 @@ zyd_scantask(struct usb2_proc_msg *pm) /* want broadcast address while scanning */ zyd_set_bssid(sc, ifp->if_broadcastaddr); break; - - case ZYD_SET_CHANNEL: - zyd_set_chan(sc, ic->ic_curchan); - break; - - default: /* ZYD_SCAN_END */ + case ZYD_SCAN_END: /* restore previous bssid */ zyd_set_bssid(sc, sc->sc_bssid); break; - } + case ZYD_SET_CHANNEL: + zyd_set_chan(sc, ic->ic_curchan); + break; + default: + device_printf(sc->sc_dev, "unknown scan action %d\n", + sc->sc_scan_action); + break; + } +} + +static void +zyd_wakeup(struct zyd_softc *sc) +{ + struct zyd_rq *rqp; + + STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) + wakeup(rqp); /* wakeup sleeping caller */ } static void @@ -3089,11 +3089,6 @@ zyd_queue_command(struct zyd_softc *sc, usb2_proc_callback_t *fn, task->hdr.pm_callback = fn; task->sc = sc; - /* - * Init and stop must be synchronous! - */ - if ((fn == zyd_init_task) || (fn == zyd_stop_task)) - usb2_proc_mwait(&sc->sc_tq, t0, t1); } static device_method_t zyd_methods[] = { diff --git a/sys/dev/usb2/wlan/if_zydreg.h b/sys/dev/usb2/wlan/if_zydreg.h index 8ef34e35472b..c43e8015e43b 100644 --- a/sys/dev/usb2/wlan/if_zydreg.h +++ b/sys/dev/usb2/wlan/if_zydreg.h @@ -1127,7 +1127,7 @@ struct zyd_notif_retry { uint16_t count; } __packed; -#define ZYD_CONFIG_INDEX 0 +#define ZYD_CONFIG_NO 1 #define ZYD_IFACE_INDEX 0 #define ZYD_INTR_TIMEOUT 1000 @@ -1270,12 +1270,13 @@ struct zyd_softc { enum ieee80211_state sc_state; int sc_arg; int sc_flags; -#define ZYD_FLAG_FWLOADED (1 << 0) -#define ZYD_FLAG_INITONCE (1 << 1) -#define ZYD_FLAG_INITDONE (1 << 2) +#define ZYD_FLAG_FWLOADED (1 << 0) +#define ZYD_FLAG_DETACHING (1 << 1) +#define ZYD_FLAG_INITONCE (1 << 2) +#define ZYD_FLAG_INITDONE (1 << 3) int sc_if_flags; + uint32_t sc_debug; - struct zyd_task sc_synctask[2]; struct zyd_task sc_mcasttask[2]; struct zyd_task sc_scantask[2]; int sc_scan_action; @@ -1316,7 +1317,7 @@ struct zyd_softc { struct mtx sc_mtx; struct cv sc_intr_cv; - struct zyd_tx_data tx_data[ZYD_TX_LIST_CNT]; + struct zyd_tx_data *tx_data; zyd_txdhead tx_q; zyd_txdhead tx_free; int tx_nfree;