]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: add DIG suspend/resume flow when scan and connection
authorChih-Kang Chang <gary.chang@realtek.com>
Thu, 10 Jul 2025 04:24:11 +0000 (12:24 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Tue, 15 Jul 2025 01:24:48 +0000 (09:24 +0800)
The PD lower bound set after one interface is connected, If second
interface needs to connect, packets might not be detected because the
PD lower bound is too high. Therefore, a DIG suspend/resume flow is
added to decrease the PD lower bound during scanning or connection,
and the original PD level is resumed afterward.

Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250710042423.73617-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/chan.c
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h

index 32cd09f77e37a3740289de25c1afb107a7f31d14..1277b1af2a4c13e9237a1245ba8f034f628a837b 100644 (file)
@@ -7,6 +7,7 @@
 #include "debug.h"
 #include "fw.h"
 #include "mac.h"
+#include "phy.h"
 #include "ps.h"
 #include "sar.h"
 #include "util.h"
@@ -2281,6 +2282,7 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
        rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START);
 
        rtw89_mcc_start_beacon_noa(rtwdev);
+       rtw89_phy_dig_suspend(rtwdev);
 
        rtw89_mcc_prepare(rtwdev, true);
        return 0;
@@ -2372,6 +2374,7 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev,
 
        rtw89_mcc_stop_beacon_noa(rtwdev);
        rtw89_fw_h2c_mcc_dig(rtwdev, RTW89_CHANCTX_0, 0, 0, false);
+       rtw89_phy_dig_resume(rtwdev, true);
 
        rtw89_mcc_prepare(rtwdev, false);
 }
@@ -2715,6 +2718,7 @@ void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
                return;
        case RTW89_ENTITY_MODE_MCC_PREPARE:
                delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE);
+               rtw89_phy_dig_suspend(rtwdev);
                break;
        case RTW89_ENTITY_MODE_MCC:
                delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC);
index 23d050041583a2fac1303f0c13fdb27993fbcd86..da82a88cce988deb3a8ef8152f59827e97d2bdb3 100644 (file)
@@ -4082,6 +4082,7 @@ int rtw89_core_sta_link_add(struct rtw89_dev *rtwdev,
                                                     &rtwsta_link->tx_retry);
                        rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, 60);
                }
+               rtw89_phy_dig_suspend(rtwdev);
        } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
                ret = rtw89_mac_set_macid_pause(rtwdev, rtwsta_link->mac_id, false);
                if (ret) {
@@ -4270,6 +4271,7 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
                if (vif->p2p)
                        rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false,
                                                     rtwsta_link->tx_retry);
+               rtw89_phy_dig_resume(rtwdev, false);
        }
 
        rtw89_assoc_link_set(rtwsta_link);
index 8c53c5db0cbc4f8d063d6b1c59f7052162ebc6f8..e0992c12c4ca7e7697f70bde6e0396f8c5086a89 100644 (file)
@@ -5243,8 +5243,10 @@ struct rtw89_dig_info {
        s8 tia_gain_a[TIA_GAIN_NUM];
        s8 tia_gain_g[TIA_GAIN_NUM];
        s8 *tia_gain;
+       u32 bak_dig;
        bool is_linked_pre;
        bool bypass_dig;
+       bool pause_dig;
 };
 
 enum rtw89_multi_cfo_mode {
index 3a3109ab71110194eefe758ae16ec59f6d0059eb..ae38ea6403840d86cb7e312876cdd4992ef4a04c 100644 (file)
@@ -7798,6 +7798,7 @@ int rtw89_hw_scan_start(struct rtw89_dev *rtwdev,
        rtw89_write32_mask(rtwdev, reg, B_AX_RX_FLTR_CFG_MASK, rx_fltr);
 
        rtw89_chanctx_pause(rtwdev, &pause_parm);
+       rtw89_phy_dig_suspend(rtwdev);
 
        if (mode == RTW89_ENTITY_MODE_MCC)
                rtw89_hw_scan_update_beacon_noa(rtwdev, req);
@@ -7831,6 +7832,7 @@ static int rtw89_hw_scan_complete_cb(struct rtw89_dev *rtwdev, void *data)
        ieee80211_wake_queues(rtwdev->hw);
        rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif_link, true);
        rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, true);
