The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=f45f66fadacc2efff3c2ff64e3528b8dbaad3673
commit f45f66fadacc2efff3c2ff64e3528b8dbaad3673 Author: Adrian Chadd <adr...@freebsd.org> AuthorDate: 2024-12-19 02:11:28 +0000 Commit: Adrian Chadd <adr...@freebsd.org> CommitDate: 2025-01-14 04:33:44 +0000 rtwn: explicitly configure RTS based on basic rates The NIC/firmware initialises the initial RTS/CTS rate to something high, like OFDM48. That's not going to be very reliable. It's not a problem right now as we program in the RTS/CTS value to use in the TX descriptor setup path based on the control rate for the given frame TX rate, and like the INIDATA/driver rate stuff in the TX descriptor, the TX descriptor RTS/CTS rate overrides the INIRTS rate. However when it's time to flip on firmware based rate control, the initial rate needs to not be OFDM48. Yes, the firmware and hardware does have some rate retry schedule for RTS/CTS frames, but there's no point in wasting short retries trying to do OFDM48 based RTS/CTS setup. Add some warning logging if there are no basic or RTS/CTS rates available, and leave things at default. If this happens in production for someone then it would be good to know and what the rate mask was. Locally tested: * RTL8192CU, STA mode (with/without firmware rate control enabled locally) Differential Revision: https://reviews.freebsd.org/D48140 --- sys/dev/rtwn/if_rtwn.c | 8 +++++--- sys/dev/rtwn/if_rtwn_rx.c | 35 +++++++++++++++++++++++++++++++++++ sys/dev/rtwn/if_rtwn_rx.h | 1 + 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/sys/dev/rtwn/if_rtwn.c b/sys/dev/rtwn/if_rtwn.c index f9950c5acf4d..2003fa7d20be 100644 --- a/sys/dev/rtwn/if_rtwn.c +++ b/sys/dev/rtwn/if_rtwn.c @@ -1308,12 +1308,14 @@ rtwn_calc_basicrates(struct rtwn_softc *sc) ieee80211_free_node(ni); } - - if (basicrates == 0) + if (basicrates == 0) { + device_printf(sc->sc_dev, + "WARNING: no configured basic rates!\n"); return; + } - /* XXX also set initial RTS rate? */ rtwn_set_basicrates(sc, basicrates); + rtwn_set_rts_rate(sc, basicrates); } static int diff --git a/sys/dev/rtwn/if_rtwn_rx.c b/sys/dev/rtwn/if_rtwn_rx.c index e5ddc7a3cb97..9b7c93fee9b6 100644 --- a/sys/dev/rtwn/if_rtwn_rx.c +++ b/sys/dev/rtwn/if_rtwn_rx.c @@ -134,6 +134,41 @@ rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates) rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RATE_BITMAP_M, rates); } +/* + * Configure the initial RTS rate to use. + */ +void +rtwn_set_rts_rate(struct rtwn_softc *sc, uint32_t rates) +{ + uint8_t ridx; + + /* + * We shouldn't set the initial RTS/CTS generation rate + * as the highest available rate - that may end up + * with trying to configure something like MCS1 RTS/CTS. + * + * Instead, choose a suitable low OFDM/CCK rate based + * on the basic rate bitmask. Assume the caller + * has filtered out CCK modes in 5GHz. + */ + rates &= (1 << RTWN_RIDX_CCK1) | (1 << RTWN_RIDX_CCK55) | + (1 << RTWN_RIDX_CCK11) | (1 << RTWN_RIDX_OFDM6) | + (1 << RTWN_RIDX_OFDM9) | (1 << RTWN_RIDX_OFDM12) | + (1 << RTWN_RIDX_OFDM18) | (1 << RTWN_RIDX_OFDM24); + if (rates == 0) { + device_printf(sc->sc_dev, + "WARNING: no configured basic RTS rate!\n"); + return; + } + ridx = fls(rates) - 1; + + RTWN_DPRINTF(sc, RTWN_DEBUG_RA, + "%s: mask=0x%08x, ridx=%d\n", + __func__, rates, ridx); + + rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, ridx); +} + static void rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int8_t rssi, int is_cck) diff --git a/sys/dev/rtwn/if_rtwn_rx.h b/sys/dev/rtwn/if_rtwn_rx.h index 3108f1d4cde4..751173d0f80f 100644 --- a/sys/dev/rtwn/if_rtwn_rx.h +++ b/sys/dev/rtwn/if_rtwn_rx.h @@ -23,6 +23,7 @@ void rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *, const struct ieee80211_htrateset *, uint32_t *, uint32_t *, int *, int); void rtwn_set_basicrates(struct rtwn_softc *, uint32_t); +void rtwn_set_rts_rate(struct rtwn_softc *, uint32_t); struct ieee80211_node * rtwn_rx_common(struct rtwn_softc *, struct mbuf *, void *); void rtwn_adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,