Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH rtw-next v3] wifi: rtw89: set RA init rate level when the station RSSI is known
@ 2026-11-13  8:07 Vincent Schurink
  2026-11-13  8:24 ` Ping-Ke Shih
  0 siblings, 1 reply; 2+ messages in thread
From: Vincent Schurink @ 2026-11-13  8:07 UTC (permalink / raw)
  To: Ping-Ke Shih; +Cc: linux-wireless, Vincent Schurink

When a station associates to an AP, the AP does not know the RSSI of
the station yet. Thus, rtw89_phy_ra_assoc() sends init_rate_lv 0 to the
firmware. With this value, the firmware RA of RTL8922A often uses 20 MHz
and VHT-MCS 2 for the station. It does not try a higher rate, also when
the PER is 0. On an 80 MHz AP, the TCP throughput to the station
then stays at approximately 36 Mbit/s for the full connection.

Move the mapping from RSSI to init_rate_lv to a function. Use it in the
RA association and in the RA update. The firmware uses init_rate_lv only
together with upd_all, and upd_all resets the RA context. Thus, set a
flag when the RSSI is not known at the RA association. The RA update
then sets upd_all one time, when the RSSI is known.

Tested on RTL8912AU (RTL8922A, USB) in AP mode with hostapd 2.10 and
VHT 80 MHz. The client is an Intel Meteor Lake CNVi (iwlwifi) at 50 cm,
-38 dBm. Each test reconnects the client, then sends TCP from the AP for
60 s.
Before: 6 of 8 connections stay at VHT-MCS 2 and 20 MHz, 36 Mbit/s.
After: 8 of 8 connections use VHT-MCS 7 to 9 at 80 MHz, 614 to
669 Mbit/s.

Signed-off-by: Vincent Schurink <spam@acio.nl>
---
v3:
- Set upd_all only one time per association, with a flag that the RA
  association sets when the RSSI is not known, as suggested by Ping-Ke.
  v2 set upd_all whenever the level changed from 0 to a known level.
- Remove prev_lv (reverse X'mas tree comment).
- Test with the client at 50 cm (-38 dBm) for 60 s per connection:
  without the fix, 6 of 8 connections stay at VHT-MCS 2 and 20 MHz
  (36 Mbit/s), and 2 of 8 go to VHT-MCS 9 at 80 MHz. A stronger signal
  does not prevent the problem. The RSSI rate mask does not remove 2SS
  MCS 0-2, and it does not limit the bandwidth.

v2: https://lore.kernel.org/linux-wireless/20261112075622.32785-1-spam@acio.nl/
v1: https://lore.kernel.org/linux-wireless/20261108131723.206533-1-spam@acio.nl/

 drivers/net/wireless/realtek/rtw89/core.h |  1 +
 drivers/net/wireless/realtek/rtw89/phy.c  | 30 ++++++++++++++++-------
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 0d893b992a4..ca5f2aced33 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4711,6 +4711,7 @@ struct rtw89_sta_link {
 	struct rtw89_vif_link *rtwvif_link;
 	struct rtw89_ra_info ra;
 	struct rtw89_ra_report ra_report;
+	bool ra_rssi_unknown;
 	int max_agg_wait;
 	u8 prev_rssi;
 	struct ewma_rssi avg_rssi;
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 795920b899d..def01000a59 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -502,6 +502,20 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
 	ra->csi_mode = csi_mode;
 }
 
+static u8 rtw89_phy_ra_get_init_rate_lv(struct rtw89_sta_link *rtwsta_link)
+{
+	u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
+
+	if (rssi > 40)
+		return 1;
+	if (rssi > 20)
+		return 2;
+	if (rssi > 1)
+		return 3;
+
+	return 0;
+}
+
 void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
 				  struct rtw89_sta_link *rtwsta_link,
 				  u32 changed)
@@ -519,6 +533,11 @@ void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
 
 	rcu_read_unlock();
 
+	ra->init_rate_lv = rtw89_phy_ra_get_init_rate_lv(rtwsta_link);
+	if (rtwsta_link->ra_rssi_unknown && ra->init_rate_lv) {
+		rtwsta_link->ra_rssi_unknown = false;
+		ra->upd_all = 1;
+	}
 	if (changed & IEEE80211_RC_SUPP_RATES_CHANGED)
 		ra->upd_mask = 1;
 	if (changed & (IEEE80211_RC_BW_CHANGED | IEEE80211_RC_NSS_CHANGED))
@@ -733,7 +752,6 @@ void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_
 	struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
 	struct rtw89_ra_info *ra = &rtwsta_link->ra;
-	u8 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
 	struct ieee80211_link_sta *link_sta;
 	bool csi;
 
@@ -747,14 +765,8 @@ void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_
 
 	rcu_read_unlock();
 
-	if (rssi > 40)
-		ra->init_rate_lv = 1;
-	else if (rssi > 20)
-		ra->init_rate_lv = 2;
-	else if (rssi > 1)
-		ra->init_rate_lv = 3;
-	else
-		ra->init_rate_lv = 0;
+	ra->init_rate_lv = rtw89_phy_ra_get_init_rate_lv(rtwsta_link);
+	rtwsta_link->ra_rssi_unknown = !ra->init_rate_lv;
 	ra->upd_all = 1;
 	rtw89_debug(rtwdev, RTW89_DBG_RA,
 		    "ra assoc: macid = %d, mode = %d, bw = %d, nss = %d, lv = %d",
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-13  8:24 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13  8:07 [PATCH rtw-next v3] wifi: rtw89: set RA init rate level when the station RSSI is known Vincent Schurink
2026-11-13  8:24 ` Ping-Ke Shih

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox