Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Jun 2007 02:22:43 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 120812 for review
Message-ID:  <200706030222.l532MhN0029125@repoman.freebsd.org>

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

Change 120812 by sam@sam_laptop on 2007/06/03 02:21:42

	o correct bg scan operation (on 2915 cards at least); use
	  a short dwell time for scans that send a probe request
	  frame; w/o this the f/w reliably gets stuck (30ms value
	  taken from linux driver)
	o rewrite code to construct a multi-channel scan list; this
	  list must be run-length encoded based on the band of the
	  channels (untested and we may need to discard the channel
	  order crafted by net80211 as the run-length encoding may
	  overflow the max #channels allowed by the f/w)
	o #if 0 code to trigger a scan of all channels to suppress
	  compiler complaints
	o add scan request dump msgs when debugging

Affected files ...

.. //depot/projects/wifi/sys/dev/iwi/if_iwi.c#39 edit

Differences ...

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

@@ -167,7 +167,9 @@
 static void	iwi_scan_end(struct ieee80211com *);
 static void	iwi_set_channel(struct ieee80211com *);
 static void	iwi_scan_curchan(struct ieee80211com *, unsigned long maxdwell);
+#if 0
 static void	iwi_scan_allchan(struct ieee80211com *, unsigned long maxdwell);
+#endif
 static void	iwi_scan_mindwell(struct ieee80211com *);
 static void     iwi_assoc(struct ieee80211com *ic);
 static void	iwi_ops(void *, int);
@@ -1388,7 +1390,7 @@
 		chan = (struct iwi_notif_scan_channel *)(notif + 1);
 
 		DPRINTFN(3, ("Scan of channel %u complete (%u)\n",
-		    ic->ic_channels[chan->nchan].ic_freq, chan->nchan));
+		    ieee80211_ieee2mhz(chan->nchan, 0), chan->nchan));
 
 		/* Reset the timer, the scan is still going */
 		sc->sc_scan_timer = 3;
@@ -2663,8 +2665,27 @@
 		*st = (*st & 0x0f) | ((scan_type & 0xf) << 4);
 }
 