+       rtw89_phy_dig_resume(rtwdev, true);
 
        rtw89_hw_scan_cleanup(rtwdev, rtwvif_link);
 
index a7412d13990210088eff5ed1d4abee7b43a112a2..d607577b353c6879444886d1a21966b8aa45f12d 100644 (file)
@@ -6390,6 +6390,7 @@ static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev,
        u32 pd_val;
 
        pd_val = __rtw89_phy_dig_dyn_pd_th(rtwdev, bb, rssi, enable, chan);
+       dig->bak_dig = pd_val;
 
        rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
                              dig_regs->pd_lower_bound_mask, pd_val, bb->phy_idx);
@@ -6532,6 +6533,52 @@ static void rtw89_phy_dig_mcc(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
        }
 }
 
+static void rtw89_phy_dig_ctrl(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb,
+                              bool pause_dig, bool restore)
+{
+       const struct rtw89_dig_regs *dig_regs = rtwdev->chip->dig_regs;
+       struct rtw89_dig_info *dig = &bb->dig;
+       bool en_dig;
+       u32 pd_val;
+
+       if (dig->pause_dig == pause_dig)
+               return;
+
+       if (pause_dig) {
+               en_dig = false;
+               pd_val = 0;
+       } else {
+               en_dig = rtwdev->total_sta_assoc > 0;
+               pd_val = restore ? dig->bak_dig : 0;
+       }
+
+       rtw89_debug(rtwdev, RTW89_DBG_DIG, "%s <%s> PD_low=%d", __func__,
+                   pause_dig ? "suspend" : "resume", pd_val);
+
+       rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
+                             dig_regs->pd_lower_bound_mask, pd_val, bb->phy_idx);
+       rtw89_phy_write32_idx(rtwdev, dig_regs->seg0_pd_reg,
+                             dig_regs->pd_spatial_reuse_en, en_dig, bb->phy_idx);
+
+       dig->pause_dig = pause_dig;
+}
+
+void rtw89_phy_dig_suspend(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_bb_ctx *bb;
+
+       rtw89_for_each_active_bb(rtwdev, bb)
+               rtw89_phy_dig_ctrl(rtwdev, bb, true, false);
+}
+
+void rtw89_phy_dig_resume(struct rtw89_dev *rtwdev, bool restore)
+{
+       struct rtw89_bb_ctx *bb;
+
+       rtw89_for_each_active_bb(rtwdev, bb)
+               rtw89_phy_dig_ctrl(rtwdev, bb, false, restore);
+}
+
 static void __rtw89_phy_dig(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
 {
        struct rtw89_dig_info *dig = &bb->dig;
@@ -6553,6 +6600,9 @@ static void __rtw89_phy_dig(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb)
                return;
        }
 
+       if (unlikely(dig->pause_dig))
+               return;
+
        if (!dig->is_linked_pre && is_linked) {
                rtw89_debug(rtwdev, RTW89_DBG_DIG, "First connected\n");
                rtw89_phy_dig_update_para(rtwdev, bb);
index 63cc33c16c9a54a8ef2caf60e97f9d3f7003abc8..dc156376d951efc230fb312946024fe6657c6bf1 100644 (file)
@@ -1010,6 +1010,8 @@ void rtw89_phy_set_phy_regs(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
                            u32 val);
 void rtw89_phy_dig_reset(struct rtw89_dev *rtwdev, struct rtw89_bb_ctx *bb);
 void rtw89_phy_dig(struct rtw89_dev *rtwdev);
+void rtw89_phy_dig_suspend(struct rtw89_dev *rtwdev);
+void rtw89_phy_dig_resume(struct rtw89_dev *rtwdev, bool restore);
 void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev);
 void rtw89_phy_antdiv_parse(struct rtw89_dev *rtwdev,
                            struct rtw89_rx_phy_ppdu *phy_ppdu);