[PATCH 03/23] wifi: mt76: mt7925: implement NAN MAC address randomization

Sean Wang sean.wang at kernel.org
Sun Sep 27 14:02:45 PDT 2026


From: Chengwei Yu <chengwei.yu at mediatek.com>

Add mt7925_nan_start/stop_mac_randomization() using a per-vif
delayed_work and period stored in struct mt792x_nan.

Per-vif (not per-dev) because the NAN iface combinations allow up
to two concurrent NAN_DATA vifs; a single dev-wide field would
silently lose randomization for the second NDI or let it overwrite
the first vif's pending work.

delayed_work (not timer_list) because the work function calls
mt7925_nan_set_nmi/ndi_address() which invokes mt76_mcu_send_msg()
with wait_resp=true; that can sleep, which is not allowed in softirq
context. This is consistent with scan_work, mlo_pm_work and ps_work
in this driver.

stop_mac_randomization() must be called without holding the dev
mutex since the work function acquires it. No caller is wired up
yet; the next patch does that in add/remove_interface.

Co-developed-by: Sean Wang <sean.wang at mediatek.com>
Signed-off-by: Sean Wang <sean.wang at mediatek.com>
Signed-off-by: Chengwei Yu <chengwei.yu at mediatek.com>
---
 .../net/wireless/mediatek/mt76/mt7925/nan.c   | 59 +++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7925/nan.h   |  7 +++
 drivers/net/wireless/mediatek/mt76/mt792x.h   |  9 +++
 3 files changed, 75 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/nan.c b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
index abbd3f7b081c..0b94bd4005d4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
@@ -745,6 +745,65 @@ int mt7925_nan_set_ndi_address(struct ieee80211_vif *vif,
 	return 0;
 }
 
+void mt7925_nan_mac_rand_work(struct work_struct *work)
+{
+	struct mt792x_vif *mvif = container_of(work, struct mt792x_vif,
+					       nan.mac_rand_work.work);
+	struct mt792x_dev *dev = mvif->phy->dev;
+	struct ieee80211_vif *vif =
+		container_of((void *)mvif, struct ieee80211_vif, drv_priv);
+	bool is_nmi = (vif->type == NL80211_IFTYPE_NAN);
+	u8 addr[ETH_ALEN];
+	int ret;
+
+	mt792x_mutex_acquire(dev);
+
+	if (!mvif->nan.mac_rand_period_sec)
+		goto out;
+
+	eth_random_addr(addr);
+
+	ret = is_nmi ? mt7925_nan_set_nmi_address(vif, dev, addr)
+		     : mt7925_nan_set_ndi_address(vif, dev, addr);
+
+	if (ret)
+		dev_err(dev->mt76.dev,
+			"NAN: failed to randomize %s address: %d\n",
+			is_nmi ? "NMI" : "NDI", ret);
+
+	ieee80211_queue_delayed_work(mt76_hw(dev), &mvif->nan.mac_rand_work,
+				     secs_to_jiffies(mvif->nan.mac_rand_period_sec));
+out:
+	mt792x_mutex_release(dev);
+}
+
+void mt7925_nan_start_mac_randomization(struct ieee80211_vif *vif,
+					u32 period_sec)
+{
+	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
+	struct mt792x_dev *dev = mvif->phy->dev;
+
+	if (!period_sec)
+		return;
+
+	mvif->nan.mac_rand_period_sec = period_sec;
+
+	ieee80211_queue_delayed_work(mt76_hw(dev), &mvif->nan.mac_rand_work, 0);
+}
+
+/*
+ * Must be called without holding the dev mutex: mt7925_nan_mac_rand_work()
+ * acquires it, so cancel_delayed_work_sync() here would deadlock against a
+ * concurrently running instance of that work otherwise.
+ */
+void mt7925_nan_stop_mac_randomization(struct ieee80211_vif *vif)
+{
+	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
+
+	mvif->nan.mac_rand_period_sec = 0;
+	cancel_delayed_work_sync(&mvif->nan.mac_rand_work);
+}
+
 static int mt7925_nan_avail_ctrl_tlv(struct sk_buff *skb,
 				     struct ieee80211_vif *vif)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/nan.h b/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
index 9fd349e1cdab..191134825c3b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
@@ -503,6 +503,13 @@ int mt7925_nan_set_ndi_address(struct ieee80211_vif *vif,
 			       struct mt792x_dev *dev,
 			       const u8 *mac_address);
 
+void mt7925_nan_mac_rand_work(struct work_struct *work);
+
+void mt7925_nan_start_mac_randomization(struct ieee80211_vif *vif,
+					u32 period_sec);
+
+void mt7925_nan_stop_mac_randomization(struct ieee80211_vif *vif);
+
 void mt7925_nan_local_sched_changed(struct mt792x_dev *dev,
 				    struct ieee80211_vif *vif);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 9722d840c1af..64cca8852359 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -181,6 +181,15 @@ struct mt792x_nan {
 
 	/* Connection index bitmap, up to NAN_MAX_CONN_CFG peers */
 	unsigned long conn_bitmap;
+
+	/*
+	 * NMI/NDI MAC address randomization. Kept per-vif (rather than a
+	 * single pointer on mt792x_dev) because up to two NAN_DATA vifs can
+	 * coexist (see if_limits_nan_mcc/scc), each needing its own
+	 * independent randomization period and pending work.
+	 */
+	struct delayed_work mac_rand_work;
+	u32 mac_rand_period_sec;
 };
 
 struct mt792x_vif {
-- 
2.43.0




More information about the Linux-mediatek mailing list