* [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