summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-02-09 22:14:38 +0000
committerthompsa <thompsa@FreeBSD.org>2009-02-09 22:14:38 +0000
commit050cf3fd9c0289b6561004b023a1a915b04a28fe (patch)
treed696004f5710c1b7468a1f04ac37963ca0d368b3
parent1ef0c422a1e2b4f9a53065ae68ec459458c8f252 (diff)
downloadFreeBSD-src-050cf3fd9c0289b6561004b023a1a915b04a28fe.zip
FreeBSD-src-050cf3fd9c0289b6561004b023a1a915b04a28fe.tar.gz
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.
-rw-r--r--sys/dev/usb2/wlan/if_rum2.c245
-rw-r--r--sys/dev/usb2/wlan/if_rumvar.h10
-rw-r--r--sys/dev/usb2/wlan/if_ural2.c230
-rw-r--r--sys/dev/usb2/wlan/if_uralvar.h7
-rw-r--r--sys/dev/usb2/wlan/if_zyd2.c217
-rw-r--r--sys/dev/usb2/wlan/if_zydreg.h13
6 files changed, 359 insertions, 363 deletions
diff --git a/sys/dev/usb2/wlan/if_rum2.c b/sys/dev/usb2/wlan/if_rum2.c
index 4e78c37..4e7db6d 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 */
- 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;
+ 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);
/* 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 @@ 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;
@@ -864,6 +852,13 @@ 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;
}
}
@@ -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 @@ tr_setup:
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 1b58dc4..1375565 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 34bb1b3..ebf6dca 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 */
- 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;
+ 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);
/* 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 @@ 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;
@@ -899,6 +885,13 @@ 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;
}
}
@@ -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 @@ tr_setup:
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_free_tx_list(sc);
- ural_unsetup_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 c7e5469..1b33580 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 0195bd8..8f4fb83 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 @@ tr_setup:
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 @@ tr_setup:
}
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_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: /* ZYD_SCAN_END */
- /* restore previous bssid */
- zyd_set_bssid(sc, sc->sc_bssid);
+ 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 8ef34e3..c43e801 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;
OpenPOWER on IntegriCloud