Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Mar 2007 15:58:19 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 116493 for review
Message-ID:  <200703241558.l2OFwJD2034322@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=116493

Change 116493 by sam@sam_ebb on 2007/03/24 15:57:27

	checkpoint scanning changes for iwi

Affected files ...

.. //depot/projects/wifi/sys/dev/iwi/if_iwi.c#25 edit
.. //depot/projects/wifi/sys/dev/iwi/if_iwivar.h#12 edit

Differences ...

==== //depot/projects/wifi/sys/dev/iwi/if_iwi.c#25 (text+ko) ====

@@ -163,12 +163,12 @@
 static int	iwi_get_firmware(struct iwi_softc *);
 static void	iwi_put_firmware(struct iwi_softc *);
 static void	iwi_scanabort(void *, int);
-static void	iwi_scandone(void *, int);
-static void	iwi_scanstart(void *, int);
-static void	iwi_scanchan(void *, int);
+static int	iwi_scanchan(struct iwi_softc *, unsigned long);
 static void	iwi_scan_start(struct ieee80211com *);
 static void	iwi_scan_end(struct ieee80211com *);
 static void	iwi_set_channel(struct ieee80211com *);
+static void	iwi_scan_curchan(struct ieee80211com *, unsigned long maxdwell);
+static void	iwi_scan_mindwell(struct ieee80211com *);
 static void     iwi_assoc(struct ieee80211com *ic);
 static void	iwi_ops(void *, int);
 static int	iwi_auth_and_assoc(struct iwi_softc *);
@@ -275,10 +275,7 @@
 #endif
 	TASK_INIT(&sc->sc_radiontask, 0, iwi_radio_on, sc);
 	TASK_INIT(&sc->sc_radiofftask, 0, iwi_radio_off, sc);
-	TASK_INIT(&sc->sc_scanstarttask, 0, iwi_scanstart, sc);
 	TASK_INIT(&sc->sc_scanaborttask, 0, iwi_scanabort, sc);
-	TASK_INIT(&sc->sc_scandonetask, 0, iwi_scandone, sc);
-	TASK_INIT(&sc->sc_scantask, 0, iwi_scanchan, sc);
 	TASK_INIT(&sc->sc_setwmetask, 0, iwi_wme_setparams, sc);
 	TASK_INIT(&sc->sc_downtask, 0, iwi_down, sc);
 	TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc);
@@ -369,12 +366,16 @@
 
 	/* set device capabilities */
 	ic->ic_caps =
-	    IEEE80211_C_IBSS |		/* IBSS mode supported */
-	    IEEE80211_C_MONITOR |	/* monitor mode supported */
-	    IEEE80211_C_PMGT |		/* power save supported */
-	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
-	    IEEE80211_C_WPA |		/* 802.11i */
-	    IEEE80211_C_WME;		/* 802.11e */
+	      IEEE80211_C_IBSS		/* IBSS mode supported */
+	    | IEEE80211_C_MONITOR	/* monitor mode supported */
+	    | IEEE80211_C_PMGT		/* power save supported */
+	    | IEEE80211_C_SHPREAMBLE	/* short preamble supported */
+	    | IEEE80211_C_WPA		/* 802.11i */
+	    | IEEE80211_C_WME		/* 802.11e */
+#if 0
+	    | IEEE80211_C_BGSCAN	/* capable of bg scanning */
+#endif
+	    ;
 
 	/* read MAC address from EEPROM */
 	val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
@@ -403,6 +404,8 @@
 	ic->ic_scan_start = iwi_scan_start;
 	ic->ic_scan_end = iwi_scan_end;
 	ic->ic_set_channel = iwi_set_channel;
+	ic->ic_scan_curchan = iwi_scan_curchan;
+	ic->ic_scan_mindwell = iwi_scan_mindwell;
 
 	/* override state transition machine */
 	sc->sc_newstate = ic->ic_newstate;
@@ -1371,7 +1374,6 @@
 		
 		DPRINTFN(3, ("Scan of channel %u complete (%u)\n",
 		    ic->ic_channels[chan->nchan].ic_freq, chan->nchan));
-		sc->flags &= ~IWI_FLAG_CHANNEL_SCAN;
 		break;
 
 	case IWI_NOTIF_TYPE_SCAN_COMPLETE:
@@ -1381,6 +1383,8 @@
 		    scan->status));
 
 		sc->sc_scan_timer = 0;
+		sc->flags &= ~IWI_FLAG_SCANNING;
+		ieee80211_scan_next(ic);
 
 		break;
 
@@ -1966,6 +1970,7 @@
 		if (--sc->sc_scan_timer == 0) {
 			if (sc->flags & IWI_FLAG_SCANNING) {
 				if_printf(ifp, "scan stuck\n");
+				ieee80211_cancel_scan(&sc->sc_ic);
 				taskqueue_enqueue(sc->sc_tq, &sc->sc_restarttask);
 			}
 		}
@@ -2638,97 +2643,6 @@
 		*st = (*st & 0x0f) | ((scan_type & 0xf) << 4);
 }
 
-static int
-iwi_scan(struct iwi_softc *sc)
-{
-	struct ieee80211com *ic = &sc->sc_ic;
-	const struct ieee80211_channel *c;
-	struct iwi_scan_ext scan;
-	int i, ix, start, scan_type, error;
-
-	IWI_LOCK_CHECK(sc);
-
-	memset(&scan, 0, sizeof scan);
-
-	/* XXX different dwell times for different scan types */
-	scan.dwell_time[IWI_SCAN_TYPE_PASSIVE] = htole16(sc->dwelltime);
-	scan.dwell_time[IWI_SCAN_TYPE_BROADCAST] = htole16(sc->dwelltime);
-	scan.dwell_time[IWI_SCAN_TYPE_BDIRECTED] = htole16(sc->dwelltime);
-
-	scan.full_scan_index = htole32(++sc->sc_scangen);
-
-	if (ic->ic_des_nssid != 0) {
-		scan_type = IWI_SCAN_TYPE_BDIRECTED;
-#ifdef IWI_DEBUG
-		if (iwi_debug > 0) {
-			printf("Setting desired ESSID to ");
-			ieee80211_print_essid(ic->ic_des_ssid[0].ssid,
-			    ic->ic_des_ssid[0].len);
-			printf("\n");
-		}
-#endif
-		error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ic->ic_des_ssid[0].ssid,
-		    ic->ic_des_ssid[0].len);
-		if (error != 0)
-			return error;
-	} else
-		scan_type = IWI_SCAN_TYPE_BROADCAST;
-
-	ix = 0;
-	if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
-		start = ix;
-		for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
-			c = &ic->ic_channels[i];
-			/*
-			 * NB: ieee80211_next_scan clears curchan from the
-			 * channel list so we must explicitly check; this
-			 * will be fixed when the new scanning support arrives.
-			 */
-			if (!IEEE80211_IS_CHAN_5GHZ(c) ||
-			    !(isset(ic->ic_chan_scan,i) || c == ic->ic_curchan))
-				continue;
-			ix++;
-			scan.channels[ix] = c->ic_ieee;
-			if (c->ic_flags & IEEE80211_CHAN_PASSIVE)
-				set_scan_type(&scan, ix, IWI_SCAN_TYPE_PASSIVE);
-			else
-				set_scan_type(&scan, ix, scan_type);
-		}
-		if (start != ix) {
-			scan.channels[start] = IWI_CHAN_5GHZ | (ix - start);
-			ix++;
-		}
-	}
-	if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
-		start = ix;
-		for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
-			c = &ic->ic_channels[i];
-			/* NB: see above */
-			if (!IEEE80211_IS_CHAN_2GHZ(c) ||
-			    !(isset(ic->ic_chan_scan,i) || c == ic->ic_curchan))
-				continue;
-			ix++;
-			scan.channels[ix] = c->ic_ieee;
-			if (c->ic_flags & IEEE80211_CHAN_PASSIVE)
-				set_scan_type(&scan, ix, IWI_SCAN_TYPE_PASSIVE);
-			else
-				set_scan_type(&scan, ix, scan_type);
-		}
-		if (start != ix)
-			scan.channels[start] = IWI_CHAN_2GHZ | (ix - start);
-	}
-
-	DPRINTF(("Start scanning\n"));
-	/*
-	 * With 100ms/channel dwell time and a max of ~20 channels
-	 * 5 seconds may be too tight; leave a bit more slack.
-	 */
-	sc->sc_scan_timer = 7;			/* seconds to complete */
-	sc->sc_ifp->if_timer = 1;
-	sc->flags |= IWI_FLAG_SCANNING;
-	return iwi_cmd(sc, IWI_CMD_SCAN_EXT, &scan, sizeof scan);
-}
-
 static void
 iwi_scanabort(void *arg, int npending)
 {
@@ -2742,88 +2656,61 @@
 	IWI_UNLOCK(sc);
 }
 
