git: 745a85824748 - main - rtwn: update rtwn_get_rates() to separate out the CCK/OFDM and HT rates

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Wed, 18 Dec 2024 23:49:03 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=745a85824748e06b9b2ca4e9639ba13bbf9c08ca

commit 745a85824748e06b9b2ca4e9639ba13bbf9c08ca
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2024-12-08 20:22:04 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2024-12-18 23:48:10 +0000

    rtwn: update rtwn_get_rates() to separate out the CCK/OFDM and HT rates
    
    The 32 bit bitmap is enough for CCK/OFDM rates and MCS0..15, but
    won't work for > MCS15, nor VHT rates.
    
    So, break out the legacy rates and HT rates.
    
    * break the rates and htrates out
    * document which calls are looking up basic rates and which care
      about the rates themselves
    * ensure the rate bitmap passed into the rate control firmware call
      (which isn't enabled yet!) is capped at 28 bits so they don't
      set the mode field.
    
    Differential Revision:  https://reviews.freebsd.org/D47993
    Reviewed by:    bz, imp
---
 sys/dev/rtwn/if_rtwn.c            |  3 ++-
 sys/dev/rtwn/if_rtwn_rx.c         | 30 ++++++++++++++++++++++--------
 sys/dev/rtwn/if_rtwn_rx.h         |  3 ++-
 sys/dev/rtwn/rtl8192c/r92c_fw.c   | 15 +++++++++++----
 sys/dev/rtwn/rtl8812a/r12a_chan.c |  3 ++-
 5 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c
index fdf44467680b..be01ececf307 100644
--- a/sys/dev/rtwn/if_rtwn.c
+++ b/sys/dev/rtwn/if_rtwn.c
@@ -1213,7 +1213,8 @@ rtwn_calc_basicrates(struct rtwn_softc *sc)
 			continue;
 
 		ni = ieee80211_ref_node(vap->iv_bss);
-		rtwn_get_rates(sc, &ni->ni_rates, NULL, &rates, NULL, 1);
+		/* Only fetches basic rates; no need to add HT/VHT here */
+		rtwn_get_rates(sc, &ni->ni_rates, NULL, &rates, NULL, NULL, 1);
 		basicrates |= rates;
 		ieee80211_free_node(ni);
 	}
diff --git a/sys/dev/rtwn/if_rtwn_rx.c b/sys/dev/rtwn/if_rtwn_rx.c
index 58cd53b01e63..977c1d17a08a 100644
--- a/sys/dev/rtwn/if_rtwn_rx.c
+++ b/sys/dev/rtwn/if_rtwn_rx.c
@@ -52,12 +52,24 @@
 
 #include <dev/rtwn/rtl8192c/r92c_reg.h>
 
+/*
+ * Get the driver rate set for the current operating rateset(s).
+ *
+ * rates_p is set to a mask of 11abg ridx values (not HW rate values.)
+ * htrates_p is set to a mask of 11n ridx values (not HW rate values),
+ *  starting at MCS0 == bit 0.
+ *
+ * maxrate_p is set to the ridx value.
+ *
+ * If basic_rates is 1 then only the 11abg basic rate logic will
+ * be applied; HT/VHT will be ignored.
+ */
 void
 rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
     const struct ieee80211_htrateset *rs_ht, uint32_t *rates_p,
