]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: wow: add wait for H2C of FW-IPS mode
authorChin-Yen Lee <timlee@realtek.com>
Mon, 26 Aug 2024 09:04:37 +0000 (17:04 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 2 Sep 2024 01:13:33 +0000 (09:13 +0800)
The C2H packet of FW-IPS mode is not handled by driver in the suspend
flow, and lead to WoWLAN firmware fail to enter PS mode and even some
SER happen. So add wait function for H2C of FW-IPS mode to check driver
handle the C2H packet before disabling interrupt and make the net-detect
function work fine.

Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20240826090439.17242-3-pkshih@realtek.com
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/fw.h
drivers/net/wireless/realtek/rtw89/mac.c

index 436c01880ed49298238d3ecfbc980f5aeebe1e79..f3db1a199b24500893f4434cec8dc11985dd38a1 100644 (file)
@@ -4321,6 +4321,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
        rtw89_init_wait(&rtwdev->mcc.wait);
        rtw89_init_wait(&rtwdev->mac.fw_ofld_wait);
        rtw89_init_wait(&rtwdev->wow.wait);
+       rtw89_init_wait(&rtwdev->mac.ps_wait);
 
        INIT_WORK(&rtwdev->c2h_work, rtw89_fw_c2h_work);
        INIT_WORK(&rtwdev->ips_work, rtw89_ips_work);
index 0f881cf99289791ded0a3ceb12bfc77aa6d70617..7c3aeedfd93aba54ebc87ef8bc8ffd7a803c8028 100644 (file)
@@ -4397,6 +4397,8 @@ struct rtw89_mac_info {
 
        /* see RTW89_FW_OFLD_WAIT_COND series for wait condition */
        struct rtw89_wait_info fw_ofld_wait;
+       /* see RTW89_PS_WAIT_COND series for wait condition */
+       struct rtw89_wait_info ps_wait;
 };
 
 enum rtw89_fwdl_check_type {
index fa2f0d8c2ec0ccd468d01e7f0acf89efccb821db..d9b0e7ebe619a3a2d7a2f01b82338c95113b358b 100644 (file)
@@ -7176,10 +7176,10 @@ fail:
 int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
                       bool enable)
 {
+       struct rtw89_wait_info *wait = &rtwdev->mac.ps_wait;
        struct rtw89_h2c_fwips *h2c;
        u32 len = sizeof(*h2c);
        struct sk_buff *skb;
-       int ret;
 
        skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
        if (!skb) {
@@ -7198,16 +7198,7 @@ int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
                              H2C_FUNC_IPS_CFG, 0, 1,
                              len);
 
-       ret = rtw89_h2c_tx(rtwdev, skb, false);
-       if (ret) {
-               rtw89_err(rtwdev, "failed to send h2c\n");
-               goto fail;
-       }
-       return 0;
-fail:
-       dev_kfree_skb_any(skb);
-
-       return ret;
+       return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, RTW89_PS_WAIT_COND_IPS_CFG);
 }
 
 int rtw89_fw_h2c_wow_request_aoac(struct rtw89_dev *rtwdev)
index deda384a5251d91de1bbadbeb0f7b3c7d70d4aa4..ad47e77d740b25f1815b27ad1a99c86a7f6e89c4 100644 (file)
@@ -4023,9 +4023,19 @@ enum rtw89_wow_h2c_func {
 
 /* CLASS 2 - PS */
 #define H2C_CL_MAC_PS                  0x2
-#define H2C_FUNC_MAC_LPS_PARM          0x0
-#define H2C_FUNC_P2P_ACT               0x1
-#define H2C_FUNC_IPS_CFG               0x3
+enum rtw89_ps_h2c_func {
+       H2C_FUNC_MAC_LPS_PARM           = 0x0,
+       H2C_FUNC_P2P_ACT                = 0x1,
+       H2C_FUNC_IPS_CFG                = 0x3,
+
+       NUM_OF_RTW89_PS_H2C_FUNC,
+};
+
+#define RTW89_PS_WAIT_COND(tag, func) \
+       ((tag) * NUM_OF_RTW89_PS_H2C_FUNC + (func))
+
+#define RTW89_PS_WAIT_COND_IPS_CFG \
+       RTW89_PS_WAIT_COND(0 /* don't care */, H2C_FUNC_IPS_CFG)
 
 /* CLASS 3 - FW download */
 #define H2C_CL_MAC_FWDL                0x3
index f336362ad45ef2a90359294238b41cd23b548b01..c70a23a763b0eeb00a92592c8ba4bc3436f279cb 100644 (file)
@@ -4887,6 +4887,7 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le
 {
        /* N.B. This will run in interrupt context. */
        struct rtw89_wait_info *fw_ofld_wait = &rtwdev->mac.fw_ofld_wait;
+       struct rtw89_wait_info *ps_wait = &rtwdev->mac.ps_wait;
        const struct rtw89_c2h_done_ack *c2h =
                (const struct rtw89_c2h_done_ack *)skb_c2h->data;
        u8 h2c_cat = le32_get_bits(c2h->w2, RTW89_C2H_DONE_ACK_W2_CAT);
@@ -4907,6 +4908,18 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le
        switch (h2c_class) {
        default:
                return;
+       case H2C_CL_MAC_PS:
+               switch (h2c_func) {
+               default:
+                       return;
+               case H2C_FUNC_IPS_CFG:
+                       cond = RTW89_PS_WAIT_COND_IPS_CFG;
+                       break;
+               }
+
+               data.err = !!h2c_return;
+               rtw89_complete_cond(ps_wait, cond, &data);
+               return;
        case H2C_CL_MAC_FW_OFLD:
                switch (h2c_func) {
                default: