Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Apr 2008 23:30:25 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 139171 for review
Message-ID:  <200804012330.m31NUPxR020200@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=139171

Change 139171 by sam@sam_ebb on 2008/04/01 23:30:11

	checkpoint work I've been holding on to; includes tracking
	of various api changes

Affected files ...

.. //depot/projects/vap/sys/dev/iwn/if_iwn.c#6 edit
.. //depot/projects/vap/sys/dev/iwn/if_iwnreg.h#4 edit
.. //depot/projects/vap/sys/dev/iwn/if_iwnvar.h#3 edit

Differences ...

==== //depot/projects/vap/sys/dev/iwn/if_iwn.c#6 (text+kox) ====

@@ -124,9 +124,6 @@
 void		iwn_unload_firmware(struct iwn_softc *);
 static void	iwn_timer_timeout(void *);
 static void	iwn_calib_reset(struct iwn_softc *);
-static void	iwn_amrr_reset(struct ieee80211vap *);
-static void	iwn_amrr_iter_func(void *, struct ieee80211_node *);
-static void	iwn_amrr_timeout(void *);
 void		iwn_ampdu_rx_start(struct iwn_softc *, struct iwn_rx_desc *);
 void		iwn_rx_intr(struct iwn_softc *, struct iwn_rx_desc *,
 		    struct iwn_rx_data *);
@@ -147,7 +144,8 @@
 static void	iwn_watchdog(struct iwn_softc *);
 int		iwn_ioctl(struct ifnet *, u_long, caddr_t);
 int		iwn_cmd(struct iwn_softc *, int, const void *, int, int);
-int		iwn_setup_node_mrr(struct iwn_softc *, uint8_t, int);
+int		iwn_set_link_quality(struct iwn_softc *, uint8_t,
+		    const struct ieee80211_channel *, int);
 int		iwn_set_key(struct ieee80211com *, struct ieee80211_node *,
 		    const struct ieee80211_key *);
 int		iwn_wme_update(struct ieee80211com *);
@@ -201,6 +199,7 @@
 	IWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
 	IWN_DEBUG_NODE		= 0x00000400,	/* node management */
 	IWN_DEBUG_LED		= 0x00000800,	/* led management */
+	IWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
 	IWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
 	IWN_DEBUG_ANY		= 0xffffffff
 };
@@ -375,8 +374,7 @@
 
 	/* set device capabilities */
 	ic->ic_caps =
-		  IEEE80211_C_WEP		/* s/w WEP */
-		| IEEE80211_C_MONITOR		/* monitor mode supported */
+		  IEEE80211_C_MONITOR		/* monitor mode supported */
 		| IEEE80211_C_TXPMGT		/* tx power management */
 		| IEEE80211_C_SHSLOT		/* short slot time supported */
 		| IEEE80211_C_WPA
@@ -514,10 +512,10 @@
 	ivp->iv_newstate = vap->iv_newstate;
 	vap->iv_newstate = iwn_newstate;
 
-	callout_init(&ivp->iv_amrr_to, CALLOUT_MPSAFE);
 	ieee80211_amrr_init(&ivp->iv_amrr, vap,
 	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
-	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD);
+	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
+	    500 /*ms*/);
 
 	/* complete setup */
 	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
@@ -530,7 +528,7 @@
 {
 	struct iwn_vap *ivp = IWN_VAP(vap);
 
-	callout_drain(&ivp->iv_amrr_to);
+	ieee80211_amrr_cleanup(&ivp->iv_amrr);
 	ieee80211_vap_detach(vap);
 	free(ivp, M_80211_VAP);
 }
@@ -948,15 +946,9 @@
 iwn_newassoc(struct ieee80211_node *ni, int isnew)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
-	int i;
 
-	ieee80211_amrr_node_init(&IWN_VAP(vap)->iv_amrr, &IWN_NODE(ni)->amn);
-
-	/* set rate to some reasonable initial value */
-	for (i = ni->ni_rates.rs_nrates - 1;
-	     i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
-	     i--);
-	ni->ni_txrate = i;
+	ieee80211_amrr_node_init(&IWN_VAP(vap)->iv_amrr,
+	   &IWN_NODE(ni)->amn, ni);
 }
 
 int
@@ -973,13 +965,13 @@
 	struct iwn_vap *ivp = IWN_VAP(vap);
 	struct ieee80211com *ic = vap->iv_ic;
 	struct iwn_softc *sc = ic->ic_ifp->if_softc;
