wifi: rtw89: coex: Add protect to avoid A2DP lag while Wi-Fi connecting
authorChing-Te Ku <ku920601@realtek.com>
Fri, 10 Jan 2025 01:54:14 +0000 (09:54 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 20 Jan 2025 01:14:44 +0000 (09:14 +0800)
To get a well Wi-Fi RF quality, Wi-Fi need to do RF calibrations. While
Wi-Fi is doing RF calibrations, driver will pause the Bluetooth traffic
to make sure the RF calibration will not be interfered by Bluetooth.
However, if the RF calibrations take too much time, Bluetooth audio
will perform a lag sound. Add a function to make Bluetooth can do
traffic between the individual calibrations to avoid Bluetooth sound
lag. And patch related A2DP coexistence mechanism actions.

Signed-off-by: Ching-Te Ku <ku920601@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250110015416.10704-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/coex.c
drivers/net/wireless/realtek/rtw89/coex.h
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/rtw8851b.c
drivers/net/wireless/realtek/rtw89/rtw8852a.c
drivers/net/wireless/realtek/rtw89/rtw8852b.c
drivers/net/wireless/realtek/rtw89/rtw8852bt.c
drivers/net/wireless/realtek/rtw89/rtw8852c.c

index 68316d44b204300752e9741d259e285754676284..d5b8091e7541d097bb9387a501707b377743822f 100644 (file)
@@ -4589,17 +4589,16 @@ static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
 
        _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 
+       if (a2dp.vendor_id == 0x4c || dm->leak_ap || bt_linfo->slave_role)
+               dm->slot_dur[CXST_W1] = 20;
+       else
+               dm->slot_dur[CXST_W1] = 40;
+
+       dm->slot_dur[CXST_B1] = BTC_B1_MAX;
+
        switch (btc->cx.state_map) {
        case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
-               if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
-                       dm->slot_dur[CXST_W1] = 40;
-                       dm->slot_dur[CXST_B1] = 200;
-                       _set_policy(rtwdev,
-                                   BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
-               } else {
-                       _set_policy(rtwdev,
-                                   BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
-               }
+               _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
                break;
        case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
                _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
@@ -4609,15 +4608,10 @@ static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
                break;
        case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
        case BTC_WLINKING: /* wl-connecting + bt-A2DP */
-               if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
-                       dm->slot_dur[CXST_W1] = 40;
-                       dm->slot_dur[CXST_B1] = 200;
-                       _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
-                                   BTC_ACT_BT_A2DP);
-               } else {
-                       _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
-                                   BTC_ACT_BT_A2DP);
-               }
+               if (btc->cx.wl.rfk_info.con_rfk)
+                       _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP);
+               else
+                       _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP);
                break;
        case BTC_WIDLE:  /* wl-idle + bt-A2DP */
                _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
@@ -4645,7 +4639,10 @@ static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
                _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
                break;
        case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
-               _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
+               if (btc->cx.wl.rfk_info.con_rfk)
+                       _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK);
+               else
+                       _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
                break;
        case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
                _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
@@ -4699,21 +4696,20 @@ static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
 
        _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
 
+       if (a2dp.vendor_id == 0x4c || dm->leak_ap || bt_linfo->slave_role)
+               dm->slot_dur[CXST_W1] = 20;
+       else
+               dm->slot_dur[CXST_W1] = 40;
+
+       dm->slot_dur[CXST_B1] = BTC_B1_MAX;
+
        switch (btc->cx.state_map) {
        case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
        case BTC_WIDLE:  /* wl-idle + bt-A2DP */
-               if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
-                       dm->slot_dur[CXST_W1] = 40;
-                       dm->slot_dur[CXST_B1] = 200;
-                       _set_policy(rtwdev,
-                                   BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
-               } else {
-                       _set_policy(rtwdev,
-                                   BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
-               }
+               _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
                break;
        case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
-               _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
+               _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID);
                break;
 
        case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
@@ -4721,15 +4717,10 @@ static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
                break;
        case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
        case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
-               if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
-                       dm->slot_dur[CXST_W1] = 40;
-                       dm->slot_dur[CXST_B1] = 200;
-                       _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
-                                   BTC_ACT_BT_A2DP_HID);
-               } else {
-                       _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
-                                   BTC_ACT_BT_A2DP_HID);
-               }
+               if (btc->cx.wl.rfk_info.con_rfk)
+                       _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID);
+               else
+                       _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
                break;
        }
 }
@@ -7002,7 +6993,7 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
                goto exit;
        }
 
-       if (wl->status.val & btc_scanning_map.val) {
+       if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) {
                _action_wl_scan(rtwdev);
                bt->scan_rx_low_pri = true;
                goto exit;
@@ -11037,3 +11028,24 @@ out:
        rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
                    (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
 }
+
+void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms)
+{
+       struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info;
+       struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
+
+       if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
+               return;
+
+       if (!a2dp.exist)
+               return;
+
+       fsleep(ms * 1000);
+}
+EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time);
+
+void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state)
+{
+       rtwdev->btc.cx.wl.rfk_info.con_rfk = state;
+}
+EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk);
index dbdb56e063ef036fa32bcae2bd9dfbb7cc39714b..757d03675cf4e67e266480253783c3dbe276726c 100644 (file)
@@ -290,6 +290,8 @@ void rtw89_coex_power_on(struct rtw89_dev *rtwdev);
 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type);
 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type);
 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev);
