blob: 244689c7f7a9ddc286b02f3127267619873de3ad [file] [log] [blame]
developer66e89bc2024-04-23 14:50:01 +08001From 103b24de6741cb11d088e6e2be478c7839d32ec4 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 19/61] mtk: mac80211: add sta-assisted DFS state update
5 mechanism
6
7Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
8Change-Id: Ida821ebb42825cd1895eaccfbbfda1106e598009
9---
10 include/net/cfg80211.h | 14 +++++++++
11 include/uapi/linux/nl80211.h | 6 ++++
12 net/mac80211/mlme.c | 14 +++++++++
13 net/wireless/chan.c | 61 ++++++++++++++++++++++++++++++++++++
14 4 files changed, 95 insertions(+)
15
16diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
17index c55028f..19cf7f7 100644
18--- a/include/net/cfg80211.h
19+++ b/include/net/cfg80211.h
20@@ -8679,6 +8679,20 @@ void cfg80211_cac_event(struct net_device *netdev,
21 const struct cfg80211_chan_def *chandef,
22 enum nl80211_radar_event event, gfp_t gfp);
23
24+/**
25+ * cfg80211_sta_update_dfs_state - Update channel's DFS state during STA channel switch,
26+ * association, and disassociation
27+ * @wdev: the wireless device
28+ * @bss_chandef: the current BSS channel definition
29+ * @csa_chandef: the CSA channel definition
30+ * @associated: whether STA is during association or disassociation process
31+ *
32+ */
33+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
34+ const struct cfg80211_chan_def *bss_chandef,
35+ const struct cfg80211_chan_def *csa_chandef,
36+ bool associated);
37+
38 /**
39 * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
40 * @wiphy: the wiphy
41diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
42index f917bc6..7999a65 100644
43--- a/include/uapi/linux/nl80211.h
44+++ b/include/uapi/linux/nl80211.h
45@@ -6822,6 +6822,10 @@ enum nl80211_smps_mode {
46 * applicable for ETSI dfs domain where pre-CAC is valid for ever.
47 * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
48 * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
49+ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
50+ * when receiving CSA/assoc resp
51+ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
52+ * when STA is disconnected or leaving the channel
53 */
54 enum nl80211_radar_event {
55 NL80211_RADAR_DETECTED,
56@@ -6830,6 +6834,8 @@ enum nl80211_radar_event {
57 NL80211_RADAR_NOP_FINISHED,
58 NL80211_RADAR_PRE_CAC_EXPIRED,
59 NL80211_RADAR_CAC_STARTED,
60+ NL80211_RADAR_STA_CAC_SKIPPED,
61+ NL80211_RADAR_STA_CAC_EXPIRED,
62 };
63
64 /**
65diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
66index 77e5898..52d1cd8 100644
67--- a/net/mac80211/mlme.c
68+++ b/net/mac80211/mlme.c
69@@ -2170,6 +2170,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
70 sdata->csa_blocked_tx = true;
71 }
72
73+ cfg80211_sta_update_dfs_state(&sdata->wdev,
74+ &link->conf->chanreq.oper,
75+ &link->csa_chanreq.oper,
76+ sdata->vif.cfg.assoc);
77+
78 cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper,
79 link->link_id, csa_ie.count,
80 csa_ie.mode);
81@@ -3245,6 +3250,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
82 link = sdata_dereference(sdata->link[link_id], sdata);
83 if (!link)
84 continue;
85+
86+ cfg80211_sta_update_dfs_state(&sdata->wdev,
87+ &link->conf->chanreq.oper,
88+ NULL, sdata->vif.cfg.assoc);
89 ieee80211_link_release_channel(link);
90 }
91
92@@ -5512,6 +5521,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
93 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
94 if (link->tx_conf[ac].uapsd)
95 resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
96+
97+ if (status_code == WLAN_STATUS_SUCCESS)
98+ cfg80211_sta_update_dfs_state(&sdata->wdev,
99+ &link->conf->chanreq.oper,
100+ NULL, sdata->vif.cfg.assoc);
101 }
102
103 if (ieee80211_vif_is_mld(&sdata->vif)) {
104diff --git a/net/wireless/chan.c b/net/wireless/chan.c
105index 2224329..c851db8 100644
106--- a/net/wireless/chan.c
107+++ b/net/wireless/chan.c
108@@ -14,6 +14,7 @@
109 #include <net/cfg80211.h>
110 #include "core.h"
111 #include "rdev-ops.h"
112+#include "nl80211.h"
113
114 static bool cfg80211_valid_60g_freq(u32 freq)
115 {
116@@ -1671,6 +1672,66 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
117 }
118 EXPORT_SYMBOL(cfg80211_any_usable_channels);
119
120+static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
121+ const struct cfg80211_chan_def *chandef,
122+ enum nl80211_radar_event event)
123+{
124+ struct wireless_dev *wdev;
125+
126+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
127+ if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
128+ nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
129+ event, wdev->netdev, GFP_KERNEL);
130+ return;
131+ }
132+ }
133+}
134+
135+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
136+ const struct cfg80211_chan_def *bss_chandef,
137+ const struct cfg80211_chan_def *csa_chandef,
138+ bool associated)
139+{
140+ bool csa_active = !!csa_chandef;
141+ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
142+ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
143+
144+ if (!bss_chandef || !bss_chandef->chan ||
145+ bss_chandef->chan->band != NL80211_BAND_5GHZ)
146+ return;
147+
148+ /* assume csa channel is cac completed */
149+ if (csa_active &&
150+ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
151+ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
152+ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
153+ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
154+ NL80211_RADAR_STA_CAC_SKIPPED);
155+ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
156+ }
157+
158+ /* avoid updating the dfs state during nop */
159+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
160+ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
161+ return;
162+
163+ if (associated && !csa_active) {
164+ dfs_state = NL80211_DFS_AVAILABLE;
165+ event = NL80211_RADAR_STA_CAC_SKIPPED;
166+ }
167+
168+ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
169+ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
170+
171+ if (csa_active)
172+ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
173+ else
174+ netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
175+ (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
176+ associated ? "association" : "disassociation");
177+}
178+EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
179+
180 struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
181 unsigned int link_id)
182 {
183--
1842.39.2
185