]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: phy: handle C2H event for PS mode report
authorEric Huang <echuang@realtek.com>
Sat, 17 Jan 2026 04:41:50 +0000 (12:41 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Thu, 22 Jan 2026 02:11:15 +0000 (10:11 +0800)
Introduce support for processing the new PS C2H report, enabling
detailed debugging of low-power state hardware changes.

Signed-off-by: Eric Huang <echuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260117044157.2392958-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/debug.h
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h

index a364e7adb0798e5373251bac96f283e4f7d2f45a..7cdceb24f52dd8d839728dc7d81065201cdf481e 100644 (file)
@@ -31,6 +31,7 @@ enum rtw89_debug_mask {
        RTW89_DBG_CHAN = BIT(20),
        RTW89_DBG_ACPI = BIT(21),
        RTW89_DBG_EDCCA = BIT(22),
+       RTW89_DBG_PS = BIT(23),
 
        RTW89_DBG_UNEXP = BIT(31),
 };
index 018b3bed57d21c3964a48212d330dbef860eb33a..12e798f01df78ee68dd8edb122a1d75d36caa8c6 100644 (file)
@@ -3829,6 +3829,26 @@ struct rtw89_c2h_ra_rpt {
 #define RTW89_C2H_RA_RPT_W3_MD_SEL_B2 BIT(15)
 #define RTW89_C2H_RA_RPT_W3_BW_B2 BIT(16)
 
+struct rtw89_c2h_lps_rpt {
+       struct rtw89_c2h_hdr hdr;
+       u8 type;
+       u8 cnt_bbcr;
+       u8 cnt_bbmcucr;
+       u8 cnt_rfcr;
+       u8 data[];
+       /*
+        * The layout of data:
+        *   u8 info[][4], size = total_len - size of below fields
+        *   __le16 bbcr_addr[], size = cnt_bbcr
+        *   __le32 bbcr_data[], size = cnt_bbcr
+        *   __le16 bbmcucr_addr[], size = cnt_bbmcucr
+        *   __le32 bbmcucr_data[], size = cnt_bbmcucr
+        *   __le16 rfcr_addr[],   size = cnt_rfcr
+        *   __le32 rfcr_data_a[], size = cnt_rfcr
+        *   __le32 rfcr_data_b[], size = cnt_rfcr
+        */
+} __packed;
+
 struct rtw89_c2h_fw_scan_rpt {
        struct rtw89_c2h_hdr hdr;
        u8 phy_idx;
index d311de093425a9af932bcace7d9d6d8216680c17..6fd903b44bdb35204ff18244b4768276883c577f 100644 (file)
@@ -3339,6 +3339,64 @@ rtw89_phy_c2h_lowrt_rty(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
 {
 }
 
+static void
+rtw89_phy_c2h_lps_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+       const struct rtw89_c2h_lps_rpt *c2h_rpt = (const void *)c2h->data;
+       const __le32 *data_a, *data_b;
+       u16 len_info, cr_len, idx;
+       const __le16 *addr;
+       const u8 *info;
+
+       /* elements size of BBCR/BBMCUCR/RFCR are 6/6/10 bytes respectively */
+       cr_len = c2h_rpt->cnt_bbcr * 6 +
+                c2h_rpt->cnt_bbmcucr * 6 +
+                c2h_rpt->cnt_rfcr * 10;
+       len_info = len - (sizeof(*c2h_rpt) + cr_len);
+
+       if (len < sizeof(*c2h_rpt) + cr_len || len_info % 4 != 0) {
+               rtw89_debug(rtwdev, RTW89_DBG_PS,
+                           "Invalid LPS RPT len(%d) TYPE(%d) CRCNT: BB(%d) MCU(%d) RF(%d)\n",
+                           len, c2h_rpt->type, c2h_rpt->cnt_bbcr,
+                           c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr);
+               return;
+       }
+
+       rtw89_debug(rtwdev, RTW89_DBG_PS,
+                   "LPS RPT TYPE(%d), CRCNT: BB(%d) MCU(%d) RF(%d)\n",
+                   c2h_rpt->type, c2h_rpt->cnt_bbcr,
+                   c2h_rpt->cnt_bbmcucr, c2h_rpt->cnt_rfcr);
+
+       info = &c2h_rpt->data[0];
+       for (idx = 0; idx < len_info; idx += 4, info += 4)
+               rtw89_debug(rtwdev, RTW89_DBG_PS,
+                           "BB LPS INFO (%02d) - 0x%02x,0x%02x,0x%02x,0x%02x\n",
+                           idx, info[3], info[2], info[1], info[0]);
+
+       addr = (const void *)(info);
+       data_a = (const void *)(addr + c2h_rpt->cnt_bbcr);
+       for (idx = 0; idx < c2h_rpt->cnt_bbcr; idx++, addr++, data_a++)
+               rtw89_debug(rtwdev, RTW89_DBG_PS,
+                           "LPS BB CR - 0x%04x=0x%08x\n",
+                           le16_to_cpu(*addr), le32_to_cpu(*data_a));
+
+       addr = (const void *)data_a;
+       data_a = (const void *)(addr + c2h_rpt->cnt_bbmcucr);
+       for (idx = 0; idx < c2h_rpt->cnt_bbmcucr; idx++, addr++, data_a++)
+               rtw89_debug(rtwdev, RTW89_DBG_PS,
+                           "LPS BBMCU - 0x%04x=0x%08x\n",
+                           le16_to_cpu(*addr), le32_to_cpu(*data_a));
+
+       addr = (const void *)data_a;
+       data_a = (const void *)(addr + c2h_rpt->cnt_rfcr);
+       data_b = (const void *)(data_a + c2h_rpt->cnt_rfcr);
+       for (idx = 0; idx < c2h_rpt->cnt_rfcr; idx++, addr++, data_a++, data_b++)
+               rtw89_debug(rtwdev, RTW89_DBG_PS,
+                           "LPS RFCR - 0x%04x=0x%05x,0x%05x\n",
+                           le16_to_cpu(*addr), le32_to_cpu(*data_a),
+                           le32_to_cpu(*data_b));
+}
+
 static void
 rtw89_phy_c2h_fw_scan_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
 {
@@ -3360,6 +3418,7 @@ void (* const rtw89_phy_c2h_dm_handler[])(struct rtw89_dev *rtwdev,
        [RTW89_PHY_C2H_DM_FUNC_SIGB] = NULL,
        [RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY] = rtw89_phy_c2h_lowrt_rty,
        [RTW89_PHY_C2H_DM_FUNC_MCC_DIG] = NULL,
+       [RTW89_PHY_C2H_DM_FUNC_LPS] = rtw89_phy_c2h_lps_rpt,
        [RTW89_PHY_C2H_DM_FUNC_FW_SCAN] = rtw89_phy_c2h_fw_scan_rpt,
 };
 
index 4e985a604338c72e7ae304cc9379325d854aaaf1..0c5224780e849078f0cea977fcdd1d3128baef5a 100644 (file)
@@ -165,6 +165,7 @@ enum rtw89_phy_c2h_dm_func {
        RTW89_PHY_C2H_DM_FUNC_SIGB,
        RTW89_PHY_C2H_DM_FUNC_LOWRT_RTY,
        RTW89_PHY_C2H_DM_FUNC_MCC_DIG,
+       RTW89_PHY_C2H_DM_FUNC_LPS = 0x9,
        RTW89_PHY_C2H_DM_FUNC_FW_SCAN = 0xc,
        RTW89_PHY_C2H_DM_FUNC_NUM,
 };