When the local NAN schedule is configured, store its chandefs, it will be used later. Reviewed-by: Johannes Berg Signed-off-by: Miri Korenblit --- include/net/cfg80211.h | 2 ++ net/wireless/core.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/wireless/core.h | 4 ++++ net/wireless/nl80211.c | 2 +- 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 640a63395e84..7b8e408528a4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -6822,6 +6822,8 @@ struct wireless_dev { } ocb; struct { u8 cluster_id[ETH_ALEN] __aligned(2); + u8 n_channels; + struct cfg80211_chan_def *chandefs; } nan; } u; diff --git a/net/wireless/core.c b/net/wireless/core.c index e53e486b1449..0429ee8237e1 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -254,6 +254,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev) { + struct cfg80211_nan_local_sched empty_sched = {}; + lockdep_assert_held(&rdev->wiphy.mtx); if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN)) @@ -262,12 +264,51 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, if (!wdev_running(wdev)) return; + /* Unschedule all */ + cfg80211_nan_set_local_schedule(rdev, wdev, &empty_sched); + rdev_stop_nan(rdev, wdev); wdev->is_running = false; rdev->opencount--; } +int cfg80211_nan_set_local_schedule(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + struct cfg80211_nan_local_sched *sched) +{ + int ret; + + lockdep_assert_held(&rdev->wiphy.mtx); + + if (wdev->iftype != NL80211_IFTYPE_NAN || !wdev_running(wdev)) + return -EINVAL; + + ret = rdev_nan_set_local_sched(rdev, wdev, sched); + if (ret) + return ret; + + kfree(wdev->u.nan.chandefs); + wdev->u.nan.chandefs = NULL; + wdev->u.nan.n_channels = 0; + + if (!sched->n_channels) + return 0; + + wdev->u.nan.chandefs = kcalloc(sched->n_channels, + sizeof(*wdev->u.nan.chandefs), + GFP_KERNEL); + if (!wdev->u.nan.chandefs) + return -ENOMEM; + + for (int i = 0; i < sched->n_channels; i++) + wdev->u.nan.chandefs[i] = sched->nan_channels[i].chandef; + + wdev->u.nan.n_channels = sched->n_channels; + + return 0; +} + void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy) { struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); diff --git a/net/wireless/core.h b/net/wireless/core.h index 63dcf315dba7..463fbcefca49 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -545,6 +545,10 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev); +int cfg80211_nan_set_local_schedule(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + struct cfg80211_nan_local_sched *sched); + struct cfg80211_internal_bss * cfg80211_bss_update(struct cfg80211_registered_device *rdev, struct cfg80211_internal_bss *tmp, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0f9e0e931b5f..5831a9b7a2c8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -16393,7 +16393,7 @@ static int nl80211_nan_set_local_sched(struct sk_buff *skb, } } - return rdev_nan_set_local_sched(rdev, wdev, sched); + return cfg80211_nan_set_local_schedule(rdev, wdev, sched); } static int nl80211_get_protocol_features(struct sk_buff *skb, -- 2.34.1