3f64864bd41f2e780a09e7abf2622a6e56a9b11f
[openwrt/openwrt.git] /
1 From: Aditya Kumar Singh <quic_adisi@quicinc.com>
2 Date: Fri, 6 Sep 2024 12:14:26 +0530
3 Subject: [PATCH] wifi: mac80211: handle ieee80211_radar_detected() for MLO
4
5 Currently DFS works under assumption there could be only one channel
6 context in the hardware. Hence, drivers just calls the function
7 ieee80211_radar_detected() passing the hardware structure. However, with
8 MLO, this obviously will not work since number of channel contexts will be
9 more than one and hence drivers would need to pass the channel information
10 as well on which the radar is detected.
11
12 Also, when radar is detected in one of the links, other link's CAC should
13 not be cancelled.
14
15 Hence, in order to support DFS with MLO, do the following changes -
16 * Add channel context conf pointer as an argument to the function
17 ieee80211_radar_detected(). During MLO, drivers would have to pass on
18 which channel context conf radar is detected. Otherwise, drivers could
19 just pass NULL.
20 * ieee80211_radar_detected() will iterate over all channel contexts
21 present and
22 * if channel context conf is passed, only mark that as radar
23 detected
24 * if NULL is passed, then mark all channel contexts as radar
25 detected
26 * Then as usual, schedule the radar detected work.
27 * In the worker, go over all the contexts again and for all such context
28 which is marked with radar detected, cancel the ongoing CAC by calling
29 ieee80211_dfs_cac_cancel() and then notify cfg80211 via
30 cfg80211_radar_event().
31 * To cancel the CAC, pass the channel context as well where radar is
32 detected to ieee80211_dfs_cac_cancel(). This ensures that CAC is
33 canceled only on the links using the provided context, leaving other
34 links unaffected.
35
36 This would also help in scenarios where there is split phy 5 GHz radio,
37 which is capable of DFS channels in both lower and upper band. In this
38 case, simultaneous radars can be detected.
39
40 Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
41 Link: https://patch.msgid.link/20240906064426.2101315-9-quic_adisi@quicinc.com
42 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
43 ---
44
45 --- a/drivers/net/wireless/ath/ath10k/debug.c
46 +++ b/drivers/net/wireless/ath/ath10k/debug.c
47 @@ -3,7 +3,7 @@
48 * Copyright (c) 2005-2011 Atheros Communications Inc.
49 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
50 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
51 - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
52 + * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
53 */
54
55 #include <linux/module.h>
56 @@ -1774,7 +1774,7 @@ static ssize_t ath10k_write_simulate_rad
57 if (!arvif->is_started)
58 return -EINVAL;
59
60 - ieee80211_radar_detected(ar->hw);
61 + ieee80211_radar_detected(ar->hw, NULL);
62
63 return count;
64 }
65 --- a/drivers/net/wireless/ath/ath10k/mac.c
66 +++ b/drivers/net/wireless/ath/ath10k/mac.c
67 @@ -1437,7 +1437,7 @@ static void ath10k_recalc_radar_detectio
68 * by indicating that radar was detected.
69 */
70 ath10k_warn(ar, "failed to start CAC: %d\n", ret);
71 - ieee80211_radar_detected(ar->hw);
72 + ieee80211_radar_detected(ar->hw, NULL);
73 }
74 }
75
76 --- a/drivers/net/wireless/ath/ath10k/wmi.c
77 +++ b/drivers/net/wireless/ath/ath10k/wmi.c
78 @@ -3990,7 +3990,7 @@ static void ath10k_radar_detected(struct
79 if (ar->dfs_block_radar_events)
80 ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
81 else
82 - ieee80211_radar_detected(ar->hw);
83 + ieee80211_radar_detected(ar->hw, NULL);
84 }
85
86 static void ath10k_radar_confirmation_work(struct work_struct *work)
87 --- a/drivers/net/wireless/ath/ath11k/wmi.c
88 +++ b/drivers/net/wireless/ath/ath11k/wmi.c
89 @@ -8358,7 +8358,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event
90 if (ar->dfs_block_radar_events)
91 ath11k_info(ab, "DFS Radar detected, but ignored as requested\n");
92 else
93 - ieee80211_radar_detected(ar->hw);
94 + ieee80211_radar_detected(ar->hw, NULL);
95
96 exit:
97 rcu_read_unlock();
98 --- a/drivers/net/wireless/ath/ath12k/wmi.c
99 +++ b/drivers/net/wireless/ath/ath12k/wmi.c
100 @@ -6789,7 +6789,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event
101 if (ar->dfs_block_radar_events)
102 ath12k_info(ab, "DFS Radar detected, but ignored as requested\n");
103 else
104 - ieee80211_radar_detected(ath12k_ar_to_hw(ar));
105 + ieee80211_radar_detected(ath12k_ar_to_hw(ar), NULL);
106
107 exit:
108 rcu_read_unlock();
109 --- a/drivers/net/wireless/ath/ath9k/dfs.c
110 +++ b/drivers/net/wireless/ath/ath9k/dfs.c
111 @@ -280,7 +280,7 @@ ath9k_dfs_process_radar_pulse(struct ath
112 if (!pd->add_pulse(pd, pe, NULL))
113 return;
114 DFS_STAT_INC(sc, radar_detected);
115 - ieee80211_radar_detected(sc->hw);
116 + ieee80211_radar_detected(sc->hw, NULL);
117 }
118
119 /*
120 --- a/drivers/net/wireless/ath/ath9k/dfs_debug.c
121 +++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
122 @@ -116,7 +116,7 @@ static ssize_t write_file_simulate_radar
123 {
124 struct ath_softc *sc = file->private_data;
125
126 - ieee80211_radar_detected(sc->hw);
127 + ieee80211_radar_detected(sc->hw, NULL);
128
129 return count;
130 }
131 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
132 +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
133 @@ -394,7 +394,7 @@ mt7615_mcu_rx_radar_detected(struct mt76
134 if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
135 return;
136
137 - ieee80211_radar_detected(mphy->hw);
138 + ieee80211_radar_detected(mphy->hw, NULL);
139 dev->hw_pattern++;
140 }
141
142 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
143 +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
144 @@ -630,7 +630,7 @@ static void mt76x02_dfs_tasklet(struct t
145 radar_detected = mt76x02_dfs_check_detection(dev);
146 if (radar_detected) {
147 /* sw detector rx radar pattern */
148 - ieee80211_radar_detected(dev->mt76.hw);
149 + ieee80211_radar_detected(dev->mt76.hw, NULL);
150 mt76x02_dfs_detector_reset(dev);
151
152 return;
153 @@ -658,7 +658,7 @@ static void mt76x02_dfs_tasklet(struct t
154
155 /* hw detector rx radar pattern */
156 dfs_pd->stats[i].hw_pattern++;
157 - ieee80211_radar_detected(dev->mt76.hw);
158 + ieee80211_radar_detected(dev->mt76.hw, NULL);
159 mt76x02_dfs_detector_reset(dev);
160
161 return;
162 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
163 +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
164 @@ -293,7 +293,7 @@ mt7915_mcu_rx_radar_detected(struct mt79
165 &dev->rdd2_chandef,
166 GFP_ATOMIC);
167 else
168 - ieee80211_radar_detected(mphy->hw);
169 + ieee80211_radar_detected(mphy->hw, NULL);
170 dev->hw_pattern++;
171 }
172
173 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
174 +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
175 @@ -371,7 +371,7 @@ mt7996_mcu_rx_radar_detected(struct mt79
176 &dev->rdd2_chandef,
177 GFP_ATOMIC);
178 else
179 - ieee80211_radar_detected(mphy->hw);
180 + ieee80211_radar_detected(mphy->hw, NULL);
181 dev->hw_pattern++;
182 }
183
184 --- a/drivers/net/wireless/ti/wl18xx/event.c
185 +++ b/drivers/net/wireless/ti/wl18xx/event.c
186 @@ -142,7 +142,7 @@ int wl18xx_process_mailbox_events(struct
187 wl18xx_radar_type_decode(mbox->radar_type));
188
189 if (!wl->radar_debug_mode)
190 - ieee80211_radar_detected(wl->hw);
191 + ieee80211_radar_detected(wl->hw, NULL);
192 }
193
194 if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
195 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c
196 +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
197 @@ -1146,7 +1146,7 @@ static int hwsim_write_simulate_radar(vo
198 {
199 struct mac80211_hwsim_data *data = dat;
200
201 - ieee80211_radar_detected(data->hw);
202 + ieee80211_radar_detected(data->hw, NULL);
203
204 return 0;
205 }
206 --- a/include/net/mac80211.h
207 +++ b/include/net/mac80211.h
208 @@ -6717,8 +6717,11 @@ void ieee80211_cqm_beacon_loss_notify(st
209 * ieee80211_radar_detected - inform that a radar was detected
210 *
211 * @hw: pointer as obtained from ieee80211_alloc_hw()
212 + * @chanctx_conf: Channel context on which radar is detected. Mandatory to
213 + * pass a valid pointer during MLO. For non-MLO %NULL can be passed
214 */
215 -void ieee80211_radar_detected(struct ieee80211_hw *hw);
216 +void ieee80211_radar_detected(struct ieee80211_hw *hw,
217 + struct ieee80211_chanctx_conf *chanctx_conf);
218
219 /**
220 * ieee80211_chswitch_done - Complete channel switch process
221 --- a/net/mac80211/chan.c
222 +++ b/net/mac80211/chan.c
223 @@ -681,6 +681,7 @@ ieee80211_alloc_chanctx(struct ieee80211
224 ctx->mode = mode;
225 ctx->conf.radar_enabled = false;
226 ctx->conf.radio_idx = radio_idx;
227 + ctx->radar_detected = false;
228 _ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
229
230 return ctx;
231 --- a/net/mac80211/ieee80211_i.h
232 +++ b/net/mac80211/ieee80211_i.h
233 @@ -895,6 +895,8 @@ struct ieee80211_chanctx {
234 struct ieee80211_chan_req req;
235
236 struct ieee80211_chanctx_conf conf;
237 +
238 + bool radar_detected;
239 };
240
241 struct mac80211_qos_map {
242 @@ -2632,7 +2634,8 @@ void ieee80211_recalc_chanctx_min_def(st
243 bool ieee80211_is_radar_required(struct ieee80211_local *local);
244
245 void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work);
246 -void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
247 +void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
248 + struct ieee80211_chanctx *chanctx);
249 void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
250 struct wiphy_work *work);
251 int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
252 --- a/net/mac80211/pm.c
253 +++ b/net/mac80211/pm.c
254 @@ -32,7 +32,7 @@ int __ieee80211_suspend(struct ieee80211
255
256 ieee80211_scan_cancel(local);
257
258 - ieee80211_dfs_cac_cancel(local);
259 + ieee80211_dfs_cac_cancel(local, NULL);
260
261 ieee80211_roc_purge(local, NULL);
262
263 --- a/net/mac80211/util.c
264 +++ b/net/mac80211/util.c
265 @@ -3451,11 +3451,16 @@ u64 ieee80211_calculate_rx_timestamp(str
266 return ts;
267 }
268
269 -void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
270 +/* Cancel CAC for the interfaces under the specified @local. If @ctx is
271 + * also provided, only the interfaces using that ctx will be canceled.
272 + */
273 +void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
274 + struct ieee80211_chanctx *ctx)
275 {
276 struct ieee80211_sub_if_data *sdata;
277 struct cfg80211_chan_def chandef;
278 struct ieee80211_link_data *link;
279 + struct ieee80211_chanctx_conf *chanctx_conf;
280 unsigned int link_id;
281
282 lockdep_assert_wiphy(local->hw.wiphy);
283 @@ -3468,6 +3473,11 @@ void ieee80211_dfs_cac_cancel(struct iee
284 if (!link)
285 continue;
286
287 + chanctx_conf = sdata_dereference(link->conf->chanctx_conf,
288 + sdata);
289 + if (ctx && &ctx->conf != chanctx_conf)
290 + continue;
291 +
292 wiphy_delayed_work_cancel(local->hw.wiphy,
293 &link->dfs_cac_timer_work);
294
295 @@ -3488,9 +3498,8 @@ void ieee80211_dfs_radar_detected_work(s
296 {
297 struct ieee80211_local *local =
298 container_of(work, struct ieee80211_local, radar_detected_work);
299 - struct cfg80211_chan_def chandef = local->hw.conf.chandef;
300 + struct cfg80211_chan_def chandef;
301 struct ieee80211_chanctx *ctx;
302 - int num_chanctx = 0;
303
304 lockdep_assert_wiphy(local->hw.wiphy);
305
306 @@ -3498,25 +3507,46 @@ void ieee80211_dfs_radar_detected_work(s
307 if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
308 continue;
309
310 - num_chanctx++;
311 + if (!ctx->radar_detected)
312 + continue;
313 +
314 + ctx->radar_detected = false;
315 +
316 chandef = ctx->conf.def;
317 +
318 + ieee80211_dfs_cac_cancel(local, ctx);
319 + cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
320 }
321 +}
322
323 - ieee80211_dfs_cac_cancel(local);
324 +static void
325 +ieee80211_radar_mark_chan_ctx_iterator(struct ieee80211_hw *hw,
326 + struct ieee80211_chanctx_conf *chanctx_conf,
327 + void *data)
328 +{
329 + struct ieee80211_chanctx *ctx =
330 + container_of(chanctx_conf, struct ieee80211_chanctx,
331 + conf);
332
333 - if (num_chanctx > 1)
334 - /* XXX: multi-channel is not supported yet */
335 - WARN_ON(1);
336 - else
337 - cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
338 + if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
339 + return;
340 +
341 + if (data && data != chanctx_conf)
342 + return;
343 +
344 + ctx->radar_detected = true;
345 }
346
347 -void ieee80211_radar_detected(struct ieee80211_hw *hw)
348 +void ieee80211_radar_detected(struct ieee80211_hw *hw,
349 + struct ieee80211_chanctx_conf *chanctx_conf)
350 {
351 struct ieee80211_local *local = hw_to_local(hw);
352
353 trace_api_radar_detected(local);
354
355 + ieee80211_iter_chan_contexts_atomic(hw, ieee80211_radar_mark_chan_ctx_iterator,
356 + chanctx_conf);
357 +
358 wiphy_work_queue(hw->wiphy, &local->radar_detected_work);
359 }
360 EXPORT_SYMBOL(ieee80211_radar_detected);