+	int error;
 
 	DPRINTF(sc, IWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
 		ieee80211_state_name[vap->iv_state],
 		ieee80211_state_name[nstate]);
 
 	callout_stop(&sc->sc_timer_to);
-	callout_stop(&ivp->iv_amrr_to);
 
 	/*
 	 * Some state transitions require issuing a configure request
@@ -989,7 +981,8 @@
 	 */
 	if (nstate == IEEE80211_S_AUTH && vap->iv_state != IEEE80211_S_AUTH) {
 		/* !AUTH -> AUTH requires adapter config */
-		return iwn_queue_cmd(sc, IWN_AUTH, arg, IWN_QUEUE_NORMAL);
+		error = iwn_queue_cmd(sc, IWN_AUTH, arg, IWN_QUEUE_NORMAL);
+		return (error != 0 ? error : EINPROGRESS);
 	}
 	if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) {
 		/*
@@ -997,18 +990,14 @@
 		 * which is done with a firmware cmd.  We also defer
 		 * starting the timers until that work is done.
 		 */
-		return iwn_queue_cmd(sc, IWN_RUN, arg, IWN_QUEUE_NORMAL);
+		error = iwn_queue_cmd(sc, IWN_RUN, arg, IWN_QUEUE_NORMAL);
+		return (error != 0 ? error : EINPROGRESS);
 	}
 	if (nstate == IEEE80211_S_RUN) {
-		const struct ieee80211_txparam *tp;
 		/*
 		 * RUN -> RUN transition; just restart the timers.
 		 */
 		iwn_calib_reset(sc);
-		tp = &vap->iv_txparms[
-		    ieee80211_chan2mode(vap->iv_bss->ni_chan)];
-		if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
-			iwn_amrr_reset(vap);
 	}
 	return ivp->iv_newstate(vap, nstate, arg);
 }
@@ -1348,34 +1337,6 @@
 	sc->calib_cnt = 60;		/* do calibration every 60s */
 }
 
-static void
-iwn_amrr_reset(struct ieee80211vap *vap)
-{
-	/* rate control updated every 500ms */
-	callout_reset(&IWN_VAP(vap)->iv_amrr_to, hz / 2, iwn_amrr_timeout, vap);
-}
-
-static void
-iwn_amrr_iter_func(void *arg, struct ieee80211_node *ni)
-{
-	struct ieee80211vap *vap = arg;
-
-	ieee80211_amrr_choose(&IWN_VAP(vap)->iv_amrr, ni, &IWN_NODE(ni)->amn);
-}
-
-static void
-iwn_amrr_timeout(void *arg)
-{
-	struct ieee80211vap *vap = arg;
-
-	if (vap->iv_opmode != IEEE80211_M_STA) {
-		struct ieee80211com *ic = vap->iv_ic;
-		ieee80211_iterate_nodes(&ic->ic_sta, iwn_amrr_iter_func, vap);
-	} else
-		iwn_amrr_iter_func(vap, vap->iv_bss);
-	iwn_amrr_reset(vap);
-}
-
 void
 iwn_ampdu_rx_start(struct iwn_softc *sc, struct iwn_rx_desc *desc)
 {
@@ -1598,11 +1559,13 @@
 	struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];
 	struct iwn_tx_data *data = &ring->data[desc->idx];
 	struct iwn_tx_stat *stat = (struct iwn_tx_stat *)(desc + 1);
-	struct iwn_node *wn = (struct iwn_node *)data->ni;
+	struct iwn_node *wn = IWN_NODE(data->ni);
 	struct mbuf *m;
 	struct ieee80211_node *ni;
 	uint32_t status;
 