-    int *maxrate_p, int basic_rates)
+    uint32_t *htrates_p, int *maxrate_p, int basic_rates)
 {
-	uint32_t rates;
+	uint32_t rates = 0, htrates = 0;
 	uint8_t ridx;
 	int i, maxrate;
 
@@ -65,7 +77,7 @@ rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
 	rates = 0;
 	maxrate = 0;
 
-	/* This is for 11bg */
+	/* This is for 11abg */
 	for (i = 0; i < rs->rs_nrates; i++) {
 		/* Convert 802.11 rate to HW rate index. */
 		ridx = rate2ridx(IEEE80211_RV(rs->rs_rates[i]));
@@ -82,15 +94,15 @@ rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
 	/* If we're doing 11n, enable 11n rates */
 	if (rs_ht != NULL && !basic_rates) {
 		for (i = 0; i < rs_ht->rs_nrates; i++) {
+			/* Only do up to 2-stream rates for now */
 			if ((rs_ht->rs_rates[i] & 0x7f) > 0xf)
 				continue;
-			/* 11n rates start at index 12 */
-			ridx = RTWN_RIDX_HT_MCS((rs_ht->rs_rates[i]) & 0xf);
-			rates |= (1 << ridx);
+			ridx = rs_ht->rs_rates[i] & 0xf;
+			htrates |= (1 << ridx);
 
 			/* Guard against the rate table being oddly ordered */
-			if (ridx > maxrate)
-				maxrate = ridx;
+			if (RTWN_RIDX_HT_MCS(ridx) > maxrate)
+				maxrate = RTWN_RIDX_HT_MCS(ridx);
 		}
 	}
 
@@ -99,6 +111,8 @@ rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs,
 
 	if (rates_p != NULL)
 		*rates_p = rates;
+	if (htrates_p != NULL)
+		*htrates_p = htrates;
 	if (maxrate_p != NULL)
 		*maxrate_p = maxrate;
 }
diff --git a/sys/dev/rtwn/if_rtwn_rx.h b/sys/dev/rtwn/if_rtwn_rx.h
index 73bdf0d7a0de..3108f1d4cde4 100644
--- a/sys/dev/rtwn/if_rtwn_rx.h
+++ b/sys/dev/rtwn/if_rtwn_rx.h
@@ -20,7 +20,8 @@
 #define	RTWN_NOISE_FLOOR	-95
 
 void	rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *,
-	    const struct ieee80211_htrateset *, uint32_t *, int *, int);
+	    const struct ieee80211_htrateset *, uint32_t *, uint32_t *,
+	    int *, int);
 void	rtwn_set_basicrates(struct rtwn_softc *, uint32_t);
 struct ieee80211_node *	rtwn_rx_common(struct rtwn_softc *, struct mbuf *,
 	    void *);
diff --git a/sys/dev/rtwn/rtl8192c/r92c_fw.c b/sys/dev/rtwn/rtl8192c/r92c_fw.c
index 426dfd0e6d3f..1ca37df7d0f4 100644
--- a/sys/dev/rtwn/rtl8192c/r92c_fw.c
+++ b/sys/dev/rtwn/rtl8192c/r92c_fw.c
@@ -196,7 +196,7 @@ r92c_init_ra(struct rtwn_softc *sc, int macid)
 {
 	struct ieee80211_htrateset *rs_ht;
 	struct ieee80211_node *ni;
-	uint32_t rates;
+	uint32_t rates, htrates;
 	int maxrate;
 
 	RTWN_NT_LOCK(sc);
@@ -212,13 +212,20 @@ r92c_init_ra(struct rtwn_softc *sc, int macid)
 		rs_ht = &ni->ni_htrates;
 	else
 		rs_ht = NULL;
-	/* XXX MACID_BC */
-	rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &maxrate, 0);
+	/*
+	 * Note: this pushes the rate bitmap and maxrate into the
+	 * firmware; and for this chipset 2-stream 11n support is enough.
+	 */
+	rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &htrates, &maxrate, 0);
 	RTWN_NT_UNLOCK(sc);
 
 #ifndef RTWN_WITHOUT_UCODE
 	if (sc->sc_ratectl == RTWN_RATECTL_FW) {
-		r92c_send_ra_cmd(sc, macid, rates, maxrate);
+		uint32_t fw_rates;
+		/* Add HT rates after normal rates; limit to MCS0..15 */
+		fw_rates = rates |
+		    ((htrates & 0xffff) << RTWN_RIDX_HT_MCS_SHIFT);
+		r92c_send_ra_cmd(sc, macid, fw_rates, maxrate);
 	}
 #endif
 
diff --git a/sys/dev/rtwn/rtl8812a/r12a_chan.c b/sys/dev/rtwn/rtl8812a/r12a_chan.c
index d71e0a8177fd..f900d1ef7b2d 100644
--- a/sys/dev/rtwn/rtl8812a/r12a_chan.c
+++ b/sys/dev/rtwn/rtl8812a/r12a_chan.c
@@ -452,8 +452,9 @@ r12a_set_band(struct rtwn_softc *sc, struct ieee80211_channel *c)
 	    !(rtwn_read_1(sc, R12A_CCK_CHECK) & R12A_CCK_CHECK_5GHZ))
 		return;
 
+	/* Note: this only fetches the basic rates, not the full rateset */
 	rtwn_get_rates(sc, ieee80211_get_suprates(ic, c), NULL, &basicrates,
-	    NULL, 1);
+	    NULL, NULL, 1);
 	if (IEEE80211_IS_CHAN_2GHZ(c)) {
 		rtwn_r12a_set_band_2ghz(sc, basicrates);
 		swing = rs->tx_bbswing_2g;