blob: d1800fec5e046ce5fc19defb60ed67f64b474fa6 [file] [log] [blame]
developer617abbd2024-04-23 14:50:01 +08001From 0455150c89b046a3ebd81134527ff4cae5025f3d Mon Sep 17 00:00:00 2001
2From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Wed, 5 Jul 2023 10:25:01 +0800
4Subject: [PATCH 070/104] mtk: hostapd: Add support for updating background
5 channel by driver
6
7Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
8---
9 src/ap/dfs.c | 107 ++++++++++++++++++++++++++++-
10 src/ap/dfs.h | 3 +
11 src/ap/drv_callbacks.c | 22 ++++++
12 src/ap/hostapd.h | 5 ++
13 src/drivers/driver.h | 12 ++++
14 src/drivers/driver_nl80211_event.c | 6 ++
15 src/drivers/nl80211_copy.h | 6 ++
16 7 files changed, 160 insertions(+), 1 deletion(-)
17
18diff --git a/src/ap/dfs.c b/src/ap/dfs.c
19index 7adaf81ac..e39f3c180 100644
20--- a/src/ap/dfs.c
21+++ b/src/ap/dfs.c
22@@ -816,11 +816,14 @@ static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq,
23
24 static void dfs_check_background_overlapped(struct hostapd_iface *iface)
25 {
26- int width = hostapd_get_oper_chwidth(iface->conf);
27+ int width = iface->radar_background.new_chwidth;
28
29 if (!dfs_use_radar_background(iface))
30 return;
31
32+ if (!width)
33+ width = hostapd_get_oper_chwidth(iface->conf);
34+
35 if (dfs_are_channels_overlapped(iface, iface->radar_background.freq,
36 width, iface->radar_background.centr_freq_seg0_idx,
37 iface->radar_background.centr_freq_seg1_idx))
38@@ -985,6 +988,15 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
39 iface->radar_background.temp_ch = 1;
40 return 1;
41 } else if (dfs_use_radar_background(iface)) {
42+ /*
43+ * AP is going to perform CAC, so reset temp_ch to 0,
44+ * when dedicated rx has already started CAC.
45+ */
46+ if (iface->radar_background.cac_started) {
47+ iface->radar_background.temp_ch = 0;
48+ return 0;
49+ }
50+
51 if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI)
52 channel_type = DFS_ANY_CHANNEL;
53
54@@ -1125,6 +1137,8 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface,
55 * ch_switch_notify event is received */
56 wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
57
58+ hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
59+
60 return 0;
61 }
62
63@@ -1176,6 +1190,9 @@ static void hostapd_dfs_update_background_chain(struct hostapd_iface *iface)
64 iface->radar_background.secondary_channel = sec;
65 iface->radar_background.centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
66 iface->radar_background.centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
67+ /* if main channel do not require dfs, then set temp_ch = 1 */
68+ if (!hostapd_is_dfs_required(iface))
69+ iface->radar_background.temp_ch = 1;
70
71 wpa_printf(MSG_DEBUG,
72 "%s: setting background chain to chan %d (%d MHz)",
73@@ -1198,6 +1215,10 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
74 u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
75 int ret;
76
77+ if (iface->radar_background.new_chwidth) {
78+ hostapd_set_oper_chwidth(iface->conf, iface->radar_background.new_chwidth);
79+ iface->radar_background.new_chwidth = 0;
80+ }
81 ret = hostapd_dfs_request_channel_switch(iface, iface->radar_background.channel,
82 iface->radar_background.freq,
83 iface->radar_background.secondary_channel,
84@@ -1220,6 +1241,52 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
85 }
86
87
88+static void
89+hostapd_dfs_background_expand(struct hostapd_iface *iface, int chan_width)
90+{
91+ struct hostapd_hw_modes *mode = iface->current_mode;
92+ struct hostapd_channel_data *chan;
93+ int i, channel, width = channel_width_to_int(chan_width);
94+
95+ if (iface->conf->channel - iface->radar_background.channel == width / 5)
96+ channel = iface->radar_background.channel;
97+ else if (iface->radar_background.channel - iface->conf->channel == width / 5)
98+ channel = iface->conf->channel;
99+ else
100+ return;
101+
102+ for (i = 0; i < mode->num_channels; i++) {
103+ chan = &mode->channels[i];
104+ if (chan->chan == channel)
105+ break;
106+ }
107+
108+ if (i == mode->num_channels || !dfs_is_chan_allowed(chan, width / 10))
109+ return;
110+
111+ switch (chan_width) {
112+ case CHAN_WIDTH_20_NOHT:
113+ case CHAN_WIDTH_20:
114+ iface->radar_background.new_chwidth = CONF_OPER_CHWIDTH_USE_HT;
115+ break;
116+ case CHAN_WIDTH_40:
117+ iface->radar_background.new_chwidth = CONF_OPER_CHWIDTH_80MHZ;
118+ break;
119+ case CHAN_WIDTH_80:
120+ iface->radar_background.new_chwidth = CONF_OPER_CHWIDTH_160MHZ;
121+ break;
122+ default:
123+ return;
124+ }
125+
126+ iface->radar_background.freq = channel * 5 + 5000;
127+ iface->radar_background.channel = channel;
128+ iface->radar_background.centr_freq_seg0_idx = channel + width / 5 - 2;
129+ iface->radar_background.secondary_channel = 1;
130+ iface->radar_background.expand_ch = 0;
131+}
132+
133+
134 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
135 int ht_enabled, int chan_offset, int chan_width,
136 int cf1, int cf2)
137@@ -1253,6 +1320,10 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
138 return 0;
139
140 iface->radar_background.temp_ch = 0;
141+
142+ if (iface->radar_background.expand_ch)
143+ hostapd_dfs_background_expand(iface, chan_width);
144+
145 return hostapd_dfs_start_channel_switch_background(iface);
146 }
147
148@@ -1283,6 +1354,8 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
149 }
150 } else if (hostapd_dfs_is_background_event(iface, freq)) {
151 iface->radar_background.cac_started = 0;
152+ iface->radar_background.temp_ch = 0;
153+ iface->radar_background.expand_ch = 0;
154 hostapd_dfs_update_background_chain(iface);
155 }
156
157@@ -1415,6 +1488,9 @@ hostapd_dfs_background_start_channel_switch(struct hostapd_iface *iface,
158 iface->conf->dfs_detect_mode == DFS_DETECT_MODE_ALL_ENABLE)
159 return 0;
160
161+ iface->radar_background.temp_ch = 0;
162+ iface->radar_background.expand_ch = 0;
163+
164 /* Check if CSA in progress */
165 if (hostapd_csa_in_progress(iface))
166 return 0;
167@@ -1649,6 +1725,35 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
168 }
169
170
171+int hostapd_dfs_background_chan_update(struct hostapd_iface *iface, int freq,
172+ int ht_enabled, int chan_offset, int chan_width,
173+ int cf1, int cf2, bool expand)
174+{
175+ switch (chan_width) {
176+ case CHAN_WIDTH_80:
177+ iface->radar_background.new_chwidth = CONF_OPER_CHWIDTH_80MHZ;
178+ break;
179+ case CHAN_WIDTH_160:
180+ iface->radar_background.new_chwidth = CONF_OPER_CHWIDTH_160MHZ;
181+ break;
182+ default:
183+ iface->radar_background.new_chwidth = CONF_OPER_CHWIDTH_USE_HT;
184+ break;
185+ };
186+
187+ iface->radar_background.freq = freq;
188+ iface->radar_background.channel = (freq - 5000) / 5;
189+ iface->radar_background.centr_freq_seg0_idx = (cf1 - 5000) / 5;
190+ iface->radar_background.centr_freq_seg1_idx = cf2 ? (cf2 - 5000) / 5 : 0;
191+ if (expand) {
192+ iface->radar_background.temp_ch = 1;
193+ iface->radar_background.expand_ch = 1;
194+ }
195+
196+ return 0;
197+}
198+
199+
200 int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
201 int ht_enabled, int chan_offset, int chan_width,
202 int cf1, int cf2)
203diff --git a/src/ap/dfs.h b/src/ap/dfs.h
204index 25ba29ca1..a1a2be5ec 100644
205--- a/src/ap/dfs.h
206+++ b/src/ap/dfs.h
207@@ -30,6 +30,9 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
208 int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
209 int ht_enabled,
210 int chan_offset, int chan_width, int cf1, int cf2);
211+int hostapd_dfs_background_chan_update(struct hostapd_iface *iface, int freq,
212+ int ht_enabled, int chan_offset, int chan_width,
213+ int cf1, int cf2, bool expand);
214 int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
215 int ht_enabled, int chan_offset, int chan_width,
216 int cf1, int cf2, u32 state);
217diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
218index caa171474..2d946afd6 100644
219--- a/src/ap/drv_callbacks.c
220+++ b/src/ap/drv_callbacks.c
221@@ -2226,6 +2226,18 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
222 radar->cf1, radar->cf2);
223 }
224
225+
226+static void hostapd_event_dfs_background_chan_update(struct hostapd_data *hapd,
227+ struct dfs_event *radar, bool expand)
228+{
229+ wpa_printf(MSG_DEBUG, "DFS background channel %s to %d MHz",
230+ expand ? "expand" : "update", radar->freq);
231+ hostapd_dfs_background_chan_update(hapd->iface, radar->freq, radar->ht_enabled,
232+ radar->chan_offset, radar->chan_width,
233+ radar->cf1, radar->cf2, expand);
234+}
235+
236+
237 static void hostapd_event_dfs_sta_cac_skipped(struct hostapd_data *hapd,
238 struct dfs_event *radar)
239 {
240@@ -2610,6 +2622,16 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
241 hapd = switch_link_hapd(hapd, data->dfs_event.link_id);
242 hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
243 break;
244+ case EVENT_DFS_BACKGROUND_CHAN_UPDATE:
245+ if (!data)
246+ break;
247+ hostapd_event_dfs_background_chan_update(hapd, &data->dfs_event, false);
248+ break;
249+ case EVENT_DFS_BACKGROUND_CHAN_EXPAND:
250+ if (!data)
251+ break;
252+ hostapd_event_dfs_background_chan_update(hapd, &data->dfs_event, true);
253+ break;
254 case EVENT_DFS_STA_CAC_SKIPPED:
255 if (!data)
256 break;
257diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
258index 1e4113459..5b37be87b 100644
259--- a/src/ap/hostapd.h
260+++ b/src/ap/hostapd.h
261@@ -640,6 +640,11 @@ struct hostapd_iface {
262 unsigned int temp_ch:1;
263 /* CAC started on radar offchain */
264 unsigned int cac_started:1;
265+ /* Main chain should expand its width according to the
266+ * current offchain channel after CAC detection on radar offchain.
267+ */
268+ unsigned int expand_ch:1;
269+ int new_chwidth;
270 } radar_background;
271
272 u16 hw_flags;
273diff --git a/src/drivers/driver.h b/src/drivers/driver.h
274index 1c0c38e24..4e3dc9bdb 100644
275--- a/src/drivers/driver.h
276+++ b/src/drivers/driver.h
277@@ -5960,6 +5960,18 @@ enum wpa_event_type {
278 * The channel in the notification is now marked as usable.
279 */
280 EVENT_DFS_STA_CAC_EXPIRED,
281+
282+ /**
283+ * EVENT_DFS_BACKGROUND_CHAN_UPDATE - Notification that background
284+ * channel has been updated.
285+ */
286+ EVENT_DFS_BACKGROUND_CHAN_UPDATE,
287+
288+ /**
289+ * EVENT_DFS_BACKGROUND_CHAN_EXPAND - Notification that background
290+ * channel has been updated and operating channel should expand its width.
291+ */
292+ EVENT_DFS_BACKGROUND_CHAN_EXPAND,
293 };
294
295
296diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
297index 7889930a0..6631285bf 100644
298--- a/src/drivers/driver_nl80211_event.c
299+++ b/src/drivers/driver_nl80211_event.c
300@@ -2529,6 +2529,12 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
301 case NL80211_RADAR_CAC_STARTED:
302 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
303 break;
304+ case NL80211_RADAR_BACKGROUND_CHAN_UPDATE:
305+ wpa_supplicant_event(drv->ctx, EVENT_DFS_BACKGROUND_CHAN_UPDATE, &data);
306+ break;
307+ case NL80211_RADAR_BACKGROUND_CHAN_EXPAND:
308+ wpa_supplicant_event(drv->ctx, EVENT_DFS_BACKGROUND_CHAN_EXPAND, &data);
309+ break;
310 case NL80211_RADAR_STA_CAC_SKIPPED:
311 wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_SKIPPED, &data);
312 break;
313diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
314index 8917d565b..c56954306 100644
315--- a/src/drivers/nl80211_copy.h
316+++ b/src/drivers/nl80211_copy.h
317@@ -6699,6 +6699,10 @@ enum nl80211_smps_mode {
318 * applicable for ETSI dfs domain where pre-CAC is valid for ever.
319 * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
320 * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
321+ * @NL80211_RADAR_BACKGROUND_CHAN_UPDATE: background channel is updated by the
322+ * driver.
323+ * @NL80211_RADAR_BACKGROUND_CHAN_EXPAND: background channel is updated by the
324+ * driver and required to expand main operating channel.
325 * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
326 * when receiving CSA/assoc resp
327 * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
328@@ -6711,6 +6715,8 @@ enum nl80211_radar_event {
329 NL80211_RADAR_NOP_FINISHED,
330 NL80211_RADAR_PRE_CAC_EXPIRED,
331 NL80211_RADAR_CAC_STARTED,
332+ NL80211_RADAR_BACKGROUND_CHAN_UPDATE,
333+ NL80211_RADAR_BACKGROUND_CHAN_EXPAND,
334 NL80211_RADAR_STA_CAC_SKIPPED,
335 NL80211_RADAR_STA_CAC_EXPIRED,
336 };
337--
3382.39.2
339