summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Huang <echuang@realtek.com>2026-01-17 07:41:50 +0300
committerPing-Ke Shih <pkshih@realtek.com>2026-01-22 05:11:15 +0300
commit496a0752fe5042908c8dd44d477916fa83414595 (patch)
treee5e7b201b8d6983fac5abaf83a27b48ec0809bb5
parent32f6bf1872cb41c46e601c1c59e55b78699d0a0d (diff)
downloadlinux-496a0752fe5042908c8dd44d477916fa83414595.tar.xz
wifi: rtw89: phy: handle C2H event for PS mode report
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
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.h1
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h20
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c59
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h1
4 files changed, 81 insertions, 0 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/debug.h b/drivers/net/wireless/realtek/rtw89/debug.h
index a364e7adb079..7cdceb24f52d 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.h
+++ b/drivers/net/wireless/realtek/rtw89/debug.h
@@ -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),
};
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 018b3bed57d2..12e798f01df7 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -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;
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index d311de093425..6fd903b44bdb 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -3340,6 +3340,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)
{
const struct rtw89_c2h_fw_scan_rpt *c2h_rpt =
@@ -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,
};
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 4e985a604338..0c5224780e84 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -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,
};