blob: aa94d8f36ce9205e62e7d0bb3f1752fd6eff3014 [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>
developer66e89bc2024-04-23 14:50:01 +08008---
9 include/net/cfg80211.h | 14 +++++++++
10 include/uapi/linux/nl80211.h | 6 ++++
11 net/mac80211/mlme.c | 14 +++++++++
12 net/wireless/chan.c | 61 ++++++++++++++++++++++++++++++++++++
13 4 files changed, 95 insertions(+)
14
15diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
16index c55028f..19cf7f7 100644
17--- a/include/net/cfg80211.h
18+++ b/include/net/cfg80211.h
19@@ -8679,6 +8679,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 f917bc6..7999a65 100644
42--- a/include/uapi/linux/nl80211.h
43+++ b/include/uapi/linux/nl80211.h
44@@ -6822,6 +6822,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@@ -6830,6 +6834,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 77e5898..52d1cd8 100644
66--- a/net/mac80211/mlme.c
67+++ b/net/mac80211/mlme.c
68@@ -2170,6 +2170,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
69 sdata->csa_blocked_tx = true;
70 }
71
72+ cfg80211_sta_update_dfs_state(&sdata->wdev,
73+ &link->conf->chanreq.oper,
74+ &link->csa_chanreq.oper,
75+ sdata->vif.cfg.assoc);
76+
77 cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chanreq.oper,
78 link->link_id, csa_ie.count,
79 csa_ie.mode);
80@@ -3245,6 +3250,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
81 link = sdata_dereference(sdata->link[link_id], sdata);
82 if (!link)
83 continue;
84+
85+ cfg80211_sta_update_dfs_state(&sdata->wdev,
86+ &link->conf->chanreq.oper,
87+ NULL, sdata->vif.cfg.assoc);
88 ieee80211_link_release_channel(link);
89 }
90
91@@ -5512,6 +5521,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
92 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
93 if (link->tx_conf[ac].uapsd)
94 resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
95+
96+ if (status_code == WLAN_STATUS_SUCCESS)
97+ cfg80211_sta_update_dfs_state(&sdata->wdev,
98+ &link->conf->chanreq.oper,
99+ NULL, sdata->vif.cfg.assoc);
100 }
101
102 if (ieee80211_vif_is_mld(&sdata->vif)) {
103diff --git a/net/wireless/chan.c b/net/wireless/chan.c
104index 2224329..c851db8 100644
105--- a/net/wireless/chan.c
106+++ b/net/wireless/chan.c
107@@ -14,6 +14,7 @@
108 #include <net/cfg80211.h>
109 #include "core.h"
110 #include "rdev-ops.h"
111+#include "nl80211.h"
112
113 static bool cfg80211_valid_60g_freq(u32 freq)
114 {
115@@ -1671,6 +1672,66 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
116 }
117 EXPORT_SYMBOL(cfg80211_any_usable_channels);
118
119+static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
120+ const struct cfg80211_chan_def *chandef,
121+ enum nl80211_radar_event event)
122+{
123+ struct wireless_dev *wdev;
124+
125+ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
126+ if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
127+ nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
128+ event, wdev->netdev, GFP_KERNEL);
129+ return;
130+ }
131+ }
132+}
133+
134+void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
135+ const struct cfg80211_chan_def *bss_chandef,
136+ const struct cfg80211_chan_def *csa_chandef,
137+ bool associated)
138+{
139+ bool csa_active = !!csa_chandef;
140+ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
141+ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
142+
143+ if (!bss_chandef || !bss_chandef->chan ||
144+ bss_chandef->chan->band != NL80211_BAND_5GHZ)
145+ return;
146+
147+ /* assume csa channel is cac completed */
148+ if (csa_active &&
149+ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
150+ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
151+ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
152+ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
153+ NL80211_RADAR_STA_CAC_SKIPPED);
154+ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
155+ }
156+
157+ /* avoid updating the dfs state during nop */
158+ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
159+ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
160+ return;
161+
162+ if (associated && !csa_active) {
163+ dfs_state = NL80211_DFS_AVAILABLE;
164+ event = NL80211_RADAR_STA_CAC_SKIPPED;
165+ }
166+
167+ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
168+ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
169+
170+ if (csa_active)
171+ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
172+ else
173+ netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
174+ (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
175+ associated ? "association" : "disassociation");
176+}
177+EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
178+
179 struct cfg80211_chan_def *wdev_chandef(struct wireless_dev *wdev,
180 unsigned int link_id)
181 {
182--
1832.39.2
184