blob: 669ddd00cd36f50b5e1f3f82c6f7812d844406cc [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From 5c4cda67753544ea5bb793d6d36fbbb7330ca0c8 Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Mon, 20 Feb 2023 14:25:24 +0800
developer05f3b2b2024-08-19 19:17:34 +08004Subject: [PATCH 28/89] mtk: mac80211: add sta-assisted DFS state update
developer66e89bc2024-04-23 14:50:01 +08005 mechanism
6
7Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
developer05f3b2b2024-08-19 19:17:34 +08008
9Add cfg80211_any_wiphy_oper_chan check before clearing dfs state.
10This avoids STA clearing the dfs state of the channel, which still has
11APs/offchain operating on the it.
12
13Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
developer66e89bc2024-04-23 14:50:01 +080014---
developer05f3b2b2024-08-19 19:17:34 +080015 include/net/cfg80211.h | 14 +++++++
16 include/uapi/linux/nl80211.h | 6 +++
17 net/mac80211/mlme.c | 14 +++++++
18 net/wireless/chan.c | 72 ++++++++++++++++++++++++++++++++++++
19 4 files changed, 106 insertions(+)
developer66e89bc2024-04-23 14:50:01 +080020
21diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
developer05f3b2b2024-08-19 19:17:34 +080022index cc1ed48..16a9a24 100644
developer66e89bc2024-04-23 14:50:01 +080023--- a/include/net/cfg80211.h
24+++ b/include/net/cfg80211.h
developer05f3b2b2024-08-19 19:17:34 +080025@@ -8775,6 +8775,20 @@ void cfg80211_cac_event(struct net_device *netdev,
26 enum nl80211_radar_event event, gfp_t gfp,
27 unsigned int link_id);
developer66e89bc2024-04-23 14:50:01 +080028
29+/**
30+ * cfg80211_sta_update_dfs_state - Update channel's DFS state during STA channel switch,
31+ * association, and disassociation
32+ * @wdev: the wireless device
33+ * @bss_chandef: the current BSS channel definition
34+ * @csa_chandef: the CSA channel definition
35+ * @associated: whether STA is during association or disassociation process
36+ *
37+ */
38+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
39+ const struct cfg80211_chan_def *bss_chandef,
40+ const struct cfg80211_chan_def *csa_chandef,
41+ bool associated);
42+
43 /**
44 * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
45 * @wiphy: the wiphy
46diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
developer05f3b2b2024-08-19 19:17:34 +080047index f97f5ad..622fa71 100644
developer66e89bc2024-04-23 14:50:01 +080048--- a/include/uapi/linux/nl80211.h
49+++ b/include/uapi/linux/nl80211.h
developer05f3b2b2024-08-19 19:17:34 +080050@@ -6843,6 +6843,10 @@ enum nl80211_smps_mode {
developer66e89bc2024-04-23 14:50:01 +080051 * applicable for ETSI dfs domain where pre-CAC is valid for ever.
52 * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
53 * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
54+ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
55+ * when receiving CSA/assoc resp
56+ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
57+ * when STA is disconnected or leaving the channel
58 */
59 enum nl80211_radar_event {
60 NL80211_RADAR_DETECTED,
developer05f3b2b2024-08-19 19:17:34 +080061@@ -6851,6 +6855,8 @@ enum nl80211_radar_event {
developer66e89bc2024-04-23 14:50:01 +080062 NL80211_RADAR_NOP_FINISHED,
63 NL80211_RADAR_PRE_CAC_EXPIRED,
64 NL80211_RADAR_CAC_STARTED,
65+ NL80211_RADAR_STA_CAC_SKIPPED,
66+ NL80211_RADAR_STA_CAC_EXPIRED,
67 };
68
69 /**
70diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
developer05f3b2b2024-08-19 19:17:34 +080071index 073e361..bf8a532 100644
developer66e89bc2024-04-23 14:50:01 +080072--- a/net/mac80211/mlme.c
73+++ b/net/mac80211/mlme.c
developer05f3b2b2024-08-19 19:17:34 +080074@@ -2599,6 +2599,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
75 if (csa_ie.mode)
76 ieee80211_vif_block_queues_csa(sdata);
developer66e89bc2024-04-23 14:50:01 +080077
78+ cfg80211_sta_update_dfs_state(&sdata->wdev,
79+ &link->conf->chanreq.oper,
80+ &link->csa_chanreq.oper,
81+ sdata->vif.cfg.assoc);
82+
83 cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper,
84 link->link_id, csa_ie.count,
85 csa_ie.mode);
developer05f3b2b2024-08-19 19:17:34 +080086@@ -3665,6 +3670,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
developer66e89bc2024-04-23 14:50:01 +080087 link = sdata_dereference(sdata->link[link_id], sdata);
88 if (!link)
89 continue;
90+
91+ cfg80211_sta_update_dfs_state(&sdata->wdev,
92+ &link->conf->chanreq.oper,
93+ NULL, sdata->vif.cfg.assoc);
94 ieee80211_link_release_channel(link);
95 }
96
developer05f3b2b2024-08-19 19:17:34 +080097@@ -5932,6 +5941,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
developer66e89bc2024-04-23 14:50:01 +080098 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
99 if (link->tx_conf[ac].uapsd)
100 resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
101+
102+ if (status_code == WLAN_STATUS_SUCCESS)
103+ cfg80211_sta_update_dfs_state(&sdata->wdev,
104+ &link->conf->chanreq.oper,
105+ NULL, sdata->vif.cfg.assoc);
106 }
107
108 if (ieee80211_vif_is_mld(&sdata->vif)) {
109diff --git a/net/wireless/chan.c b/net/wireless/chan.c
developer05f3b2b2024-08-19 19:17:34 +0800110index be2261f..7b511d3 100644
developer66e89bc2024-04-23 14:50:01 +0800111--- a/net/wireless/chan.c
112+++ b/net/wireless/chan.c
113@@ -14,6 +14,7 @@
114 #include <net/cfg80211.h>
115 #include "core.h"
116 #include "rdev-ops.h"
117+#include "nl80211.h"
118
119 static bool cfg80211_valid_60g_freq(u32 freq)
120 {
developer05f3b2b2024-08-19 19:17:34 +0800121@@ -1721,6 +1722,77 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
developer66e89bc2024-04-23 14:50:01 +0800122 }
123 EXPORT_SYMBOL(cfg80211_any_usable_channels);
124
125+static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
126+ const struct cfg80211_chan_def *chandef,
127+ enum nl80211_radar_event event)
128+{
129+ struct wireless_dev *wdev;
130+
131+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
132+ if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
133+ nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
134+ event, wdev->netdev, GFP_KERNEL);
135+ return;
136+ }
137+ }
138+}
139+
140+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
141+ const struct cfg80211_chan_def *bss_chandef,
142+ const struct cfg80211_chan_def *csa_chandef,
143+ bool associated)
144+{
145+ bool csa_active = !!csa_chandef;
146+ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
147+ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
148+
developer05f3b2b2024-08-19 19:17:34 +0800149+ lockdep_assert_wiphy(wdev->wiphy);
150+
developer66e89bc2024-04-23 14:50:01 +0800151+ if (!bss_chandef || !bss_chandef->chan ||
152+ bss_chandef->chan->band != NL80211_BAND_5GHZ)
153+ return;
154+
155+ /* assume csa channel is cac completed */
156+ if (csa_active &&
157+ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
158+ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
159+ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
160+ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
161+ NL80211_RADAR_STA_CAC_SKIPPED);
162+ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
163+ }
164+
165+ /* avoid updating the dfs state during nop */
166+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
167+ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
168+ return;
169+
170+ if (associated && !csa_active) {
171+ dfs_state = NL80211_DFS_AVAILABLE;
172+ event = NL80211_RADAR_STA_CAC_SKIPPED;
173+ }
174+
developer05f3b2b2024-08-19 19:17:34 +0800175+ /* avoid setting the dfs state to usable
176+ * when other interfaces still operate on this channel
177+ */
178+ if (dfs_state == NL80211_DFS_USABLE &&
179+ (cfg80211_is_wiphy_oper_chan(wdev->wiphy, bss_chandef->chan) ||
180+ cfg80211_offchan_chain_is_active(wiphy_to_rdev(wdev->wiphy),
181+ bss_chandef->chan)))
182+ return;
183+
developer66e89bc2024-04-23 14:50:01 +0800184+ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
185+ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
186+
187+ if (csa_active)
188+ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
189+ else
190+ netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
191+ (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
192+ associated ? "association" : "disassociation");
193+}
194+EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
195+
196 struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
197 unsigned int link_id)
198 {
199--
developer05f3b2b2024-08-19 19:17:34 +08002002.18.0
developer66e89bc2024-04-23 14:50:01 +0800201