blob: 0dc5ea22f6a492e29e410e4ce04ed33d867466cf [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From f08e9c0b36a76033554c0fc89b6e3cfbf8019d8c Mon Sep 17 00:00:00 2001
2From: Aditya Kumar Singh <quic_adisi@quicinc.com>
3Date: Thu, 11 Jul 2024 09:21:44 +0530
4Subject: [PATCH 13/89] bp: wifi: cfg80211: handle DFS per link
5
6Currently, during starting a radar detection, no link id information is
7parsed and passed down. In order to support starting radar detection
8during Multi Link Operation, it is required to pass link id as well.
9
10Add changes to first parse and then pass link id in the start radar
11detection path.
12
13Additionally, update notification APIs to allow drivers/mac80211 to
14pass the link ID.
15
16However, everything is handled at link 0 only until all API's are ready to
17handle it per link.
18
19Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
20---
21 drivers/net/wireless/marvell/mwifiex/11h.c | 7 +++--
22 .../net/wireless/marvell/mwifiex/cfg80211.c | 2 +-
23 .../net/wireless/quantenna/qtnfmac/cfg80211.c | 2 +-
24 .../net/wireless/quantenna/qtnfmac/event.c | 6 ++--
25 include/net/cfg80211.h | 8 +++--
26 net/mac80211/cfg.c | 6 ++--
27 net/mac80211/iface.c | 2 +-
28 net/mac80211/mlme.c | 2 +-
29 net/mac80211/util.c | 2 +-
30 net/wireless/mlme.c | 9 +++---
31 net/wireless/nl80211.c | 24 +++++++++++---
32 net/wireless/rdev-ops.h | 13 ++++----
33 net/wireless/reg.c | 19 +++++++-----
34 net/wireless/trace.h | 31 ++++++++++++-------
35 14 files changed, 82 insertions(+), 51 deletions(-)
36
37diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c
38index fb2cad0..032b93a 100644
39--- a/drivers/net/wireless/marvell/mwifiex/11h.c
40+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
41@@ -122,7 +122,7 @@ void mwifiex_dfs_cac_work_queue(struct work_struct *work)
42 "CAC timer finished; No radar detected\n");
43 cfg80211_cac_event(priv->netdev, &chandef,
44 NL80211_RADAR_CAC_FINISHED,
45- GFP_KERNEL);
46+ GFP_KERNEL, 0);
47 }
48 }
49
50@@ -182,7 +182,8 @@ void mwifiex_abort_cac(struct mwifiex_private *priv)
51 "Aborting delayed work for CAC.\n");
52 cancel_delayed_work_sync(&priv->dfs_cac_work);
53 cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
54- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
55+ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL,
56+ 0);
57 }
58 }
59
60@@ -221,7 +222,7 @@ int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
61 cfg80211_cac_event(priv->netdev,
62 &priv->dfs_chandef,
63 NL80211_RADAR_DETECTED,
64- GFP_KERNEL);
65+ GFP_KERNEL, 0);
66 }
67 break;
68 default:
69diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
70index 436d391..18fe850 100644
71--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
72+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
73@@ -4145,7 +4145,7 @@ static int
74 mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
75 struct net_device *dev,
76 struct cfg80211_chan_def *chandef,
77- u32 cac_time_ms)
78+ u32 cac_time_ms, int link_id)
79 {
80 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
81 struct mwifiex_radar_params radar_params;
82diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
83index 663d777..8b97acc 100644
84--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
85+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
86@@ -837,7 +837,7 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
87 static int qtnf_start_radar_detection(struct wiphy *wiphy,
88 struct net_device *ndev,
89 struct cfg80211_chan_def *chandef,
90- u32 cac_time_ms)
91+ u32 cac_time_ms, int link_id)
92 {
93 struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
94 int ret;
95diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
96index 8bd1e14..71840f4 100644
97--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
98+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
99@@ -524,14 +524,14 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif,
100 break;
101
102 cfg80211_cac_event(vif->netdev, &chandef,
103- NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
104+ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
105 break;
106 case QLINK_RADAR_CAC_ABORTED:
107 if (!vif->wdev.links[0].cac_started)
108 break;
109
110 cfg80211_cac_event(vif->netdev, &chandef,
111- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
112+ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0);
113 break;
114 case QLINK_RADAR_CAC_STARTED:
115 if (vif->wdev.links[0].cac_started)
116@@ -542,7 +542,7 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif,
117 break;
118
119 cfg80211_cac_event(vif->netdev, &chandef,
120- NL80211_RADAR_CAC_STARTED, GFP_KERNEL);
121+ NL80211_RADAR_CAC_STARTED, GFP_KERNEL, 0);
122 break;
123 default:
124 pr_warn("%s: unhandled radar event %u\n",
125diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
126index 86634cc..906e48b 100644
127--- a/include/net/cfg80211.h
128+++ b/include/net/cfg80211.h
129@@ -4846,9 +4846,9 @@ struct cfg80211_ops {
130 int (*start_radar_detection)(struct wiphy *wiphy,
131 struct net_device *dev,
132 struct cfg80211_chan_def *chandef,
133- u32 cac_time_ms);
134+ u32 cac_time_ms, int link_id);
135 void (*end_cac)(struct wiphy *wiphy,
136- struct net_device *dev);
137+ struct net_device *dev, unsigned int link_id);
138 int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
139 struct cfg80211_update_ft_ies_params *ftie);
140 int (*crit_proto_start)(struct wiphy *wiphy,
141@@ -8762,6 +8762,7 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
142 * @chandef: chandef for the current channel
143 * @event: type of event
144 * @gfp: context flags
145+ * @link_id: valid link_id for MLO operation or 0 otherwise.
146 *
147 * This function is called when a Channel availability check (CAC) is finished
148 * or aborted. This must be called to notify the completion of a CAC process,
149@@ -8769,7 +8770,8 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
150 */
151 void cfg80211_cac_event(struct net_device *netdev,
152 const struct cfg80211_chan_def *chandef,
153- enum nl80211_radar_event event, gfp_t gfp);
154+ enum nl80211_radar_event event, gfp_t gfp,
155+ unsigned int link_id);
156
157 /**
158 * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
159diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
160index 4d5eb60..cf60420 100644
161--- a/net/mac80211/cfg.c
162+++ b/net/mac80211/cfg.c
163@@ -1661,7 +1661,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
164 wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
165 cfg80211_cac_event(sdata->dev, &chandef,
166 NL80211_RADAR_CAC_ABORTED,
167- GFP_KERNEL);
168+ GFP_KERNEL, 0);
169 }
170
171 drv_stop_ap(sdata->local, sdata, link_conf);
172@@ -3455,7 +3455,7 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
173 static int ieee80211_start_radar_detection(struct wiphy *wiphy,
174 struct net_device *dev,
175 struct cfg80211_chan_def *chandef,
176- u32 cac_time_ms)
177+ u32 cac_time_ms, int link_id)
178 {
179 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
180 struct ieee80211_chan_req chanreq = { .oper = *chandef };
181@@ -3483,7 +3483,7 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
182 }
183
184 static void ieee80211_end_cac(struct wiphy *wiphy,
185- struct net_device *dev)
186+ struct net_device *dev, unsigned int link_id)
187 {
188 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
189 struct ieee80211_local *local = sdata->local;
190diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
191index f0d9024..71e8b0d 100644
192--- a/net/mac80211/iface.c
193+++ b/net/mac80211/iface.c
194@@ -558,7 +558,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
195 ieee80211_link_release_channel(&sdata->deflink);
196 cfg80211_cac_event(sdata->dev, &chandef,
197 NL80211_RADAR_CAC_ABORTED,
198- GFP_KERNEL);
199+ GFP_KERNEL, 0);
200 }
201
202 if (sdata->vif.type == NL80211_IFTYPE_AP) {
203diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
204index 2258858..2c7a3dc 100644
205--- a/net/mac80211/mlme.c
206+++ b/net/mac80211/mlme.c
207@@ -3043,7 +3043,7 @@ void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work)
208 ieee80211_link_release_channel(link);
209 cfg80211_cac_event(sdata->dev, &chandef,
210 NL80211_RADAR_CAC_FINISHED,
211- GFP_KERNEL);
212+ GFP_KERNEL, 0);
213 }
214 }
215
216diff --git a/net/mac80211/util.c b/net/mac80211/util.c
217index 424d8d6..5996ea7 100644
218--- a/net/mac80211/util.c
219+++ b/net/mac80211/util.c
220@@ -3468,7 +3468,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
221 cfg80211_cac_event(sdata->dev,
222 &chandef,
223 NL80211_RADAR_CAC_ABORTED,
224- GFP_KERNEL);
225+ GFP_KERNEL, 0);
226 }
227 }
228 }
229diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
230index eda999d..7d52222 100644
231--- a/net/wireless/mlme.c
232+++ b/net/wireless/mlme.c
233@@ -1111,18 +1111,19 @@ EXPORT_SYMBOL(__cfg80211_radar_event);
234
235 void cfg80211_cac_event(struct net_device *netdev,
236 const struct cfg80211_chan_def *chandef,
237- enum nl80211_radar_event event, gfp_t gfp)
238+ enum nl80211_radar_event event, gfp_t gfp,
239+ unsigned int link_id)
240 {
241 struct wireless_dev *wdev = netdev->ieee80211_ptr;
242 struct wiphy *wiphy = wdev->wiphy;
243 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
244 unsigned long timeout;
245
246- /* not yet supported */
247- if (wdev->valid_links)
248+ if (WARN_ON(wdev->valid_links &&
249+ !(wdev->valid_links & BIT(link_id))))
250 return;
251
252- trace_cfg80211_cac_event(netdev, event);
253+ trace_cfg80211_cac_event(netdev, event, link_id);
254
255 if (WARN_ON(!wdev->links[0].cac_started &&
256 event != NL80211_RADAR_CAC_STARTED))
257diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
258index 3e87f5a..6893256 100644
259--- a/net/wireless/nl80211.c
260+++ b/net/wireless/nl80211.c
261@@ -10154,7 +10154,20 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
262 goto unlock;
263 }
264
265- if (cfg80211_beaconing_iface_active(wdev) || wdev->links[0].cac_started) {
266+ if (cfg80211_beaconing_iface_active(wdev)) {
267+ /* During MLO other link(s) can beacon, only the current link
268+ * can not already beacon
269+ */
270+ if (wdev->valid_links &&
271+ !wdev->links[0].ap.beacon_interval) {
272+ /* nothing */
273+ } else {
274+ err = -EBUSY;
275+ goto unlock;
276+ }
277+ }
278+
279+ if (wdev->links[0].cac_started) {
280 err = -EBUSY;
281 goto unlock;
282 }
283@@ -10174,7 +10187,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
284 if (WARN_ON(!cac_time_ms))
285 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
286
287- err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
288+ err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms,
289+ 0);
290 if (!err) {
291 wdev->links[0].ap.chandef = chandef;
292 wdev->links[0].cac_started = true;
293@@ -16531,10 +16545,10 @@ nl80211_set_ttlm(struct sk_buff *skb, struct genl_info *info)
294 SELECTOR(__sel, NETDEV_UP_NOTMX, \
295 NL80211_FLAG_NEED_NETDEV_UP | \
296 NL80211_FLAG_NO_WIPHY_MTX) \
297- SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO, \
298+ SELECTOR(__sel, NETDEV_UP_NOTMX_MLO, \
299 NL80211_FLAG_NEED_NETDEV_UP | \
300 NL80211_FLAG_NO_WIPHY_MTX | \
301- NL80211_FLAG_MLO_UNSUPPORTED) \
302+ NL80211_FLAG_MLO_VALID_LINK_ID) \
303 SELECTOR(__sel, NETDEV_UP_CLEAR, \
304 NL80211_FLAG_NEED_NETDEV_UP | \
305 NL80211_FLAG_CLEAR_SKB) \
306@@ -17441,7 +17455,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
307 .flags = GENL_UNS_ADMIN_PERM,
308 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
309 NL80211_FLAG_NO_WIPHY_MTX |
310- NL80211_FLAG_MLO_UNSUPPORTED),
311+ NL80211_FLAG_MLO_VALID_LINK_ID),
312 },
313 {
314 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
315diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
316index 951ca95..4e8c895 100644
317--- a/net/wireless/rdev-ops.h
318+++ b/net/wireless/rdev-ops.h
319@@ -1200,26 +1200,27 @@ static inline int
320 rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
321 struct net_device *dev,
322 struct cfg80211_chan_def *chandef,
323- u32 cac_time_ms)
324+ u32 cac_time_ms, int link_id)
325 {
326 int ret = -EOPNOTSUPP;
327
328 trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef,
329- cac_time_ms);
330+ cac_time_ms, link_id);
331 if (rdev->ops->start_radar_detection)
332 ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev,
333- chandef, cac_time_ms);
334+ chandef, cac_time_ms,
335+ link_id);
336 trace_rdev_return_int(&rdev->wiphy, ret);
337 return ret;
338 }
339
340 static inline void
341 rdev_end_cac(struct cfg80211_registered_device *rdev,
342- struct net_device *dev)
343+ struct net_device *dev, unsigned int link_id)
344 {
345- trace_rdev_end_cac(&rdev->wiphy, dev);
346+ trace_rdev_end_cac(&rdev->wiphy, dev, link_id);
347 if (rdev->ops->end_cac)
348- rdev->ops->end_cac(&rdev->wiphy, dev);
349+ rdev->ops->end_cac(&rdev->wiphy, dev, link_id);
350 trace_rdev_return_void(&rdev->wiphy);
351 }
352
353diff --git a/net/wireless/reg.c b/net/wireless/reg.c
354index 0040862..1a393f3 100644
355--- a/net/wireless/reg.c
356+++ b/net/wireless/reg.c
357@@ -4233,6 +4233,8 @@ EXPORT_SYMBOL(regulatory_pre_cac_allowed);
358 static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
359 {
360 struct wireless_dev *wdev;
361+ unsigned int link_id;
362+
363 /* If we finished CAC or received radar, we should end any
364 * CAC running on the same channels.
365 * the check !cfg80211_chandef_dfs_usable contain 2 options:
366@@ -4245,16 +4247,17 @@ static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
367 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
368 struct cfg80211_chan_def *chandef;
369
370- if (!wdev->links[0].cac_started)
371- continue;
372+ for_each_valid_link(wdev, link_id) {
373+ if (!wdev->links[link_id].cac_started)
374+ continue;
375
376- /* FIXME: radar detection is tied to link 0 for now */
377- chandef = wdev_chandef(wdev, 0);
378- if (!chandef)
379- continue;
380+ chandef = wdev_chandef(wdev, link_id);
381+ if (!chandef)
382+ continue;
383
384- if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
385- rdev_end_cac(rdev, wdev->netdev);
386+ if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
387+ rdev_end_cac(rdev, wdev->netdev, link_id);
388+ }
389 }
390 }
391
392diff --git a/net/wireless/trace.h b/net/wireless/trace.h
393index 881c01d..a831f94 100644
394--- a/net/wireless/trace.h
395+++ b/net/wireless/trace.h
396@@ -806,17 +806,21 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
397 );
398
399 TRACE_EVENT(rdev_end_cac,
400- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
401- TP_ARGS(wiphy, netdev),
402+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
403+ unsigned int link_id),
404+ TP_ARGS(wiphy, netdev, link_id),
405 TP_STRUCT__entry(
406 WIPHY_ENTRY
407 NETDEV_ENTRY
408+ __field(unsigned int, link_id)
409 ),
410 TP_fast_assign(
411 WIPHY_ASSIGN;
412 NETDEV_ASSIGN;
413+ __entry->link_id = link_id;
414 ),
415- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
416+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d",
417+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id)
418 );
419
420 DECLARE_EVENT_CLASS(station_add_change,
421@@ -2661,24 +2665,26 @@ TRACE_EVENT(rdev_external_auth,
422 TRACE_EVENT(rdev_start_radar_detection,
423 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
424 struct cfg80211_chan_def *chandef,
425- u32 cac_time_ms),
426- TP_ARGS(wiphy, netdev, chandef, cac_time_ms),
427+ u32 cac_time_ms, int link_id),
428+ TP_ARGS(wiphy, netdev, chandef, cac_time_ms, link_id),
429 TP_STRUCT__entry(
430 WIPHY_ENTRY
431 NETDEV_ENTRY
432 CHAN_DEF_ENTRY
433 __field(u32, cac_time_ms)
434+ __field(int, link_id)
435 ),
436 TP_fast_assign(
437 WIPHY_ASSIGN;
438 NETDEV_ASSIGN;
439 CHAN_DEF_ASSIGN(chandef);
440 __entry->cac_time_ms = cac_time_ms;
441+ __entry->link_id = link_id;
442 ),
443 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
444- ", cac_time_ms=%u",
445+ ", cac_time_ms=%u, link_id=%d",
446 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
447- __entry->cac_time_ms)
448+ __entry->cac_time_ms, __entry->link_id)
449 );
450
451 TRACE_EVENT(rdev_set_mcast_rate,
452@@ -3492,18 +3498,21 @@ TRACE_EVENT(cfg80211_radar_event,
453 );
454
455 TRACE_EVENT(cfg80211_cac_event,
456- TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt),
457- TP_ARGS(netdev, evt),
458+ TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt,
459+ unsigned int link_id),
460+ TP_ARGS(netdev, evt, link_id),
461 TP_STRUCT__entry(
462 NETDEV_ENTRY
463 __field(enum nl80211_radar_event, evt)
464+ __field(unsigned int, link_id)
465 ),
466 TP_fast_assign(
467 NETDEV_ASSIGN;
468 __entry->evt = evt;
469+ __entry->link_id = link_id;
470 ),
471- TP_printk(NETDEV_PR_FMT ", event: %d",
472- NETDEV_PR_ARG, __entry->evt)
473+ TP_printk(NETDEV_PR_FMT ", event: %d, link_id=%u",
474+ NETDEV_PR_ARG, __entry->evt, __entry->link_id)
475 );
476
477 DECLARE_EVENT_CLASS(cfg80211_rx_evt,
478--
4792.18.0
480