+	KASSERT(data->ni != NULL, ("no node"));
+
 	DPRINTF(sc, IWN_DEBUG_XMIT, "%s: "
 	    "qid %d idx %d retries %d nkill %d rate %x duration %d status %x\n",
 	    __func__, desc->qid, desc->idx, stat->ntries,
@@ -1612,19 +1575,18 @@
 	/*
 	 * Update rate control statistics for the node.
 	 */
-	wn->amn.amn_txcnt++;
-	if (stat->ntries > 0) {
-		DPRINTF(sc, IWN_DEBUG_XMIT, "%s: ntries %d\n",
-		    __func__, stat->ntries);
-		wn->amn.amn_retrycnt++;
-	}
-
 	status = le32toh(stat->status) & 0xff;
 	if (status & 0x80) {
 		DPRINTF(sc, IWN_DEBUG_ANY, "%s: status 0x%x\n",
 		    __func__, le32toh(stat->status));
 		ifp->if_oerrors++;
+		ieee80211_amrr_tx_complete(&wn->amn,
+		    IEEE80211_AMRR_FAILURE, stat->ntries);
+	} else {
+		ieee80211_amrr_tx_complete(&wn->amn,
+		    IEEE80211_AMRR_SUCCESS, stat->ntries);
 	}
+
 	bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE);
 	bus_dmamap_unload(ring->data_dmat, data->map);
 
@@ -1933,9 +1895,10 @@
 		rate = tp->mcastrate;
 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
 		rate = tp->ucastrate;
-	else
-		rate = ni->ni_rates.rs_rates[ni->ni_txrate];
-	rate &= IEEE80211_RATE_VAL;
+	else {
+		(void) ieee80211_amrr_choose(ni, &IWN_NODE(ni)->amn);
+		rate = ni->ni_txrate;
+	}
 
 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 		k = ieee80211_crypto_encap(ni, m0);
@@ -2701,6 +2664,9 @@
 		htole16(8);
 	}
 
+	DPRINTF(sc, IWN_DEBUG_CMD, "%s: %s (0x%x) flags %d qid %d idx %d\n",
+	    __func__, iwn_intr_str(cmd->code), cmd->code,
+	    cmd->flags, cmd->qid, cmd->idx);
 
 	/* kick cmd ring */
 	ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;
@@ -2709,45 +2675,87 @@
 	return async ? 0 : msleep(cmd, &sc->sc_mtx, PCATCH, "iwncmd", hz);
 }
 
+static const uint8_t iwn_ridx_to_plcp[] = {
+	10, 20, 55, 110, /* CCK */
+	0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3, 0x3 /* OFDM R1-R4 */
+};
+static const uint8_t iwn_siso_mcs_to_plcp[] = {
+	0, 0, 0, 0, 			/* CCK */
+	0, 0, 1, 2, 3, 4, 5, 6, 7	/* HT */
+};
+static const uint8_t iwn_mimo_mcs_to_plcp[] = {
+	0, 0, 0, 0, 			/* CCK */
+	8, 8, 9, 10, 11, 12, 13, 14, 15	/* HT */
+};
+static const uint8_t iwn_prev_ridx[] = {
+	/* NB: allow fallback from CCK11 to OFDM9 and from OFDM6 to CCK5 */
+	0, 0, 1, 5,			/* CCK */
+	2, 4, 3, 6, 7, 8, 9, 10, 10	/* OFDM */
+};
+
 /*
- * Configure hardware multi-rate retries for one node.
+ * Configure hardware link parameters for the specified
+ * node operating on the specified channel.
  */
 int
-iwn_setup_node_mrr(struct iwn_softc *sc, uint8_t id, int async)
+iwn_set_link_quality(struct iwn_softc *sc, uint8_t id,
+	const struct ieee80211_channel *c, int async)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
-	struct iwn_cmd_mrr mrr;
+	struct iwn_cmd_link_quality lq;
 	int i, ridx;
 
