]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: 8922a: pass channel information when enter LPS
authorKuan-Chung Chen <damon.chen@realtek.com>
Fri, 6 Jun 2025 02:04:37 +0000 (10:04 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Tue, 10 Jun 2025 02:07:59 +0000 (10:07 +0800)
Newer firmware requires the driver to pass channel information
when switching from normal mode to low power mode; otherwise it
will result in poor RX beacon performance.

Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250606020437.17160-1-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/ps.c

index 0547eb11d37825ba8093d8d5ad64800b7038e0e4..95865eafb2cd605cf0df252c44665696706056b8 100644 (file)
@@ -5919,6 +5919,65 @@ fail:
 }
 EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc);
 
+int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       struct rtw89_vif_link *rtwvif_link;
+       struct rtw89_h2c_rf_ps_info *h2c;
+       const struct rtw89_chan *chan;
+       u32 len = sizeof(*h2c);
+       unsigned int link_id;
+       struct sk_buff *skb;
+       int ret;
+       u8 path;
+       u32 val;
+
+       if (chip->chip_gen != RTW89_CHIP_BE)
+               return 0;
+
+       skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+       if (!skb) {
+               rtw89_err(rtwdev, "failed to alloc skb for h2c rf ps info\n");
+               return -ENOMEM;
+       }
+       skb_put(skb, len);
+       h2c = (struct rtw89_h2c_rf_ps_info *)skb->data;
+       h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
+
+       rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+               chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+               path = rtw89_phy_get_syn_sel(rtwdev, rtwvif_link->phy_idx);
+               val = rtw89_chip_chan_to_rf18_val(rtwdev, chan);
+
+               if (path >= chip->rf_path_num) {
+                       rtw89_err(rtwdev, "unsupported rf path (%d)\n", path);
+                       ret = -ENOENT;
+                       goto fail;
+               }
+
+               h2c->rf18[path] = cpu_to_le32(val);
+               h2c->pri_ch[path] = chan->primary_channel;
+       }
+
+       rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+                             H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY,
+                             H2C_FUNC_OUTSRC_RF_PS_INFO, 0, 0,
+                             sizeof(*h2c));
+
+       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;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_rf_ps_info);
+
 int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
                             enum rtw89_phy_idx phy_idx)
 {
index d4815bcce91bcbafca44236ebe44a05726e94b37..14f55b10be2ea3efd7b4e85f669fdb0f32302502 100644 (file)
@@ -4337,6 +4337,7 @@ enum rtw89_mrc_h2c_func {
 #define H2C_CL_OUTSRC_RF_REG_B         0x9
 #define H2C_CL_OUTSRC_RF_FW_NOTIFY     0xa
 #define H2C_FUNC_OUTSRC_RF_GET_MCCCH   0x2
+#define H2C_FUNC_OUTSRC_RF_PS_INFO     0x10
 #define H2C_CL_OUTSRC_RF_FW_RFK                0xb
 
 enum rtw89_rfk_offload_h2c_func {
@@ -4361,6 +4362,12 @@ struct rtw89_fw_h2c_rf_get_mccch {
 #define NUM_OF_RTW89_FW_RFK_PATH 2
 #define NUM_OF_RTW89_FW_RFK_TBL 3
 
+struct rtw89_h2c_rf_ps_info {
+       __le32 rf18[NUM_OF_RTW89_FW_RFK_PATH];
+       __le32 mlo_mode;
+       u8 pri_ch[NUM_OF_RTW89_FW_RFK_PATH];
+} __packed;
+
 struct rtw89_fw_h2c_rfk_pre_info_common {
        struct {
                __le32 ch[NUM_OF_RTW89_FW_RFK_PATH][NUM_OF_RTW89_FW_RFK_TBL];
@@ -4744,6 +4751,7 @@ int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
                        struct rtw89_fw_h2c_rf_reg_info *info,
                        u16 len, u8 page);
 int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev);
+int rtw89_fw_h2c_rf_ps_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
 int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
                             enum rtw89_phy_idx phy_idx);
 int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
index 8e4fe73e7d775a153edb0f34d9054460d4b1ea8a..c255c2f9b94587b41cf218f40de80613404c41a7 100644 (file)
@@ -137,6 +137,8 @@ void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
                        can_ps_mode = false;
        }
 
+       rtw89_fw_h2c_rf_ps_info(rtwdev, rtwvif);
+
        if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw))
                rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif);
        else