Linux-mediatek Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/9] wifi: mt76: mt7925: drop P2P mgmt frames received on foreign channel
@ 2026-11-04  9:23 JB Tsai
  2026-11-04  9:23 ` [PATCH 2/9] wifi: mt76: mt7925: bound P2P off-channel mgmt TX lifetime JB Tsai
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: JB Tsai @ 2026-11-04  9:23 UTC (permalink / raw)
  To: nbd, lorenzo
  Cc: linux-wireless, linux-mediatek, Sean.Wang, James-LY.Huang,
	jb.tsai, james-ly huang

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



^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-11-06  0:34 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 9/9] wifi: mt76: mt7925: send the common scan IEs and size the request JB Tsai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox