summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorChih-Kang Chang <gary.chang@realtek.com>2024-05-02 05:24:55 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-05-30 10:49:21 +0300
commitbe0536161e425c07e7e087c0772c3e293e058b94 (patch)
treeaef23a1f9205a74fff3298c9f2258d78f33d6792 /drivers
parent4e2a5566462b53db7d4c4722da86eedf0b8f546c (diff)
downloadlinux-be0536161e425c07e7e087c0772c3e293e058b94.tar.xz
wifi: rtw89: wow: refine WoWLAN flows of HCI interrupts and low power mode
[ Upstream commit baaf806e4632a259cc959fd1c516c2d9ed48df6d ] After enabling packet offload, the TX will be stuck after resume from WoWLAN mode. And the 8852c gets error messages like rtw89_8852ce 0000:04:00.0: No busy txwd pages available rtw89_8852ce 0000:04:00.0: queue 0 txwd 100 is not idle rtw89_8852ce 0000:04:00.0: queue 0 txwd 101 is not idle rtw89_8852ce 0000:04:00.0: queue 0 txwd 102 is not idle rtw89_8852ce 0000:04:00.0: queue 0 txwd 103 is not idle If suspend/resume many times that firmware will download failed and disconnection. To fix these issues, We removed the rtw89_hci_disable_intr() and rtw89_hci_enable_intr() during rtw89_wow_swap_fw() to prevent add packet offload can't receive c2h back due to interrupt disable. Only 8852C and 8922A needs to disable interrupt before downloading fw. Furthermore, we avoid using low power HCI mode on WoWLAN mode, to prevent interrupt enabled, then get interrupt and calculate RXBD mismatched due to software RXBD index already reset but hardware RXBD index not yet. Fixes: 5c12bb66b79d ("wifi: rtw89: refine packet offload flow") Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://msgid.link/20240502022505.28966-3-pkshih@realtek.com Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.c3
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c12
2 files changed, 12 insertions, 3 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index 917c01e5e9ed..e86d5588ec60 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -54,7 +54,8 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
{
- if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode))
+ if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
+ !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
else
rtw89_mac_power_mode_change(rtwdev, enter);
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 5c7ca36c09b6..abb4d1cc55d0 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -489,14 +489,17 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
+ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
const struct rtw89_chip_info *chip = rtwdev->chip;
bool include_bb = !!chip->bbmcu_nr;
+ bool disable_intr_for_dlfw = false;
struct ieee80211_sta *wow_sta;
struct rtw89_sta *rtwsta = NULL;
bool is_conn = true;
int ret;
- rtw89_hci_disable_intr(rtwdev);
+ if (chip_id == RTL8852C || chip_id == RTL8922A)
+ disable_intr_for_dlfw = true;
wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid);
if (wow_sta)
@@ -504,12 +507,18 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
else
is_conn = false;
+ if (disable_intr_for_dlfw)
+ rtw89_hci_disable_intr(rtwdev);
+
ret = rtw89_fw_download(rtwdev, fw_type, include_bb);
if (ret) {
rtw89_warn(rtwdev, "download fw failed\n");
return ret;
}
+ if (disable_intr_for_dlfw)
+ rtw89_hci_enable_intr(rtwdev);
+
rtw89_phy_init_rf_reg(rtwdev, true);
ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
@@ -552,7 +561,6 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
}
rtw89_mac_hw_mgnt_sec(rtwdev, wow);
- rtw89_hci_enable_intr(rtwdev);
return 0;
}