-static void
-iwi_scanstart(void *arg, int npending)
-{
-	struct iwi_softc *sc = arg;
-	struct ieee80211com *ic = &sc->sc_ic;
-	IWI_LOCK_DECL;
-
-	IWI_LOCK(sc);
-	/*
-	 * Tell the card to kick off a scan.  We guard this
-	 * by checking IWI_FLAG_SCANNING as otherwise we'll
-	 * do this twice because ieee80211_begin_scan will
-	 * immediately call us back to scan the first channel
-	 * in the list.
-	 */
-	if (sc->flags & IWI_FLAG_SCANNING) {
-		if (iwi_scan(sc) != 0) {
-			/* XXX should not happen */
-			sc->flags &= ~IWI_FLAG_SCANNING;
-			ieee80211_new_state(ic, IEEE80211_S_INIT, 0);
-		}
-	}
-	IWI_UNLOCK(sc);
-}
-
-static void
-iwi_scandone(void *arg, int npending)
-{
-	struct iwi_softc *sc = arg;
-	IWI_LOCK_DECL;
-
-	IWI_LOCK(sc);
-	if (sc->flags & IWI_FLAG_ASSOCIATED)
-		iwi_disassociate(sc, 0);
-#if 0
-	ieee80211_end_scan(ic);
-#endif
-	IWI_UNLOCK(sc);
-}
-
 /*
- * Set the current channel by doing a passive scan.  Note this
- * is explicitly for monitor mode operation; do not use it for
- * anything else (sigh).
+ * Scan on ic_curchan according to ic_scan (essid, active/passive, dwell ...)
  */
-static void
-iwi_scanchan(void *arg, int npending)
+static int
+iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell)
 {
-	struct iwi_softc *sc = arg;
 	struct ieee80211com *ic;
 	struct ieee80211_channel *chan;
+	struct ieee80211_scan_state *ss;
 	struct iwi_scan_ext scan;
-	IWI_LOCK_DECL;
+	int error = 0;
+
+	IWI_LOCK_CHECK(sc);
+	if (sc->flags & IWI_FLAG_SCANNING) {
+		/*
+		 * This should not happen as we only trigger scan_next after
+		 * completion
+		 */
+		DPRINTF(("%s: called too early - still scanning\n", __func__));
+		return (EBUSY);
+	}
 
-	IWI_LOCK(sc);
 	ic = &sc->sc_ic;
-	KASSERT(ic->ic_opmode == IEEE80211_M_MONITOR,
-		("opmode %u", ic->ic_opmode));
+	ss = ic->ic_scan;
 	chan = ic->ic_curchan;
 
 	memset(&scan, 0, sizeof scan);
-	/*
-	 * Set the dwell time to a fairly small value.  The firmware
-	 * is prone to crash when aborting a scan so it's better to
-	 * let a scan complete before changing channels--such as when
-	 * channel hopping in monitor mode.
-	 */
-	scan.dwell_time[IWI_SCAN_TYPE_PASSIVE] = htole16(20);
-	scan.dwell_time[IWI_SCAN_TYPE_BROADCAST] = htole16(20);
-	scan.dwell_time[IWI_SCAN_TYPE_BDIRECTED] = htole16(20);
 	scan.full_scan_index = htole32(++sc->sc_scangen);
+	scan.dwell_time[IWI_SCAN_TYPE_PASSIVE] = htole16(maxdwell);
+	scan.dwell_time[IWI_SCAN_TYPE_BROADCAST] = htole16(maxdwell);
+	scan.dwell_time[IWI_SCAN_TYPE_BDIRECTED] = htole16(maxdwell);
+
 	if (IEEE80211_IS_CHAN_5GHZ(chan))
 		scan.channels[0] = 1 | IWI_CHAN_5GHZ;
 	else
 		scan.channels[0] = 1 | IWI_CHAN_2GHZ;
 	scan.channels[1] = ieee80211_chan2ieee(ic, chan);
-	set_scan_type(&scan, 1, IWI_SCAN_TYPE_PASSIVE);
+	/* We can only set one essid for a directed scan */
+	if (ss->ss_nssid != 0) {
+		set_scan_type(&scan, 1, IWI_SCAN_TYPE_BDIRECTED);
+		error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ss->ss_ssid[0].ssid,
+		    ss->ss_ssid[0].len);
+		if (error)
+			return (error);
+	} else if ((ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
+	    (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) {
+		set_scan_type(&scan, 1, IWI_SCAN_TYPE_BROADCAST);
+	} else
+		set_scan_type(&scan, 1, IWI_SCAN_TYPE_PASSIVE);
 
-	DPRINTF(("Setting channel to %u\n", ieee80211_chan2ieee(ic, chan)));
+	DPRINTF(("Scanning on channel %u\n", ieee80211_chan2ieee(ic, chan)));
 	sc->flags |= IWI_FLAG_SCANNING;
-	(void) iwi_cmd(sc, IWI_CMD_SCAN_EXT, &scan, sizeof scan);
-	IWI_UNLOCK(sc);
+	sc->sc_scan_timer = 1;
+
+	return (iwi_cmd(sc, IWI_CMD_SCAN_EXT, &scan, sizeof scan));
 }
 
 static int
@@ -3333,11 +3220,6 @@
 	    CTLTYPE_OPAQUE | CTLFLAG_RD, sc, 0, iwi_sysctl_stats, "S",
 	    "statistics");
 
