svn commit: r361626 - head/sys/dev/usb/wlan

Adrian Chadd adrian at FreeBSD.org
Fri May 29 15:56:45 UTC 2020


Author: adrian
Date: Fri May 29 15:56:44 2020
New Revision: 361626
URL: https://svnweb.freebsd.org/changeset/base/361626

Log:
  [run] Add initial 802.11n support.
  
  * Enable self-generated 11n frames
  * add MCS rates for 1-stream and 2-stream rates; will do 3-stream
    once the rest of this tests out OK with other people.
  * Hard-code 1 stream for now
  * Add A-MPDU RX mbuf tagging
  * RTS/CTS if doing RTSCTS in HT protmode as well as legacy; they're
    separate configuration flags
  * Update the amrr rate index stuff - walk the rates array like others
    to find the right one - this now works for MCS and CCK/OFDM rates
  * Add support for atheros fast frames/AMSDU support as we can generate
    those in net80211.
  
  TODO:
  
  * HT40 isn't enabled yet
  * No A-MPDU support just yet; that requires some more firmware research
    and maybe porting some ath(4) A-MPDU support/tracking into net80211
  * Short preamble flags aren't set yet for MCS; need to check the linux
    driver and see what's going on there
  * Add 3x3 rates and set tx/rx stream configuration appropriately
  * More 5GHz testing; I have a 3x3 dual band USB NIC coming soon that'll
    let me test this.
  * Figure out why the RX path isn't performing as fast as it could -
    there's only a single buffer loaded at a time for the receive path
    in the USB bulk handler and this may not be super useful.
  
  Tested:
  
  * RT5390 usb, 1x1, RF5370 (2GHz radio), STA mode - A-MSDU TX, A-MPDU RX
  
  Submitted by:	Ashish Gupta <ashishgu at andrew.cmu.edu>
  Differential Revision:	https://reviews.freebsd.org/D22840

Modified:
  head/sys/dev/usb/wlan/if_run.c
  head/sys/dev/usb/wlan/if_runreg.h
  head/sys/dev/usb/wlan/if_runvar.h

Modified: head/sys/dev/usb/wlan/if_run.c
==============================================================================
--- head/sys/dev/usb/wlan/if_run.c	Fri May 29 13:07:52 2020	(r361625)
+++ head/sys/dev/usb/wlan/if_run.c	Fri May 29 15:56:44 2020	(r361626)
@@ -64,6 +64,9 @@ __FBSDID("$FreeBSD$");
 #include <net80211/ieee80211_regdomain.h>
 #include <net80211/ieee80211_radiotap.h>
 #include <net80211/ieee80211_ratectl.h>
+#ifdef	IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -495,6 +498,9 @@ static void	run_adjust_freq_offset(struct run_softc *)
 static void	run_init_locked(struct run_softc *);
 static void	run_stop(void *);
 static void	run_delay(struct run_softc *, u_int);
+static void	run_update_chw(struct ieee80211com *ic);
+static int	run_ampdu_enable(struct ieee80211_node *ni,
+		    struct ieee80211_tx_ampdu *tap);
 
 static eventhandler_tag run_etag;
 
