From 9126020ab03c60053819c19294f46fc6ce11b52e Mon Sep 17 00:00:00 2001 From: Chih-Kang Chang Date: Thu, 10 Jul 2025 12:24:11 +0800 Subject: [PATCH] wifi: rtw89: add DIG suspend/resume flow when scan and connection 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 Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20250710042423.73617-3-pkshih@realtek.com --- drivers/net/wireless/realtek/rtw89/chan.c | 4 ++ drivers/net/wireless/realtek/rtw89/core.c | 2 + drivers/net/wireless/realtek/rtw89/core.h | 2 + drivers/net/wireless/realtek/rtw89/fw.c | 2 + drivers/net/wireless/realtek/rtw89/phy.c | 50 +++++++++++++++++++++++ drivers/net/wireless/realtek/rtw89/phy.h | 2 + 6 files changed, 62 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c index 32cd09f77e37a..1277b1af2a4c1 100644 --- a/drivers/net/wireless/realtek/rtw89/chan.c +++ b/drivers/net/wireless/realtek/rtw89/chan.c @@ -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); diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 23d050041583a..da82a88cce988 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -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); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 8c53c5db0cbc4..e0992c12c4ca7 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -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 { diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 3a3109ab71110..ae38ea6403840 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -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); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index a7412d1399021..d607577b353c6 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -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); diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h index 63cc33c16c9a5..dc156376d951e 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.h +++ b/drivers/net/wireless/realtek/rtw89/phy.h @@ -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); -- 2.47.2