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