]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: 8922d: update RF calibration flow for MLD
authorZong-Zhe Yang <kevin_yang@realtek.com>
Mon, 20 Apr 2026 03:40:51 +0000 (11:40 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Wed, 29 Apr 2026 04:53:51 +0000 (12:53 +0800)
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>
Link: https://patch.msgid.link/20260420034051.17666-17-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/rtw8922d.c
drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.c
drivers/net/wireless/realtek/rtw89/rtw8922d_rfk.h

index 570d5883761b84209dc6b058fd9f5522a8a9afbb..1e1125235f0c46458630921ce8e05acae97b4994 100644 (file)
 #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)
 #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
index aa58a0a0d554792aa0e9647bf0de8ff6e1c07f86..ba736b967880a3067aaedf2c90ac6a825e00ba82 100644 (file)
@@ -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,
index 7957f7b2d8e50dd122a3925ec319306e1e6847c9..a465e6631a22ba84fa4512ab383796430f1cadcb 100644 (file)
@@ -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)
index c5bbe0eb972ae5663cc3a183ec879a5ee4a61976..11742b4a8f599ccdd74f4b4e1170e3661b1615cc 100644 (file)
@@ -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