diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -1213,7 +1213,8 @@ 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.h b/sys/dev/rtwn/if_rtwn_rx.h --- 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/if_rtwn_rx.c b/sys/dev/rtwn/if_rtwn_rx.c --- a/sys/dev/rtwn/if_rtwn_rx.c +++ b/sys/dev/rtwn/if_rtwn_rx.c @@ -52,12 +52,24 @@ #include +/* + * 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 @@ 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 @@ /* 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 @@ 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/rtl8192c/r92c_fw.c b/sys/dev/rtwn/rtl8192c/r92c_fw.c --- a/sys/dev/rtwn/rtl8192c/r92c_fw.c +++ b/sys/dev/rtwn/rtl8192c/r92c_fw.c @@ -196,7 +196,7 @@ { 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 @@ 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 --- a/sys/dev/rtwn/rtl8812a/r12a_chan.c +++ b/sys/dev/rtwn/rtl8812a/r12a_chan.c @@ -452,8 +452,9 @@ !(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;