PERFORCE change 116493 for review
Sam Leffler
sam at FreeBSD.org
Sat Mar 24 15:58:21 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=116493
Change 116493 by sam at 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 {
More information about the p4-projects
mailing list