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 @@ -1308,12 +1308,14 @@ 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.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 @@ -23,6 +23,7 @@ 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, 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 @@ -134,6 +134,41 @@ 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)