-	memset(&mrr, 0, sizeof mrr);
-	mrr.id = id;
-	if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
-	    IEEE80211_IS_CHAN_HT(ic->ic_bsschan)) {
-		mrr.mimo = 1;
-		mrr.ssmask = 1;
+	memset(&lq, 0, sizeof(lq));
+	lq.id = id;
+	if (IEEE80211_IS_CHAN_HT(c)) {
+		lq.mimo = 1;
+		lq.ssmask = 0x1;
 	} else
-		mrr.ssmask = 2;
-	mrr.dsmask = 3;
-	mrr.ampdu_disable = 3;
-	mrr.ampdu_limit = htole16(4000);
+		lq.ssmask = 0x2;
 
 	if (id == IWN_ID_BSS)
-		ridx = IWN_OFDM54;
-	else if (IEEE80211_IS_CHAN_A(ic->ic_curchan))
-		ridx = IWN_OFDM6;
+		ridx = IWN_RATE_OFDM54;
+	else if (IEEE80211_IS_CHAN_A(c))
+		ridx = IWN_RATE_OFDM6;
 	else
-		ridx = IWN_CCK1;
+		ridx = IWN_RATE_CCK1;
 	for (i = 0; i < IWN_MAX_TX_RETRIES; i++) {
-		mrr.table[i].rate = iwn_ridx_to_plcp[ridx];
-		mrr.table[i].rflags = IWN_RFLAG_ANT_B;
-		if (ridx <= IWN_CCK11)
-			mrr.table[i].rflags |= IWN_RFLAG_CCK;
+		/* XXX toggle antenna for retry patterns */
+		if (IEEE80211_IS_CHAN_HT40(c)) {
+			lq.table[i].rate = iwn_mimo_mcs_to_plcp[ridx]
+					 | IWN_RATE_MCS;
+			lq.table[i].rflags = IWN_RFLAG_HT
+					 | IWN_RFLAG_HT40
+					 | IWN_RFLAG_ANT_A;
+			/* XXX shortGI */
+		} else if (IEEE80211_IS_CHAN_HT(c)) {
+			lq.table[i].rate = iwn_siso_mcs_to_plcp[ridx]
+					 | IWN_RATE_MCS;
+			lq.table[i].rflags = IWN_RFLAG_HT
+					 | IWN_RFLAG_ANT_A;
+			/* XXX shortGI */
+		} else {
+			lq.table[i].rate = iwn_ridx_to_plcp[ridx];
+			if (ridx <= IWN_RATE_CCK11)
+				lq.table[i].rflags = IWN_RFLAG_CCK;
+			lq.table[i].rflags |= IWN_RFLAG_ANT_B;
+		}
 		ridx = iwn_prev_ridx[ridx];
 	}
-	DPRINTF(sc, IWN_DEBUG_STATE,
-	    "%s: set MRR for node %d, mimo %d ssmask %d\n",
-	    __func__, id, mrr.mimo, mrr.ssmask);
-	return iwn_cmd(sc, IWN_CMD_NODE_MRR_SETUP, &mrr, sizeof mrr, async);
+
+	lq.dsmask = 0x3;
+	lq.ampdu_disable = 3;
+	lq.ampdu_limit = htole16(4000);
+#ifdef IWN_DEBUG
+	if (sc->sc_debug & IWN_DEBUG_STATE) {
+		printf("%s: set link quality for node %d, mimo %d ssmask %d\n",
+		    __func__, id, lq.mimo, lq.ssmask);
+		printf("%s:", __func__);
+		for (i = 0; i < IWN_MAX_TX_RETRIES; i++)
+			printf(" %d:%x", lq.table[i].rate, lq.table[i].rflags);
+		printf("\n");
+	}
+#endif
+	return iwn_cmd(sc, IWN_CMD_TX_LINK_QUALITY, &lq, sizeof(lq), async);
 }
 
 #if 0
@@ -3463,6 +3471,7 @@
 		    "%s: could not configure, error %d\n", __func__, error);
 		return error;
 	}
+	sc->sc_curchan = ic->ic_curchan;
 
 	/* configuration has changed, set Tx power accordingly */
 	error = iwn_set_txpower(sc, ni->ni_chan, 1);
@@ -3487,7 +3496,7 @@
 		    __func__, error);
 		return error;
 	}
-	error = iwn_setup_node_mrr(sc, node.id, 1);
+	error = iwn_set_link_quality(sc, node.id, ic->ic_curchan, 1);
 	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "%s: could not setup MRR for broadcast node, error %d\n",
@@ -3508,7 +3517,6 @@
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);	/*XXX*/
 	struct ieee80211_node *ni = vap->iv_bss;
-	const struct ieee80211_txparam *tp;
 	struct iwn_node_info node;
 	int error, maxrxampdu, ampdudensity;
 
@@ -3538,6 +3546,12 @@
 			sc->config.flags |= htole32(IWN_CONFIG_HT40D);
 		else
 			sc->config.flags |= htole32(IWN_CONFIG_HT20);
+		sc->config.rxchain = htole16(
+			  (3 << IWN_RXCHAIN_VALID_S)
+			| (3 << IWN_RXCHAIN_MIMO_CNT_S)
+			| (1 << IWN_RXCHAIN_CNT_S)
+			| IWN_RXCHAIN_MIMO_FORCE);
+
 		maxrxampdu = MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU);
 		ampdudensity = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY);
 	} else
@@ -3563,6 +3577,7 @@
 		    __func__, error);
 		return error;
 	}
+	sc->sc_curchan = ni->ni_chan;
 
 	/* configuration has changed, set Tx power accordingly */
 	error = iwn_set_txpower(sc, ni->ni_chan, 1);
@@ -3577,8 +3592,8 @@
 	IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr);
 	node.id = IWN_ID_BSS;
 	node.htflags = htole32(
-	    (maxrxampdu << IWN_MAXRXAMPDU_SHIFT) |
-	    (ampdudensity << IWN_MPDUDENSITY_SHIFT));
+	    (maxrxampdu << IWN_MAXRXAMPDU_S) |
+	    (ampdudensity << IWN_MPDUDENSITY_S));
 	DPRINTF(sc, IWN_DEBUG_STATE, "%s: add BSS node, id %d htflags 0x%x\n",
 	    __func__, node.id, le32toh(node.htflags));
 	error = iwn_cmd(sc, IWN_CMD_ADD_NODE, &node, sizeof node, 1);
@@ -3586,7 +3601,7 @@
 		device_printf(sc->sc_dev,"could not add BSS node\n");
 		return error;
 	}
-	error = iwn_setup_node_mrr(sc, node.id, 1);
+	error = iwn_set_link_quality(sc, node.id, ni->ni_chan, 1);
 	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "%s: could not setup MRR for node %d, error %d\n",
@@ -3614,11 +3629,6 @@
 	/* link LED always on while associated */
 	iwn_set_led(sc, IWN_LED_LINK, 0, 1);
 
-	/* start rate control timer is not fixed rate */
-	tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
-	if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
-		iwn_amrr_reset(vap);
-
 	return 0;
 #undef MS
 }
@@ -3679,7 +3689,7 @@
 	hdr->plcp_threshold = htole16(1);	/* min # of packets */
 
 	/* select Ant B and Ant C for scanning */
-	hdr->rxchain = htole16(0x3e1 | 7 << IWN_RXCHAIN_ANTMSK_SHIFT);
+	hdr->rxchain = htole16(0x3e1 | (7 << IWN_RXCHAIN_VALID_S));
 
 	tx = (struct iwn_cmd_data *)(hdr + 1);
 	memset(tx, 0, sizeof (struct iwn_cmd_data));
@@ -3691,11 +3701,11 @@
 	if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) {
 		hdr->crc_threshold = htole16(1);
 		/* send probe requests at 6Mbps */
-		tx->rate = iwn_ridx_to_plcp[IWN_OFDM6];
+		tx->rate = iwn_ridx_to_plcp[IWN_RATE_OFDM6];
 	} else {
 		hdr->flags = htole32(IWN_CONFIG_24GHZ | IWN_CONFIG_AUTO);
 		/* send probe requests at 1Mbps */
-		tx->rate = iwn_ridx_to_plcp[IWN_CCK1];
+		tx->rate = iwn_ridx_to_plcp[IWN_RATE_CCK1];
 		tx->rflags |= IWN_RFLAG_CCK;
 	}
 
@@ -3883,7 +3893,7 @@
 	sc->config.ofdm_mask = 0xff;	/* not yet negotiated */
 	sc->config.ht_single_mask = 0xff;
 	sc->config.ht_dual_mask = 0xff;
-	sc->config.rxchain = htole16(0x2800 | 7 << IWN_RXCHAIN_ANTMSK_SHIFT);
+	sc->config.rxchain = htole16(0x2800 | (7 << IWN_RXCHAIN_VALID_S));
 
 	DPRINTF(sc, IWN_DEBUG_STATE,
 	   "%s: config chan %d mode %d flags 0x%x cck 0x%x ofdm 0x%x "
@@ -3904,6 +3914,7 @@
 		    __func__, error);
 		return error;
 	}
+	sc->sc_curchan = ic->ic_curchan;
 
 	/* configuration has changed, set Tx power accordingly */
 	error = iwn_set_txpower(sc, ic->ic_curchan, 0);
@@ -3926,7 +3937,7 @@
 		    __func__, error);
 		return error;
 	}
-	error = iwn_setup_node_mrr(sc, node.id, 0);
+	error = iwn_set_link_quality(sc, node.id, ic->ic_curchan, 0);
 	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "%s: could not setup MRR for node %d, error %d\n",
@@ -4285,11 +4296,13 @@
 	struct iwn_softc *sc = ifp->if_softc;
 	const struct ieee80211_channel *c = ic->ic_curchan;
 
