blob: c0bd42fc640984af9f4560633fbad753229025d2 [file] [log] [blame]
developer1d9da7d2023-04-15 12:45:34 +08001From 49f5a07866ca6a6be26cec9886e702d54308a78c Mon Sep 17 00:00:00 2001
developerd7360ad2023-02-20 17:47:00 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Mon, 20 Feb 2023 14:25:24 +0800
developered7222c2023-04-14 07:19:52 +08004Subject: [PATCH 13/17] mac80211: mtk: add sta-assisted DFS state update
5 mechanism
developerd7360ad2023-02-20 17:47:00 +08006
7Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
8---
9 include/net/cfg80211.h | 14 +++++++++
10 include/uapi/linux/nl80211.h | 6 ++++
11 net/mac80211/mlme.c | 11 +++++++
12 net/wireless/chan.c | 60 ++++++++++++++++++++++++++++++++++++
13 4 files changed, 91 insertions(+)
14
15diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
16index b97ddbd..02ad2b2 100644
17--- a/include/net/cfg80211.h
18+++ b/include/net/cfg80211.h
19@@ -7641,6 +7641,20 @@ void cfg80211_cac_event(struct net_device *netdev,
20 const struct cfg80211_chan_def *chandef,
21 enum nl80211_radar_event event, gfp_t gfp);
22
23+/**
24+ * cfg80211_sta_update_dfs_state - Update channel's DFS state during STA channel switch,
25+ * association, and disassociation
26+ * @wdev: the wireless device
27+ * @bss_chandef: the current BSS channel definition
28+ * @csa_chandef: the CSA channel definition
29+ * @associated: whether STA is during association or disassociation process
30+ *
31+ */
32+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
33+ const struct cfg80211_chan_def *bss_chandef,
34+ const struct cfg80211_chan_def *csa_chandef,
35+ bool associated);
36+
37 /**
38 * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
39 * @wiphy: the wiphy
40diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
41index e674aa7..3e348a5 100644
42--- a/include/uapi/linux/nl80211.h
43+++ b/include/uapi/linux/nl80211.h
44@@ -6294,6 +6294,10 @@ enum nl80211_smps_mode {
45 * applicable for ETSI dfs domain where pre-CAC is valid for ever.
46 * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
47 * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
48+ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
49+ * when receiving CSA/assoc resp
50+ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
51+ * when STA is disconnected or leaving the channel
52 */
53 enum nl80211_radar_event {
54 NL80211_RADAR_DETECTED,
55@@ -6302,6 +6306,8 @@ enum nl80211_radar_event {
56 NL80211_RADAR_NOP_FINISHED,
57 NL80211_RADAR_PRE_CAC_EXPIRED,
58 NL80211_RADAR_CAC_STARTED,
59+ NL80211_RADAR_STA_CAC_SKIPPED,
60+ NL80211_RADAR_STA_CAC_EXPIRED,
61 };
62
63 /**
64diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
65index 8ee325a..48053e4 100644
66--- a/net/mac80211/mlme.c
67+++ b/net/mac80211/mlme.c
68@@ -1442,6 +1442,10 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
69 IEEE80211_QUEUE_STOP_REASON_CSA);
70 mutex_unlock(&local->mtx);
71
72+ cfg80211_sta_update_dfs_state(&sdata->wdev,
73+ &sdata->vif.bss_conf.chandef,
74+ &sdata->csa_chandef,
75+ sdata->vif.bss_conf.assoc);
76 cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
77 csa_ie.count, csa_ie.mode);
78
79@@ -2420,6 +2424,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
80 cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);
81
82 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
83+
84+ cfg80211_sta_update_dfs_state(&sdata->wdev,
85+ &sdata->vif.bss_conf.chandef,
86+ NULL, sdata->vif.bss_conf.assoc);
87 }
88
89 static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
90@@ -3782,6 +3790,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.bss_conf.assoc);
97
98 /*
99 * destroy assoc_data afterwards, as otherwise an idle
100diff --git a/net/wireless/chan.c b/net/wireless/chan.c
101index 5f50ac4..0309758 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@@ -1386,3 +1387,62 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
113 return false;
114 }
115 EXPORT_SYMBOL(cfg80211_any_usable_channels);
116+
117+static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
118+ const struct cfg80211_chan_def *chandef,
119+ enum nl80211_radar_event event)
120+{
121+ struct wireless_dev *wdev;
122+
123+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
124+ if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
125+ nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
126+ event, wdev->netdev, GFP_KERNEL);
127+ return;
128+ }
129+ }
130+}
131+
132+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
133+ const struct cfg80211_chan_def *bss_chandef,
134+ const struct cfg80211_chan_def *csa_chandef,
135+ bool associated)
136+{
137+ bool csa_active = !!csa_chandef;
138+ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
139+ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
140+
141+ if (!bss_chandef)
142+ return;
143+
144+ /* assume csa channel is cac completed */
145+ if (csa_active &&
146+ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
147+ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
148+ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
149+ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
150+ NL80211_RADAR_STA_CAC_SKIPPED);
151+ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
152+ }
153+
154+ /* avoid updating the dfs state during nop */
155+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
156+ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
157+ return;
158+
159+ if (associated && !csa_active) {
160+ dfs_state = NL80211_DFS_AVAILABLE;
161+ event = NL80211_RADAR_STA_CAC_SKIPPED;
162+ }
163+
164+ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
165+ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
166+
167+ if (csa_active)
168+ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
169+ else
170+ netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
171+ (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
172+ associated ? "association" : "disassociation");
173+}
174+EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
175--
1762.18.0
177