From: JB Tsai <jb.tsai@mediatek.com>
To: <nbd@nbd.name>, <lorenzo@kernel.org>
Cc: <linux-wireless@vger.kernel.org>,
<linux-mediatek@lists.infradead.org>, <Sean.Wang@mediatek.com>,
<James-LY.Huang@mediatek.com>, <jb.tsai@mediatek.com>,
Jacobs Wu <jacobs.wu@mediatek.com>, <stable@vger.kernel.org>
Subject: [PATCH 9/9] wifi: mt76: mt7925: send the common scan IEs and size the request
Date: Wed, 4 Nov 2026 17:23:44 +0800 [thread overview]
Message-ID: <20261104092344.1932406-9-jb.tsai@mediatek.com> (raw)
In-Reply-To: <20261104092344.1932406-1-jb.tsai@mediatek.com>
From: Jacobs Wu <jacobs.wu@mediatek.com>
mt7925_mcu_build_scan_ie_tlv() sends the per-band sets of
struct ieee80211_scan_ies but not scan_ies->common_ies. mac80211 puts
only the band capabilities, and the custom IEs that must precede them,
into the per-band sets; every other custom IE of the request, the
vendor specific elements (P2P, WPS, MBO, ...) included, goes to
common_ies. Since commit 9f8f4a51f3c1 ("wifi: mt76: mt7925: fix
incorrect scan probe IE handling for hw_scan") these IEs are missing
from the probe requests.
Send common_ies in a UNI_SCAN_IE TLV without a band: the firmware
appends such a TLV to the probe requests of every band. It keeps up to
MT76_CONNAC_SCAN_IE_LEN bytes of it, which max_scan_ie_len already
guarantees for hw_scan; sched_scan shares the TLV, so give it the same
limit instead of the IEEE80211_MAX_DATA_LEN of the connac devices that
have a sched_scan command of their own. The per-band TLVs keep carrying
the per-band sets; the firmware stores their length in a byte, so a
longer set is left out instead of being truncated.
Size the request for the IEs it carries. hw_scan reserved a fixed
sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN, which the
per-band TLVs of a request can exceed, and sched_scan reserved nothing
beyond the TLV header since struct scan_ie_tlv lost its ies[] array, so
mt76_connac_mcu_add_tlv() put the TLVs past the end of the buffer,
which skb_put() turns into a panic, whenever the kmalloc slack did not
happen to cover them. The builder now checks the tailroom of the skb
instead of a budget of its own.
Fixes: 9f8f4a51f3c1 ("wifi: mt76: mt7925: fix incorrect scan probe IE handling for hw_scan")
Cc: stable@vger.kernel.org
Signed-off-by: Jacobs Wu <jacobs.wu@mediatek.com>
---
.../net/wireless/mediatek/mt76/mt7925/init.c | 5 +
.../net/wireless/mediatek/mt76/mt7925/mcu.c | 107 ++++++++++++------
2 files changed, 79 insertions(+), 33 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/init.c b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
index 8c3049b66a85..05305f4e1db8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/init.c
@@ -301,6 +301,11 @@ int mt7925_register_device(struct mt792x_dev *dev)
if (ret)
return ret;
+ /* hw_scan and sched_scan share the UNI_SCAN_IE TLV, and the firmware
+ * keeps at most MT76_CONNAC_SCAN_IE_LEN bytes of IEs for either.
+ */
+ hw->wiphy->max_sched_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
+
hw->wiphy->reg_notifier = mt7925_regd_notifier;
dev->mphy.sband_2g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 24de2ff3a15d..22a6338acaf1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -3347,56 +3347,99 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
}
EXPORT_SYMBOL_GPL(mt7925_mcu_set_dbdc);
+/* Room for a UNI_SCAN_IE TLV carrying ies_len bytes of IEs */
+static u32
+mt7925_mcu_scan_ie_tlv_len(struct mt76_dev *mdev, u32 ies_len)
+{
+ u32 len = sizeof(struct scan_ie_tlv) + ies_len;
+
+ if (is_mt7928(mdev))
+ len = ALIGN(len, 4);
+
+ return len;
+}
+
+/* Room for the UNI_SCAN_IE TLVs of a scan request */
+static u32
+mt7925_mcu_scan_ies_len(struct mt76_dev *mdev,
+ struct ieee80211_scan_ies *scan_ies)
+{
+ enum nl80211_band i;
+ u32 len = 0;
+
+ if (scan_ies->common_ie_len)
+ len += mt7925_mcu_scan_ie_tlv_len(mdev, scan_ies->common_ie_len);
+
+ for (i = 0; i <= NL80211_BAND_6GHZ; i++) {
+ if (i == NL80211_BAND_60GHZ || !scan_ies->len[i])
+ continue;
+
+ len += mt7925_mcu_scan_ie_tlv_len(mdev, scan_ies->len[i]);
+ }
+
+ return len;
+}
+
+static void
+mt7925_mcu_add_scan_ie_tlv(struct mt76_dev *mdev, struct sk_buff *skb,
+ u8 band, const u8 *ies, u32 ies_len)
+{
+ u32 alloc_len = mt7925_mcu_scan_ie_tlv_len(mdev, ies_len);
+ struct scan_ie_tlv *ie;
+ struct tlv *tlv;
+
+ if (alloc_len > skb_tailroom(skb))
+ return;
+
+ tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, alloc_len);
+ ie = (struct scan_ie_tlv *)tlv;
+
+ memcpy(ie->ies, ies, ies_len);
+ ie->ies_len = cpu_to_le16(ies_len);
+ ie->band = band;
+}
+
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;
- u32 ies_len, alloc_len;
- struct scan_ie_tlv *ie;
enum nl80211_band i;
- struct tlv *tlv;
- const u8 *ies;
+
+ /* The firmware appends a TLV without a band to the probe requests
+ * of every band: that is where the common IEs of the request go.
+ */
+ if (scan_ies->common_ie_len)
+ mt7925_mcu_add_scan_ie_tlv(mdev, skb, 0, scan_ies->common_ies,
+ scan_ies->common_ie_len);
for (i = 0; i <= NL80211_BAND_6GHZ; i++) {
+ u8 band;
+
if (i == NL80211_BAND_60GHZ)
continue;
- ies = scan_ies->ies[i];
- ies_len = scan_ies->len[i];
-
- if (!ies || !ies_len)
+ if (!scan_ies->ies[i] || !scan_ies->len[i])
continue;
- if (is_mt7928(mdev))
- alloc_len = ALIGN(sizeof(*ie) + ies_len, 4);
- else
- alloc_len = sizeof(*ie) + ies_len;
-
- if (alloc_len > max_len)
- return;
-
- tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE,
- alloc_len);
- ie = (struct scan_ie_tlv *)tlv;
-
- memcpy(ie->ies, ies, ies_len);
- ie->ies_len = cpu_to_le16(ies_len);
+ /* The firmware keeps the length of a per-band set in a byte */
+ if (scan_ies->len[i] > U8_MAX)
+ continue;
switch (i) {
case NL80211_BAND_2GHZ:
- ie->band = 1;
+ band = 1;
break;
case NL80211_BAND_6GHZ:
- ie->band = 3;
+ band = 3;
break;
default:
- ie->band = 2;
+ band = 2;
break;
}
- max_len -= alloc_len;
+ mt7925_mcu_add_scan_ie_tlv(mdev, skb, band, scan_ies->ies[i],
+ scan_ies->len[i]);
}
}
@@ -3415,7 +3458,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct scan_ssid_tlv *ssid;
struct scan_bssid_tlv *bssid;
struct scan_chan_info_tlv *chan_info;
- struct scan_ie_tlv *ie;
struct scan_misc_tlv *misc;
struct tlv *tlv;
int max_len;
@@ -3425,8 +3467,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) +
- MT76_CONNAC_SCAN_IE_LEN;
+ sizeof(*chan_info) + sizeof(*misc) +
+ mt7925_mcu_scan_ies_len(mdev, &scan_req->ies);
skb = mt76_mcu_msg_alloc(mdev, NULL, max_len);
if (!skb)
@@ -3546,15 +3588,14 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
struct scan_sched_req *req;
struct scan_ssid_tlv *ssid;
struct scan_chan_info_tlv *chan_info;
- struct scan_ie_tlv *ie;
struct scan_sched_ssid_match_sets *match;
struct sk_buff *skb;
struct tlv *tlv;
int i, max_len;
max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) +
- sizeof(*chan_info) + sizeof(*ie) +
- sizeof(*match);
+ sizeof(*chan_info) + sizeof(*match) +
+ mt7925_mcu_scan_ies_len(mdev, ies);
skb = mt76_mcu_msg_alloc(mdev, NULL, max_len);
if (!skb)
--
2.45.2
prev parent reply other threads:[~2026-11-04 9:24 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 9:23 [PATCH 1/9] wifi: mt76: mt7925: drop P2P mgmt frames received on foreign channel JB Tsai
2026-11-04 9:23 ` [PATCH 2/9] wifi: mt76: mt7925: bound P2P off-channel mgmt TX lifetime JB Tsai
2026-11-04 9:23 ` [PATCH 3/9] wifi: mt76: mt7925: give every P2P interface a BMC wcid of its own JB Tsai
2026-11-04 9:23 ` [PATCH 4/9] wifi: mt76: mt7925: harden the ROC channel-grant handshake JB Tsai
2026-11-04 9:23 ` [PATCH 5/9] wifi: mt76: mt7925: describe the real chandef in ROC requests JB Tsai
2026-11-04 9:23 ` [PATCH 6/9] wifi: mt76: mt7925: request the channel before programming a GO BSS JB Tsai
2026-11-04 9:23 ` [PATCH 7/9] wifi: mt76: mt7925: inject the deauth for an aging-timeout SAP event JB Tsai
2026-11-06 0:34 ` kernel test robot
2026-11-04 9:23 ` [PATCH 8/9] wifi: mt76: mt7925: track BSS absence and drop stale GO probe responses JB Tsai
2026-11-04 9:23 ` JB Tsai [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261104092344.1932406-9-jb.tsai@mediatek.com \
--to=jb.tsai@mediatek.com \
--cc=James-LY.Huang@mediatek.com \
--cc=Sean.Wang@mediatek.com \
--cc=jacobs.wu@mediatek.com \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-wireless@vger.kernel.org \
--cc=lorenzo@kernel.org \
--cc=nbd@nbd.name \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox