diff options
| author | Adrian Chadd <adrian@FreeBSD.org> | 2024-12-10 19:03:34 +0000 |
|---|---|---|
| committer | Adrian Chadd <adrian@FreeBSD.org> | 2024-12-19 16:06:29 +0000 |
| commit | aaaca5f288fa257a745743d03e51eef0517b246f (patch) | |
| tree | 7394c3c890d2acf050ec074ea20dc8263d3a1c60 /sys/dev/rtwn/if_rtwn.c | |
| parent | 4e2bd8cf08f4c803f93a4d9d5c9479fa72372869 (diff) | |
rtwn: add a default OFDM / CCK rate for self-generated frames
I noticed during testing that the MAC was generating MCS7 ACKs and
MCS7 block-ACK frames in response to MCS frames from its peer.
This is very suboptimal - it means that unless you're very close
to your peer (in this case a 2GHz AP), you'll end up failing a lot
of ACKs.
Linux faced the opposite problem in rtl8xxxu - the rate set being
programmed in here included a lot MORE rates, including MCS 0->7
and OFDM 6M->54M. This meant that they were INTENTIONALLY telling
the hardware to transmit at higher rates, and their fix was to
mask out the higher rates so self-generated frames don't try the
high rates at all.
Now, I am not sure why I'm not seeing any OFDM or HT basic rates.
We don't mark any OFDM / HT rates as basic in net80211 (in
ieee80211_phy.c) so I'm going to need to go and do a review of the
standard to see what's up. Additionally, the HT rate set that we
populate isn't tagging any of the HT rates as IEEE80211_RATE_BASIC,
so the code I added for now is a no-op.
So:
* Extend rtwn_get_rates() and its consumers to populate the HT rateset
with basic rates if they're provided
* Add a default 2GHz / 5GHz mask, inspired by linux, applied over the
basic rates provided.
* Make sure there's at least an OFDM rate (for 2G/5G) rate available if
the peer node is HT, which avoids the MAC defaulting to MCS7 when
generating ACK/block-ACK.
* Add register definitions for INIDATA/INIRTS, which set the default
data rate when the driver doesn't specify the initial data / RTS/CTS
rates in the TX descriptor.
* Leave a comment about why I've modified the mask from Linux.
Locally tested:
* RTL8192CU, STA mode
* RTL8188EU, STA mode
* RTL8192EU, STA mode
* RTL8812AU, STA mode
Differential Revision: https://reviews.freebsd.org/D48019
Reviewed by: bz
Diffstat (limited to 'sys/dev/rtwn/if_rtwn.c')
| -rw-r--r-- | sys/dev/rtwn/if_rtwn.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index be01ececf307..3b286d9adba9 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -1202,7 +1202,8 @@ rtwn_calc_basicrates(struct rtwn_softc *sc) struct rtwn_vap *rvp; struct ieee80211vap *vap; struct ieee80211_node *ni; - uint32_t rates; + struct ieee80211_htrateset *rs_ht; + uint32_t rates = 0, htrates = 0; rvp = sc->vaps[i]; if (rvp == NULL || rvp->curr_mode == R92C_MSR_NOLINK) @@ -1213,16 +1214,45 @@ rtwn_calc_basicrates(struct rtwn_softc *sc) continue; ni = ieee80211_ref_node(vap->iv_bss); - /* Only fetches basic rates; no need to add HT/VHT here */ - rtwn_get_rates(sc, &ni->ni_rates, NULL, &rates, NULL, NULL, 1); + if (ni->ni_flags & IEEE80211_NODE_HT) + rs_ht = &ni->ni_htrates; + else + rs_ht = NULL; + /* + * Only fetches basic rates; fetch 802.11abg and 11n basic + * rates + */ + rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &htrates, + NULL, 1); + + /* + * We need at least /an/ OFDM and/or MCS rate for HT + * operation, or the MAC will generate MCS7 ACK/Block-ACK + * frames and thus performance will suffer. + */ + if (ni->ni_flags & IEEE80211_NODE_HT) { + htrates |= 0x01; /* MCS0 */ + rates |= (1 << RTWN_RIDX_OFDM6); + } + basicrates |= rates; + basicrates |= (htrates << RTWN_RIDX_HT_MCS_SHIFT); + + /* Filter out undesired high rates */ + if (ni->ni_chan != IEEE80211_CHAN_ANYC && + IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) + basicrates &= R92C_RRSR_RATE_MASK_5GHZ; + else + basicrates &= R92C_RRSR_RATE_MASK_2GHZ; + ieee80211_free_node(ni); } + if (basicrates == 0) return; - /* XXX initial RTS rate? */ + /* XXX also set initial RTS rate? */ rtwn_set_basicrates(sc, basicrates); } |
