PERFORCE change 112529 for review
Kip Macy
kmacy at FreeBSD.org
Thu Jan 4 21:40:14 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=112529
Change 112529 by kmacy at kmacy_serendipity:sam_wifi on 2007/01/05 05:40:01
tie iwi into ieee80211 scanning state machine
add ic_{scan_start, scan_done, set_channel}
move iwi_auth_and_assoc into new taskqueue task
sta mode appears to be fully functional
Affected files ...
.. //depot/projects/wifi/sys/dev/iwi/if_iwi.c#19 edit
.. //depot/projects/wifi/sys/dev/iwi/if_iwivar.h#10 edit
Differences ...
==== //depot/projects/wifi/sys/dev/iwi/if_iwi.c#19 (text+ko) ====
@@ -165,6 +165,11 @@
static void iwi_scandone(void *, int);
static void iwi_scanstart(void *, int);
static void iwi_scanchan(void *, int);
+static void iwi_scan_start(struct ieee80211com *);
+static void iwi_scan_end(struct ieee80211com *);
+static void iwi_set_channel(struct ieee80211com *);
+static void iwi_assoc(struct ieee80211com *ic);
+static void iwi_ops(void *, 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);
@@ -288,6 +293,7 @@
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);
+ TASK_INIT(&sc->sc_opstask, 0, iwi_ops, sc);
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
device_printf(dev, "chip is in D%d power mode "
@@ -422,6 +428,10 @@
ic->ic_node_alloc = iwi_node_alloc;
sc->sc_node_free = ic->ic_node_free;
ic->ic_node_free = iwi_node_free;
+ ic->ic_scan_start = iwi_scan_start;
+ ic->ic_scan_end = iwi_scan_end;
+ ic->ic_set_channel = iwi_set_channel;
+
/* override state transition machine */
sc->sc_newstate = ic->ic_newstate;
ic->ic_newstate = iwi_newstate;
@@ -945,6 +955,7 @@
{
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
+ int error = 0;
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
ieee80211_state_name[ic->ic_state],
@@ -952,30 +963,9 @@
/* XXX state change race with taskqueue */
switch (nstate) {
- case IEEE80211_S_SCAN:
- if (ic->ic_state == IEEE80211_S_RUN) {
- /*
- * Beacon miss, send disassoc and wait for a reply
- * from the card; we'll start a scan then. Note
- * this only happens with auto roaming; otherwise
- * just notify users and wait to be directed.
- */
- /* notify directly as we bypass net80211 */
- ieee80211_sta_leave(ic, ic->ic_bss);
- if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
- taskqueue_enqueue(sc->sc_tq, &sc->sc_downtask);
- break;
- }
- if ((sc->flags & IWI_FLAG_SCANNING) == 0) {
- sc->flags |= IWI_FLAG_SCANNING;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_scanstarttask);
- }
- break;
-
case IEEE80211_S_AUTH:
- iwi_auth_and_assoc(sc);
+ iwi_assoc(ic);
break;
-
case IEEE80211_S_RUN:
if (ic->ic_opmode == IEEE80211_M_IBSS) {
/*
@@ -987,17 +977,9 @@
* This is all totally bogus and needs to be redone.
*/
if (ic->ic_state == IEEE80211_S_SCAN)
- iwi_auth_and_assoc(sc);
- } else if (ic->ic_opmode == IEEE80211_M_MONITOR)
- taskqueue_enqueue(sc->sc_tq, &sc->sc_scantask);
-
- /* XXX way wrong */
- return sc->sc_newstate(ic, nstate,
- IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
-
- case IEEE80211_S_ASSOC:
+ iwi_assoc(ic);
+ }
break;
-
case IEEE80211_S_INIT:
/*
* NB: don't try to do this if iwi_stop_master has
@@ -1006,11 +988,16 @@
if (ic->ic_state == IEEE80211_S_RUN &&
(sc->flags & IWI_FLAG_FW_INITED))
taskqueue_enqueue(sc->sc_tq, &sc->sc_downtask);
+ if (ic->ic_state == IEEE80211_S_SCAN &&
+ (sc->flags & IWI_FLAG_SCANNING))
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_scanaborttask);
+ break;
+ case IEEE80211_S_ASSOC:
+ default:
break;
}
+ return (error != 0) ? error : sc->sc_newstate(ic, nstate, arg);
- ic->ic_state = nstate;
- return 0;
}
/*
@@ -1191,8 +1178,6 @@
iwi_setcurchan(struct iwi_softc *sc, int chan)
{
struct ieee80211com *ic = &sc->sc_ic;
-
- ic->ic_curchan = &ic->ic_channels[chan];
sc->curchan = chan;
sc->sc_rxtap.wr_chan_freq = sc->sc_txtap.wt_chan_freq =
@@ -1406,9 +1391,10 @@
switch (notif->type) {
case IWI_NOTIF_TYPE_SCAN_CHANNEL:
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));
+ sc->flags &= ~IWI_FLAG_CHANNEL_SCAN;
break;
case IWI_NOTIF_TYPE_SCAN_COMPLETE:
@@ -1419,19 +1405,6 @@
sc->sc_scan_timer = 0;
- if (ic->ic_opmode == IEEE80211_M_MONITOR) {
- /*
- * Monitor mode works by doing a passive scan to set
- * the channel and enable rx. Because we don't want
- * to abort a scan lest the firmware crash we scan
- * for a short period of time and automatically restart
- * the scan when notified the sweep has completed.
- */
- taskqueue_enqueue(sc->sc_tq, &sc->sc_scantask);
- } else {
- sc->flags &= ~IWI_FLAG_SCANNING;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_scandonetask);
- }
break;
case IWI_NOTIF_TYPE_AUTHENTICATION:
@@ -1504,15 +1477,6 @@
beacon->state, le32toh(beacon->number)));
if (beacon->state == IWI_BEACON_MISS) {
-#if 0
- if (sc->flags & IWI_FLAG_SCANNING) {
- /* XXX terminate scan, linux driver
- says fw can get stuck */
- /* XXX should be handled in iwi_newstate */
- taskqueue_enqueue(sc->sc_tq,
- &sc->sc_scanaborttask);
- }
-#endif
/*
* The firmware notifies us of every beacon miss
* so we need to track the count against the
@@ -1646,6 +1610,9 @@
/* don't restart if the interface isn't up */
if (sc->sc_ifp->if_flags & IFF_DRV_RUNNING)
taskqueue_enqueue(sc->sc_tq, &sc->sc_restarttask);
+
+ sc->flags &= ~IWI_FLAG_BUSY;
+ wakeup(sc);
}
if (r & IWI_INTR_FW_INITED) {
@@ -2838,7 +2805,7 @@
ic = &sc->sc_ic;
KASSERT(ic->ic_opmode == IEEE80211_M_MONITOR,
("opmode %u", ic->ic_opmode));
- chan = ic->ic_bsschan;
+ chan = ic->ic_curchan;
memset(&scan, 0, sizeof scan);
/*
@@ -2847,7 +2814,9 @@
* let a scan complete before changing channels--such as when
* channel hopping in monitor mode.
*/
- scan.dwell_time[IWI_SCAN_TYPE_PASSIVE] = htole16(2000);
+ 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);
if (IEEE80211_IS_CHAN_5GHZ(chan))
scan.channels[0] = 1 | IWI_CHAN_5GHZ;
@@ -2885,8 +2854,12 @@
struct iwi_rateset rs;
uint16_t capinfo;
int error;
+ IWI_LOCK_DECL;
- if (IEEE80211_IS_CHAN_2GHZ(ic->ic_bsschan)) {
+
+ error = 0;
+ IWI_LOCK(sc);
+ if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
memset(&config, 0, sizeof config);
config.bluetooth_coexistence = sc->bluetooth;
config.antenna = sc->antenna;
@@ -2899,7 +2872,7 @@
DPRINTF(("Configuring adapter\n"));
error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config);
if (error != 0)
- return error;
+ goto done;
}
#ifdef IWI_DEBUG
@@ -2911,11 +2884,16 @@
#endif
error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ni->ni_essid, ni->ni_esslen);
if (error != 0)
- return error;
+ goto done;
/* the rate set has already been "negotiated" */
- rs.mode = IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan) ? IWI_MODE_11A :
- IWI_MODE_11G;
+ if (IEEE80211_IS_CHAN_A(ic->ic_curchan))
+ rs.mode = IWI_MODE_11A;
+ else if (IEEE80211_IS_CHAN_G(ic->ic_curchan))
+ rs.mode = IWI_MODE_11G;
+ if (IEEE80211_IS_CHAN_B(ic->ic_curchan))
+ rs.mode = IWI_MODE_11B;
+
rs.type = IWI_RATESET_TYPE_NEGOTIATED;
rs.nrates = ni->ni_rates.rs_nrates;
if (rs.nrates > IWI_RATESET_SIZE) {
@@ -2927,7 +2905,7 @@
DPRINTF(("Setting negotiated rates (%u)\n", rs.nrates));
error = iwi_cmd(sc, IWI_CMD_SET_RATES, &rs, sizeof rs);
if (error != 0)
- return error;
+ goto done;
memset(assoc, 0, sizeof *assoc);
@@ -2943,21 +2921,21 @@
error = iwi_cmd(sc, IWI_CMD_SET_OPTIE, ic->ic_opt_ie,
ic->ic_opt_ie_len);
if (error != 0)
- return error;
+ goto done;
}
error = iwi_set_sensitivity(sc, ni->ni_rssi);
if (error != 0)
- return error;
+ goto done;
- if (IEEE80211_IS_CHAN_A(ni->ni_chan))
+ if (IEEE80211_IS_CHAN_A(ic->ic_curchan))
assoc->mode = IWI_MODE_11A;
- else if (IEEE80211_IS_CHAN_G(ni->ni_chan))
+ else if (IEEE80211_IS_CHAN_G(ic->ic_curchan))
assoc->mode = IWI_MODE_11G;
- else if (IEEE80211_IS_CHAN_B(ni->ni_chan))
+ else if (IEEE80211_IS_CHAN_B(ic->ic_curchan))
assoc->mode = IWI_MODE_11B;
- /* XXX else error */
- assoc->chan = ieee80211_chan2ieee(ic, ni->ni_chan);
+
+ assoc->chan = ic->ic_curchan->ic_ieee;
/*
* NB: do not arrange for shared key auth w/o privacy
* (i.e. a wep key); it causes a firmware error.
@@ -2976,7 +2954,7 @@
error = iwi_setwepkeys(sc);
if (error != 0)
- return error;
+ goto done;
}
if (ic->ic_flags & IEEE80211_F_WPA)
assoc->policy |= htole16(IWI_POLICY_WPA);
@@ -2993,7 +2971,7 @@
if (ic->ic_flags & IEEE80211_F_PRIVACY)
capinfo |= IEEE80211_CAPINFO_PRIVACY;
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
- IEEE80211_IS_CHAN_2GHZ(ic->ic_bsschan))
+ IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)
capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
@@ -3014,7 +2992,11 @@
assoc->chan, le16toh(assoc->policy), assoc->auth,
le16toh(assoc->capinfo), le16toh(assoc->lintval),
le16toh(assoc->intval)));
- return iwi_cmd(sc, IWI_CMD_ASSOCIATE, assoc, sizeof *assoc);
+ error = iwi_cmd(sc, IWI_CMD_ASSOCIATE, assoc, sizeof *assoc);
+done:
+ IWI_UNLOCK(sc);
+
+ return (error);
}
static int
@@ -3521,3 +3503,74 @@
sc->sc_ledpin = IWI_RST_LED_ASSOCIATED;
}
}
+
+static void
+iwi_ops(void *arg, int npending)
+{
+ struct iwi_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+ IWI_LOCK_DECL;
+
+ IWI_LOCK(sc);
+ while ((ic->ic_state != IEEE80211_S_INIT) && (sc->flags & IWI_FLAG_BUSY)) {
+ msleep(sc, &sc->sc_mtx, 0, "iwicmd", hz/10);
+ }
+
+ if (ic->ic_state == IEEE80211_S_INIT)
+ goto done;
+
+ switch (sc->sc_scanop) {
+ case IWI_ASSOC:
+ iwi_auth_and_assoc(sc);
+ break;
+ case IWI_SCAN_START:
+ iwi_scan(sc);
+ break;
+ case IWI_SCAN_END:
+ iwi_scanabort(sc, 0);
+ break;
+ }
+done:
+ IWI_UNLOCK(sc);
+}
+
+static void
+iwi_scan_start(struct ieee80211com *ic)
+{
+ 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);
+
+}
+
+static void
+iwi_set_channel(struct ieee80211com *ic)
+{
+ struct ifnet *ifp = ic->ic_ifp;
+ struct iwi_softc *sc = ifp->if_softc;
+ if (!(sc->flags & IWI_FLAG_SCANNING))
+ iwi_setcurchan(sc, ic->ic_curchan->ic_ieee);
+}
+
+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);
+}
+
+static void
+iwi_assoc(struct ieee80211com *ic)
+{
+ 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);
+}
==== //depot/projects/wifi/sys/dev/iwi/if_iwivar.h#10 (text+ko) ====
@@ -136,7 +136,7 @@
#define IWI_FLAG_FW_LOADING (1 << 2)
#define IWI_FLAG_BUSY (1 << 3) /* busy sending a command */
#define IWI_FLAG_ASSOCIATED (1 << 4) /* currently associated */
-
+#define IWI_FLAG_CHANNEL_SCAN (1 << 5)
struct iwi_cmd_ring cmdq;
struct iwi_tx_ring txq[WME_NUM_AC];
struct iwi_rx_ring rxq;
@@ -176,6 +176,7 @@
struct task sc_setwmetask; /* set wme params processing */
struct task sc_downtask; /* disassociate processing */
struct task sc_restarttask; /* restart adapter processing */
+ struct task sc_opstask; /* scan / auth processing */
unsigned int sc_softled : 1, /* enable LED gpio status */
sc_ledstate: 1, /* LED on/off state */
@@ -195,6 +196,11 @@
int sc_rfkill_timer;/* poll for rfkill change */
int sc_scan_timer; /* scan request timeout */
+#define IWI_SCAN_START (1 << 0)
+#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 */
struct bpf_if *sc_drvbpf;
union {
More information about the p4-projects
mailing list