Introduce cfg80211_cac_offchan_event routine in order to notify userland when a Channel Availability Check (CAC) is finished, started or aborted by a offchannel dedicated chain. Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> --- include/net/cfg80211.h | 13 ++++++++++ net/wireless/mlme.c | 57 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3bb76835f4b1..8d075e11a1f8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -7646,6 +7646,19 @@ void cfg80211_cac_event(struct net_device *netdev, const struct cfg80211_chan_def *chandef, enum nl80211_radar_event event, gfp_t gfp); +/** + * cfg80211_offchan_cac_event - Channel Availability Check (CAC) offchan event + * @wiphy: the wiphy + * @chandef: chandef for the current channel + * @event: type of event + * @gfp: context flags + * + * This function is called when a Channel Availability Check (CAC) is finished, + * started or aborted by a offchannel dedicated chain. + */ +void cfg80211_offchan_cac_event(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, + enum nl80211_radar_event event, gfp_t gfp); /** * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 053293f51188..9f379a91d7fd 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -969,6 +969,57 @@ void cfg80211_cac_event(struct net_device *netdev, } EXPORT_SYMBOL(cfg80211_cac_event); +static void +__cfg80211_offchan_cac_event(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, + const struct cfg80211_chan_def *chandef, + enum nl80211_radar_event event, gfp_t gfp) +{ + struct wiphy *wiphy = &rdev->wiphy; + struct net_device *netdev; + + lockdep_assert_held(&rdev->offchan_mutex); + + if (event != NL80211_RADAR_CAC_STARTED && !rdev->offchan_radar_wdev) + return; + + switch (event) { + case NL80211_RADAR_CAC_FINISHED: + cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); + memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef)); + queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); + cfg80211_sched_dfs_chan_update(rdev); + wdev = rdev->offchan_radar_wdev; + rdev->offchan_radar_wdev = NULL; + break; + case NL80211_RADAR_CAC_ABORTED: + wdev = rdev->offchan_radar_wdev; + rdev->offchan_radar_wdev = NULL; + break; + case NL80211_RADAR_CAC_STARTED: + WARN_ON(!wdev); + rdev->offchan_radar_wdev = wdev; + break; + default: + return; + } + + netdev = wdev ? wdev->netdev : NULL; + nl80211_radar_notify(rdev, chandef, event, netdev, gfp); +} + +void cfg80211_offchan_cac_event(struct wiphy *wiphy, + const struct cfg80211_chan_def *chandef, + enum nl80211_radar_event event, gfp_t gfp) +{ + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + + mutex_lock(&rdev->offchan_mutex); + __cfg80211_offchan_cac_event(rdev, NULL, chandef, event, gfp); + mutex_unlock(&rdev->offchan_mutex); +} +EXPORT_SYMBOL(cfg80211_offchan_cac_event); + int cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, @@ -984,7 +1035,8 @@ cfg80211_start_offchan_radar_detection(struct cfg80211_registered_device *rdev, if (err) goto out; - rdev->offchan_radar_wdev = wdev; + __cfg80211_offchan_cac_event(rdev, wdev, chandef, + NL80211_RADAR_CAC_STARTED, GFP_KERNEL); out: mutex_unlock(&rdev->offchan_mutex); return err; @@ -1003,7 +1055,8 @@ cfg80211_stop_offchan_radar_detection(struct cfg80211_registered_device *rdev) if (err) goto out; - rdev->offchan_radar_wdev = NULL; + __cfg80211_offchan_cac_event(rdev, NULL, NULL, + NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); out: mutex_unlock(&rdev->offchan_mutex); return err; -- 2.31.1