PERFORCE change 157570 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Feb 11 13:40:31 PST 2009
http://perforce.freebsd.org/chv.cgi?CH=157570
Change 157570 by hselasky at hselasky_laptop001 on 2009/02/11 21:39:58
USB WLAN patches.
- try to handle more detach races with the network stack
- next state and argument must be atomically read before
passing to iv_nextstate callback
- increase control request timeout
- make sure INIT state is handled correctly USB wise
- revert changes to "ieee80211_proto.c"
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#38 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#37 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#38 edit
.. //depot/projects/usb/src/sys/net80211/ieee80211_proto.c#13 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#38 (text+ko) ====
@@ -125,7 +125,7 @@
static usb2_proc_callback_t rum_stop_task;
static usb2_proc_callback_t rum_flush_task;
-static void rum_do_request(struct rum_softc *sc,
+static usb2_error_t rum_do_request(struct rum_softc *sc,
struct usb2_device_request *req, void *data);
static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
const char name[IFNAMSIZ], int unit, int opmode,
@@ -154,8 +154,8 @@
static uint32_t rum_read(struct rum_softc *, uint16_t);
static void rum_read_multi(struct rum_softc *, uint16_t, void *,
int);
-static void rum_write(struct rum_softc *, uint16_t, uint32_t);
-static void rum_write_multi(struct rum_softc *, uint16_t, void *,
+static usb2_error_t rum_write(struct rum_softc *, uint16_t, uint32_t);
+static usb2_error_t rum_write_multi(struct rum_softc *, uint16_t, void *,
size_t);
static void rum_bbp_write(struct rum_softc *, uint8_t, uint8_t);
static uint8_t rum_bbp_read(struct rum_softc *, uint8_t);
@@ -178,7 +178,7 @@
static void rum_read_eeprom(struct rum_softc *);
static int rum_bbp_init(struct rum_softc *);
static void rum_init(void *);
-static int rum_load_microcode(struct rum_softc *, const uint8_t *,
+static void rum_load_microcode(struct rum_softc *, const uint8_t *,
size_t);
static int rum_prepare_beacon(struct rum_softc *,
struct ieee80211vap *);
@@ -444,7 +444,6 @@
struct ifnet *ifp;
struct ieee80211com *ic;
unsigned int ntries;
- int error;
uint32_t tmp;
uint8_t bands;
@@ -466,11 +465,12 @@
device_printf(sc->sc_dev, "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));
- if (error != 0) {
- device_printf(sc->sc_dev, "could not load 8051 microcode\n");
+ rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode));
+
+ /* XXX WLAN race --hps */
+ if (usb2_proc_is_gone(&sc->sc_tq))
return;
- }
+
RUM_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
@@ -578,20 +578,21 @@
return (0);
}
-static void
+static usb2_error_t
rum_do_request(struct rum_softc *sc,
struct usb2_device_request *req, void *data)
{
usb2_error_t err;
err = usb2_do_request_proc(sc->sc_udev, &sc->sc_tq,
- req, data, 0, NULL, 250 /* ms */);
+ req, data, 0, NULL, 1000 /* ms */);
if (err) {
- DPRINTFN(1, "Control request failed! (ignored)\n");
+ DPRINTFN(1, "Control request failed, "
+ "%s! (ignored)\n", usb2_errstr(err));
rum_pause(sc, hz / 100);
}
- return;
+ return (err);
}
static struct ieee80211vap *
@@ -736,21 +737,21 @@
struct rum_vap *rvp = RUM_VAP(vap);
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
+ enum ieee80211_state nstate;
struct ieee80211_node *ni;
+ int arg;
uint32_t tmp;
ostate = vap->iv_state;
+ nstate = sc->sc_state;
+ arg = sc->sc_arg;
/* callout it stopped */
usb2_callout_stop(&rvp->amrr_ch);
- switch (sc->sc_state) {
+ switch (nstate) {
case IEEE80211_S_INIT:
if (ostate == IEEE80211_S_RUN) {
- /*
- * BUG: this code is not executed like it
- * should --hps
- */
/* abort TSF synchronization */
tmp = rum_read(sc, RT2573_TXRX_CSR9);
rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
@@ -785,11 +786,17 @@
break;
}
+ /* sanity checks */
+ if (nstate == IEEE80211_S_INIT)
+ return;
+ if (nstate != sc->sc_state)
+ return;
+
RUM_UNLOCK(sc);
IEEE80211_LOCK(ic);
- rvp->newstate(vap, sc->sc_state, sc->sc_arg);
+ rvp->newstate(vap, nstate, arg);
if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
+ vap->iv_newstate_cb(vap, nstate, arg);
IEEE80211_UNLOCK(ic);
RUM_LOCK(sc);
}
@@ -809,18 +816,16 @@
/* do it in a process context */
sc->sc_state = nstate;
sc->sc_arg = arg;
+ rum_queue_command(sc, rum_task,
+ &sc->sc_task[0].hdr,
+ &sc->sc_task[1].hdr);
RUM_UNLOCK(sc);
if (nstate == IEEE80211_S_INIT) {
rvp->newstate(vap, nstate, arg);
return 0;
- } else {
- RUM_LOCK(sc);
- rum_queue_command(sc, rum_task, &sc->sc_task[0].hdr,
- &sc->sc_task[1].hdr);
- RUM_UNLOCK(sc);
- return EINPROGRESS;
}
+ return (EINPROGRESS);
}
static void
@@ -1084,8 +1089,6 @@
}
}
-#define RUM_TX_TIMEOUT 5000
-
static int
rum_sendprot(struct rum_softc *sc,
const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
@@ -1468,15 +1471,15 @@
rum_do_request(sc, &req, buf);
}
-static void
+static usb2_error_t
rum_write(struct rum_softc *sc, uint16_t reg, uint32_t val)
{
uint32_t tmp = htole32(val);
- rum_write_multi(sc, reg, &tmp, sizeof tmp);
+ return (rum_write_multi(sc, reg, &tmp, sizeof tmp));
}
-static void
+static usb2_error_t
rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len)
{
struct usb2_device_request req;
@@ -1487,7 +1490,7 @@
USETW(req.wIndex, reg);
USETW(req.wLength, len);
- rum_do_request(sc, &req, buf);
+ return (rum_do_request(sc, &req, buf));
}
static void
@@ -1496,6 +1499,8 @@
uint32_t tmp;
int ntries;
+ DPRINTFN(2, "reg=0x%08x\n", reg);
+
for (ntries = 0; ntries != 100; ntries++) {
if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
break;
@@ -1517,6 +1522,8 @@
uint32_t val;
int ntries;
+ DPRINTFN(2, "reg=0x%08x\n", reg);
+
for (ntries = 0; ntries != 100; ntries++) {
if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
break;
@@ -2088,6 +2095,8 @@
rum_write(sc, RT2573_TXRX_CSR0, tmp);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+ usb2_transfer_set_stall(sc->sc_xfer[RUM_BULK_WR]);
usb2_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
return;
@@ -2145,20 +2154,22 @@
rum_write(sc, RT2573_MAC_CSR1, 0);
}
-static int
+static void
rum_load_microcode(struct rum_softc *sc, const uint8_t *ucode, size_t size)
{
struct usb2_device_request req;
uint16_t reg = RT2573_MCU_CODE_BASE;
-
- /*
- * TODO: If the firmware is already loaded,
- * then we need to return from here!
- */
+ usb2_error_t err;
/* copy firmware image into NIC */
- for (; size >= 4; reg += 4, ucode += 4, size -= 4)
- rum_write(sc, reg, UGETDW(ucode));
+ for (; size >= 4; reg += 4, ucode += 4, size -= 4) {
+ err = rum_write(sc, reg, UGETDW(ucode));
+ if (err) {
+ /* firmware already loaded ? */
+ device_printf(sc->sc_dev, "Firmware load failed.\n");
+ break;
+ }
+ }
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = RT2573_MCU_CNTL;
@@ -2167,7 +2178,9 @@
USETW(req.wLength, 0);
rum_do_request(sc, &req, NULL);
- return (0);
+
+ /* give the chip some time to boot */
+ rum_pause(sc, hz / 8);
}
static int
@@ -2359,10 +2372,9 @@
RUM_LOCK(sc);
/* do it in a process context */
sc->sc_scan_action = RUM_SET_CHANNEL;
+ sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
rum_queue_command(sc, rum_scantask,
&sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
-
- sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
RUM_UNLOCK(sc);
}
==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#37 (text+ko) ====
@@ -454,6 +454,11 @@
/* retrieve MAC address and various other things from EEPROM */
ural_read_eeprom(sc);
+
+ /* XXX WLAN race --hps */
+ if (usb2_proc_is_gone(&sc->sc_tq))
+ return;
+
RAL_UNLOCK(sc);
device_printf(sc->sc_dev, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
@@ -571,7 +576,7 @@
usb2_error_t err;
err = usb2_do_request_proc(sc->sc_udev, &sc->sc_tq,
- req, data, 0, NULL, 250 /* ms */);
+ req, data, 0, NULL, 1000 /* ms */);
if (err) {
DPRINTFN(1, "Control request failed! (ignored)\n");
@@ -721,21 +726,21 @@
struct ural_vap *uvp = URAL_VAP(vap);
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
+ enum ieee80211_state nstate;
struct ieee80211_node *ni;
struct mbuf *m;
+ int arg;
ostate = vap->iv_state;
+ nstate = sc->sc_state;
+ arg = sc->sc_arg;
/* callout is stopped */
usb2_callout_stop(&uvp->amrr_ch);
- switch (sc->sc_state) {
+ switch (nstate) {
case IEEE80211_S_INIT:
if (ostate == IEEE80211_S_RUN) {
- /*
- * BUG: this code is not executed like it
- * should --hps
- */
/* abort TSF synchronization */
ural_write(sc, RAL_TXRX_CSR19, 0);
@@ -788,11 +793,17 @@
break;
}
+ /* sanity checks */
+ if (nstate == IEEE80211_S_INIT)
+ return;
+ if (nstate != sc->sc_state)
+ return;
+
RAL_UNLOCK(sc);
IEEE80211_LOCK(ic);
- uvp->newstate(vap, sc->sc_state, sc->sc_arg);
+ uvp->newstate(vap, nstate, arg);
if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
+ vap->iv_newstate_cb(vap, nstate, arg);
IEEE80211_UNLOCK(ic);
RAL_LOCK(sc);
}
@@ -842,21 +853,18 @@
/* do it in a process context */
sc->sc_state = nstate;
sc->sc_arg = arg;
+ ural_queue_command(sc, ural_task,
+ &sc->sc_task[0].hdr,
+ &sc->sc_task[1].hdr);
RAL_UNLOCK(sc);
if (nstate == IEEE80211_S_INIT) {
uvp->newstate(vap, nstate, arg);
return 0;
- } else {
- RAL_LOCK(sc);
- ural_queue_command(sc, ural_task, &sc->sc_task[0].hdr,
- &sc->sc_task[1].hdr);
- RAL_UNLOCK(sc);
- return EINPROGRESS;
}
+ return (EINPROGRESS);
}
-
static void
ural_bulk_write_callback(struct usb2_xfer *xfer)
{
@@ -1726,7 +1734,7 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
uint8_t power, tmp;
- u_int i, chan;
+ unsigned int i, chan;
chan = ieee80211_chan2ieee(ic, c);
if (chan == 0 || chan == IEEE80211_CHAN_ANY)
@@ -2215,6 +2223,7 @@
ural_write(sc, RAL_TXRX_CSR2, tmp);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ usb2_transfer_set_stall(sc->sc_xfer[URAL_BULK_WR]);
usb2_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
return;
==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#38 (text+ko) ====
@@ -105,7 +105,7 @@
const uint8_t mac[IEEE80211_ADDR_LEN]);
static int zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static int zyd_cmd(struct zyd_softc *, uint16_t, const void *, int,
- void *, int, u_int);
+ void *, int, unsigned int);
static int zyd_read16(struct zyd_softc *, uint16_t, uint16_t *);
static int zyd_read32(struct zyd_softc *, uint16_t, uint32_t *);
static int zyd_write16(struct zyd_softc *, uint16_t, uint16_t);
@@ -371,6 +371,10 @@
return;
}
+ /* XXX WLAN race --hps */
+ if (usb2_proc_is_gone(&sc->sc_tq))
+ return;
+
ZYD_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
@@ -612,10 +616,15 @@
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
+ enum ieee80211_state nstate;
struct zyd_vap *zvp = ZYD_VAP(vap);
+ int arg;
int error;
- switch (sc->sc_state) {
+ nstate = sc->sc_state;
+ arg = sc->sc_arg;
+
+ switch (nstate) {
case IEEE80211_S_AUTH:
zyd_set_chan(sc, ic->ic_curchan);
break;
@@ -638,11 +647,17 @@
break;
}
fail:
+ /* sanity checks */
+ if (nstate == IEEE80211_S_INIT)
+ return;
+ if (nstate != sc->sc_state)
+ return;
+
ZYD_UNLOCK(sc);
IEEE80211_LOCK(ic);
- zvp->newstate(vap, sc->sc_state, sc->sc_arg);
+ zvp->newstate(vap, nstate, arg);
if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
+ vap->iv_newstate_cb(vap, nstate, arg);
IEEE80211_UNLOCK(ic);
ZYD_LOCK(sc);
}
@@ -662,18 +677,16 @@
/* do it in a process context */
sc->sc_state = nstate;
sc->sc_arg = arg;
+ zyd_queue_command(sc, zyd_task,
+ &sc->sc_task[0].hdr,
+ &sc->sc_task[1].hdr);
ZYD_UNLOCK(sc);
if (nstate == IEEE80211_S_INIT) {
zvp->newstate(vap, nstate, arg);
return (0);
- } else {
- ZYD_LOCK(sc);
- zyd_queue_command(sc, zyd_task, &sc->sc_task[0].hdr,
- &sc->sc_task[1].hdr);
- ZYD_UNLOCK(sc);
- return (EINPROGRESS);
}
+ return (EINPROGRESS);
}
/*
@@ -829,7 +842,7 @@
static int
zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen,
- void *odata, int olen, u_int flags)
+ void *odata, int olen, unsigned int flags)
{
struct zyd_cmd cmd;
struct zyd_rq rq;
@@ -1279,7 +1292,7 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6;
- u_int chan = ieee80211_chan2ieee(ic, c);
+ unsigned int chan = ieee80211_chan2ieee(ic, c);
if (chan == 1 || chan == 11)
r[0].val = 0x12;
@@ -2104,7 +2117,7 @@
struct ieee80211com *ic = ifp->if_l2com;
struct zyd_rf *rf = &sc->sc_rf;
uint32_t tmp;
- u_int chan;
+ unsigned int chan;
chan = ieee80211_chan2ieee(ic, c);
if (chan == 0 || chan == IEEE80211_CHAN_ANY) {
@@ -2885,6 +2898,7 @@
zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ usb2_transfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]);
usb2_transfer_start(sc->sc_xfer[ZYD_BULK_RD]);
usb2_transfer_start(sc->sc_xfer[ZYD_INTR_RD]);
==== //depot/projects/usb/src/sys/net80211/ieee80211_proto.c#13 (text+ko) ====
@@ -154,8 +154,6 @@
ieee80211_wds_detach(ic);
ieee80211_adhoc_detach(ic);
ieee80211_sta_detach(ic);
-
- taskqueue_drain(taskqueue_thread, &ic->ic_parent_task);
}
static void
More information about the p4-projects
mailing list