From: Ping-Ke Shih <pkshih@realtek.com>
To: <linux-wireless@vger.kernel.org>
Cc: <leo.li@realtek.com>, <gary.chang@realtek.com>,
<echuang@realtek.com>, <wenjie.tsai@realtek.com>,
<phhuang@realtek.com>, <isaiah@realtek.com>,
<kevin_yang@realtek.com>, <mh_chen@realtek.com>
Subject: [PATCH rtw-next 16/16] wifi: rtw89: 8922d: update RF calibration flow for MLD
Date: Mon, 20 Apr 2026 11:40:51 +0800 [thread overview]
Message-ID: <20260420034051.17666-17-pkshih@realtek.com> (raw)
In-Reply-To: <20260420034051.17666-1-pkshih@realtek.com>
From: Zong-Zhe Yang <kevin_yang@realtek.com>
RF calibration (RFK) will record the results in HW RFK tables. SW can
select and configure the target HW RFK table to reuse the RFK result
on the target channel. Though the above can work as before, when MLD
runs eMLSR mode, a faster switching between links than SW is needed.
So, introduce a new working flow for MLD. With the new settings, HW
can easily switch RFK results between links during eMLSR mode.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/reg.h | 4 ++
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 7 ++
.../net/wireless/realtek/rtw89/rtw8922d_rfk.c | 70 +++++++++++++++----
.../net/wireless/realtek/rtw89/rtw8922d_rfk.h | 1 +
4 files changed, 69 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 42ffe83931a3..b8b2aabedc8f 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -8462,6 +8462,8 @@
#define RR_MODOPT_V1 0x10001
#define RR_SW_SEL BIT(19)
#define RR_TXG_SEL GENMASK(19, 17)
+#define RR_TBL_SEL_IDX1 GENMASK(9, 8)
+#define RR_TBL_SEL_IDX0 GENMASK(7, 6)
#define RR_MODOPT_M_TXPWR GENMASK(5, 0)
#define RR_WLSEL 0x02
#define RR_WLSEL_AG GENMASK(18, 16)
@@ -10687,6 +10689,8 @@
#define R_KTBL0B_BE4 0x38204
#define B_KTBL0_IDX0 GENMASK(1, 0)
#define B_KTBL0_IDX1 GENMASK(9, 8)
+#define B_KTBL0_MLD_IDX0 GENMASK(25, 24)
+#define B_KTBL0_MLD_IDX1 GENMASK(27, 26)
#define B_KTBL0_RST BIT(31)
#define R_KTBL1A_BE4 0x38154
#define R_KTBL1B_BE4 0x38254
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index f0c9d8661e57..47e0e360ed6e 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2332,12 +2332,16 @@ static void rtw8922d_rfk_tssi(struct rtw89_dev *rtwdev,
static void rtw8922d_rfk_channel(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link)
{
+ struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif_link->rtwvif);
enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx);
enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB, chanctx_idx);
u32 tx_en;
+ if (ieee80211_vif_is_mld(vif))
+ rtw8922d_chlk_ktbl_ctl_mld(rtwdev, phy_idx, true);
+
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_CHLK, BTC_WRFK_START);
rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL);
_wait_rx_mode(rtwdev, RF_AB);
@@ -2353,6 +2357,9 @@ static void rtw8922d_rfk_channel(struct rtw89_dev *rtwdev,
rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en);
rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_CHLK, BTC_WRFK_STOP);
+
+ if (ieee80211_vif_is_mld(vif))
+ rtw8922d_chlk_ktbl_ctl_mld(rtwdev, phy_idx, false);
}
static void rtw8922d_rfk_band_changed(struct rtw89_dev *rtwdev,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c
index 7957f7b2d8e5..a465e6631a22 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c
@@ -105,26 +105,60 @@ static void rtw8922d_set_syn01(struct rtw89_dev *rtwdev, enum _rf_syn_pow syn)
}
}
-static void rtw8922d_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx)
+void rtw8922d_chlk_ktbl_ctl_mld(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool manual)
{
- bool mlo_linking = false;
+ if (manual) {
+ struct rtw89_rfk_mcc_info_data *rfk_mcc = rtwdev->rfk_mcc.data;
+ u8 path = phy_idx; /* numerical equal for target */
+ u8 idx = rfk_mcc[path].table_idx;
- if (idx > 2) {
- rtw89_warn(rtwdev, "[DBCC][ERROR]indx is out of limit!! index(%d)", idx);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0A_BE4, B_KTBL0_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0B_BE4, B_KTBL0_RST, 0x1);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0A_BE4, B_KTBL0_IDX0, idx);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0A_BE4, B_KTBL0_IDX1, idx);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0B_BE4, B_KTBL0_IDX0, idx);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0B_BE4, B_KTBL0_IDX1, idx);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL1A_BE4, B_KTBL1_TBL0, idx & BIT(0));
+ rtw89_phy_write32_mask(rtwdev, R_KTBL1A_BE4, B_KTBL1_TBL1, (idx & BIT(1)) >> 1);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL1B_BE4, B_KTBL1_TBL0, idx & BIT(0));
+ rtw89_phy_write32_mask(rtwdev, R_KTBL1B_BE4, B_KTBL1_TBL1, (idx & BIT(1)) >> 1);
return;
}
- if (mlo_linking) {
- if (kpath & RF_A) {
- rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT, RR_SW_SEL, 0x0);
- rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT_V1, RR_SW_SEL, 0x0);
- }
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0A_BE4, B_KTBL0_RST, 0x0);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0B_BE4, B_KTBL0_RST, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT, RR_SW_SEL, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT_V1, RR_SW_SEL, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT, RR_SW_SEL, 0x0);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT_V1, RR_SW_SEL, 0x0);
+}
- if (kpath & RF_B) {
- rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT, RR_SW_SEL, 0x0);
- rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT_V1, RR_SW_SEL, 0x0);
- }
+static void rtw8922d_chlk_ktbl_sel_mld(struct rtw89_dev *rtwdev,
+ enum rtw89_phy_idx phy_idx, u8 idx)
+{
+ if (phy_idx == RTW89_PHY_0) {
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0A_BE4, B_KTBL0_MLD_IDX0, idx);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0B_BE4, B_KTBL0_MLD_IDX0, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT, RR_TBL_SEL_IDX0, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT_V1, RR_TBL_SEL_IDX0, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT, RR_TBL_SEL_IDX0, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT_V1, RR_TBL_SEL_IDX0, idx);
+ } else if (phy_idx == RTW89_PHY_1) {
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0A_BE4, B_KTBL0_MLD_IDX1, idx);
+ rtw89_phy_write32_mask(rtwdev, R_KTBL0B_BE4, B_KTBL0_MLD_IDX1, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT, RR_TBL_SEL_IDX1, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT_V1, RR_TBL_SEL_IDX1, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT, RR_TBL_SEL_IDX1, idx);
+ rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT_V1, RR_TBL_SEL_IDX1, idx);
+ }
+
+ rtw8922d_chlk_ktbl_ctl_mld(rtwdev, phy_idx, false);
+}
+static void rtw8922d_chlk_ktbl_sel(struct rtw89_dev *rtwdev, u8 kpath, u8 idx)
+{
+ if (idx > 2) {
+ rtw89_warn(rtwdev, "[DBCC][ERROR]indx is out of limit!! index(%d)", idx);
return;
}
@@ -195,8 +229,18 @@ static void rtw8922d_chlk_reload(struct rtw89_dev *rtwdev)
s0_tbl = rtw8922d_chlk_reload_sel_tbl(rtwdev, conf.chans[0], 0);
s1_tbl = rtw8922d_chlk_reload_sel_tbl(rtwdev, conf.chans[1], 1);
+ if (conf.is_mld)
+ goto mld;
+
rtw8922d_chlk_ktbl_sel(rtwdev, RF_A, s0_tbl);
rtw8922d_chlk_ktbl_sel(rtwdev, RF_B, s1_tbl);
+ return;
+
+mld:
+ if (test_bit(RTW89_PHY_0, conf.hw_bitmap))
+ rtw8922d_chlk_ktbl_sel_mld(rtwdev, RTW89_PHY_0, s0_tbl);
+ if (test_bit(RTW89_PHY_1, conf.hw_bitmap))
+ rtw8922d_chlk_ktbl_sel_mld(rtwdev, RTW89_PHY_1, s1_tbl);
}
static enum _rf_syn_pow rtw8922d_get_syn_pow(struct rtw89_dev *rtwdev)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h
index c5bbe0eb972a..11742b4a8f59 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h
@@ -18,5 +18,6 @@ void rtw8922d_rfk_mlo_ctrl(struct rtw89_dev *rtwdev);
void rtw8922d_pre_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw8922d_post_set_channel_rf(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
void rtw8922d_lck_track(struct rtw89_dev *rtwdev);
+void rtw8922d_chlk_ktbl_ctl_mld(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool manual);
#endif
--
2.25.1
prev parent reply other threads:[~2026-04-20 3:42 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-20 3:40 [PATCH rtw-next 00/16] wifi: rtw89: add USB IO offload and some refactors Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 01/16] wifi: rtw89: 8922d: fix typo rx_freq_frome_ie Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 02/16] wifi: rtw89: 8852a: refine power save to lower latency Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 03/16] wifi: rtw89: debug: disable hw_scan for latency-sensitive scenarios Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 04/16] wifi: rtw89: debug: disable inactive power save to reduce bus overhead Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 05/16] wifi: rtw89: phy: support static PD level setting Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 06/16] wifi: rtw89: Correct data type for scan index to avoid infinite loop Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 07/16] wifi: rtw89: 8852bt: configure support_noise field explicitly Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 08/16] wifi: rtw89: add IO offload support via firmware Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 09/16] wifi: rtw89: offload DMAC and CMAC init IO to firmware Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 10/16] wifi: rtw89: use firmware offload for PHY and RF batch register writes Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 11/16] wifi: rtw89: 8832cu: Add ID 2c7c:8206 for RTL8832CU Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 12/16] wifi: rtw89: use struct to fill C2H recv ack Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 13/16] wifi: rtw89: check scan C2H event recv ack instead of C2H event done ack Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 14/16] wifi: rtw89: suspend DIG when remain-on-channel Ping-Ke Shih
2026-04-20 3:40 ` [PATCH rtw-next 15/16] wifi: rtw89: chan: introduce new helper to get entity current configuration Ping-Ke Shih
2026-04-20 3:40 ` Ping-Ke Shih [this message]
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=20260420034051.17666-17-pkshih@realtek.com \
--to=pkshih@realtek.com \
--cc=echuang@realtek.com \
--cc=gary.chang@realtek.com \
--cc=isaiah@realtek.com \
--cc=kevin_yang@realtek.com \
--cc=leo.li@realtek.com \
--cc=linux-wireless@vger.kernel.org \
--cc=mh_chen@realtek.com \
--cc=phhuang@realtek.com \
--cc=wenjie.tsai@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