@@ -506,10 +512,13 @@ static const struct rt2860_rate {
 	uint16_t	sp_ack_dur;
 	uint16_t	lp_ack_dur;
 } rt2860_rates[] = {
+	/* CCK rates (11b) */
 	{   2, 0, IEEE80211_T_DS,   0, 314, 314 },
 	{   4, 1, IEEE80211_T_DS,   1, 258, 162 },
 	{  11, 2, IEEE80211_T_DS,   2, 223, 127 },
 	{  22, 3, IEEE80211_T_DS,   3, 213, 117 },
+
+	/* OFDM rates (11a / 11g) */
 	{  12, 0, IEEE80211_T_OFDM, 4,  60,  60 },
 	{  18, 1, IEEE80211_T_OFDM, 4,  52,  52 },
 	{  24, 2, IEEE80211_T_OFDM, 6,  48,  48 },
@@ -517,9 +526,35 @@ static const struct rt2860_rate {
 	{  48, 4, IEEE80211_T_OFDM, 8,  44,  44 },
 	{  72, 5, IEEE80211_T_OFDM, 8,  40,  40 },
 	{  96, 6, IEEE80211_T_OFDM, 8,  40,  40 },
-	{ 108, 7, IEEE80211_T_OFDM, 8,  40,  40 }
+	{ 108, 7, IEEE80211_T_OFDM, 8,  40,  40 },
+
+	/* MCS - single stream */
+	{  0x80, 0, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x81, 1, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x82, 2, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x83, 3, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x84, 4, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x85, 5, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x86, 6, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x87, 7, IEEE80211_T_HT, 4, 60, 60 },
+	/* MCS - 2 streams */
+	{  0x88, 8, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x89, 9, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x8a, 10, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x8b, 11, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x8c, 12, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x8d, 13, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x8e, 14, IEEE80211_T_HT, 4, 60, 60 },
+	{  0x8f, 15, IEEE80211_T_HT, 4, 60, 60 },
 };
 
+/* These are indexes into the above rt2860_rates[] array */
+#define	RT2860_RIDX_CCK1		0
+#define	RT2860_RIDX_CCK11		3
+#define	RT2860_RIDX_OFDM6		4
+#define	RT2860_RIDX_MCS0		12
+#define	RT2860_RIDX_MAX			28
+
 static const struct {
 	uint16_t	reg;
 	uint32_t	val;
@@ -807,9 +842,25 @@ run_attach(device_t self)
 	    IEEE80211_C_MBSS |
 	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
 	    IEEE80211_C_SHSLOT |	/* short slot time supported */
+	    IEEE80211_C_SWAMSDUTX |	/* Do software A-MSDU TX */
+	    IEEE80211_C_FF | 		/* Atheros fast-frames */
 	    IEEE80211_C_WME |		/* WME */
 	    IEEE80211_C_WPA;		/* WPA1|WPA2(RSN) */
 
+	ic->ic_htcaps =
+		    IEEE80211_HTC_HT |
+		    IEEE80211_HTC_AMPDU |
+		    IEEE80211_HTC_AMSDU |
+		    IEEE80211_HTCAP_MAXAMSDU_3839 |
+		    IEEE80211_HTCAP_SMPS_OFF;
+
+	/*
+	 * For now, just do 1 stream.  Later on we'll figure out
+	 * how many tx/rx streams a particular NIC supports.
+	 */
+	ic->ic_rxstream = 1;
+	ic->ic_txstream = 1;
+
 	ic->ic_cryptocaps =
 	    IEEE80211_CRYPTO_WEP |
 	    IEEE80211_CRYPTO_AES_CCM |
@@ -839,6 +890,8 @@ run_attach(device_t self)
 	ic->ic_vap_delete = run_vap_delete;
 	ic->ic_transmit = run_transmit;
 	ic->ic_parent = run_parent;
+	ic->ic_update_chw = run_update_chw;
+	ic->ic_ampdu_enable = run_ampdu_enable;
 
 	ieee80211_radiotap_attach(ic,
 	    &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -974,6 +1027,10 @@ run_vap_create(struct ieee80211com *ic, const char nam
 
 	vap->iv_update_beacon = run_update_beacon;
 	vap->iv_max_aid = RT2870_WCID_MAX;
+
+	vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K;
+	vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_2;
+
 	/*
 	 * To delete the right key from h/w, we need wcid.
 	 * Luckily, there is unused space in ieee80211_key{}, wk_pad,
@@ -2059,11 +2116,13 @@ run_media_change(struct ifnet *ifp)
 		struct ieee80211_node *ni;
 		struct run_node	*rn;
 
+		/* XXX TODO: methodize with MCS rates */
 		rate = ic->ic_sup_rates[ic->ic_curmode].
 		    rs_rates[tp->ucastrate] & IEEE80211_RATE_VAL;
 		for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
 			if (rt2860_rates[ridx].rate == rate)
 				break;
+
 		ni = ieee80211_ref_node(vap->iv_bss);
 		rn = RUN_NODE(ni);
 		rn->fix_ridx = ridx;
@@ -2605,7 +2664,7 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
 	struct run_node *rn = RUN_NODE(ni);
 	union run_stats sta[2];
 	uint16_t (*wstat)[3];
-	int error;
+	int error, ridx;
 
 	RUN_LOCK(sc);
 
@@ -2656,12 +2715,17 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
 	}
 
 	ieee80211_ratectl_tx_update(vap, txs);
-	rn->amrr_ridx = ieee80211_ratectl_rate(ni, NULL, 0);
+	ieee80211_ratectl_rate(ni, NULL, 0);
+	/* XXX TODO: methodize with MCS rates */
+	for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
+		if (rt2860_rates[ridx].rate == ni->ni_txrate)
+			break;
+	rn->amrr_ridx = ridx;
 
 fail:
 	RUN_UNLOCK(sc);
 
-	RUN_DPRINTF(sc, RUN_DEBUG_RATE, "ridx=%d\n", rn->amrr_ridx);
+	RUN_DPRINTF(sc, RUN_DEBUG_RATE, "rate=%d, ridx=%d\n", ni->ni_txrate, rn->amrr_ridx);
 }
 
 static void
@@ -2684,14 +2748,12 @@ static void
 run_newassoc(struct ieee80211_node *ni, int isnew)
 {
 	struct run_node *rn = RUN_NODE(ni);
-	struct ieee80211_rateset *rs = &ni->ni_rates;
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = vap->iv_ic;
 	struct run_softc *sc = ic->ic_softc;
 	uint8_t rate;
 	uint8_t ridx;
 	uint8_t wcid;
-	int i, j;
 
 	wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
 	    1 : RUN_AID2WCID(ni->ni_associd);
@@ -2721,31 +2783,8 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
 	    "new assoc isnew=%d associd=%x addr=%s\n",
 	    isnew, ni->ni_associd, ether_sprintf(ni->ni_macaddr));
 
-	for (i = 0; i < rs->rs_nrates; i++) {
-		rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
-		/* convert 802.11 rate to hardware rate index */
-		for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
-			if (rt2860_rates[ridx].rate == rate)
-				break;
-		rn->ridx[i] = ridx;
-		/* determine rate of control response frames */
-		for (j = i; j >= 0; j--) {
-			if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) &&
-			    rt2860_rates[rn->ridx[i]].phy ==
-			    rt2860_rates[rn->ridx[j]].phy)
-				break;
-		}
-		if (j >= 0) {
-			rn->ctl_ridx[i] = rn->ridx[j];
-		} else {
-			/* no basic rate found, use mandatory one */
-			rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx;
-		}
-		RUN_DPRINTF(sc, RUN_DEBUG_STATE | RUN_DEBUG_RATE,
-		    "rate=0x%02x ridx=%d ctl_ridx=%d\n",
-		    rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]);
-	}
 	rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate;
