Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH rtw-next v2] wifi: rtw89: set RA init rate level from RSSI in RA update
@ 2026-11-12  7:56 Vincent Schurink
  2026-11-13  1:20 ` Ping-Ke Shih
  0 siblings, 1 reply; 2+ messages in thread
From: Vincent Schurink @ 2026-11-12  7:56 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 uses 20 MHz and
VHT-MCS 2 for the station. The firmware RA does not try a higher rate,
also when the PER is 0. On an 80 MHz AP, the TCP throughput to the
station stays at approximately 35 Mbit/s.

Move the mapping from RSSI to init_rate_lv to a function, and use it in
the RA association and in the RA update. The firmware uses
init_rate_lv only together with upd_all. Thus, the RA update also sets
upd_all one time, when the level changes from 0 to a known level.

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
-48 dBm. Each test reconnects the client, then sends TCP from the AP
for 3 x 20 s.
Before: TX rate VHT-MCS 2 at 20 MHz, TCP 34 Mbit/s.
With init_rate_lv in the RA update but without upd_all: no change,
TCP 34 Mbit/s.
After: TX rate VHT-MCS 5 to 9 at 80 MHz, TCP 323 to 380 Mbit/s.

Signed-off-by: Vincent Schurink <spam@acio.nl>
---
v2:
- Add rtw89_phy_ra_get_init_rate_lv() and use it in the RA association
  and in the RA update, as suggested by Ping-Ke. Remove the
  ra_rssi_unknown flag and the second rtw89_phy_ra_assoc() call.
- Set upd_all when the level changes from 0 to a known level. The test
  shows that init_rate_lv in the RA update without upd_all has no
  effect: the rate stays at VHT-MCS 2, 20 MHz.
- For AX chips, an RA update with upd_all has no CSI fields, because
  the RA update calls rtw89_fw_h2c_ra() with csi false. I could not
  test AX chips.

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

 drivers/net/wireless/realtek/rtw89/phy.c | 28 ++++++++++++++++--------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 795920b899d..b6057465c87 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)
@@ -509,6 +523,7 @@ void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
 	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 prev_lv = ra->init_rate_lv;
 	struct ieee80211_link_sta *link_sta;
 
 	rcu_read_lock();
@@ -519,6 +534,9 @@ 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 (!prev_lv && ra->init_rate_lv)
+		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 +751,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 +764,7 @@ 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);
 	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

* RE: [PATCH rtw-next v2] wifi: rtw89: set RA init rate level from RSSI in RA update
  2026-11-12  7:56 [PATCH rtw-next v2] wifi: rtw89: set RA init rate level from RSSI in RA update Vincent Schurink
@ 2026-11-13  1:20 ` Ping-Ke Shih
  0 siblings, 0 replies; 2+ messages in thread
From: Ping-Ke Shih @ 2026-11-13  1:20 UTC (permalink / raw)
  To: Vincent Schurink; +Cc: linux-wireless@vger.kernel.org

Vincent Schurink <spam@acio.nl> wrote:
> 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 uses 20 MHz and
> VHT-MCS 2 for the station. The firmware RA does not try a higher rate,
> also when the PER is 0. On an 80 MHz AP, the TCP throughput to the
> station stays at approximately 35 Mbit/s.

As rtw89_phy_ra_sta_update() does below periodically to update rate mask.

    ra_mask &= rtw89_phy_ra_mask_rssi(rtwdev, rssi, 0);

Could you try moving AP and station closer to see if this can improve?
(Please run over 1 minute to have enough time for the RA algorithm.)

> 
> Move the mapping from RSSI to init_rate_lv to a function, and use it in
> the RA association and in the RA update. The firmware uses
> init_rate_lv only together with upd_all. Thus, the RA update also sets
> upd_all one time, when the level changes from 0 to a known level.

The upd_all will reset RA context, so only do this once if RSSI is unknown
during association like your v1.

[...]

> @@ -509,6 +523,7 @@ void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
>         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 prev_lv = ra->init_rate_lv;
>         struct ieee80211_link_sta *link_sta;

reverse X'mas tree order.

> 
>         rcu_read_lock();
> @@ -519,6 +534,9 @@ 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 (!prev_lv && ra->init_rate_lv)
> +               ra->upd_all = 1;

As I mentioned above.

>         if (changed & IEEE80211_RC_SUPP_RATES_CHANGED)
>                 ra->upd_mask = 1;
>         if (changed & (IEEE80211_RC_BW_CHANGED | IEEE80211_RC_NSS_CHANGED))



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

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

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12  7:56 [PATCH rtw-next v2] wifi: rtw89: set RA init rate level from RSSI in RA update Vincent Schurink
2026-11-13  1:20 ` 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