-	sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq);
-	sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags);
-	sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq);
-	sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags);
-	iwn_queue_cmd(sc, IWN_SET_CHAN, 0, IWN_QUEUE_NORMAL);
+	if (c != sc->sc_curchan) {
+		sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq);
+		sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags);
+		sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq);
+		sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags);
+		iwn_queue_cmd(sc, IWN_SET_CHAN, 0, IWN_QUEUE_NORMAL);
+	}
 }
 
 /*
@@ -4325,6 +4338,7 @@
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211vap *vap;
 	int cmd, arg, error;
+	enum ieee80211_state nstate;
 
 	for (;;) {
 		IWN_CMD_LOCK(sc);
@@ -4344,7 +4358,7 @@
 		sc->sc_cmd_cur = (sc->sc_cmd_cur + 1) % IWN_CMD_MAXOPS;
 		IWN_CMD_UNLOCK(sc);
 
-		DPRINTF(sc, IWN_DEBUG_OPS, "%s: %s (cmd %d)\n",
+		DPRINTF(sc, IWN_DEBUG_OPS, "%s: %s (cmd 0x%x)\n",
 		    __func__, iwn_ops_str(cmd), cmd);
 
 		vap = TAILQ_FIRST(&ic->ic_vaps);	/* XXX */
@@ -4380,31 +4394,28 @@
 			}
 			break;
 		case IWN_AUTH:
+		case IWN_RUN:
 			IWN_LOCK(sc);
