blob: 2006b27967001b6ab2b48679bc5cb0e47d2550af [file] [log] [blame]
developerd7360ad2023-02-20 17:47:00 +08001From 8fdded8b5d47f1ab5fb7ab1fd2a4247cd81edad0 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 | 11 +++++++
11 net/wireless/chan.c | 60 ++++++++++++++++++++++++++++++++++++
12 4 files changed, 91 insertions(+)
13
14diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
15index b97ddbd..02ad2b2 100644
16--- a/include/net/cfg80211.h
17+++ b/include/net/cfg80211.h
18@@ -7641,6 +7641,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 e674aa7..3e348a5 100644
41--- a/include/uapi/linux/nl80211.h
42+++ b/include/uapi/linux/nl80211.h
43@@ -6294,6 +6294,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@@ -6302,6 +6306,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 8ee325a..48053e4 100644
65--- a/net/mac80211/mlme.c
66+++ b/net/mac80211/mlme.c
67@@ -1442,6 +1442,10 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
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+ &sdata->csa_chandef,
74+ sdata->vif.bss_conf.assoc);
75 cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
76 csa_ie.count, csa_ie.mode);
77
78@@ -2420,6 +2424,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
79 cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);
80
81 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
82+
83+ cfg80211_sta_update_dfs_state(&sdata->wdev,
84+ &sdata->vif.bss_conf.chandef,
85+ NULL, sdata->vif.bss_conf.assoc);
86 }
87
88 static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
89@@ -3782,6 +3790,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
90 event.u.mlme.status = MLME_SUCCESS;
91 drv_event_callback(sdata->local, sdata, &event);
92 sdata_info(sdata, "associated\n");
93+ cfg80211_sta_update_dfs_state(&sdata->wdev,
94+ &sdata->vif.bss_conf.chandef,
95+ NULL, sdata->vif.bss_conf.assoc);
96
97 /*
98 * destroy assoc_data afterwards, as otherwise an idle
99diff --git a/net/wireless/chan.c b/net/wireless/chan.c
100index 5f50ac4..0309758 100644
101--- a/net/wireless/chan.c
102+++ b/net/wireless/chan.c
103@@ -14,6 +14,7 @@
104 #include <net/cfg80211.h>
105 #include "core.h"
106 #include "rdev-ops.h"
107+#include "nl80211.h"
108
109 static bool cfg80211_valid_60g_freq(u32 freq)
110 {
111@@ -1386,3 +1387,62 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
112 return false;
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--
1752.18.0
176