summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Gabay <daniel.gabay@intel.com>2026-05-06 06:44:27 +0300
committerJohannes Berg <johannes.berg@intel.com>2026-05-06 11:41:50 +0200
commita6ea8948e3c3ebec6146655e868e85b8613260eb (patch)
treef9dd7fb3e3b931e958264cd84680d28a4fe5cca3
parent408f38d1e3071a9813bf1a760c1a465b80230c7e (diff)
downloadlinux-a6ea8948e3c3ebec6146655e868e85b8613260eb.tar.gz
linux-a6ea8948e3c3ebec6146655e868e85b8613260eb.zip
wifi: mac80211_hwsim: implement NAN schedule callbacks
Implement mac80211 schedule callbacks for NAN Data Path support: - Track local schedule via BSS_CHANGED_NAN_LOCAL_SCHED, caching the channel for each 16TU time slot. - Copy peer schedule to driver-private storage in nan_peer_sched_changed callback for use in TX availability decisions. Signed-off-by: Daniel Gabay <daniel.gabay@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260506064301.f3ad9e3dc9d4.I75cf3555b7506d5b8bb30e70a0f3721ab73477cb@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim_i.h21
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim_main.c14
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim_nan.c80
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim_nan.h15
4 files changed, 121 insertions, 9 deletions
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_i.h b/drivers/net/wireless/virtual/mac80211_hwsim_i.h
index d182b5117bfb..0f0f2ac6d80e 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_i.h
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_i.h
@@ -14,6 +14,27 @@
#include "mac80211_hwsim.h"
#include "mac80211_hwsim_nan.h"
+struct hwsim_sta_nan_sched {
+ /* Later members are protected by this lock */
+ spinlock_t lock;
+ u16 committed_dw;
+ struct {
+ u8 map_id;
+ struct cfg80211_chan_def chans[CFG80211_NAN_SCHED_NUM_TIME_SLOTS];
+ } maps[CFG80211_NAN_MAX_PEER_MAPS];
+};
+
+struct hwsim_sta_priv {
+ u32 magic;
+ unsigned int last_link;
+ u16 active_links_rx;
+
+ /* NAN peer schedule - must be accessed under nan_sched.lock */
+ struct hwsim_sta_nan_sched nan_sched;
+};
+
+#define HWSIM_STA_MAGIC 0x6d537749
+
struct mac80211_hwsim_link_data {
u32 link_id;
u64 beacon_int /* beacon interval in us */;
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
index fc940b38c52c..1ea33ec577dd 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
@@ -252,14 +252,6 @@ static inline void hwsim_clear_magic(struct ieee80211_vif *vif)
vp->magic = 0;
}
-struct hwsim_sta_priv {
- u32 magic;
- unsigned int last_link;
- u16 active_links_rx;
-};
-
-#define HWSIM_STA_MAGIC 0x6d537749
-
static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
{
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
@@ -2652,6 +2644,9 @@ static void mac80211_hwsim_vif_info_changed(struct ieee80211_hw *hw,
vp->aid = vif->cfg.aid;
}
+ if (changed & BSS_CHANGED_NAN_LOCAL_SCHED)
+ mac80211_hwsim_nan_local_sched_changed(hw, vif);
+
if (vif->type == NL80211_IFTYPE_STATION &&
changed & (BSS_CHANGED_MLD_VALID_LINKS | BSS_CHANGED_MLD_TTLM)) {
u16 usable_links = ieee80211_vif_usable_links(vif);
@@ -2818,6 +2813,8 @@ static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
sp->active_links_rx = sta->valid_links;
}
+ spin_lock_init(&sp->nan_sched.lock);
+
return 0;
}
@@ -4245,6 +4242,7 @@ static int mac80211_hwsim_set_radar_background(struct ieee80211_hw *hw,
.start_nan = mac80211_hwsim_nan_start, \
.stop_nan = mac80211_hwsim_nan_stop, \
.nan_change_conf = mac80211_hwsim_nan_change_config, \
+ .nan_peer_sched_changed = mac80211_hwsim_nan_peer_sched_changed, \
HWSIM_DEBUGFS_OPS
#define HWSIM_NON_MLO_OPS \
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_nan.c b/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
index 6053b6f8f91f..16883edd2215 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
@@ -1008,3 +1008,83 @@ bool mac80211_hwsim_nan_receive(struct ieee80211_hw *hw,
return false;
}
+
+void mac80211_hwsim_nan_local_sched_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct mac80211_hwsim_data *data = hw->priv;
+ struct ieee80211_nan_channel **slots = vif->cfg.nan_sched.schedule;
+
+ if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
+ return;
+
+ spin_lock_bh(&data->nan.state_lock);
+
+ for (int i = 0; i < ARRAY_SIZE(data->nan.local_sched); i++) {
+ struct ieee80211_chanctx_conf *chanctx;
+
+ if (!slots[i] || IS_ERR(slots[i])) {
+ memset(&data->nan.local_sched[i], 0,
+ sizeof(data->nan.local_sched[i]));
+ continue;
+ }
+
+ chanctx = slots[i]->chanctx_conf;
+ if (!chanctx) {
+ memset(&data->nan.local_sched[i], 0,
+ sizeof(data->nan.local_sched[i]));
+ continue;
+ }
+
+ data->nan.local_sched[i] = chanctx->def;
+ }
+
+ spin_unlock_bh(&data->nan.state_lock);
+}
+
+int mac80211_hwsim_nan_peer_sched_changed(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta)
+{
+ struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
+ struct ieee80211_nan_peer_sched *sched = sta->nan_sched;
+
+ spin_lock_bh(&sp->nan_sched.lock);
+
+ /* Clear existing schedule */
+ sp->nan_sched.committed_dw = 0;
+ for (int i = 0; i < CFG80211_NAN_MAX_PEER_MAPS; i++) {
+ sp->nan_sched.maps[i].map_id = CFG80211_NAN_INVALID_MAP_ID;
+ memset(sp->nan_sched.maps[i].chans, 0,
+ sizeof(sp->nan_sched.maps[i].chans));
+ }
+
+ if (!sched)
+ goto out;
+
+ sp->nan_sched.committed_dw = sched->committed_dw;
+
+ for (int i = 0; i < CFG80211_NAN_MAX_PEER_MAPS; i++) {
+ struct ieee80211_nan_peer_map *map = &sched->maps[i];
+
+ if (map->map_id == CFG80211_NAN_INVALID_MAP_ID)
+ continue;
+
+ sp->nan_sched.maps[i].map_id = map->map_id;
+
+ for (int j = 0; j < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; j++) {
+ struct ieee80211_nan_channel *peer_chan =
+ map->slots[j];
+
+ if (peer_chan && peer_chan->chanreq.oper.chan)
+ sp->nan_sched.maps[i].chans[j] =
+ peer_chan->chanreq.oper;
+ else
+ memset(&sp->nan_sched.maps[i].chans[j], 0,
+ sizeof(sp->nan_sched.maps[i].chans[j]));
+ }
+ }
+
+out:
+ spin_unlock_bh(&sp->nan_sched.lock);
+ return 0;
+}
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_nan.h b/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
index 3199e5c5376b..eb53bacee206 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* mac80211_hwsim_nan - NAN software simulation for mac80211_hwsim
- * Copyright (C) 2025 Intel Corporation
+ * Copyright (C) 2025-2026 Intel Corporation
*/
#ifndef __MAC80211_HWSIM_NAN_H
@@ -52,6 +52,13 @@ struct mac80211_hwsim_nan_data {
bool tsf_adjusted;
bool tsf_discontinuity;
+
+ /*
+ * Local schedule - stores channel definition for each 16TU slot.
+ * Derived from NMI vif->cfg.nan_schedule. chan == NULL means not
+ * available in that slot (except DW which is implicit).
+ */
+ struct cfg80211_chan_def local_sched[CFG80211_NAN_SCHED_NUM_TIME_SLOTS];
};
enum hrtimer_restart
@@ -73,6 +80,9 @@ int mac80211_hwsim_nan_change_config(struct ieee80211_hw *hw,
struct cfg80211_nan_conf *conf,
u32 changes);
+int mac80211_hwsim_nan_peer_sched_changed(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta);
+
bool mac80211_hwsim_nan_txq_transmitting(struct ieee80211_hw *hw,
struct ieee80211_txq *txq);
@@ -86,4 +96,7 @@ bool mac80211_hwsim_nan_receive(struct ieee80211_hw *hw,
void mac80211_hwsim_nan_rx(struct ieee80211_hw *hw,
struct sk_buff *skb);
+void mac80211_hwsim_nan_local_sched_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+
#endif /* __MAC80211_HWSIM_NAN_H */