-			error = iwn_auth(sc);
-			IWN_UNLOCK(sc);
-			if (error != 0) {
-				device_printf(sc->sc_dev,
-				    "%s: could not move to auth state, error %d\n",
-				    __func__, error);
-				return;
+			if (cmd == IWN_AUTH) {
+				error = iwn_auth(sc);
+				nstate = IEEE80211_S_AUTH;
+			} else {
+				error = iwn_run(sc);
+				nstate = IEEE80211_S_RUN;
 			}
-			IWN_VAP(vap)->iv_newstate(vap, IEEE80211_S_AUTH, arg);
-			break;
-		case IWN_RUN:
-			IWN_LOCK(sc);
-			error = iwn_run(sc);
 			IWN_UNLOCK(sc);
-			if (error != 0) {
+			if (error == 0) {
+				IEEE80211_LOCK(ic);
+				IWN_VAP(vap)->iv_newstate(vap, nstate, arg);
+				if (vap->iv_newstate_cb != NULL)
+					vap->iv_newstate_cb(vap, nstate, arg);
+				IEEE80211_UNLOCK(ic);
+			} else {
 				device_printf(sc->sc_dev,
-				    "%s: could not move to run state, error %d\n",
-				    __func__, error);
-				return;
+				    "%s: %s state change failed, error %d\n",
+				    __func__, ieee80211_state_name[nstate],
+				    error);
 			}
-			IWN_VAP(vap)->iv_newstate(vap, IEEE80211_S_RUN, arg);
-			/* XXX compensate for deferred handling of newstate */
-			vap->iv_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-			if_start(vap->iv_ifp);
 			break;
 		case IWN_REINIT:
 			//XXX DEBUG
@@ -4528,7 +4539,7 @@
 	case IWN_CMD_ASSOCIATE:		return "IWN_CMD_ASSOCIATE";
 	case IWN_CMD_EDCA_PARAMS:	return "IWN_CMD_EDCA_PARAMS";
 	case IWN_CMD_TSF:		return "IWN_CMD_TSF";
-	case IWN_CMD_NODE_MRR_SETUP:	return "IWN_CMD_NODE_MRR_SETUP";
+	case IWN_CMD_TX_LINK_QUALITY:	return "IWN_CMD_TX_LINK_QUALITY";
 	case IWN_CMD_SET_LED:		return "IWN_CMD_SET_LED";
 	case IWN_CMD_SET_POWER_MODE:	return "IWN_CMD_SET_POWER_MODE";
 	case IWN_CMD_SCAN:		return "IWN_CMD_SCAN";

==== //depot/projects/vap/sys/dev/iwn/if_iwnreg.h#4 (text+kox) ====

@@ -251,30 +251,29 @@
 
 struct iwn_tx_cmd {
 	uint8_t	code;
-#define IWN_CMD_CONFIGURE		 16
-#define IWN_CMD_ASSOCIATE		 17
-#define IWN_CMD_EDCA_PARAMS		 19
-#define IWN_CMD_TSF			 20
-#define IWN_CMD_ADD_NODE		 24
-#define IWN_CMD_TX_DATA			 28
-#define IWN_CMD_NODE_MRR_SETUP		 78
-#define IWN_CMD_SET_LED			 72
-#define IWN_CMD_SET_POWER_MODE		119
-#define IWN_CMD_SCAN			128
-#define IWN_CMD_TXPOWER			151
-#define IWN_CMD_BLUETOOTH		155
-#define IWN_CMD_GET_STATISTICS		156
-#define IWN_CMD_SET_CRITICAL_TEMP	164
-#define IWN_SENSITIVITY			168
-#define IWN_PHY_CALIB			176
-
+#define IWN_CMD_CONFIGURE		0x10	/* REPLY_RXON */
+#define IWN_CMD_ASSOCIATE		0x11	/* REPLY_RXON_ASSOC */
+#define IWN_CMD_EDCA_PARAMS		0x13	/* REPLY_QOS_PARAM */
+#define IWN_CMD_TSF			0x14	/* REPLY_RXON_TIMING */
+#define IWN_CMD_ADD_NODE		0x18	/* REPLY_ADD_STA */
+#define IWN_CMD_TX_DATA			0x1c	/* REPLY_TX */
+#define IWN_CMD_TX_LINK_QUALITY		0x4e	/* REPLY_TX_LINK_QUALITY_CMD */
+#define IWN_CMD_SET_LED			0x48	/* REPLY_LEDS_CMD */
+#define IWN_CMD_SET_POWER_MODE		0x77	/* POWER_TABLE_CMD */
+#define IWN_CMD_SCAN			0x80	/* REPLY_SCAN_CMD */
+#define IWN_CMD_TXPOWER			0x97	/* REPLY_TX_PWR_TABLE_CMD */
+#define IWN_CMD_BLUETOOTH		0x9b	/* REPLY_BT_CONFIG */
+#define IWN_CMD_GET_STATISTICS		0x9c	/* REPLY_STATISTICS_CMD */
+#define IWN_CMD_SET_CRITICAL_TEMP	0xa4	/* REPLY_CT_KILL_CONFIG_CMD */
+#define IWN_SENSITIVITY			0xa8	/* SENSITIVITY_CMD */
+#define IWN_PHY_CALIB			0xb0	/* REPLY_PHY_CALIBRATION_CMD */
 	uint8_t	flags;
 	uint8_t	idx;
 	uint8_t	qid;
 	uint8_t	data[136];
 } __packed;
 
-/* structure for command IWN_CMD_CONFIGURE (NB: RXON) */
+/* structure for command IWN_CMD_CONFIGURE (aka RXON) */
 struct iwn_config {
 	uint8_t		myaddr[IEEE80211_ADDR_LEN];
 	uint16_t	reserved1;
@@ -289,8 +288,18 @@
 #define IWN_MODE_MONITOR	6
 	uint8_t		unused4;	/* air propagation */
 	uint16_t	rxchain;
-#define IWN_RXCHAIN_ANTMSK_SHIFT	1
-#define IWN_RXCHAIN_FORCE_MIMO		(1 << 14)
+#define	IWN_RXCHAIN_VALID	0x000e	/* which antennae are valid */
+#define IWN_RXCHAIN_VALID_S	1
+#define	IWN_RXCHAIN_FORCE	0x0070
+#define	IWN_RXCHAIN_FORCE_S	4
+#define	IWN_RXCHAIN_FORCE_MIMO	0x0380
+#define	IWN_RXCHAIN_FORCE_MIMO_S	7
+#define	IWN_RXCHAIN_CNT		0x0c00
+#define	IWN_RXCHAIN_CNT_S	10
+#define	IWN_RXCHAIN_MIMO_CNT	0x3000
+#define	IWN_RXCHAIN_MIMO_CNT_S	12
+#define IWN_RXCHAIN_MIMO_FORCE	0x4000
+#define IWN_RXCHAIN_MIMO_FORCE_S	14
 	uint8_t		ofdm_mask;	/* basic rates */
 	uint8_t		cck_mask;	/* basic rates */
 	uint16_t	associd;
@@ -362,17 +371,14 @@
 struct iwn_node_info {
 	uint8_t		control;
 #define IWN_NODE_UPDATE		(1 << 0)
-
 	uint8_t		reserved1[3];
 	uint8_t		macaddr[IEEE80211_ADDR_LEN];
 	uint16_t	reserved2;
 	uint8_t		id;
 #define IWN_ID_BSS		 0
 #define IWN_ID_BROADCAST	31
-
 	uint8_t		flags;
 #define IWN_FLAG_SET_KEY	(1 << 0)
-
 	uint16_t	reserved3;
 	uint16_t	security;
 	uint8_t		tsc2;	/* TKIP TSC2 */
@@ -381,17 +387,19 @@
 	uint16_t	reserved5;
 	uint8_t		key[IEEE80211_KEYBUF_SIZE];
 	uint32_t	htflags;
-#define IWN_MAXRXAMPDU_SHIFT	19
-#define IWN_MPDUDENSITY_SHIFT	23
-
+#define IWN_MAXRXAMPDU_S	19
+#define IWN_MPDUDENSITY_S	23
 	uint32_t	mask;
 	uint16_t	tid;
-	uint8_t		rate;
+	uint8_t		rate;		/* legacy rate/MCS */
+#define	IWN_RATE_MCS	0x08		/* or'd to indicate MCS */
 	uint8_t		rflags;
-#define IWN_RFLAG_CCK	(1 << 1)
-#define IWN_RFLAG_ANT_A	(1 << 6)
-#define IWN_RFLAG_ANT_B	(1 << 7)
-
+#define	IWN_RFLAG_HT	(1 << 0)	/* use HT modulation */
+#define IWN_RFLAG_CCK	(1 << 1)	/* use CCK modulation */
+#define	IWN_RFLAG_HT40	(1 << 3)	/* use dual-stream */
+#define	IWN_RFLAG_SGI	(1 << 5)	/* use short GI */
+#define IWN_RFLAG_ANT_A	(1 << 6)	/* start on antenna port A */
+#define IWN_RFLAG_ANT_B	(1 << 7)	/* start on antenna port B */
 	uint8_t		add_imm;
 	uint8_t		del_imm;
 	uint16_t	add_imm_start;
@@ -443,9 +451,9 @@
 	uint16_t	txop;
 } __packed;
 
-/* structure for command IWN_CMD_MRR_NODE_SETUP */
+/* structure for command IWN_CMD_TX_LINK_QUALITY */
 #define IWN_MAX_TX_RETRIES	16
-struct iwn_cmd_mrr {
+struct iwn_cmd_link_quality {
 	uint8_t		id;
 	uint8_t		reserved1;
 	uint16_t	ctl;
@@ -460,10 +468,10 @@
 	uint32_t	reserved2;
 	struct {
 		uint8_t		rate;
-#define IWN_CCK1	 0
-#define IWN_CCK11	 3
-#define IWN_OFDM6	 4
-#define IWN_OFDM54	11
+#define IWN_RATE_CCK1	 0
+#define IWN_RATE_CCK11	 3
+#define IWN_RATE_OFDM6	 4
+#define IWN_RATE_OFDM54	11
 		uint8_t		rflags;
 		uint16_t	xrflags;
 	} table[IWN_MAX_TX_RETRIES];
@@ -888,17 +896,6 @@
 	struct	iwn_eeprom_chan_samples chans[2];
 } __packed;
 
-static const uint8_t iwn_ridx_to_plcp[] = {
-	10, 20, 55, 110, /* CCK */
-	0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3, 0x3 /* OFDM R1-R4 */
-};
-
-/* allow fallback from CCK11 to OFDM9 and from OFDM6 to CCK5 */
-static const uint8_t iwn_prev_ridx[] = {
-	0, 0, 1, 5, /* CCK */
-	2, 4, 3, 6, 7, 8, 9, 10, 10 /* OFDM */
-};
-
 #define IWN_MAX_PWR_INDEX	107
 
 /*

==== //depot/projects/vap/sys/dev/iwn/if_iwnvar.h#3 (text+kox) ====

@@ -141,6 +141,7 @@
 	int			sc_debug;
 	struct callout		sc_timer_to;	/* calib+watchdog timer */
 	int			sc_tx_timer;	/* tx watchdog timer/counter */
+	const struct ieee80211_channel *sc_curchan;
 
         struct iwn_rx_radiotap_header sc_rxtap;
         int                     sc_rxtap_len;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200804012330.m31NUPxR020200>