diff mbox series

[v2,mac80211-next,4/6] cfg80211: introduce cfg80211_cac_offchan_event routine

Message ID 85fa50f57fc3adb2934c8d9ca0be30394de6b7e8.1634979655.git.lorenzo@kernel.org (mailing list archive)
State Accepted
Delegated to: Johannes Berg
Headers show
Series add offchannel radar chain support | expand

Commit Message

Lorenzo Bianconi Oct. 23, 2021, 9:10 a.m. UTC
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@kernel.org>
---
 include/net/cfg80211.h | 13 ++++++++++
 net/wireless/mlme.c    | 57 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 68 insertions(+), 2 deletions(-)
diff mbox series

Patch

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;