]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: dynamically update EHT preamble puncturing
authorKuan-Chung Chen <damon.chen@realtek.com>
Tue, 15 Jul 2025 03:52:57 +0000 (11:52 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Fri, 18 Jul 2025 06:00:33 +0000 (14:00 +0800)
When the 'Disabled Subchannel Bitmap' within the EHT Operation
element is changed, mac80211 parse and pass it to the driver.
The driver is then updated with this puncturing bitmap to
optimize bandwidth usage and prevent interference from
degrading performance across the entire channel.

Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250715035259.45061-4-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/chan.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/rtw8851b.c
drivers/net/wireless/realtek/rtw89/rtw8852a.c
drivers/net/wireless/realtek/rtw89/rtw8852b.c
drivers/net/wireless/realtek/rtw89/rtw8852bt.c
drivers/net/wireless/realtek/rtw89/rtw8852c.c
drivers/net/wireless/realtek/rtw89/rtw8922a.c

index ed0d89ac349563b0494dd39971786fb7dcd7ed47..f7d1c5d3b92e5a66da6fd38080e64a19e665d092 100644 (file)
@@ -129,6 +129,48 @@ void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
                                                    bandwidth);
 }
 
+static void _rtw89_chan_update_punctured(struct rtw89_dev *rtwdev,
+                                        struct rtw89_vif_link *rtwvif_link,
+                                        const struct cfg80211_chan_def *chandef)
+{
+       struct ieee80211_bss_conf *bss_conf;
+
+       if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
+           rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
+               return;
+
+       rcu_read_lock();
+
+       bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
+       if (!bss_conf->eht_support) {
+               rcu_read_unlock();
+               return;
+       }
+
+       rcu_read_unlock();
+
+       rtw89_chip_h2c_punctured_cmac_tbl(rtwdev, rtwvif_link, chandef->punctured);
+}
+
+static void rtw89_chan_update_punctured(struct rtw89_dev *rtwdev,
+                                       enum rtw89_chanctx_idx idx,
+                                       const struct cfg80211_chan_def *chandef)
+{
+       struct rtw89_vif_link *rtwvif_link;
+       struct rtw89_vif *rtwvif;
+       unsigned int link_id;
+
+       rtw89_for_each_rtwvif(rtwdev, rtwvif) {
+               rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+                       if (!rtwvif_link->chanctx_assigned ||
+                           rtwvif_link->chanctx_idx != idx)
+                               continue;
+
+                       _rtw89_chan_update_punctured(rtwdev, rtwvif_link, chandef);
+               }
+       }
+}
+
 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
                              enum rtw89_chanctx_idx idx,
                              const struct rtw89_chan *new)
@@ -3245,6 +3287,9 @@ void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
                rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
                rtw89_set_channel(rtwdev);
        }
+
+       if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
+               rtw89_chan_update_punctured(rtwdev, idx, &ctx->def);
 }
 
 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
@@ -3388,5 +3433,7 @@ assign:
                return ret;
        }
 
+       _rtw89_chan_update_punctured(rtwdev, rtwvif_link, &new_ctx->def);
+
        return 0;
 }
index 59ec81adac7ed649dcad8ce4634f5d2dfc946bdc..a99a0dc710d8350aa43353ebbcbae0c49442d3cd 100644 (file)
@@ -3779,6 +3779,9 @@ struct rtw89_chip_ops {
                                  struct rtw89_sta_link *rtwsta_link);
        int (*h2c_txtime_cmac_tbl)(struct rtw89_dev *rtwdev,
                                   struct rtw89_sta_link *rtwsta_link);
+       int (*h2c_punctured_cmac_tbl)(struct rtw89_dev *rtwdev,
+                                     struct rtw89_vif_link *rtwvif_link,
+                                     u16 punctured);
        int (*h2c_default_dmac_tbl)(struct rtw89_dev *rtwdev,
                                    struct rtw89_vif_link *rtwvif_link,
                                    struct rtw89_sta_link *rtwsta_link);
