Date: Mon, 9 Feb 2009 22:18:11 +0000 (UTC) From: Andrew Thompson <thompsa@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r188419 - head/sys/dev/usb2/wlan Message-ID: <200902092218.n19MIBbL073131@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: thompsa Date: Mon Feb 9 22:18:11 2009 New Revision: 188419 URL: http://svn.freebsd.org/changeset/base/188419 Log: MFp4 //depot/projects/usb; 157429, 157433, 157443 Various changes wrt. usb procs and tasks. Submitted by: Hans Petter Selasky Modified: head/sys/dev/usb2/wlan/if_rum2.c head/sys/dev/usb2/wlan/if_rumvar.h head/sys/dev/usb2/wlan/if_ural2.c head/sys/dev/usb2/wlan/if_uralvar.h head/sys/dev/usb2/wlan/if_zyd2.c head/sys/dev/usb2/wlan/if_zydreg.h Modified: head/sys/dev/usb2/wlan/if_rum2.c ============================================================================== --- head/sys/dev/usb2/wlan/if_rum2.c Mon Feb 9 22:14:38 2009 (r188418) +++ head/sys/dev/usb2/wlan/if_rum2.c Mon Feb 9 22:18:11 2009 (r188419) @@ -54,6 +54,9 @@ SYSCTL_INT(_hw_usb2_rum, OID_AUTO, debug "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) }, @@ -116,10 +119,13 @@ 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, @@ -127,8 +133,8 @@ static struct ieee80211vap *rum_vap_crea 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 int rum_alloc_tx_list(struct rum_softc *); -static void rum_free_tx_list(struct rum_softc *); +static void rum_setup_tx_list(struct rum_softc *); +static void rum_unsetup_tx_list(struct rum_softc *); static int rum_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void rum_setup_tx_desc(struct rum_softc *, @@ -169,9 +175,7 @@ static void rum_set_macaddr(struct rum_ 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 *, @@ -391,12 +395,8 @@ rum_attach(device_t self) { struct usb2_attach_arg *uaa = device_get_ivars(self); struct rum_softc *sc = device_get_softc(self); - struct ieee80211com *ic; - struct ifnet *ifp; - const uint8_t *ucode = NULL; - uint8_t bands, iface_index; - uint32_t tmp; - int error, ntries, size; + uint8_t iface_index; + int error; device_set_usb2_desc(self); sc->sc_udev = uaa->device; @@ -420,42 +420,64 @@ rum_attach(device_t self) goto detach; } - 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; - + /* fork rest of the attach code */ 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; - DELAY(1000); + usb2_pause_mtx(&sc->sc_mtx, hz / 1000); } if (ntries == 1000) { - device_printf(self, "timeout waiting for chip to settle\n"); - RUM_UNLOCK(sc); - goto detach; + device_printf(sc->sc_dev, "timeout waiting for chip to settle\n"); + return; } /* retrieve MAC address and various other things from EEPROM */ rum_read_eeprom(sc); - device_printf(self, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n", + device_printf(sc->sc_dev, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n", tmp, rum_get_rf(sc->rf_rev)); - ucode = rt2573_ucode; - size = sizeof rt2573_ucode; - error = rum_load_microcode(sc, ucode, size); + error = rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode)); if (error != 0) { - device_printf(self, "could not load 8051 microcode\n"); RUM_UNLOCK(sc); - goto detach; + device_printf(sc->sc_dev, "could not load 8051 microcode\n"); + return; } 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; @@ -468,6 +490,7 @@ rum_attach(device_t self) 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 = @@ -516,10 +539,7 @@ rum_attach(device_t self) if (bootverbose) ieee80211_announce(ic); - return 0; -detach: - rum_detach(self); - return (ENXIO); /* failure */ + RUM_LOCK(sc); } static int @@ -529,20 +549,24 @@ rum_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - RUM_LOCK(sc); - sc->sc_flags |= RUM_FLAG_DETACH; - rum_stop(sc); - RUM_UNLOCK(sc); + /* wait for any post attach or other command to complete */ + usb2_proc_drain(&sc->sc_tq); - /* stop all USB transfers first */ + /* stop all USB transfers */ 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); @@ -590,11 +614,8 @@ static void rum_vap_delete(struct ieee80211vap *vap) { struct rum_vap *rvp = RUM_VAP(vap); - struct rum_softc *sc = rvp->sc; - RUM_LOCK(sc); - usb2_callout_stop(&rvp->amrr_ch); - RUM_UNLOCK(sc); + usb2_callout_drain(&rvp->amrr_ch); ieee80211_amrr_cleanup(&rvp->amrr); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); @@ -619,17 +640,12 @@ rum_tx_free(struct rum_tx_data *data, in sc->tx_nfree++; } -static int -rum_alloc_tx_list(struct rum_softc *sc) +static void +rum_setup_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); @@ -641,18 +657,20 @@ rum_alloc_tx_list(struct rum_softc *sc) STAILQ_INSERT_TAIL(&sc->tx_free, data, next); sc->tx_nfree++; } - return 0; } static void -rum_free_tx_list(struct rum_softc *sc) +rum_unsetup_tx_list(struct rum_softc *sc) { struct rum_tx_data *data; int i; - if (sc->tx_data == NULL) - return; + /* make sure any subsequent use of the queues will fail */ + sc->tx_nfree = 0; + STAILQ_INIT(&sc->tx_q); + STAILQ_INIT(&sc->tx_free); + /* free up all node references and mbufs */ for (i = 0; i < RUM_TX_LIST_COUNT; i++) { data = &sc->tx_data[i]; @@ -665,8 +683,6 @@ rum_free_tx_list(struct rum_softc *sc) data->ni = NULL; } } - free(sc->tx_data, M_USB); - sc->tx_data = NULL; } static void @@ -683,9 +699,6 @@ 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) { @@ -705,7 +718,8 @@ rum_task(struct usb2_proc_msg *pm) rum_enable_mrr(sc); rum_set_txpreamble(sc); rum_set_basicrates(sc); - rum_set_bssid(sc, ni->ni_bssid); + IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); + rum_set_bssid(sc, sc->sc_bssid); } if (vap->iv_opmode == IEEE80211_M_HOSTAP || @@ -773,7 +787,7 @@ rum_bulk_write_callback(struct usb2_xfer struct ieee80211_channel *c = ic->ic_curchan; struct rum_tx_data *data; struct mbuf *m; - int len; + unsigned int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -790,15 +804,6 @@ rum_bulk_write_callback(struct usb2_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); @@ -845,6 +850,13 @@ tr_setup: 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; @@ -852,13 +864,6 @@ tr_setup: } 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; } } @@ -873,7 +878,7 @@ rum_bulk_read_callback(struct usb2_xfer struct mbuf *m = NULL; uint32_t flags; uint8_t rssi = 0; - int len; + unsigned int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -965,7 +970,6 @@ tr_setup: goto tr_setup; } return; - } } @@ -1333,15 +1337,20 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, RUM_LOCK(sc); if (ifp->if_flags & IFF_UP) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - rum_init_locked(sc); + rum_queue_command(sc, rum_init_task, + &sc->sc_synctask[0].hdr, + &sc->sc_synctask[1].hdr); 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_stop(sc); + 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); + } } RUM_UNLOCK(sc); if (startall) @@ -1372,7 +1381,7 @@ rum_eeprom_read(struct rum_softc *sc, ui USETW(req.wIndex, addr); USETW(req.wLength, len); - error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); + error = rum_do_request(sc, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not read EEPROM: %s\n", usb2_errstr(error)); @@ -1401,7 +1410,7 @@ rum_read_multi(struct rum_softc *sc, uin USETW(req.wIndex, reg); USETW(req.wLength, len); - error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); + error = rum_do_request(sc, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not multi read MAC register: %s\n", @@ -1429,7 +1438,7 @@ rum_write_multi(struct rum_softc *sc, ui USETW(req.wIndex, reg); USETW(req.wLength, len); - error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf); + error = rum_do_request(sc, &req, buf); if (error != 0) { device_printf(sc->sc_dev, "could not multi write MAC register: %s\n", @@ -1787,9 +1796,6 @@ 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; @@ -1817,15 +1823,13 @@ 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, ic->ic_myaddr, 6); + rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6); rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2); val = le16toh(val); @@ -1933,9 +1937,11 @@ rum_bbp_init(struct rum_softc *sc) } static void -rum_init_locked(struct rum_softc *sc) +rum_init_task(struct usb2_proc_msg *pm) { #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; @@ -1944,10 +1950,7 @@ rum_init_locked(struct rum_softc *sc) RUM_LOCK_ASSERT(sc, MA_OWNED); - if (sc->sc_flags & RUM_FLAG_DETACH) - return; - - rum_stop(sc); + rum_stop_task(pm); /* initialize MAC registers to default values */ for (i = 0; i < N(rum_def_mac); i++) @@ -1990,11 +1993,7 @@ rum_init_locked(struct rum_softc *sc) /* * Allocate Tx and Rx xfer queues. */ - error = rum_alloc_tx_list(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate Tx list\n"); - goto fail; - } + rum_setup_tx_list(sc); /* update Rx filter */ tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff; @@ -2015,7 +2014,7 @@ rum_init_locked(struct rum_softc *sc) usb2_transfer_start(sc->sc_xfer[RUM_BULK_RD]); return; -fail: rum_stop(sc); +fail: rum_stop_task(pm); #undef N } @@ -2027,7 +2026,9 @@ rum_init(void *priv) struct ieee80211com *ic = ifp->if_l2com; RUM_LOCK(sc); - rum_init_locked(sc); + rum_queue_command(sc, rum_init_task, + &sc->sc_synctask[0].hdr, + &sc->sc_synctask[1].hdr); RUM_UNLOCK(sc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -2035,9 +2036,10 @@ rum_init(void *priv) } static void -rum_stop(void *priv) +rum_stop_task(struct usb2_proc_msg *pm) { - struct rum_softc *sc = priv; + struct rum_task *task = (struct rum_task *)pm; + struct rum_softc *sc = task->sc; struct ifnet *ifp = sc->sc_ifp; uint32_t tmp; @@ -2045,17 +2047,17 @@ rum_stop(void *priv) ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + RUM_UNLOCK(sc); + /* - * stop all the transfers, if not already stopped: + * Drain the USB transfers, if not already drained: */ - usb2_transfer_stop(sc->sc_xfer[RUM_BULK_WR]); - usb2_transfer_stop(sc->sc_xfer[RUM_BULK_RD]); + usb2_transfer_drain(sc->sc_xfer[RUM_BULK_WR]); + usb2_transfer_drain(sc->sc_xfer[RUM_BULK_RD]); - rum_free_tx_list(sc); + RUM_LOCK(sc); - /* Stop now if the device has vanished */ - if (sc->sc_flags & RUM_FLAG_DETACH) - return; + rum_unsetup_tx_list(sc); /* disable Rx */ tmp = rum_read(sc, RT2573_TXRX_CSR0); @@ -2083,7 +2085,7 @@ rum_load_microcode(struct rum_softc *sc, USETW(req.wIndex, 0); USETW(req.wLength, 0); - error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL); + error = rum_do_request(sc, &req, NULL); if (error != 0) { device_printf(sc->sc_dev, "could not run firmware: %s\n", usb2_errstr(error)); @@ -2291,14 +2293,10 @@ 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 */ @@ -2307,19 +2305,13 @@ 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: - panic("unknown scan action %d\n", sc->sc_scan_action); - /* NEVER REACHED */ + default: /* RUM_SCAN_END */ + rum_enable_tsf_sync(sc); + rum_set_bssid(sc, sc->sc_bssid); break; } } @@ -2395,6 +2387,11 @@ rum_queue_command(struct rum_softc *sc, 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[] = { Modified: head/sys/dev/usb2/wlan/if_rumvar.h ============================================================================== --- head/sys/dev/usb2/wlan/if_rumvar.h Mon Feb 9 22:14:38 2009 (r188418) +++ head/sys/dev/usb2/wlan/if_rumvar.h Mon Feb 9 22:18:11 2009 (r188419) @@ -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; + struct rum_tx_data tx_data[RUM_TX_LIST_COUNT]; rum_txdhead tx_q; rum_txdhead tx_free; int tx_nfree; @@ -124,12 +124,10 @@ 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; Modified: head/sys/dev/usb2/wlan/if_ural2.c ============================================================================== --- head/sys/dev/usb2/wlan/if_ural2.c Mon Feb 9 22:14:38 2009 (r188418) +++ head/sys/dev/usb2/wlan/if_ural2.c Mon Feb 9 22:18:11 2009 (r188419) @@ -55,6 +55,9 @@ SYSCTL_INT(_hw_usb2_ural, OID_AUTO, debu "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) @@ -95,10 +98,13 @@ static const struct usb2_device_id ural_ 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, @@ -106,8 +112,8 @@ static struct ieee80211vap *ural_vap_cre 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 int ural_alloc_tx_list(struct ural_softc *); -static void ural_free_tx_list(struct ural_softc *); +static void ural_setup_tx_list(struct ural_softc *); +static void ural_unsetup_tx_list(struct ural_softc *); static int ural_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void ural_setup_tx_desc(struct ural_softc *, @@ -153,9 +159,7 @@ static void ural_read_eeprom(struct ura 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 *, @@ -394,10 +398,8 @@ 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 bands, iface_index; + uint8_t iface_index; device_set_usb2_desc(self); sc->sc_udev = uaa->device; @@ -422,14 +424,28 @@ ural_attach(device_t self) goto detach; } - 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; - + /* fork rest of the attach code */ 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); @@ -440,6 +456,14 @@ ural_attach(device_t self) 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; @@ -452,6 +476,7 @@ ural_attach(device_t self) 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 = @@ -500,11 +525,7 @@ ural_attach(device_t self) if (bootverbose) ieee80211_announce(ic); - return (0); /* success */ - -detach: - ural_detach(self); - return (ENXIO); /* failure */ + RAL_LOCK(sc); } static int @@ -514,20 +535,24 @@ ural_detach(device_t self) struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; - RAL_LOCK(sc); - sc->sc_flags |= URAL_FLAG_DETACH; - ural_stop(sc); - RAL_UNLOCK(sc); + /* wait for any post attach or other command to complete */ + usb2_proc_drain(&sc->sc_tq); - /* stop all USB transfers first */ + /* stop all USB transfers */ 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); @@ -575,11 +600,8 @@ static void ural_vap_delete(struct ieee80211vap *vap) { struct ural_vap *uvp = URAL_VAP(vap); - struct ural_softc *sc = uvp->sc; - RAL_LOCK(sc); - usb2_callout_stop(&uvp->amrr_ch); - RAL_UNLOCK(sc); + usb2_callout_drain(&uvp->amrr_ch); ieee80211_amrr_cleanup(&uvp->amrr); ieee80211_vap_detach(vap); free(uvp, M_80211_VAP); @@ -604,17 +626,12 @@ ural_tx_free(struct ural_tx_data *data, sc->tx_nfree++; } -static int -ural_alloc_tx_list(struct ural_softc *sc) +static void +ural_setup_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); @@ -626,18 +643,20 @@ ural_alloc_tx_list(struct ural_softc *sc STAILQ_INSERT_TAIL(&sc->tx_free, data, next); sc->tx_nfree++; } - return 0; } static void -ural_free_tx_list(struct ural_softc *sc) +ural_unsetup_tx_list(struct ural_softc *sc) { struct ural_tx_data *data; int i; - if (sc->tx_data == NULL) - return; + /* make sure any subsequent use of the queues will fail */ + sc->tx_nfree = 0; + STAILQ_INIT(&sc->tx_q); + STAILQ_INIT(&sc->tx_free); + /* free up all node references and mbufs */ for (i = 0; i < RAL_TX_LIST_COUNT; i++) { data = &sc->tx_data[i]; @@ -650,8 +669,6 @@ ural_free_tx_list(struct ural_softc *sc) data->ni = NULL; } } - free(sc->tx_data, M_USB); - sc->tx_data = NULL; } static void @@ -668,9 +685,6 @@ 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) { @@ -691,7 +705,8 @@ ural_task(struct usb2_proc_msg *pm) ural_update_slot(ic->ic_ifp); ural_set_txpreamble(sc); ural_set_basicrates(sc, ic->ic_bsschan); - ural_set_bssid(sc, ni->ni_bssid); + IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); + ural_set_bssid(sc, sc->sc_bssid); } if (vap->iv_opmode == IEEE80211_M_HOSTAP || @@ -743,26 +758,27 @@ 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); - if (sc->sc_flags & URAL_FLAG_DETACH) - return; - - if (sc->sc_scan_action == URAL_SCAN_START) { + switch (sc->sc_scan_action) { + case URAL_SCAN_START: /* abort TSF synchronization */ DPRINTF("starting scan\n"); ural_write(sc, RAL_TXRX_CSR19, 0); ural_set_bssid(sc, ifp->if_broadcastaddr); - } else if (sc->sc_scan_action == URAL_SET_CHANNEL) { + break; + + case URAL_SET_CHANNEL: ural_set_chan(sc, ic->ic_curchan); - } else { + break; + + default: /* URAL_SCAN_END */ DPRINTF("stopping scan\n"); ural_enable_tsf_sync(sc); - /* XXX keep local copy */ - ural_set_bssid(sc, vap->iv_bss->ni_bssid); - } + ural_set_bssid(sc, sc->sc_bssid); + break; + } } static int @@ -806,7 +822,7 @@ ural_bulk_write_callback(struct usb2_xfe struct ieee80211_channel *c = ic->ic_curchan; struct ural_tx_data *data; struct mbuf *m; - int len; + unsigned int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -823,15 +839,6 @@ ural_bulk_write_callback(struct usb2_xfe /* 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); @@ -878,6 +885,13 @@ tr_setup: 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; @@ -885,13 +899,6 @@ tr_setup: } 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; } } @@ -906,7 +913,7 @@ ural_bulk_read_callback(struct usb2_xfer struct mbuf *m = NULL; uint32_t flags; uint8_t rssi = 0; - int len; + unsigned int len; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -1001,7 +1008,6 @@ tr_setup: goto tr_setup; } return; - } } @@ -1406,15 +1412,20 @@ ural_ioctl(struct ifnet *ifp, u_long cmd RAL_LOCK(sc); if (ifp->if_flags & IFF_UP) { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - ural_init_locked(sc); + ural_queue_command(sc, ural_init_task, + &sc->sc_synctask[0].hdr, + &sc->sc_synctask[1].hdr); 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_stop(sc); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902092218.n19MIBbL073131>