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