[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