PERFORCE change 120812 for review
Sam Leffler
sam at FreeBSD.org
Sun Jun 3 02:22:44 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=120812
Change 120812 by sam at 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)
More information about the p4-projects
mailing list