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,

Reply via email to