index 73a4ec988d165f1dfe28e7d61f1408c3676211bc..8230115c29b40b0fe68631d117a493d8588bd9a9 100644 (file)
@@ -3745,6 +3745,49 @@ fail:
 }
 EXPORT_SYMBOL(rtw89_fw_h2c_txtime_cmac_tbl_g7);
 
+int rtw89_fw_h2c_punctured_cmac_tbl_g7(struct rtw89_dev *rtwdev,
+                                      struct rtw89_vif_link *rtwvif_link,
+                                      u16 punctured)
+{
+       struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
+       u32 len = sizeof(*h2c);
+       struct sk_buff *skb;
+       int ret;
+
+       skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+       if (!skb) {
+               rtw89_err(rtwdev, "failed to alloc skb for punctured cmac g7\n");
+               return -ENOMEM;
+       }
+
+       skb_put(skb, len);
+       h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data;
+
+       h2c->c0 = le32_encode_bits(rtwvif_link->mac_id, CCTLINFO_G7_C0_MACID) |
+                 le32_encode_bits(1, CCTLINFO_G7_C0_OP);
+
+       h2c->w4 = le32_encode_bits(~punctured, CCTLINFO_G7_W4_ACT_SUBCH_CBW);
+       h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_ACT_SUBCH_CBW);
+
+       rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+                             H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
+                             H2C_FUNC_MAC_CCTLINFO_UD_G7, 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;
+}
+EXPORT_SYMBOL(rtw89_fw_h2c_punctured_cmac_tbl_g7);
+
 int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
                                 struct rtw89_sta_link *rtwsta_link)
 {
index 98be7e72c685be4521fefc050b32907c8cfb58b3..b64edc9e8abe78ac5d85f030de946b24c4dfd617 100644 (file)
@@ -4736,6 +4736,9 @@ int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
                                 struct rtw89_sta_link *rtwsta_link);
 int rtw89_fw_h2c_txtime_cmac_tbl_g7(struct rtw89_dev *rtwdev,
                                    struct rtw89_sta_link *rtwsta_link);
+int rtw89_fw_h2c_punctured_cmac_tbl_g7(struct rtw89_dev *rtwdev,
+                                      struct rtw89_vif_link *rtwvif_link,
+                                      u16 punctured);
 int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
                                 struct rtw89_sta_link *rtwsta_link);
 int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
@@ -5038,6 +5041,19 @@ int rtw89_chip_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
        return chip->ops->h2c_txtime_cmac_tbl(rtwdev, rtwsta_link);
 }
 
+static inline
+int rtw89_chip_h2c_punctured_cmac_tbl(struct rtw89_dev *rtwdev,
+                                     struct rtw89_vif_link *rtwvif_link,
+                                     u16 punctured)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+
+       if (!chip->ops->h2c_punctured_cmac_tbl)
+               return 0;
+
+       return chip->ops->h2c_punctured_cmac_tbl(rtwdev, rtwvif_link, punctured);
+}
+
 static inline
 int rtw89_chip_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
                          bool valid, struct ieee80211_ampdu_params *params)
index 96edaf8e9ec4a439feb3d1c007d1d417d75ceb05..393df2b0dcae6c14e7ff4022c860b966333424aa 100644 (file)
@@ -2546,6 +2546,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
        .h2c_assoc_cmac_tbl     = rtw89_fw_h2c_assoc_cmac_tbl,
        .h2c_ampdu_cmac_tbl     = NULL,
        .h2c_txtime_cmac_tbl    = rtw89_fw_h2c_txtime_cmac_tbl,
+       .h2c_punctured_cmac_tbl = NULL,
        .h2c_default_dmac_tbl   = NULL,
        .h2c_update_beacon      = rtw89_fw_h2c_update_beacon,
        .h2c_ba_cam             = rtw89_fw_h2c_ba_cam,