+void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms);
+void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state);
 
 static inline u8 rtw89_btc_phymap(struct rtw89_dev *rtwdev,
                                  enum rtw89_phy_idx phy_idx,
index ff4894c7fa8a5c26daf43f9291a7de59b5170853..0f2a46e36b0423eb5523f582856b33f0f7dbbd79 100644 (file)
@@ -1761,7 +1761,8 @@ struct rtw89_btc_wl_rfk_info {
        u32 phy_map: 2;
        u32 band: 2;
        u32 type: 8;
-       u32 rsvd: 14;
+       u32 con_rfk: 1;
+       u32 rsvd: 13;
 
        u32 start_time;
        u32 proc_time;
index c56f70267882a63a3a45306b4a79a5b812cf72d2..0487d1cbe60576c79531e43c45933ae7aff2af8d 100644 (file)
@@ -1596,10 +1596,16 @@ static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev,
        enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
        enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
 
+       rtw89_btc_ntfy_conn_rfk(rtwdev, true);
+
        rtw8851b_rx_dck(rtwdev, phy_idx, chanctx_idx);
        rtw8851b_iqk(rtwdev, phy_idx, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8851b_tssi(rtwdev, phy_idx, true, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8851b_dpk(rtwdev, phy_idx, chanctx_idx);
+
+       rtw89_btc_ntfy_conn_rfk(rtwdev, false);
 }
 
 static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev,
index 9bd2842c27d50f6a79f324eeb95962bdde95e2e3..8a9a5201b2ee6395882e065e42cb9dea4ff31c2a 100644 (file)
@@ -1356,10 +1356,16 @@ static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev,
        enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
        enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
 
+       rtw89_btc_ntfy_conn_rfk(rtwdev, true);
+
        rtw8852a_rx_dck(rtwdev, phy_idx, true, chanctx_idx);
        rtw8852a_iqk(rtwdev, phy_idx, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852a_tssi(rtwdev, phy_idx, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852a_dpk(rtwdev, phy_idx, chanctx_idx);
+
+       rtw89_btc_ntfy_conn_rfk(rtwdev, false);
 }
 
 static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev,
index dfb2bf61b0b834adeadc845f86d0ddecaeef3132..cbaf54f88af6fc9f0e24f6d5d6b593c7e808ccbd 100644 (file)
@@ -568,10 +568,16 @@ static void rtw8852b_rfk_channel(struct rtw89_dev *rtwdev,
        enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
        enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
 
+       rtw89_btc_ntfy_conn_rfk(rtwdev, true);
+
        rtw8852b_rx_dck(rtwdev, phy_idx, chanctx_idx);
        rtw8852b_iqk(rtwdev, phy_idx, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852b_tssi(rtwdev, phy_idx, true, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852b_dpk(rtwdev, phy_idx, chanctx_idx);
+
+       rtw89_btc_ntfy_conn_rfk(rtwdev, false);
 }
 
 static void rtw8852b_rfk_band_changed(struct rtw89_dev *rtwdev,
index bde3e1fb7ca62857ce29241a10eaa0ef72daf7f9..c0ae5dca30492a25792f0a15aad4c4ef6838aa48 100644 (file)
@@ -541,10 +541,16 @@ static void rtw8852bt_rfk_channel(struct rtw89_dev *rtwdev,
        enum rtw89_chanctx_idx chanctx_idx = rtwvif_link->chanctx_idx;
        enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
 
+       rtw89_btc_ntfy_conn_rfk(rtwdev, true);
+
        rtw8852bt_rx_dck(rtwdev, phy_idx, chanctx_idx);
        rtw8852bt_iqk(rtwdev, phy_idx, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852bt_tssi(rtwdev, phy_idx, true, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852bt_dpk(rtwdev, phy_idx, chanctx_idx);
+
+       rtw89_btc_ntfy_conn_rfk(rtwdev, false);
 }
 
 static void rtw8852bt_rfk_band_changed(struct rtw89_dev *rtwdev,
index bc84b15e7826dd173aab2bc8ade663a084e79a55..106df618bb588cfc6c76d0d3301b371b9e98b75e 100644 (file)
@@ -1853,10 +1853,16 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev,
        enum rtw89_phy_idx phy_idx = rtwvif_link->phy_idx;
 
        rtw8852c_mcc_get_ch_info(rtwdev, phy_idx);
+       rtw89_btc_ntfy_conn_rfk(rtwdev, true);
+
        rtw8852c_rx_dck(rtwdev, phy_idx, false);
        rtw8852c_iqk(rtwdev, phy_idx, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852c_tssi(rtwdev, phy_idx, chanctx_idx);
+       rtw89_btc_ntfy_preserve_bt_time(rtwdev, 30);
        rtw8852c_dpk(rtwdev, phy_idx, chanctx_idx);
+
+       rtw89_btc_ntfy_conn_rfk(rtwdev, false);
        rtw89_fw_h2c_rf_ntfy_mcc(rtwdev);
 }