PERFORCE change 120683 for review
Andrew Thompson
thompsa at FreeBSD.org
Thu May 31 22:12:33 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=120683
Change 120683 by thompsa at thompsa_heff on 2007/05/31 22:11:35
Add a simple scan command ring so that sc_scanop does not get clobbered
if the taskqueue hasnt fired before the next call. (testing this new
code showed it happened often)
Affected files ...
.. //depot/projects/wifi/sys/dev/iwi/if_iwi.c#35 edit
.. //depot/projects/wifi/sys/dev/iwi/if_iwivar.h#15 edit
Differences ...
==== //depot/projects/wifi/sys/dev/iwi/if_iwi.c#35 (text+ko) ====
@@ -171,6 +171,7 @@
static void iwi_scan_mindwell(struct ieee80211com *);
static void iwi_assoc(struct ieee80211com *ic);
static void iwi_ops(void *, int);
+static int iwi_scan_cmd(struct iwi_softc *, int);
static int iwi_auth_and_assoc(struct iwi_softc *);
static int iwi_disassociate(struct iwi_softc *, int quiet);
static void iwi_down(void *, int);
@@ -257,8 +258,8 @@
sc->sc_dev = dev;
- mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF);
+ IWI_LOCK_INIT(sc);
+ IWI_SCAN_LOCK_INIT(sc);
sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx);
@@ -481,7 +482,8 @@
if (sc->sc_unr != NULL)
delete_unrhdr(sc->sc_unr);
- mtx_destroy(&sc->sc_mtx);
+ IWI_LOCK_DESTROY(sc);
+ IWI_SCAN_LOCK_DESTROY(sc);
return 0;
}
@@ -3439,7 +3441,20 @@
struct iwi_softc *sc = arg;
struct ieee80211com *ic = &sc->sc_ic;
IWI_LOCK_DECL;
-
+ int cmd;
+
+again:
+ IWI_SCAN_LOCK(sc);
+ cmd = sc->sc_scanop[sc->sc_scan_cur];
+ if (cmd == 0) {
+ /* No more commands to process */
+ IWI_SCAN_UNLOCK(sc);
+ return;
+ }
+ sc->sc_scanop[sc->sc_scan_cur] = 0; /* free the slot */
+ sc->sc_scan_cur = (sc->sc_scan_cur + 1) % IWI_SCAN_OPS;
+ IWI_SCAN_UNLOCK(sc);
+
IWI_LOCK(sc);
while ((ic->ic_state != IEEE80211_S_INIT) && (sc->flags & IWI_FLAG_BUSY)) {
msleep(sc, &sc->sc_mtx, 0, "iwicmd", hz/10);
@@ -3448,7 +3463,7 @@
if (ic->ic_state == IEEE80211_S_INIT)
goto done;
- switch (sc->sc_scanop) {
+ switch (cmd) {
case IWI_ASSOC:
iwi_auth_and_assoc(sc);
break;
@@ -3466,8 +3481,7 @@
if (!(sc->flags & IWI_FLAG_CHANNEL_SCAN)) {
DPRINTF(("%s: ic_scan_curchan while not scanning\n",
__func__));
- IWI_UNLOCK(sc);
- return;
+ goto done;
}
if (iwi_scanchan(sc, sc->sc_maxdwell, sc->sc_scanop))
ieee80211_cancel_scan(ic);
@@ -3476,16 +3490,34 @@
}
done:
IWI_UNLOCK(sc);
+
+ /* Take another pass */
+ goto again;
}
+static int
+iwi_scan_cmd(struct iwi_softc *sc, int cmd)
+{
+ IWI_SCAN_LOCK(sc);
+ if (sc->sc_scanop[sc->sc_scan_next] != 0) {
+ IWI_SCAN_UNLOCK(sc);
+ DPRINTF(("%s: scan command %d dropped\n", __func__, cmd));
+ return (EBUSY);
+ }
+
+ sc->sc_scanop[sc->sc_scan_next] = cmd;
+ sc->sc_scan_next = (sc->sc_scan_next + 1) % IWI_SCAN_OPS;
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
+ IWI_SCAN_UNLOCK(sc);
+}
+
static void
iwi_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
- sc->sc_scanop = IWI_SCAN_START;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
+ iwi_scan_cmd(sc, IWI_SCAN_START);
}
static void
@@ -3503,9 +3535,8 @@
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
- sc->sc_scanop = IWI_SCAN_CURCHAN;
sc->sc_maxdwell = maxdwell;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
+ iwi_scan_cmd(sc, IWI_SCAN_CURCHAN);
}
static void
@@ -3514,9 +3545,8 @@
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
- sc->sc_scanop = IWI_SCAN_ALLCHAN;
sc->sc_maxdwell = maxdwell;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
+ iwi_scan_cmd(sc, IWI_SCAN_ALLCHAN);
}
static void
@@ -3531,8 +3561,7 @@
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
- sc->sc_scanop = IWI_SCAN_END;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
+ iwi_scan_cmd(sc, IWI_SCAN_END);
}
static void
@@ -3541,6 +3570,5 @@
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
- sc->sc_scanop = IWI_ASSOC;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
+ iwi_scan_cmd(sc, IWI_ASSOC);
}
==== //depot/projects/wifi/sys/dev/iwi/if_iwivar.h#15 (text+ko) ====
@@ -123,6 +123,8 @@
device_t sc_dev;
struct mtx sc_mtx;
+ struct mtx sc_scanlock;
+ char sc_scanname[12]; /* e.g. "iwi0_scan" */
uint8_t sc_mcast[IEEE80211_ADDR_LEN];
struct unrhdr *sc_unr;
struct taskqueue *sc_tq; /* private task queue */
@@ -212,7 +214,10 @@
#define IWI_ASSOC (1 << 3)
#define IWI_SCAN_CURCHAN (1 << 4)
#define IWI_SCAN_ALLCHAN (1 << 5)
- int sc_scanop; /* op for scan task to do */
+#define IWI_SCAN_OPS 5
+ int sc_scanop[IWI_SCAN_OPS];
+ int sc_scan_cur; /* current queued scan task */
+ int sc_scan_next; /* last queued scan task */
unsigned long sc_maxdwell; /* max dwell time for curchan */
struct bpf_if *sc_drvbpf;
@@ -235,6 +240,10 @@
* NB.: This models the only instance of async locking in iwi_init_locked
* and must be kept in sync.
*/
+#define IWI_LOCK_INIT(sc) \
+ mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->sc_dev), \
+ MTX_NETWORK_LOCK, MTX_DEF)
+#define IWI_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
#define IWI_LOCK_DECL int __waslocked = 0
#define IWI_LOCK_CHECK(sc) do { \
if (!mtx_owned(&(sc)->sc_mtx)) \
@@ -248,3 +257,11 @@
if (!__waslocked) \
mtx_unlock(&(sc)->sc_mtx); \
} while (0)
+#define IWI_SCAN_LOCK_INIT(sc) do { \
+ snprintf((sc)->sc_scanname, sizeof((sc)->sc_scanname), "%s_scan", \
+ device_get_nameunit((sc)->sc_dev)); \
+ mtx_init(&(sc)->sc_scanlock, (sc)->sc_scanname, NULL, MTX_DEF); \
+} while (0)
+#define IWI_SCAN_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_scanlock)
+#define IWI_SCAN_LOCK(sc) mtx_lock(&(sc)->sc_scanlock)
+#define IWI_SCAN_UNLOCK(sc) mtx_unlock(&(sc)->sc_scanlock)
More information about the p4-projects
mailing list