index 0496deb7278fd8f87cfb93a2bf1df8edbd992af8..3bbe2a808844e5299c130260e9134875e5743e6d 100644 (file)
@@ -2151,6 +2151,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
        .h2c_assoc_cmac_tbl     = rtw89_fw_h2c_assoc_cmac_tbl,
        .h2c_ampdu_cmac_tbl     = NULL,
        .h2c_txtime_cmac_tbl    = rtw89_fw_h2c_txtime_cmac_tbl,
+       .h2c_punctured_cmac_tbl = NULL,
        .h2c_default_dmac_tbl   = NULL,
        .h2c_update_beacon      = rtw89_fw_h2c_update_beacon,
        .h2c_ba_cam             = rtw89_fw_h2c_ba_cam,
index 389dfac26028aeae82c5a47e65027c3447a9294b..7ede07f7b1eb19524fd6ae1b4df83eba10097ab0 100644 (file)
@@ -851,6 +851,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
        .h2c_assoc_cmac_tbl     = rtw89_fw_h2c_assoc_cmac_tbl,
        .h2c_ampdu_cmac_tbl     = NULL,
        .h2c_txtime_cmac_tbl    = rtw89_fw_h2c_txtime_cmac_tbl,
+       .h2c_punctured_cmac_tbl = NULL,
        .h2c_default_dmac_tbl   = NULL,
        .h2c_update_beacon      = rtw89_fw_h2c_update_beacon,
        .h2c_ba_cam             = rtw89_fw_h2c_ba_cam,
index 06a06c190553439df458c5259de56f54ffdd9562..9427823aca2fba584f0f432a912e76e7001fa4d6 100644 (file)
@@ -717,6 +717,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
        .h2c_assoc_cmac_tbl     = rtw89_fw_h2c_assoc_cmac_tbl,
        .h2c_ampdu_cmac_tbl     = NULL,
        .h2c_txtime_cmac_tbl    = rtw89_fw_h2c_txtime_cmac_tbl,
+       .h2c_punctured_cmac_tbl = NULL,
        .h2c_default_dmac_tbl   = NULL,
        .h2c_update_beacon      = rtw89_fw_h2c_update_beacon,
        .h2c_ba_cam             = rtw89_fw_h2c_ba_cam,
index 6e27f1ff94dc33080d881c0dbf0cb3cda2481ca0..88cf8ea13e7c952651ce9c5d8c2277485ad51aef 100644 (file)
@@ -2971,6 +2971,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
        .h2c_assoc_cmac_tbl     = rtw89_fw_h2c_assoc_cmac_tbl,
        .h2c_ampdu_cmac_tbl     = NULL,
        .h2c_txtime_cmac_tbl    = rtw89_fw_h2c_txtime_cmac_tbl,
+       .h2c_punctured_cmac_tbl = NULL,
        .h2c_default_dmac_tbl   = NULL,
        .h2c_update_beacon      = rtw89_fw_h2c_update_beacon,
        .h2c_ba_cam             = rtw89_fw_h2c_ba_cam,
index e23655f3e4c102bea9c4652963571bb4a2a1aca5..36c641e3bc136f9a6790f73ec0cd95ee70f9562d 100644 (file)
@@ -2826,6 +2826,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
        .h2c_assoc_cmac_tbl     = rtw89_fw_h2c_assoc_cmac_tbl_g7,
        .h2c_ampdu_cmac_tbl     = rtw89_fw_h2c_ampdu_cmac_tbl_g7,
        .h2c_txtime_cmac_tbl    = rtw89_fw_h2c_txtime_cmac_tbl_g7,
+       .h2c_punctured_cmac_tbl = rtw89_fw_h2c_punctured_cmac_tbl_g7,
        .h2c_default_dmac_tbl   = rtw89_fw_h2c_default_dmac_tbl_v2,
        .h2c_update_beacon      = rtw89_fw_h2c_update_beacon_be,
        .h2c_ba_cam             = rtw89_fw_h2c_ba_cam_v1,