mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
wifi: mac80211: update NAN data path state on schedule changes
A carrier of an NDI interface is turned on when there is at least one NDI station that: (1) correlates to this interface (2) is authorized (3) the NAN peer to which this station belongs has at least one common slot with the local schedule. Otherwise, it is turned off. (common slots are slots where both schedules are active on compatible channels.) Implement the calculation of the carrier state and trigger it when needed. Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260326121156.98ff4115406f.Ie796487ab9eb23cda819b0afac57e7267b134911@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
840492bf33
commit
e1d5c95456
|
|
@ -2502,7 +2502,15 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
test_sta_flag(sta, WLAN_STA_ASSOC))
|
||||
rate_control_rate_init_all_links(sta);
|
||||
|
||||
return sta_info_insert(sta);
|
||||
err = sta_info_insert(sta);
|
||||
|
||||
/*
|
||||
* ieee80211_nan_update_ndi_carrier was called from sta_apply_parameters,
|
||||
* but then we did not have the STA in the list.
|
||||
*/
|
||||
if (!err && sdata->vif.type == NL80211_IFTYPE_NAN_DATA)
|
||||
ieee80211_nan_update_ndi_carrier(sta->sdata);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ieee80211_del_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
|
|
|
|||
|
|
@ -2045,6 +2045,7 @@ int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata,
|
|||
int ieee80211_nan_set_peer_sched(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_nan_peer_sched *sched);
|
||||
void ieee80211_nan_free_peer_sched(struct ieee80211_nan_peer_sched *sched);
|
||||
void ieee80211_nan_update_ndi_carrier(struct ieee80211_sub_if_data *ndi_sdata);
|
||||
|
||||
/* scan/BSS handling */
|
||||
void ieee80211_scan_work(struct wiphy *wiphy, struct wiphy_work *work);
|
||||
|
|
|
|||
|
|
@ -220,6 +220,23 @@ ieee80211_nan_remove_channel(struct ieee80211_sub_if_data *sdata,
|
|||
ieee80211_free_chanctx(sdata->local, ctx, false);
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_nan_update_all_ndi_carriers(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
||||
/* Iterate all interfaces and update carrier for NDI interfaces */
|
||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||
if (!ieee80211_sdata_running(sdata) ||
|
||||
sdata->vif.type != NL80211_IFTYPE_NAN_DATA)
|
||||
continue;
|
||||
|
||||
ieee80211_nan_update_ndi_carrier(sdata);
|
||||
}
|
||||
}
|
||||
|
||||
static struct ieee80211_nan_channel *
|
||||
ieee80211_nan_find_free_channel(struct ieee80211_nan_sched_cfg *sched_cfg)
|
||||
{
|
||||
|
|
@ -347,6 +364,7 @@ int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata,
|
|||
if (sched_cfg->deferred)
|
||||
return 0;
|
||||
|
||||
ieee80211_nan_update_all_ndi_carriers(sdata->local);
|
||||
bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
|
||||
|
||||
return 0;
|
||||
|
|
@ -409,6 +427,7 @@ int ieee80211_nan_set_local_sched(struct ieee80211_sub_if_data *sdata,
|
|||
bitmap_zero(sdata->u.nan.removed_channels, IEEE80211_NAN_MAX_CHANNELS);
|
||||
|
||||
drv_vif_cfg_changed(sdata->local, sdata, BSS_CHANGED_NAN_LOCAL_SCHED);
|
||||
ieee80211_nan_update_all_ndi_carriers(sdata->local);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -423,6 +442,8 @@ void ieee80211_nan_sched_update_done(struct ieee80211_vif *vif)
|
|||
if (WARN_ON(!sched_cfg->deferred))
|
||||
return;
|
||||
|
||||
ieee80211_nan_update_all_ndi_carriers(sdata->local);
|
||||
|
||||
/*
|
||||
* Clear the deferred flag before removing channels. Removing channels
|
||||
* will trigger another schedule update to the driver, and there is no
|
||||
|
|
@ -531,6 +552,91 @@ ieee80211_nan_init_peer_map(struct ieee80211_nan_peer_sched *peer_sched,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the local schedule and a peer schedule have at least one common
|
||||
* slot - a slot where both schedules are active on compatible channels.
|
||||
*/
|
||||
static bool
|
||||
ieee80211_nan_has_common_slots(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_nan_peer_sched *peer_sched)
|
||||
{
|
||||
for (int slot = 0; slot < CFG80211_NAN_SCHED_NUM_TIME_SLOTS; slot++) {
|
||||
struct ieee80211_nan_channel *local_chan =
|
||||
sdata->vif.cfg.nan_sched.schedule[slot];
|
||||
|
||||
if (!local_chan || !local_chan->chanctx_conf)
|
||||
continue;
|
||||
|
||||
/* Check all peer maps for this slot */
|
||||
for (int m = 0; m < CFG80211_NAN_MAX_PEER_MAPS; m++) {
|
||||
struct ieee80211_nan_peer_map *map = &peer_sched->maps[m];
|
||||
struct ieee80211_nan_channel *peer_chan;
|
||||
|
||||
if (map->map_id == CFG80211_NAN_INVALID_MAP_ID)
|
||||
continue;
|
||||
|
||||
peer_chan = map->slots[slot];
|
||||
if (!peer_chan)
|
||||
continue;
|
||||
|
||||
if (local_chan->chanctx_conf == peer_chan->chanctx_conf)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ieee80211_nan_update_ndi_carrier(struct ieee80211_sub_if_data *ndi_sdata)
|
||||
{
|
||||
struct ieee80211_local *local = ndi_sdata->local;
|
||||
struct ieee80211_sub_if_data *nmi_sdata;
|
||||
struct sta_info *sta;
|
||||
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
||||
if (WARN_ON(ndi_sdata->vif.type != NL80211_IFTYPE_NAN_DATA ||
|
||||
!ndi_sdata->dev) || !ieee80211_sdata_running(ndi_sdata))
|
||||
return;
|
||||
|
||||
nmi_sdata = wiphy_dereference(local->hw.wiphy, ndi_sdata->u.nan_data.nmi);
|
||||
if (WARN_ON(!nmi_sdata))
|
||||
return;
|
||||
|
||||
list_for_each_entry(sta, &local->sta_list, list) {
|
||||
struct ieee80211_sta *nmi_sta;
|
||||
|
||||
if (sta->sdata != ndi_sdata ||
|
||||
!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
||||
continue;
|
||||
|
||||
nmi_sta = wiphy_dereference(local->hw.wiphy, sta->sta.nmi);
|
||||
if (WARN_ON(!nmi_sta) || !nmi_sta->nan_sched)
|
||||
continue;
|
||||
|
||||
if (ieee80211_nan_has_common_slots(nmi_sdata, nmi_sta->nan_sched)) {
|
||||
netif_carrier_on(ndi_sdata->dev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
netif_carrier_off(ndi_sdata->dev);
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211_nan_update_peer_ndis_carrier(struct ieee80211_local *local,
|
||||
struct sta_info *nmi_sta)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
||||
list_for_each_entry(sta, &local->sta_list, list) {
|
||||
if (rcu_access_pointer(sta->sta.nmi) == &nmi_sta->sta)
|
||||
ieee80211_nan_update_ndi_carrier(sta->sdata);
|
||||
}
|
||||
}
|
||||
|
||||
int ieee80211_nan_set_peer_sched(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_nan_peer_sched *sched)
|
||||
{
|
||||
|
|
@ -592,6 +698,8 @@ int ieee80211_nan_set_peer_sched(struct ieee80211_sub_if_data *sdata,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ieee80211_nan_update_peer_ndis_carrier(sdata->local, sta);
|
||||
|
||||
/* Success - free old schedule */
|
||||
to_free = old_sched;
|
||||
ret = 0;
|
||||
|
|
|
|||
|
|
@ -1454,6 +1454,8 @@ static int _sta_info_move_state(struct sta_info *sta,
|
|||
} else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
|
||||
ieee80211_vif_dec_num_mcast(sta->sdata);
|
||||
clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
|
||||
if (sta->sdata->vif.type == NL80211_IFTYPE_NAN_DATA)
|
||||
ieee80211_nan_update_ndi_carrier(sta->sdata);
|
||||
|
||||
/*
|
||||
* If we have encryption offload, flush (station) queues
|
||||
|
|
@ -1482,6 +1484,8 @@ static int _sta_info_move_state(struct sta_info *sta,
|
|||
set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
|
||||
ieee80211_check_fast_xmit(sta);
|
||||
ieee80211_check_fast_rx(sta);
|
||||
if (sta->sdata->vif.type == NL80211_IFTYPE_NAN_DATA)
|
||||
ieee80211_nan_update_ndi_carrier(sta->sdata);
|
||||
}
|
||||
if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
|
||||
sta->sdata->vif.type == NL80211_IFTYPE_AP)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user