-	sc->dwelltime = 100;
-	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "dwell",
-	    CTLFLAG_RW, &sc->dwelltime, 0,
-	    "channel dwell time (ms) for AP/station scanning");
-
 	sc->bluetooth = 0;
 	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "bluetooth",
 	    CTLFLAG_RW, &sc->bluetooth, 0, "bluetooth coexistence");
@@ -3557,11 +3439,25 @@
 		iwi_auth_and_assoc(sc);
 		break;
 	case IWI_SCAN_START:
-		iwi_scan(sc);
+		sc->flags |= IWI_FLAG_CHANNEL_SCAN;
 		break;
 	case IWI_SCAN_END:
+		sc->flags &= ~IWI_FLAG_CHANNEL_SCAN;
 		iwi_scanabort(sc, 0);
 		break;
+	case IWI_SCAN_CURCHAN:
+		if (!(sc->flags & IWI_FLAG_CHANNEL_SCAN)) {
+			DPRINTF(("%s: ic_scan_curchan while not scanning\n",
+			    __func__));
+			return;
+		}
+		if (iwi_scanchan(sc, sc->sc_maxdwell)) {
+			iwi_scanabort(sc, 0);
+			IWI_UNLOCK(sc);
+			ieee80211_cancel_scan(ic);
+			return;
+		}
+		break;
 	}
 done:
 	IWI_UNLOCK(sc);
@@ -3572,7 +3468,7 @@
 {
 	struct ifnet *ifp = ic->ic_ifp;
 	struct iwi_softc *sc = ifp->if_softc;
-	printf("start scan\n");
+
 	sc->sc_scanop = IWI_SCAN_START;
 	taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
 	
@@ -3583,17 +3479,33 @@
 {
 	struct ifnet *ifp = ic->ic_ifp;
 	struct iwi_softc *sc = ifp->if_softc;
-	if (!(sc->flags & IWI_FLAG_SCANNING)) 
+	if (!(sc->flags & (IWI_FLAG_SCANNING | IWI_FLAG_CHANNEL_SCAN))) 
 		iwi_setcurchan(sc, ic->ic_curchan->ic_ieee);
 }
 
 static void
+iwi_scan_curchan(struct ieee80211com *ic, unsigned long maxdwell)
+{
+	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);
+}
+
+static void
+iwi_scan_mindwell(struct ieee80211com *ic)
+{
+	/* NB: don't try to abort scan; wait for firmware to finish */
+}
+
+static void
 iwi_scan_end(struct ieee80211com *ic)
 {
 	struct ifnet *ifp = ic->ic_ifp;
 	struct iwi_softc *sc = ifp->if_softc;
 
-	printf("end scan\n");
 	sc->sc_scanop = IWI_SCAN_END;
 	taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
 }

==== //depot/projects/wifi/sys/dev/iwi/if_iwivar.h#12 (text+ko) ====

@@ -176,7 +176,6 @@
 
 	int			curchan;	/* current h/w channel # */
 	int			antenna;
-	int			dwelltime;
 	int			bluetooth;
 	struct iwi_associate	assoc;
 	struct iwi_wme_params	wme[3];
@@ -187,7 +186,6 @@
 	struct task		sc_scanstarttask;/* scan start processing */
 	struct task		sc_scanaborttask;/* scan abort processing */
 	struct task		sc_scandonetask;/* scan completed processing */
-	struct task		sc_scantask;	/* scan channel processing */
 	struct task		sc_setwmetask;	/* set wme params processing */
 	struct task		sc_downtask;	/* disassociate processing */
 	struct task		sc_restarttask;	/* restart adapter processing */
@@ -215,7 +213,9 @@
 #define IWI_SET_CHANNEL	        (1 << 1)
 #define	IWI_SCAN_END    	(1 << 2)
 #define	IWI_ASSOC    	        (1 << 3)
-	int                     sc_scanop;      /* operation for scan task to perform */
+#define	IWI_SCAN_CURCHAN	(1 << 4)
+	int                     sc_scanop;      /* op for scan task to do */
+	unsigned long		sc_maxdwell;	/* max dwell time for curchan */
 	struct bpf_if		*sc_drvbpf;
 
 	union {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200703241558.l2OFwJD2034322>