+	/* XXX TODO: methodize with MCS rates */
 	for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
 		if (rt2860_rates[ridx].rate == rate)
 			break;
@@ -2876,6 +2915,10 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uin
 	} else
 		ni = NULL;
 
+	if(ni && ni->ni_flags & IEEE80211_NODE_HT) {
+		m->m_flags |= M_AMPDU;
+	}
+
 	if (__predict_false(flags & RT2860_RX_MICERR)) {
 		/* report MIC failures to net80211 for TKIP */
 		if (ni != NULL)
@@ -3089,6 +3132,9 @@ tr_setup:
 	/* make sure we free the source buffer, if any */
 	m_freem(m);
 
+#ifdef	IEEE80211_SUPPORT_SUPERG
+	ieee80211_ff_age_all(ic, 100);
+#endif
 	RUN_LOCK(sc);
 }
 
@@ -3234,6 +3280,15 @@ tr_setup:
 		}
 		break;
 	}
+#ifdef	IEEE80211_SUPPORT_SUPERG
+	/* XXX TODO: make this deferred rather than unlock/relock */
+	/* XXX TODO: should only do the QoS AC this belongs to */
+	if (pq->tx_nfree >= RUN_TX_RING_COUNT) {
+		RUN_UNLOCK(sc);
+		ieee80211_ff_flush_all(ic);
+		RUN_LOCK(sc);
+	}
+#endif
 }
 
 static void
@@ -3318,15 +3373,21 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_da
 		if (ridx != RT2860_RIDX_CCK1 &&
 		    (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
 			mcs |= RT2860_PHY_SHPRE;
-	} else
+	} else if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) {
 		mcs |= RT2860_PHY_OFDM;
+	} else if (rt2860_rates[ridx].phy == IEEE80211_T_HT) {
+		/* XXX TODO: [adrian] set short preamble for MCS? */
+		mcs |= RT2860_PHY_HT; /* Mixed, not greenfield */
+	}
 	txwi->phy = htole16(mcs);
 
 	/* check if RTS/CTS or CTS-to-self protection is required */
 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
-	    (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold ||
+	    ((m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) ||
 	     ((ic->ic_flags & IEEE80211_F_USEPROT) &&
-	      rt2860_rates[ridx].phy == IEEE80211_T_OFDM)))
+	      rt2860_rates[ridx].phy == IEEE80211_T_OFDM) ||
+	     ((ic->ic_htprotmode == IEEE80211_PROT_RTSCTS) &&
+	      rt2860_rates[ridx].phy == IEEE80211_T_HT)))
 		txwi->txop |= RT2860_TX_TXOP_HT;
 	else
 		txwi->txop |= RT2860_TX_TXOP_BACKOFF;
@@ -3390,7 +3451,8 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ie
 	/* pickup a rate index */
 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
 	    type != IEEE80211_FC0_TYPE_DATA || m->m_flags & M_EAPOL) {
-		ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
+		/* XXX TODO: methodize for 11n; use MCS0 for 11NA/11NG */
+		ridx = (ic->ic_curmode == IEEE80211_MODE_11A || ic->ic_curmode == IEEE80211_MODE_11NA) ?
 		    RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1;
 		ctl_ridx = rt2860_rates[ridx].ctl_ridx;
 	} else {
@@ -3609,6 +3671,7 @@ run_sendprot(struct run_softc *sc,
 	data->m = mprot;
 	data->ni = ieee80211_ref_node(ni);
 
+	/* XXX TODO: methodize with MCS rates */
 	for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
 		if (rt2860_rates[ridx].rate == protrate)
 			break;
@@ -3684,6 +3747,7 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, str
 
         data->m = m;
         data->ni = ni;
+	/* XXX TODO: methodize with MCS rates */
 	for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
 		if (rt2860_rates[ridx].rate == rate)
 			break;
@@ -4856,12 +4920,17 @@ run_getradiocaps(struct ieee80211com *ic,
 	memset(bands, 0, sizeof(bands));
 	setbit(bands, IEEE80211_MODE_11B);
 	setbit(bands, IEEE80211_MODE_11G);
+	setbit(bands, IEEE80211_MODE_11NG);
+
+	/* Note: for now, only support HT20 channels */
 	ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0);
 
 	if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 ||
 	    sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 ||
 	    sc->rf_rev == RT5592_RF_5592) {
 		setbit(bands, IEEE80211_MODE_11A);
+		setbit(bands, IEEE80211_MODE_11NA);
+		/* Note: for now, only support HT20 channels */
 		ieee80211_add_channel_list_5ghz(chans, maxchans, nchans,
 		    run_chan_5ghz, nitems(run_chan_5ghz), bands, 0);
 	}
@@ -6205,6 +6274,10 @@ run_init_locked(struct run_softc *sc)
 	/* turn radio LED on */
 	run_set_leds(sc, RT2860_LED_RADIO);
 
+	/* Set up AUTO_RSP_CFG register for auto response */
+	run_write(sc, RT2860_AUTO_RSP_CFG, RT2860_AUTO_RSP_EN |
+	    RT2860_BAC_ACKPOLICY_EN | RT2860_CTS_40M_MODE_EN);
+
 	sc->sc_flags |= RUN_RUNNING;
 	sc->cmdq_run = RUN_CMDQ_GO;
 
@@ -6309,6 +6382,22 @@ run_delay(struct run_softc *sc, u_int ms)
 {
 	usb_pause_mtx(mtx_owned(&sc->sc_mtx) ? 
 	    &sc->sc_mtx : NULL, USB_MS_TO_TICKS(ms));
+}
+
+
+static void
+run_update_chw(struct ieee80211com *ic)
+{
+
+	printf("%s: TODO\n", __func__);
+}
+
+static int
+run_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
+{
+
+	/* For now, no A-MPDU TX support in the driver */
+	return (0);
 }
 
 static device_method_t run_methods[] = {

Modified: head/sys/dev/usb/wlan/if_runreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_runreg.h	Fri May 29 13:07:52 2020	(r361625)
+++ head/sys/dev/usb/wlan/if_runreg.h	Fri May 29 15:56:44 2020	(r361626)
@@ -955,11 +955,6 @@ struct rt2860_rxwi {
 #define	RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ	0x14e
 #define	RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ	0x14f
 
-#define	RT2860_RIDX_CCK1	 0
-#define	RT2860_RIDX_CCK11	 3
-#define	RT2860_RIDX_OFDM6	 4
-#define	RT2860_RIDX_MAX		12
-
 /*
  * EEPROM access macro.
  */

Modified: head/sys/dev/usb/wlan/if_runvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_runvar.h	Fri May 29 13:07:52 2020	(r361625)
+++ head/sys/dev/usb/wlan/if_runvar.h	Fri May 29 15:56:44 2020	(r361626)
@@ -97,8 +97,6 @@ STAILQ_HEAD(run_tx_data_head, run_tx_data);
 
 struct run_node {
 	struct ieee80211_node	ni;
-	uint8_t			ridx[IEEE80211_RATE_MAXSIZE];
-	uint8_t			ctl_ridx[IEEE80211_RATE_MAXSIZE];
 	uint8_t			amrr_ridx;
 	uint8_t			mgt_ridx;
 	uint8_t			fix_ridx;


More information about the svn-src-head mailing list