blob: f14111cbb941ac5d1c64580fbc1ba0624be37c78 [file] [log] [blame]
developer8a6d4bd2023-06-12 13:23:37 +08001From e545285e24de95d0d620bb7e9c97abba39e363b9 Mon Sep 17 00:00:00 2001
2From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Mon, 20 Feb 2023 14:25:24 +0800
4Subject: [PATCH] mac80211: mtk: add sta-assisted DFS state update mechanism
5
6Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
7---
8 include/net/cfg80211.h | 14 +++++++++
9 include/uapi/linux/nl80211.h | 6 ++++
10 net/mac80211/mlme.c | 12 ++++++++
11 net/wireless/chan.c | 60 ++++++++++++++++++++++++++++++++++++
12 4 files changed, 92 insertions(+)
13
14diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
15index 84564bd..06d1567 100644
16--- a/include/net/cfg80211.h
17+++ b/include/net/cfg80211.h
18@@ -8180,6 +8180,20 @@ void cfg80211_cac_event(struct net_device *netdev,
19 const struct cfg80211_chan_def *chandef,
20 enum nl80211_radar_event event, gfp_t gfp);
21
22+/**
23+ * cfg80211_sta_update_dfs_state - Update channel's DFS state during STA channel switch,
24+ * association, and disassociation
25+ * @wdev: the wireless device
26+ * @bss_chandef: the current BSS channel definition
27+ * @csa_chandef: the CSA channel definition
28+ * @associated: whether STA is during association or disassociation process
29+ *
30+ */
31+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
32+ const struct cfg80211_chan_def *bss_chandef,
33+ const struct cfg80211_chan_def *csa_chandef,
34+ bool associated);
35+
36 /**
37 * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
38 * @wiphy: the wiphy
39diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
40index bd26a06..e453d64 100644
41--- a/include/uapi/linux/nl80211.h
42+++ b/include/uapi/linux/nl80211.h
43@@ -6565,6 +6565,10 @@ enum nl80211_smps_mode {
44 * applicable for ETSI dfs domain where pre-CAC is valid for ever.
45 * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
46 * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
47+ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
48+ * when receiving CSA/assoc resp
49+ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
50+ * when STA is disconnected or leaving the channel
51 */
52 enum nl80211_radar_event {
53 NL80211_RADAR_DETECTED,
54@@ -6573,6 +6577,8 @@ enum nl80211_radar_event {
55 NL80211_RADAR_NOP_FINISHED,
56 NL80211_RADAR_PRE_CAC_EXPIRED,
57 NL80211_RADAR_CAC_STARTED,
58+ NL80211_RADAR_STA_CAC_SKIPPED,
59+ NL80211_RADAR_STA_CAC_EXPIRED,
60 };
61
62 /**
63diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
64index 72d153f..5a3dd31 100644
65--- a/net/mac80211/mlme.c
66+++ b/net/mac80211/mlme.c
67@@ -1987,6 +1987,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
68 IEEE80211_QUEUE_STOP_REASON_CSA);
69 mutex_unlock(&local->mtx);
70
71+ cfg80211_sta_update_dfs_state(&sdata->wdev,
72+ &sdata->vif.bss_conf.chandef,
73+ &link->csa_chandef,
74+ sdata->vif.cfg.assoc);
75+
76 cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, 0,
77 csa_ie.count, csa_ie.mode, 0);
78
79@@ -3072,6 +3077,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
80 sizeof(sdata->vif.bss_conf.tx_pwr_env));
81
82 ieee80211_vif_set_links(sdata, 0);
83+
84+ cfg80211_sta_update_dfs_state(&sdata->wdev,
85+ &sdata->vif.bss_conf.chandef,
86+ NULL, sdata->vif.cfg.assoc);
87 }
88
89 static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
90@@ -5276,6 +5285,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
91 event.u.mlme.status = MLME_SUCCESS;
92 drv_event_callback(sdata->local, sdata, &event);
93 sdata_info(sdata, "associated\n");
94+ cfg80211_sta_update_dfs_state(&sdata->wdev,
95+ &sdata->vif.bss_conf.chandef,
96+ NULL, sdata->vif.cfg.assoc);
97
98 info.success = 1;
99 }
100diff --git a/net/wireless/chan.c b/net/wireless/chan.c
101index fef0ba5..13276bc 100644
102--- a/net/wireless/chan.c
103+++ b/net/wireless/chan.c
104@@ -14,6 +14,7 @@
105 #include <net/cfg80211.h>
106 #include "core.h"
107 #include "rdev-ops.h"
108+#include "nl80211.h"
109
110 static bool cfg80211_valid_60g_freq(u32 freq)
111 {
112@@ -1436,6 +1437,65 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
113 }
114 EXPORT_SYMBOL(cfg80211_any_usable_channels);
115
116+static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
117+ const struct cfg80211_chan_def *chandef,
118+ enum nl80211_radar_event event)
119+{
120+ struct wireless_dev *wdev;
121+
122+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
123+ if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
124+ nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
125+ event, wdev->netdev, GFP_KERNEL);
126+ return;
127+ }
128+ }
129+}
130+
131+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
132+ const struct cfg80211_chan_def *bss_chandef,
133+ const struct cfg80211_chan_def *csa_chandef,
134+ bool associated)
135+{
136+ bool csa_active = !!csa_chandef;
137+ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
138+ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
139+
140+ if (!bss_chandef)
141+ return;
142+
143+ /* assume csa channel is cac completed */
144+ if (csa_active &&
145+ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
146+ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
147+ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
148+ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
149+ NL80211_RADAR_STA_CAC_SKIPPED);
150+ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
151+ }
152+
153+ /* avoid updating the dfs state during nop */
154+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
155+ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
156+ return;
157+
158+ if (associated && !csa_active) {
159+ dfs_state = NL80211_DFS_AVAILABLE;
160+ event = NL80211_RADAR_STA_CAC_SKIPPED;
161+ }
162+
163+ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
164+ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
165+
166+ if (csa_active)
167+ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
168+ else
169+ netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
170+ (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
171+ associated ? "association" : "disassociation");
172+}
173+EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
174+
175 struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
176 unsigned int link_id)
177 {
178--
1792.18.0
180