+static int
+scan_type(const struct ieee80211_scan_state *ss,
+	const struct ieee80211_channel *chan)
+{
+	/* We can only set one essid for a directed scan */
+	if (ss->ss_nssid != 0)
+		return IWI_SCAN_TYPE_BDIRECTED;
+	if ((ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
+	    (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0)
+		return IWI_SCAN_TYPE_BROADCAST;
+	return IWI_SCAN_TYPE_PASSIVE;
+}
+
+static __inline int
+scan_band(const struct ieee80211_channel *c)
+{
+	return IEEE80211_IS_CHAN_5GHZ(c) ?  IWI_CHAN_5GHZ : IWI_CHAN_2GHZ;
+}
+
 /*
- * Scan on ic_curchan according to ic_scan (essid, active/passive, dwell ...)
+ * Start a scan on the current channel or all channels.
  */
 static int
 iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int mode)
@@ -2674,7 +2695,6 @@
 	struct ieee80211_scan_state *ss;
 	struct iwi_scan_ext scan;
 	int error = 0;
-	int i, type;
 
 	IWI_LOCK_CHECK(sc);
 	if (sc->flags & IWI_FLAG_SCANNING) {
@@ -2688,47 +2708,97 @@
 
 	ic = &sc->sc_ic;
 	ss = ic->ic_scan;
-	chan = ic->ic_curchan;
 
 	memset(&scan, 0, sizeof scan);
 	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 (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) {
+		/*
+		 * Use very short dwell times for when we send probe request
+		 * frames.  Without this bg scans hang.  Ideally this should
+		 * be handled with early-termination as done by net80211 but
+		 * that's not feasible (aborting a scan is problematic).
+		 */
+		scan.dwell_time[IWI_SCAN_TYPE_BROADCAST] = htole16(30);
+		scan.dwell_time[IWI_SCAN_TYPE_BDIRECTED] = htole16(30);
+	} else {
+		scan.dwell_time[IWI_SCAN_TYPE_BROADCAST] = htole16(maxdwell);
+		scan.dwell_time[IWI_SCAN_TYPE_BDIRECTED] = htole16(maxdwell);
+	}
 
 	/* We can only set one essid for a directed scan */
 	if (ss->ss_nssid != 0) {
-		type = 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) {
-		type = IWI_SCAN_TYPE_BROADCAST;
-	} else
-		type = IWI_SCAN_TYPE_PASSIVE;
+	}
 
 	if (mode == IWI_SCAN_ALLCHAN) {
-		for (i = 0; i < ss->ss_last;) {
+		int i, next, band, b, bstart;
+		/*
+		 * Convert scan list to run-length encoded channel list
+		 * the firmware requires (preserving the order setup by
+		 * net80211).  The first entry in each run specifies the
+		 * band and the count of items in the run.
+		 */
+		next = 0;		/* next open slot */
+		bstart = 0;		/* NB: not needed, silence compiler */
+		band = -1;		/* NB: impossible value */
+		KASSERT(ss->ss_last > 0, ("no channels"));
+		for (i = 0; i < ss->ss_last; i++) {
 			chan = ss->ss_chans[i];
-			scan.channels[++i] = ieee80211_chan2ieee(ic, chan);
-			set_scan_type(&scan, i, type);
+			b = scan_band(chan);
+			if (b != band) {
+				if (band != -1)
+					scan.channels[bstart] =
+					    (next - bstart) | band;
+				/* NB: this allocates a slot for the run-len */
+				band = b, bstart = next++;
+			}
+			if (next >= IWI_SCAN_CHANNELS) {
+				DPRINTF(("truncating scan list\n"));
+				break;
+			}
+			scan.channels[next] = ieee80211_chan2ieee(ic, chan);
+			set_scan_type(&scan, next, scan_type(ss, chan));
+			next++;
 		}
-		DPRINTF(("Scanning on %d channel(s)\n", i));
+		scan.channels[bstart] = (next - bstart) | band;
 	} else {
 		/* Scan the current channel only */
-		i = 1;
-		scan.channels[i] = ieee80211_chan2ieee(ic, chan);
-		set_scan_type(&scan, i, type);
-		DPRINTF(("Scanning on channel %u\n",
-			    ieee80211_chan2ieee(ic, chan)));
+		chan = ic->ic_curchan;
+		scan.channels[0] = 1 | scan_band(chan);
+		scan.channels[1] = ieee80211_chan2ieee(ic, chan);
+		set_scan_type(&scan, 1, scan_type(ss, chan));
+	}
+#ifdef IWI_DEBUG
+	if (iwi_debug > 0) {
+		static const char *scantype[8] =
+		   { "PSTOP", "PASV", "DIR", "BCAST", "BDIR", "5", "6", "7" };
+		int i;
+		printf("Scan request: index %u dwell %d/%d/%d\n"
+		    , le32toh(scan.full_scan_index)
+		    , le16toh(scan.dwell_time[IWI_SCAN_TYPE_PASSIVE])
+		    , le16toh(scan.dwell_time[IWI_SCAN_TYPE_BROADCAST])
+		    , le16toh(scan.dwell_time[IWI_SCAN_TYPE_BDIRECTED])
+		);
+		i = 0;
+		do {
+			int run = scan.channels[i];
+			if (run == 0)
+				break;
+			printf("Scan %d %s channels:", run & 0x3f,
+			    run & IWI_CHAN_2GHZ ? "2.4GHz" : "5GHz");
+			for (run &= 0x3f, i++; run > 0; run--, i++) {
+				uint8_t type = scan.scan_type[i/2];
+				printf(" %u/%s", scan.channels[i],
+				    scantype[(i & 1 ? type : type>>4) & 7]);
+			}
+			printf("\n");
+		} while (i < IWI_SCAN_CHANNELS);
 	}
-	if (IEEE80211_IS_CHAN_5GHZ(chan))
-		scan.channels[0] = i | IWI_CHAN_5GHZ;
-	else
-		scan.channels[0] = i | IWI_CHAN_2GHZ;
-
+#endif
 	sc->flags |= IWI_FLAG_SCANNING;
 	sc->sc_scan_timer = 3;
 	sc->sc_ifp->if_timer = 1;
@@ -3547,6 +3617,7 @@
 	iwi_scan_cmd(sc, IWI_SCAN_CURCHAN);
 }
 
+#if 0
 static void
 iwi_scan_allchan(struct ieee80211com *ic, unsigned long maxdwell)
 {
@@ -3556,6 +3627,7 @@
 	sc->sc_maxdwell = maxdwell;
 	iwi_scan_cmd(sc, IWI_SCAN_ALLCHAN);
 }
+#endif
 
 static void
 iwi_scan_mindwell(struct ieee80211com *ic)



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