wifi: mt76: mt7925: fix incorrect scan probe IE handling for hw_scan
authorMing Yen Hsieh <mingyen.hsieh@mediatek.com>
Mon, 16 Jun 2025 06:36:49 +0000 (14:36 +0800)
committerFelix Fietkau <nbd@nbd.name>
Mon, 7 Jul 2025 15:42:20 +0000 (17:42 +0200)
The IEs should be processed and filled into the command tlv separately
according to each band.

Cc: stable@vger.kernel.org
Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
Link: https://patch.msgid.link/20250616063649.1100503-1-mingyen.hsieh@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7925/main.c
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
drivers/net/wireless/mediatek/mt76/mt7925/mcu.h

index 94b0099dcd411b6064074135ca00c92a6792f07c..f0f1b1e4d507373e3bff6310ad758cd9d3f76902 100644 (file)
@@ -1481,7 +1481,7 @@ mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
        mt792x_mutex_acquire(dev);
 
-       err = mt7925_mcu_sched_scan_req(mphy, vif, req);
+       err = mt7925_mcu_sched_scan_req(mphy, vif, req, ies);
        if (err < 0)
                goto out;
 
index 0ba33409924a9dc5d79c493ec3d51e72c1ca2604..8ac6fbb736ab87de6a1486b98de87a2001b7d752 100644 (file)
@@ -164,6 +164,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
                               bool suspend, struct cfg80211_wowlan *wowlan)
 {
        struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
+       struct ieee80211_scan_ies ies = {};
        struct mt76_dev *dev = phy->dev;
        struct {
                struct {
@@ -194,7 +195,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
                req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT |
                                             UNI_WOW_DETECT_TYPE_BCN_LOST);
        if (wowlan->nd_config) {
-               mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config);
+               mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config, &ies);
                req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT;
                mt7925_mcu_sched_scan_enable(phy, vif, suspend);
        }
@@ -2818,6 +2819,54 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
        return err;
 }
 
+static void
+mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
+                            struct sk_buff *skb,
+                            struct ieee80211_scan_ies *scan_ies)
+{
+       u32 max_len = sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN;
+       struct scan_ie_tlv *ie;
+       enum nl80211_band i;
+       struct tlv *tlv;
+       const u8 *ies;
+       u16 ies_len;
+
+       for (i = 0; i <= NL80211_BAND_6GHZ; i++) {
+               if (i == NL80211_BAND_60GHZ)
+                       continue;
+
+               ies = scan_ies->ies[i];
+               ies_len = scan_ies->len[i];
+
+               if (!ies || !ies_len)
+                       continue;
+
+               if (ies_len > max_len)
+                       return;
+
+               tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE,
+                                             sizeof(*ie) + ies_len);
+               ie = (struct scan_ie_tlv *)tlv;
+
+               memcpy(ie->ies, ies, ies_len);
+               ie->ies_len = cpu_to_le16(ies_len);
+
+               switch (i) {
+               case NL80211_BAND_2GHZ:
+                       ie->band = 1;
+                       break;
+               case NL80211_BAND_6GHZ:
+                       ie->band = 3;
+                       break;
+               default:
+                       ie->band = 2;
+                       break;
+               }
+
+               max_len -= (sizeof(*ie) + ies_len);
+       }
+}
+
 int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
                       struct ieee80211_scan_request *scan_req)
 {
@@ -2843,7 +2892,8 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
 
        max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) +
                  sizeof(*bssid) * MT7925_RNR_SCAN_MAX_BSSIDS +
-                 sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie);
+                 sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie) +
+                 MT76_CONNAC_SCAN_IE_LEN;
 
        skb = mt76_mcu_msg_alloc(mdev, NULL, max_len);
        if (!skb)
@@ -2925,13 +2975,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
        }
        chan_info->channel_type = sreq->n_channels ? 4 : 0;
 
-       tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
-       ie = (struct scan_ie_tlv *)tlv;
-       if (sreq->ie_len > 0) {
-               memcpy(ie->ies, sreq->ie, sreq->ie_len);
-               ie->ies_len = cpu_to_le16(sreq->ie_len);
-       }
-
        req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
 
        tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_MISC, sizeof(*misc));
@@ -2942,6 +2985,9 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
                req->scan_func |= SCAN_FUNC_RANDOM_MAC;
        }
 
+       /* Append scan probe IEs as the last tlv */
+       mt7925_mcu_build_scan_ie_tlv(mdev, skb, &scan_req->ies);
+
        err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
                                    true);
        if (err < 0)
@@ -2953,7 +2999,8 @@ EXPORT_SYMBOL_GPL(mt7925_mcu_hw_scan);
 
 int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
                              struct ieee80211_vif *vif,
-                             struct cfg80211_sched_scan_request *sreq)
+                             struct cfg80211_sched_scan_request *sreq,
+                             struct ieee80211_scan_ies *ies)
 {
        struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
        struct ieee80211_channel **scan_list = sreq->channels;
@@ -3041,12 +3088,8 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
        }
        chan_info->channel_type = sreq->n_channels ? 4 : 0;
 
-       tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
-       ie = (struct scan_ie_tlv *)tlv;
-       if (sreq->ie_len > 0) {
-               memcpy(ie->ies, sreq->ie, sreq->ie_len);
-               ie->ies_len = cpu_to_le16(sreq->ie_len);
-       }
+       /* Append scan probe IEs as the last tlv */
+       mt7925_mcu_build_scan_ie_tlv(mdev, skb, ies);
 
        return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
                                     true);
index ee6fb16e83c5d700c197f1fdb17b6e971a650314..a40764d89a1ff439604012280c86b8c1045117cb 100644 (file)
@@ -269,7 +269,7 @@ struct scan_ie_tlv {
        __le16 ies_len;
        u8 band;
        u8 pad;
-       u8 ies[MT76_CONNAC_SCAN_IE_LEN];
+       u8 ies[];
 };
 
 struct scan_misc_tlv {
@@ -673,7 +673,8 @@ int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
                              struct ieee80211_vif *vif);
 int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
                              struct ieee80211_vif *vif,
-                             struct cfg80211_sched_scan_request *sreq);
+                             struct cfg80211_sched_scan_request *sreq,
+                             struct ieee80211_scan_ies *ies);
 int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
                                 struct ieee80211_vif *vif,
                                 bool enable);