From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
To: linux-wireless@vger.kernel.org
Subject: Re: [PATCH 5/6] wifi: rtw88: 88xxa: adapt channel sensing to receiver gain
Date: Fri, 30 Oct 2026 16:57:58 +0200 [thread overview]
Message-ID: <15240b8b-31f0-4587-a7a6-28cd4d36775b@gmail.com> (raw)
In-Reply-To: <20261029055212.84711-6-hjf3108@gmail.com>
On 29/10/2026 07:52, Ho Jie Feng wrote:
> Implement adaptivity for 88xxa, since they support it in
> the hardware.
>
> Signed-off-by: Ho Jie Feng <hjf3108@gmail.com>
This patch makes scans while connected to a network much slower:
[2026-10-30 16:28:31.822427]: wlp3s0f3u2 (phy #5): scan started
[2026-10-30 16:29:00.622378]: wlp3s0f3u2 (phy #5): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452
2457 2462 2467 2472 5180 5200 5220 5240 5260
5280 5300 5320 5500 5520 5540 5560 5580 5600
5620 5640 5660 5680 5700 5720 5745 5765 5785
5805 5825, ""
During the scans I see a lot of "timed out to flush queue 1" (and 3)
in dmesg. You need debug_mask=0x80000000 to see these.
Pinging the router during the scan:
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=157 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=194 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=107 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=139 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=154 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=186 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=12639 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=11612 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=10588 ms
64 bytes from 192.168.1.1: icmp_seq=12 ttl=64 time=7822 ms
64 bytes from 192.168.1.1: icmp_seq=14 ttl=64 time=21134 ms
64 bytes from 192.168.1.1: icmp_seq=15 ttl=64 time=20110 ms
64 bytes from 192.168.1.1: icmp_seq=16 ttl=64 time=19086 ms
64 bytes from 192.168.1.1: icmp_seq=17 ttl=64 time=18062 ms
64 bytes from 192.168.1.1: icmp_seq=18 ttl=64 time=17038 ms
64 bytes from 192.168.1.1: icmp_seq=19 ttl=64 time=16014 ms
64 bytes from 192.168.1.1: icmp_seq=20 ttl=64 time=15014 ms
64 bytes from 192.168.1.1: icmp_seq=21 ttl=64 time=13967 ms
64 bytes from 192.168.1.1: icmp_seq=22 ttl=64 time=12942 ms
64 bytes from 192.168.1.1: icmp_seq=23 ttl=64 time=11918 ms
64 bytes from 192.168.1.1: icmp_seq=24 ttl=64 time=10895 ms
64 bytes from 192.168.1.1: icmp_seq=25 ttl=64 time=9871 ms
64 bytes from 192.168.1.1: icmp_seq=26 ttl=64 time=8847 ms
64 bytes from 192.168.1.1: icmp_seq=27 ttl=64 time=7823 ms
64 bytes from 192.168.1.1: icmp_seq=35 ttl=64 time=1.61 ms
64 bytes from 192.168.1.1: icmp_seq=36 ttl=64 time=2.10 ms
64 bytes from 192.168.1.1: icmp_seq=37 ttl=64 time=1.87 ms
^C
--- 192.168.1.1 ping statistics ---
37 packets transmitted, 27 received, 27.027% packet loss, time 36658ms
rtt min/avg/max/mdev = 1.611/9123.175/21133.788/7187.269 ms, pipe 21
Without this patch:
[2026-10-30 16:34:18.354110]: wlp3s0f3u2 (phy #7): scan started
[2026-10-30 16:34:31.141463]: wlp3s0f3u2 (phy #7): scan finished: 2412 2417 2422 2427 2432 2437 2442 2447 2452
2457 2462 2467 2472 5180 5200 5220 5240 5260
5280 5300 5320 5500 5520 5540 5560 5580 5600
5620 5640 5660 5680 5700 5720 5745 5765 5785
5805 5825, ""
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=317 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=134 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=157 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=4.41 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=202 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=122 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=145 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=168 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=190 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=106 ms
64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=36.8 ms
64 bytes from 192.168.1.1: icmp_seq=12 ttl=64 time=2.45 ms
64 bytes from 192.168.1.1: icmp_seq=13 ttl=64 time=3.84 ms
64 bytes from 192.168.1.1: icmp_seq=14 ttl=64 time=1.78 ms
64 bytes from 192.168.1.1: icmp_seq=15 ttl=64 time=6.42 ms
64 bytes from 192.168.1.1: icmp_seq=16 ttl=64 time=148 ms
64 bytes from 192.168.1.1: icmp_seq=17 ttl=64 time=2.10 ms
64 bytes from 192.168.1.1: icmp_seq=18 ttl=64 time=27.8 ms
64 bytes from 192.168.1.1: icmp_seq=19 ttl=64 time=103 ms
64 bytes from 192.168.1.1: icmp_seq=20 ttl=64 time=2.71 ms
64 bytes from 192.168.1.1: icmp_seq=21 ttl=64 time=30.9 ms
64 bytes from 192.168.1.1: icmp_seq=22 ttl=64 time=1.52 ms
64 bytes from 192.168.1.1: icmp_seq=23 ttl=64 time=2.06 ms
64 bytes from 192.168.1.1: icmp_seq=24 ttl=64 time=5.16 ms
64 bytes from 192.168.1.1: icmp_seq=25 ttl=64 time=138 ms
64 bytes from 192.168.1.1: icmp_seq=26 ttl=64 time=162 ms
64 bytes from 192.168.1.1: icmp_seq=27 ttl=64 time=79.3 ms
64 bytes from 192.168.1.1: icmp_seq=28 ttl=64 time=204 ms
^C
--- 192.168.1.1 ping statistics ---
28 packets transmitted, 28 received, 0% packet loss, time 27043ms
rtt min/avg/max/mdev = 1.516/89.407/316.521/84.581 ms
(100-300 ms is normal for RTL8812A when power saving is enabled.)
My network is on channel 13, with 40 MHz width, WPA2-PSK.
> ---
> drivers/net/wireless/realtek/rtw88/main.h | 1 +
> drivers/net/wireless/realtek/rtw88/rtw8812a.c | 10 ++
> drivers/net/wireless/realtek/rtw88/rtw8821a.c | 10 ++
> drivers/net/wireless/realtek/rtw88/rtw88xxa.c | 123 ++++++++++++++++++
> drivers/net/wireless/realtek/rtw88/rtw88xxa.h | 5 +
> 5 files changed, 149 insertions(+)
>
> diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
> index d59f6e323adf0..796fea308fdf7 100644
> --- a/drivers/net/wireless/realtek/rtw88/main.h
> +++ b/drivers/net/wireless/realtek/rtw88/main.h
> @@ -1787,6 +1787,7 @@ struct rtw_dm_info {
> bool is_bt_iqk_timeout;
>
> s8 l2h_th_ini;
> + s8 l2h_th_lb;
> enum rtw_edcca_mode edcca_mode;
> u8 scan_density;
> };
> diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
> index c8008cf43da9d..d93c4776e0303 100644
> --- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c
> +++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
> @@ -945,6 +945,8 @@ static const struct rtw_chip_ops rtw8812a_ops = {
> .coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain,
> .cfo_init = rtw_phy_cfo_xcap_init,
> .cfo_track = rtw88xxa_cfo_track,
> + .adaptivity_init = rtw88xxa_adaptivity_init,
> + .adaptivity = rtw88xxa_adaptivity,
> };
>
> static const struct rtw_page_table page_table_8812a[] = {
> @@ -999,6 +1001,11 @@ static const struct rtw_hw_reg rtw8812a_dig[] = {
> [1] = { .addr = REG_RXIGI_B, .mask = 0x7f },
> };
>
> +static const struct rtw_hw_reg_offset rtw8812a_edcca_th[] = {
> + [EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0},
> + [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
> +};
> +
> static const struct rtw_rfe_def rtw8812a_rfe_defs[] = {
> [0] = { .phy_pg_tbl = &rtw8812a_bb_pg_tbl,
> .txpwr_lmt_tbl = &rtw8812a_txpwr_lmt_tbl,
> @@ -1089,6 +1096,9 @@ const struct rtw_chip_info rtw8812a_hw_spec = {
> .bfer_su_max_num = 2,
> .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
> .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
> + .edcca_th = rtw8812a_edcca_th,
> + .l2h_th_ini_cs = 10,
> + .l2h_th_ini_ad = -17,
>
> .coex_para_ver = 0, /* no coex code in 8812au driver */
> .bt_desired_ver = 0,
> diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
> index 17d3677ca463c..f7391f6aa3039 100644
> --- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c
> +++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
> @@ -891,6 +891,8 @@ static const struct rtw_chip_ops rtw8821a_ops = {
> .coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain,
> .cfo_init = rtw_phy_cfo_xcap_init,
> .cfo_track = rtw88xxa_cfo_track,
> + .adaptivity_init = rtw88xxa_adaptivity_init,
> + .adaptivity = rtw88xxa_adaptivity,
> };
>
> static const struct rtw_page_table page_table_8821a[] = {
> @@ -944,6 +946,11 @@ static const struct rtw_hw_reg rtw8821a_dig[] = {
> [0] = { .addr = REG_RXIGI_A, .mask = 0x7f },
> };
>
> +static const struct rtw_hw_reg_offset rtw8821a_edcca_th[] = {
> + [EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0},
> + [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
> +};
> +
> static const struct rtw_rfe_def rtw8821a_rfe_defs[] = {
> [0] = { .phy_pg_tbl = &rtw8821a_bb_pg_tbl,
> .txpwr_lmt_tbl = &rtw8821a_txpwr_lmt_tbl,
> @@ -1193,6 +1200,9 @@ const struct rtw_chip_info rtw8821a_hw_spec = {
> .bfer_su_max_num = 2,
> .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
> .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
> + .edcca_th = rtw8821a_edcca_th,
> + .l2h_th_ini_cs = 10,
> + .l2h_th_ini_ad = -17,
>
> .coex_para_ver = 20190509, /* glcoex_ver_date_8821a_1ant */
> .bt_desired_ver = 0x62, /* But for 2 ant it's 0x5c */
> diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
> index 586bb57a10061..aff62d61f4719 100644
> --- a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
> +++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
> @@ -2040,6 +2040,129 @@ void rtw88xxa_cfo_track(struct rtw_dev *rtwdev)
> }
> EXPORT_SYMBOL(rtw88xxa_cfo_track);
>
> +#define EDCCA_TH_MAX_88XXA 0x7f
> +#define EDCCA_L2H_CAP_88XXA 10
> +#define EDCCA_L2H_INI_NORMAL_88XXA 20
> +#define EDCCA_DBG_PORT_88XXA 0x209
> +#define EDCCA_DC_BACKOFF_88XXA 2
> +#define EDCCA_LB_START_88XXA (EDCCA_L2H_H2L_DIFF - 30)
> +#define EDCCA_LB_RETRY_88XXA (EDCCA_LB_START_88XXA + 18)
> +
> +static void rtw88xxa_set_rf_mode_rx(struct rtw_dev *rtwdev, u32 data0,
> + u32 data1)
> +{
> + u8 path;
> +
> + for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) {
> + rtw_write_rf(rtwdev, path, RF_LUTWE, BIT(19), 1);
> + rtw_write_rf(rtwdev, path, RF_MODE_TABLE_ADDR, RFREG_MASK,
> + 0x18000);
> + rtw_write_rf(rtwdev, path, RF_MODE_TABLE_DATA0, RFREG_MASK,
> + data0);
> + rtw_write_rf(rtwdev, path, RF_MODE_TABLE_DATA1, RFREG_MASK,
> + data1);
> + rtw_write_rf(rtwdev, path, RF_LUTWE, BIT(19), 0);
> + }
> +}
> +
> +static void rtw88xxa_set_lna(struct rtw_dev *rtwdev, bool enable)
> +{
> + if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
> + rtw88xxa_set_rf_mode_rx(rtwdev, 0x3f7ff,
> + enable ? 0xc26bf : 0xc22bf);
> + else
> + rtw88xxa_set_rf_mode_rx(rtwdev, 0x0002f,
> + enable ? 0xfb0bb : 0xfb09b);
> +}
> +
> +static u8 rtw88xxa_edcca_count(struct rtw_dev *rtwdev)
> +{
> + u8 cnt = 0;
> + int i;
> +
> + rtw_write32(rtwdev, REG_DBGSEL, 0);
> + for (i = 0; i < 3 &&
> + rtw_read32(rtwdev, REG_DBGRPT) & BIT_DBG_CCA_BUSY; i++)
> + usleep_range(3000, 3500);
> +
> + rtw_write32(rtwdev, REG_DBGSEL, EDCCA_DBG_PORT_88XXA);
> + for (i = 0; i < 20; i++)
> + if (rtw_read32(rtwdev, REG_DBGRPT) & BIT_DBG_EDCCA_BUSY)
> + cnt++;
> +
> + return cnt;
> +}
> +
> +static s8 rtw88xxa_edcca_search_floor(struct rtw_dev *rtwdev)
> +{
> + s8 l2h = EDCCA_LB_START_88XXA;
> +
> + rtw_phy_set_edcca_th(rtwdev, l2h, l2h - EDCCA_L2H_H2L_DIFF);
> + msleep(30);
> +
> + while (l2h < EDCCA_L2H_CAP_88XXA && rtw88xxa_edcca_count(rtwdev) > 1) {
> + l2h++;
> + rtw_phy_set_edcca_th(rtwdev, l2h, l2h - EDCCA_L2H_H2L_DIFF);
> + }
> +
> + return l2h;
> +}
> +
> +void rtw88xxa_adaptivity_init(struct rtw_dev *rtwdev)
> +{
> + struct rtw_dm_info *dm_info = &rtwdev->dm_info;
> + u32 dbgsel = rtw_read32(rtwdev, REG_DBGSEL);
> + s8 l2h;
> +
> + rtw_write32_clr(rtwdev, REG_TX_PTCL_CTRL, BIT_DIS_EDCCA);
> +
> + rtw88xxa_set_lna(rtwdev, false);
> + l2h = rtw88xxa_edcca_search_floor(rtwdev);
> + if (l2h >= EDCCA_LB_RETRY_88XXA)
> + l2h = rtw88xxa_edcca_search_floor(rtwdev);
> + rtw88xxa_set_lna(rtwdev, true);
> + rtw_write32(rtwdev, REG_DBGSEL, dbgsel);
> +
> + dm_info->l2h_th_lb = l2h + EDCCA_DC_BACKOFF_88XXA;
> + rtw_phy_set_edcca_th(rtwdev, EDCCA_TH_MAX_88XXA, EDCCA_TH_MAX_88XXA);
> +
> + rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, "EDCCA L2H floor %d\n",
> + dm_info->l2h_th_lb);
> +}
> +EXPORT_SYMBOL(rtw88xxa_adaptivity_init);
> +
> +void rtw88xxa_adaptivity(struct rtw_dev *rtwdev)
> +{
> + struct rtw_dm_info *dm_info = &rtwdev->dm_info;
> + int igi_diff = EDCCA_IGI_BASE - dm_info->igi_history[0];
> + s8 l2h_lb = dm_info->l2h_th_lb;
> + s8 l2h, h2l;
> +
> + /* toggle the ADC mask to work around an EDCCA hang */
> + if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A) {
> + rtw_write32_set(rtwdev, REG_FPGA0_RFMOD, BIT(10));
> + rtw_write32_clr(rtwdev, REG_FPGA0_RFMOD, BIT(10));
> + }
> +
> + if (dm_info->edcca_mode == RTW_EDCCA_ADAPTIVITY) {
> + l2h = min(dm_info->l2h_th_ini + igi_diff, EDCCA_L2H_CAP_88XXA);
> + h2l = l2h - EDCCA_L2H_H2L_DIFF;
> + } else {
> + l2h = EDCCA_L2H_INI_NORMAL_88XXA + igi_diff;
> + h2l = l2h - EDCCA_L2H_H2L_DIFF_NORMAL;
> + }
> +
> + l2h = max(l2h, l2h_lb);
> + h2l = max_t(s8, h2l, l2h_lb - EDCCA_L2H_H2L_DIFF);
> +
> + rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
> +
> + rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY,
> + "EDCCA mode %d, IGI 0x%x, L2H %d, H2L %d\n",
> + dm_info->edcca_mode, dm_info->igi_history[0], l2h, h2l);
> +}
> +EXPORT_SYMBOL(rtw88xxa_adaptivity);
> +
> MODULE_AUTHOR("Realtek Corporation");
> MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a/8812a common code");
> MODULE_LICENSE("Dual BSD/GPL");
> diff --git a/drivers/net/wireless/realtek/rtw88/rtw88xxa.h b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
> index 09b72d33f62e1..b8719c278df73 100644
> --- a/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
> +++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
> @@ -139,6 +139,9 @@ struct rtw_jaguar_phy_status_rpt {
>
> #define RF18_BW_MASK (BIT(11) | BIT(10))
>
> +#define BIT_DBG_CCA_BUSY BIT(3)
> +#define BIT_DBG_EDCCA_BUSY BIT(29)
> +
> void rtw88xxa_efuse_grant(struct rtw_dev *rtwdev, bool on);
> int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map);
> void rtw88xxa_power_off(struct rtw_dev *rtwdev,
> @@ -173,5 +176,7 @@ void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev,
> void rtw88xxa_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
> struct rtw_bfee *bfee, bool enable);
> void rtw88xxa_cfo_track(struct rtw_dev *rtwdev);
> +void rtw88xxa_adaptivity_init(struct rtw_dev *rtwdev);
> +void rtw88xxa_adaptivity(struct rtw_dev *rtwdev);
>
> #endif
next prev parent reply other threads:[~2026-10-30 14:58 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 5:52 [PATCH 0/6] wifi: rtw88: extend 88xxA support Ho Jie Feng
2026-10-29 5:52 ` [PATCH 1/6] wifi: rtw88: 8812a, 8814a: enable STBC for HT transmissions Ho Jie Feng
2026-10-29 5:52 ` [PATCH 2/6] wifi: rtw88: 88xxa: receive VHT SU beamformed transmissions Ho Jie Feng
2026-10-29 12:33 ` Bitterblue Smith
2026-10-29 14:13 ` Ho Jie Feng
2026-10-29 21:06 ` Bitterblue Smith
2026-10-29 5:52 ` [PATCH 3/6] wifi: rtw88: prepare frequency-offset correction for more chips Ho Jie Feng
2026-10-29 5:52 ` [PATCH 4/6] wifi: rtw88: 88xxa: correct carrier-frequency offset Ho Jie Feng
2026-10-29 5:52 ` [PATCH 5/6] wifi: rtw88: 88xxa: adapt channel sensing to receiver gain Ho Jie Feng
2026-10-30 14:57 ` Bitterblue Smith [this message]
2026-10-29 5:52 ` [PATCH 6/6] wifi: rtw88: 8812a, 8821a: respect peer A-MPDU size limits Ho Jie Feng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=15240b8b-31f0-4587-a7a6-28cd4d36775b@gmail.com \
--to=rtl8821cerfe2@gmail.com \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox