From: Ho Jie Feng <hjf3108@gmail.com>
To: Ping-Ke Shih <pkshih@realtek.com>
Cc: linux-wireless@vger.kernel.org, Ho Jie Feng <hjf3108@gmail.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH 5/6] wifi: rtw88: 88xxa: adapt channel sensing to receiver gain
Date: Thu, 29 Oct 2026 13:52:07 +0800 [thread overview]
Message-ID: <20261029055212.84711-6-hjf3108@gmail.com> (raw)
In-Reply-To: <20261029055212.84711-1-hjf3108@gmail.com>
Implement adaptivity for 88xxa, since they support it in
the hardware.
Signed-off-by: Ho Jie Feng <hjf3108@gmail.com>
---
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
--
2.55.0
next prev parent reply other threads:[~2026-10-29 5:52 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20261029055212.84711-1-hjf3108@gmail.com>
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 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 ` Ho Jie Feng [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=20261029055212.84711-6-hjf3108@gmail.com \
--to=hjf3108@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=pkshih@realtek.com \
/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
all inboxes | Powered by JetHome®