Date: Fri, 5 Jan 2007 05:40:13 GMT From: Kip Macy <kmacy@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 112529 for review Message-ID: <200701050540.l055eDIY041687@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=112529 Change 112529 by kmacy@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 {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701050540.l055eDIY041687>