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>
This commit is contained in:
Daniel Gabay 2026-05-06 06:44:27 +03:00 committed by Johannes Berg
parent 408f38d1e3
commit a6ea8948e3
4 changed files with 121 additions and 9 deletions

View File

@ -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 */;

View File

@ -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 \

View File

@ -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;
}

View File

@ -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 */