linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
To: linux-wireless@vger.kernel.org
Subject: Re: [PATCH rtw-next v2 6/7] wifi: rtw88: 88xxa: adapt channel sensing to receiver gain
Date: Tue, 3 Nov 2026 19:41:32 +0200	[thread overview]
Message-ID: <08bfa108-3e8a-40fb-a901-99031b284236@gmail.com> (raw)
In-Reply-To: <20261031070950.425176-7-hjf3108@gmail.com>

On 31/10/2026 09:09, 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 version doesn't have the high latency during scans anymore.
However, the message "firmware failed to leave lps state" appears
a lot more often now. It stops if I disable EDCCA.

> ---
>  drivers/net/wireless/realtek/rtw88/main.h     |   1 +
>  drivers/net/wireless/realtek/rtw88/phy.c      |   7 +
>  drivers/net/wireless/realtek/rtw88/rtw8812a.c |  10 ++
>  drivers/net/wireless/realtek/rtw88/rtw8821a.c |  10 ++
>  drivers/net/wireless/realtek/rtw88/rtw88xxa.c | 125 ++++++++++++++++++
>  drivers/net/wireless/realtek/rtw88/rtw88xxa.h |   5 +
>  6 files changed, 158 insertions(+)
> 
> diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
> index d59f6e323adf0c9bf9aeab7a62adb77e3e5f9d74..796fea308fdf7bf2b46f42c703b1b518327e1e0a 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/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
> index 69998c0d7c1f851bb30d2702233d62e14b305bf0..7a04aec9a045f1e308a4c5d331c900e013996bd5 100644
> --- a/drivers/net/wireless/realtek/rtw88/phy.c
> +++ b/drivers/net/wireless/realtek/rtw88/phy.c
> @@ -377,6 +377,10 @@ void rtw_phy_dig_set_max_coverage(struct rtw_dev *rtwdev)
>  		DIG_CVRG_MIN);
>  
>  	rtw_phy_dig_write(rtwdev, DIG_CVRG_MIN);
> +
> +	/* EDCCA thresholds can be relative to the IGI */
> +	if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_ADAPTIVITY))
> +		rtw_phy_adaptivity(rtwdev);
>  }
>  
>  void rtw_phy_dig_reset(struct rtw_dev *rtwdev)
> @@ -388,6 +392,9 @@ void rtw_phy_dig_reset(struct rtw_dev *rtwdev)
>  	rtw_dbg(rtwdev, RTW_DBG_PHY, "Resetting IGI=%#x\n", last_igi);
>  
>  	rtw_phy_dig_write(rtwdev, last_igi);
> +
> +	if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_ADAPTIVITY))
> +		rtw_phy_adaptivity(rtwdev);
>  }
>  
>  static bool
> diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
> index c8008cf43da9df68a8c1dfb277d529a1191bda01..d93c4776e0303f52273d92eaa75341ebbcfcb066 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 17d3677ca463cf633d8c138612deaa676bc02986..f7391f6aa3039c7ba4d88249d968a5f1763ea866 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 851d198f76f3b10d5ba77c7e07e4be9d7fd54e4b..ee72380757721dab7dc409aabc24b2b825969465 100644
> --- a/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
> +++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
> @@ -2040,6 +2040,131 @@ 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;
> +	/* igi_history[0] keeps the pre-scan IGI while scanning */
> +	u8 igi = rtw_read32_mask(rtwdev, REG_RXIGI_A, 0x7f);
> +	int igi_diff = EDCCA_IGI_BASE - igi;
> +	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, igi, 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 09b72d33f62e1e99a2ac5af23ac1630dabb38ef9..b8719c278df7326842e09509fc52d12f226fd417 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


  reply	other threads:[~2026-11-03 17:41 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-31  7:09 [PATCH rtw-next v2 0/7] wifi: rtw88: extend 88xxA support Ho Jie Feng
2026-10-31  7:09 ` [PATCH rtw-next v2 1/7] wifi: rtw88: 8812a, 8814a: enable STBC for HT transmissions Ho Jie Feng
2026-11-06 17:21   ` Luka Gejak
2026-10-31  7:09 ` [PATCH rtw-next v2 2/7] wifi: rtw88: 88xxa: receive VHT SU beamformed transmissions Ho Jie Feng
2026-11-03 16:36   ` Bitterblue Smith
2026-11-06 17:23   ` Luka Gejak
2026-10-31  7:09 ` [PATCH rtw-next v2 3/7] wifi: rtw88: correctly expose beamformee capabilities Ho Jie Feng
2026-11-06 17:25   ` Luka Gejak
2026-10-31  7:09 ` [PATCH rtw-next v2 4/7] wifi: rtw88: prepare frequency-offset correction for more chips Ho Jie Feng
2026-10-31  7:09 ` [PATCH rtw-next v2 5/7] wifi: rtw88: 88xxa: correct carrier-frequency offset Ho Jie Feng
2026-11-06 17:27   ` Luka Gejak
2026-11-06 20:03     ` Bitterblue Smith
2026-11-09 13:39       ` Ho Jie Feng
2026-11-10  8:03         ` Luka Gejak
2026-10-31  7:09 ` [PATCH rtw-next v2 6/7] wifi: rtw88: 88xxa: adapt channel sensing to receiver gain Ho Jie Feng
2026-11-03 17:41   ` Bitterblue Smith [this message]
2026-11-04 12:47     ` Ho Jie Feng
2026-11-06 17:34   ` Luka Gejak
2026-11-06 19:46     ` Bitterblue Smith
2026-11-06 20:27       ` Luka Gejak
2026-11-10 14:36         ` Bitterblue Smith
2026-11-10 19:57           ` Luka Gejak
2026-10-31  7:09 ` [PATCH rtw-next v2 7/7] wifi: rtw88: 8812a, 8821a: respect peer A-MPDU size limits Ho Jie Feng
2026-11-06 17:35   ` Luka Gejak
2026-11-08 18:09     ` Jie Feng
2026-11-09  7:25       ` Luka Gejak
2026-11-06 17:44 ` [PATCH rtw-next v2 0/7] wifi: rtw88: extend 88xxA support Luka Gejak
2026-11-08 18:10   ` 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=08bfa108-3e8a-40fb-a901-99031b284236@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;
as well as URLs for NNTP newsgroup(s).