PERFORCE change 157497 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Tue Feb 10 09:40:40 PST 2009
http://perforce.freebsd.org/chv.cgi?CH=157497
Change 157497 by hselasky at hselasky_laptop001 on 2009/02/10 17:39:48
USB WLAN: Fix more races and panics after that
Andrew Thompson re-ported the WLAN drivers
from the old USB stack.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#31 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#31 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#33 edit
.. //depot/projects/usb/src/sys/dev/usb2/wlan/if_zydreg.h#7 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_rum2.c#31 (text+ko) ====
@@ -126,6 +126,7 @@
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 usb2_proc_callback_t rum_flush_task;
static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
const char name[IFNAMSIZ], int unit, int opmode,
@@ -611,9 +612,31 @@
}
static void
+rum_flush_task(struct usb2_proc_msg *pm)
+{
+ 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;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct rum_vap *rvp = RUM_VAP(vap);
+
+ /* callout it stopped */
+ usb2_callout_stop(&rvp->amrr_ch);
+}
+
+static void
rum_vap_delete(struct ieee80211vap *vap)
{
struct rum_vap *rvp = RUM_VAP(vap);
+ struct rum_softc *sc = rvp->sc;
+
+ RUM_LOCK(sc);
+ /* wait for any pending tasks to complete */
+ rum_queue_command(sc, rum_flush_task,
+ &sc->sc_synctask[0].hdr,
+ &sc->sc_synctask[1].hdr);
+ RUM_UNLOCK(sc);
usb2_callout_drain(&rvp->amrr_ch);
ieee80211_amrr_cleanup(&rvp->amrr);
@@ -701,9 +724,16 @@
ostate = vap->iv_state;
+ /* callout it stopped */
+ usb2_callout_stop(&rvp->amrr_ch);
+
switch (sc->sc_state) {
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);
@@ -759,8 +789,6 @@
ieee80211_state_name[nstate]);
RUM_LOCK(sc);
- usb2_callout_stop(&rvp->amrr_ch);
-
/* do it in a process context */
sc->sc_state = nstate;
sc->sc_arg = arg;
@@ -2183,7 +2211,9 @@
ieee80211_amrr_node_init(&rvp->amrr, &RUM_NODE(ni)->amn, ni);
- usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
+ /* XXX WLAN race --hps */
+ if (sc->sc_state != IEEE80211_S_INIT)
+ usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
}
static void
@@ -2192,8 +2222,15 @@
struct rum_vap *rvp = arg;
struct rum_softc *sc = rvp->sc;
+ /* XXX WLAN race --hps */
+ if (sc->sc_state == IEEE80211_S_INIT)
+ return;
+
rum_queue_command(sc, rum_amrr_task,
&rvp->amrr_task[0].hdr, &rvp->amrr_task[1].hdr);
+
+ /* to avoid sync-issues we need to reset the callout here */
+ usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
}
static void
@@ -2204,7 +2241,6 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct rum_vap *rvp = RUM_VAP(vap);
struct ieee80211_node *ni = vap->iv_bss;
int ok, fail;
@@ -2215,13 +2251,15 @@
(le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ retry */
fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */
+ /* XXX WLAN race --hps */
+ if (sc->sc_state == IEEE80211_S_INIT)
+ return;
+
ieee80211_amrr_tx_update(&RUM_NODE(ni)->amn,
ok+fail, ok, (le32toh(sc->sta[5]) & 0xffff) + fail);
(void) ieee80211_amrr_choose(ni, &RUM_NODE(ni)->amn);
ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */
-
- usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
}
/* ARGUSED */
@@ -2388,9 +2426,10 @@
task->sc = sc;
/*
- * Init and stop must be synchronous!
+ * Init, stop and flush must be synchronous!
*/
- if ((fn == rum_init_task) || (fn == rum_stop_task))
+ if ((fn == rum_init_task) || (fn == rum_stop_task) ||
+ (fn == rum_flush_task))
usb2_proc_mwait(&sc->sc_tq, t0, t1);
}
==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_ural2.c#31 (text+ko) ====
@@ -105,6 +105,7 @@
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 usb2_proc_callback_t ural_flush_task;
static struct ieee80211vap *ural_vap_create(struct ieee80211com *,
const char name[IFNAMSIZ], int unit, int opmode,
@@ -597,9 +598,31 @@
}
static void
+ural_flush_task(struct usb2_proc_msg *pm)
+{
+ 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;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ural_vap *uvp = URAL_VAP(vap);
+
+ /* callout it stopped */
+ usb2_callout_stop(&uvp->amrr_ch);
+}
+
+static void
ural_vap_delete(struct ieee80211vap *vap)
{
struct ural_vap *uvp = URAL_VAP(vap);
+ struct ural_softc *sc = uvp->sc;
+
+ RAL_LOCK(sc);
+ /* wait for any pending tasks to complete */
+ ural_queue_command(sc, ural_flush_task,
+ &sc->sc_synctask[0].hdr,
+ &sc->sc_synctask[1].hdr);
+ RAL_UNLOCK(sc);
usb2_callout_drain(&uvp->amrr_ch);
ieee80211_amrr_cleanup(&uvp->amrr);
@@ -687,9 +710,16 @@
ostate = vap->iv_state;
+ /* callout is stopped */
+ usb2_callout_stop(&uvp->amrr_ch);
+
switch (sc->sc_state) {
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);
@@ -793,8 +823,6 @@
ieee80211_state_name[nstate]);
RAL_LOCK(sc);
- usb2_callout_stop(&uvp->amrr_ch);
-
/* do it in a process context */
sc->sc_state = nstate;
sc->sc_arg = arg;
@@ -2269,7 +2297,9 @@
ieee80211_amrr_node_init(&uvp->amrr, &URAL_NODE(ni)->amn, ni);
- usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
+ /* XXX WLAN race --hps */
+ if (sc->sc_state != IEEE80211_S_INIT)
+ usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
}
static void
@@ -2278,8 +2308,15 @@
struct ural_vap *uvp = arg;
struct ural_softc *sc = uvp->sc;
+ /* XXX WLAN race --hps */
+ if (sc->sc_state == IEEE80211_S_INIT)
+ return;
+
ural_queue_command(sc, ural_amrr_task,
&uvp->amrr_task[0].hdr, &uvp->amrr_task[1].hdr);
+
+ /* to avoid sync-issues we need to reset the callout here */
+ usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
}
static void
@@ -2290,7 +2327,6 @@
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct ural_vap *uvp = URAL_VAP(vap);
struct ieee80211_node *ni = vap->iv_bss;
int ok, fail;
@@ -2301,13 +2337,15 @@
sc->sta[8]; /* TX ok w/ retry */
fail = sc->sta[9]; /* TX retry-fail count */
+ /* XXX WLAN race --hps */
+ if (sc->sc_state == IEEE80211_S_INIT)
+ return;
+
ieee80211_amrr_tx_update(&URAL_NODE(ni)->amn,
ok+fail, ok, sc->sta[8] + fail);
(void) ieee80211_amrr_choose(ni, &URAL_NODE(ni)->amn);
ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */
-
- usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
}
static void
@@ -2335,9 +2373,9 @@
task->sc = sc;
/*
- * Init and stop must be synchronous!
+ * Init, stop and flush must be synchronous!
*/
- if ((fn == ural_init_task) || (fn == ural_stop_task))
+ if ((fn == ural_init_task) || (fn == ural_stop_task) ||
+ (fn == ural_stop_task))
usb2_proc_mwait(&sc->sc_tq, t0, t1);
}
-
==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_zyd2.c#33 (text+ko) ====
@@ -91,6 +91,7 @@
static usb2_proc_callback_t zyd_multitask;
static usb2_proc_callback_t zyd_init_task;
static usb2_proc_callback_t zyd_stop_task;
+static usb2_proc_callback_t zyd_flush_task;
static struct ieee80211vap *zyd_vap_create(struct ieee80211com *,
const char name[IFNAMSIZ], int unit, int opmode,
@@ -469,6 +470,7 @@
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
+ struct zyd_softc *sc = ic->ic_ifp->if_softc;
struct zyd_vap *zvp;
struct ieee80211vap *vap;
@@ -487,6 +489,7 @@
zvp->newstate = vap->iv_newstate;
vap->iv_newstate = zyd_newstate;
+ zvp->sc = sc;
ieee80211_amrr_init(&zvp->amrr, vap,
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
@@ -500,10 +503,24 @@
}
static void
+zyd_flush_task(struct usb2_proc_msg *_pm)
+{
+ /* nothing to do */
+}
+
+static void
zyd_vap_delete(struct ieee80211vap *vap)
{
struct zyd_vap *zvp = ZYD_VAP(vap);
+ struct zyd_softc *sc = zvp->sc;
+ ZYD_LOCK(sc);
+ /* wait for any pending tasks to complete */
+ zyd_queue_command(sc, zyd_flush_task,
+ &sc->sc_synctask[0].hdr,
+ &sc->sc_synctask[1].hdr);
+ ZYD_UNLOCK(sc);
+
ieee80211_amrr_cleanup(&zvp->amrr);
ieee80211_vap_detach(vap);
free(zvp, M_80211_VAP);
@@ -3092,7 +3109,8 @@
/*
* Init and stop must be synchronous!
*/
- if ((fn == zyd_init_task) || (fn == zyd_stop_task))
+ if ((fn == zyd_init_task) || (fn == zyd_stop_task) ||
+ (fn == zyd_flush_task))
usb2_proc_mwait(&sc->sc_tq, t0, t1);
}
==== //depot/projects/usb/src/sys/dev/usb2/wlan/if_zydreg.h#7 (text+ko) ====
@@ -1247,6 +1247,7 @@
struct ieee80211vap vap;
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
+ struct zyd_softc *sc;
struct ieee80211_amrr amrr;
};
#define ZYD_VAP(vap) ((struct zyd_vap *)(vap))
More information about the p4-projects
mailing list