]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: check LPS H2C command complete by C2H reg instead of done ack
authorChih-Kang Chang <gary.chang@realtek.com>
Thu, 10 Jul 2025 04:24:16 +0000 (12:24 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Tue, 15 Jul 2025 01:31:31 +0000 (09:31 +0800)
8852B after FW 0.29.127, 8852BT after FW 0.29.127 and 8922A after FW
0.35.76 driver check LPS H2C command received by FW using C2H reg instead
of done ack.

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-8-pkshih@realtek.com
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/ps.c

index 2e5f129ff4f837bf213151ddc24f4335ca15ca23..7afb84ea0e26fb0cba68aec9610756cede6e98fd 100644 (file)
@@ -4608,6 +4608,7 @@ enum rtw89_fw_feature {
        RTW89_FW_FEATURE_BEACON_LOSS_COUNT_V1,
        RTW89_FW_FEATURE_SCAN_OFFLOAD_EXTRA_OP,
        RTW89_FW_FEATURE_RFK_NTFY_MCC_V0,
+       RTW89_FW_FEATURE_LPS_DACK_BY_C2H_REG,
 };
 
 struct rtw89_fw_suit {
index 20b7b4b15450c35c3189ed18bb3074b3fdaa727c..8157774b2bb1a727e2024dad41b3d42d05c0d297 100644 (file)
@@ -827,11 +827,13 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
        __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD),
        __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 7, BEACON_FILTER),
        __CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX),
+       __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 127, 0, LPS_DACK_BY_C2H_REG),
        __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG),
        __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE),
        __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER),
        __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 91, 0, SCAN_OFFLOAD),
        __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 110, 0, BEACON_FILTER),
+       __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 127, 0, LPS_DACK_BY_C2H_REG),
        __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS),
        __CFG_FW_FEAT(RTL8852C, ge, 0, 0, 0, 0, RFK_NTFY_MCC_V0),
        __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE),
@@ -856,6 +858,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
        __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 51, 0, NO_PHYCAP_P1),
        __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 64, 0, NO_POWER_DIFFERENCE),
        __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 71, 0, BEACON_LOSS_COUNT_V1),
+       __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 76, 0, LPS_DACK_BY_C2H_REG),
 };
 
 static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
@@ -2824,8 +2827,14 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
                          struct rtw89_lps_parm *lps_param)
 {
        struct sk_buff *skb;
+       bool done_ack;
        int ret;
 
+       if (RTW89_CHK_FW_FEATURE(LPS_DACK_BY_C2H_REG, &rtwdev->fw))
+               done_ack = false;
+       else
+               done_ack = !lps_param->psmode;
+
        skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LPS_PARM_LEN);
        if (!skb) {
                rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
@@ -2847,7 +2856,7 @@ int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
        rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
                              H2C_CAT_MAC,
                              H2C_CL_MAC_PS,
-                             H2C_FUNC_MAC_LPS_PARM, 0, !lps_param->psmode,
+                             H2C_FUNC_MAC_LPS_PARM, 0, done_ack,
                              H2C_LPS_PARM_LEN);
 
        ret = rtw89_h2c_tx(rtwdev, skb, false);
index 479a9f980b7f5c63029ce50b56f10a2042ab48b4..629e54adcb83ad6eb053b955a69bb5d6d9ca47b3 100644 (file)
@@ -87,6 +87,9 @@ struct rtw89_c2hreg_phycap {
 #define RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_6 GENMASK(7, 0)
 #define RTW89_C2HREG_AOAC_RPT_2_W3_IGTK_IPN_IV_7 GENMASK(15, 8)
 
+#define RTW89_C2HREG_PS_LEAVE_ACK_RET GENMASK(7, 0)
+#define RTW89_C2HREG_PS_LEAVE_ACK_MACID GENMASK(31, 16)
+
 struct rtw89_h2creg_hdr {
        u32 w0;
 };
@@ -154,6 +157,7 @@ enum rtw89_mac_c2h_type {
        RTW89_FWCMD_C2HREG_FUNC_TX_PAUSE_RPT,
        RTW89_FWCMD_C2HREG_FUNC_WOW_CPUIO_RX_ACK = 0xA,
        RTW89_FWCMD_C2HREG_FUNC_PHY_CAP_PART1 = 0xC,
+       RTW89_FWCMD_C2HREG_FUNC_PS_LEAVE_ACK = 0xD,
        RTW89_FWCMD_C2HREG_FUNC_NULL = 0xFF,
 };
 
index 3411d642c84a7be469386d18eab3867b46420ac9..652f8fc81b79e05317740ef6331d8a02a498c260 100644 (file)
 #include "reg.h"
 #include "util.h"
 
+static int rtw89_fw_receive_lps_h2c_check(struct rtw89_dev *rtwdev, u8 macid)
+{
+       struct rtw89_mac_c2h_info c2h_info = {};
+       u16 c2hreg_macid;
+       u32 c2hreg_ret;
+       int ret;
+
+       if (!RTW89_CHK_FW_FEATURE(LPS_DACK_BY_C2H_REG, &rtwdev->fw))
+               return 0;
+
+       c2h_info.id = RTW89_FWCMD_C2HREG_FUNC_PS_LEAVE_ACK;
+       ret = rtw89_fw_msg_reg(rtwdev, NULL, &c2h_info);
+       if (ret)
+               return ret;
+
+       c2hreg_macid = u32_get_bits(c2h_info.u.c2hreg[0],
+                                   RTW89_C2HREG_PS_LEAVE_ACK_MACID);
+       c2hreg_ret = u32_get_bits(c2h_info.u.c2hreg[1], RTW89_C2HREG_PS_LEAVE_ACK_RET);
+
+       if (macid != c2hreg_macid || c2hreg_ret)
+               rtw89_warn(rtwdev, "rtw89: check lps h2c received by firmware fail\n");
+
+       return 0;
+}
+
 static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid)
 {
        const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
@@ -106,7 +131,8 @@ static void __rtw89_leave_lps(struct rtw89_dev *rtwdev,
        };
 
        rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
-       rtw89_fw_leave_lps_check(rtwdev, 0);
+       rtw89_fw_receive_lps_h2c_check(rtwdev, rtwvif_link->mac_id);
+       rtw89_fw_leave_lps_check(rtwdev, rtwvif_link->mac_id);
        rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
        rtw89_chip_digital_pwr_comp(rtwdev, rtwvif_link->phy_idx);
 }