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>,
james-ly huang <james-ly.huang@mediatek.com>
Subject: [PATCH 1/9] wifi: mt76: mt7925: drop P2P mgmt frames received on foreign channel
Date: Wed, 4 Nov 2026 17:23:36 +0800 [thread overview]
Message-ID: <20261104092344.1932406-1-jb.tsai@mediatek.com> (raw)
From: james-ly huang <james-ly.huang@mediatek.com>
Start a dedicated p2p.c/p2p.h module for the P2P-only logic the
generic mt7925 data paths hook into, and put the RX-side filter
there first:
- a Probe Response received while P2P discovery walks the social
channels may carry IEs advertising a band/channel other than the
one it was received on (WFA P2P IE only) - drop it;
- an active P2P GO only cares about broadcast Probe Requests that
arrive on its own operating channel - drop foreign-channel ones.
mac.c hooks the filter in mt7925_queue_rx_skb() via the new
mt7925_p2p_rx_drop_chan_mismatch().
Signed-off-by: james-ly huang <james-ly.huang@mediatek.com>
---
.../wireless/mediatek/mt76/mt7925/Makefile | 2 +-
.../net/wireless/mediatek/mt76/mt7925/mac.c | 10 ++
.../net/wireless/mediatek/mt76/mt7925/p2p.c | 166 ++++++++++++++++++
.../net/wireless/mediatek/mt76/mt7925/p2p.h | 18 ++
4 files changed, 195 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/mediatek/mt76/mt7925/p2p.c
create mode 100644 drivers/net/wireless/mediatek/mt76/mt7925/p2p.h
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
index 33539121a15c..697a2bbce46c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_MT7925_COMMON) += mt7925-common.o
obj-$(CONFIG_MT7925E) += mt7925e.o
obj-$(CONFIG_MT7925U) += mt7925u.o
-mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o nan.o
+mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o nan.o p2p.o
mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt7925e-y := pci.o pci_mac.o pci_mcu.o cached_cal.o
mt7925u-y := usb.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index 7af996abe294..6e67ef3c52fa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -5,6 +5,7 @@
#include <linux/etherdevice.h>
#include <linux/timekeeping.h>
#include "mt7925.h"
+#include "p2p.h"
#include "../dma.h"
#include "regd.h"
#include "mac.h"
@@ -1459,6 +1460,15 @@ void mt7925_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
case PKT_TYPE_NORMAL_MCU:
case PKT_TYPE_NORMAL:
if (!mt7925_mac_fill_rx(dev, skb)) {
+ struct mt76_rx_status *status =
+ (struct mt76_rx_status *)skb->cb;
+
+ if (!(status->flag & RX_FLAG_8023) &&
+ mt7925_p2p_rx_drop_chan_mismatch(dev, skb)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
mt76_rx(&dev->mt76, q, skb);
return;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/p2p.c b/drivers/net/wireless/mediatek/mt76/mt7925/p2p.c
new file mode 100644
index 000000000000..12d6eee8ce10
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/p2p.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/* Copyright (C) 2026 MediaTek Inc. */
+
+/* Everything in this file is P2P-only logic that the generic mt7925 data
+ * paths hook into: RX-side filtering of foreign-channel discovery frames,
+ * TX-side TXD (lifetime / retry / timestamp) overrides for off-channel and
+ * GO Probe Response frames, the per-P2P-interface BMC wcid bookkeeping,
+ * the pre-grant .change_chanctx gate and the P2P-only MCU event handlers
+ * (SAP aging timeout, BSS absence).
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/units.h>
+#include <net/mac80211.h>
+
+#include "../mt76.h"
+#include "../mt76_connac.h"
+#include "../mt792x.h"
+#include "mt7925.h"
+#include "mac.h"
+#include "mcu.h"
+#include "p2p.h"
+
+/* ------------------------------------------------------------------ */
+/* RX: foreign-channel discovery frames */
+/* ------------------------------------------------------------------ */
+
+/* Channel number a management frame advertises in its own IEs: DSSS Parameter
+ * Set, or the HT Operation primary channel when there is no DS Params element.
+ */
+static u8 mt7925_rx_ie_chan(const u8 *ies, int ies_len)
+{
+ const struct ieee80211_ht_operation *ht_oper;
+ const struct element *elem;
+
+ elem = cfg80211_find_elem(WLAN_EID_DS_PARAMS, ies, ies_len);
+ if (elem && elem->datalen == 1)
+ return elem->data[0];
+
+ elem = cfg80211_find_elem(WLAN_EID_HT_OPERATION, ies, ies_len);
+ if (elem && elem->datalen >= sizeof(*ht_oper)) {
+ ht_oper = (const void *)elem->data;
+ return ht_oper->primary_chan;
+ }
+
+ return 0;
+}
+
+/* A Probe Response received while P2P discovery walks the social channels may
+ * carry IEs advertising a band/channel other than the one it was received on.
+ * Scope: only Probe Responses that carry the WFA P2P IE.
+ */
+static bool
+mt7925_rx_drop_p2p_probe_resp(struct sk_buff *skb,
+ struct mt76_rx_status *status)
+{
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ int hdr_len = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ const u8 *ies;
+ int ies_len;
+ u8 ie_chan;
+
+ if (skb->len <= hdr_len)
+ return false;
+
+ ies = mgmt->u.probe_resp.variable;
+ ies_len = skb->len - hdr_len;
+
+ if (!cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,
+ ies, ies_len))
+ return false;
+
+ ie_chan = mt7925_rx_ie_chan(ies, ies_len);
+ if (!ie_chan)
+ return false;
+
+ if (ieee80211_channel_to_frequency(ie_chan, status->band) ==
+ status->freq)
+ return false;
+
+ return true;
+}
+
+struct mt7925_rx_chan_iter_data {
+ u16 freq;
+ u8 band;
+ bool p2p_go_active;
+ bool chan_match;
+};
+
+static void mt7925_rx_chan_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct mt7925_rx_chan_iter_data *data = priv;
+ unsigned int link_id;
+
+ for (link_id = 0; link_id < ARRAY_SIZE(vif->link_conf); link_id++) {
+ struct ieee80211_chanctx_conf *ctx;
+ struct ieee80211_bss_conf *conf;
+
+ conf = rcu_dereference(vif->link_conf[link_id]);
+ if (!conf)
+ continue;
+
+ ctx = rcu_dereference(conf->chanctx_conf);
+ if (!ctx || !ctx->def.chan)
+ continue;
+
+ if (vif->type == NL80211_IFTYPE_AP && vif->p2p)
+ data->p2p_go_active = true;
+
+ if (ctx->def.chan->band == data->band &&
+ ctx->def.chan->center_freq == data->freq)
+ data->chan_match = true;
+ }
+}
+
+/* An active P2P GO only cares about broadcast Probe Requests that arrive on its
+ * own operating channel. Drop foreign-channel broadcast Probe Requests.
+ */
+static bool
+mt7925_rx_drop_go_probe_req(struct mt792x_dev *dev, struct sk_buff *skb,
+ struct mt76_rx_status *status)
+{
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+ struct mt7925_rx_chan_iter_data data = {
+ .freq = status->freq,
+ .band = status->band,
+ };
+
+ if (!is_broadcast_ether_addr(mgmt->da))
+ return false;
+
+ if (test_bit(MT76_STATE_ROC, &dev->mphy.state))
+ return false;
+
+ ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
+ IEEE80211_IFACE_ITER_RESUME_ALL,
+ mt7925_rx_chan_iter, &data);
+
+ if (!data.p2p_go_active || data.chan_match)
+ return false;
+
+ return true;
+}
+
+/* Drop management frames whose own notion of the channel contradicts the
+ * channel the hardware reported them on.
+ */
+bool
+mt7925_p2p_rx_drop_chan_mismatch(struct mt792x_dev *dev, struct sk_buff *skb)
+{
+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ if (skb->len < sizeof(struct ieee80211_hdr_3addr) || !status->freq)
+ return false;
+
+ if (ieee80211_is_probe_resp(hdr->frame_control))
+ return mt7925_rx_drop_p2p_probe_resp(skb, status);
+
+ if (ieee80211_is_probe_req(hdr->frame_control))
+ return mt7925_rx_drop_go_probe_req(dev, skb, status);
+
+ return false;
+}
+
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/p2p.h b/drivers/net/wireless/mediatek/mt76/mt7925/p2p.h
new file mode 100644
index 000000000000..ed51670d9633
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/p2p.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/* Copyright (C) 2026 MediaTek Inc. */
+
+#ifndef __MT7925_P2P_H
+#define __MT7925_P2P_H
+
+#include <net/mac80211.h>
+
+#include "../mt76.h"
+#include "../mt792x.h"
+
+/* TX/RX path overrides, BMC wcid bookkeeping and the P2P-only MCU event
+ * handlers.
+ */
+bool mt7925_p2p_rx_drop_chan_mismatch(struct mt792x_dev *dev,
+ struct sk_buff *skb);
+
+#endif /* __MT7925_P2P_H */
--
2.45.2
next reply other threads:[~2026-11-04 9:23 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 9:23 JB Tsai [this message]
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 ` [PATCH 9/9] wifi: mt76: mt7925: send the common scan IEs and size the request JB Tsai
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-1-jb.tsai@mediatek.com \
--to=jb.tsai@mediatek.com \
--cc=James-LY.Huang@mediatek.com \
--cc=Sean.Wang@mediatek.com \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-wireless@vger.kernel.org \
--cc=lorenzo@kernel.org \
--cc=nbd@nbd.name \
/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