]> Git Repo - J-linux.git/blob - net/mac80211/chan.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / net / mac80211 / chan.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * mac80211 - channel management
4  * Copyright 2020 - 2024 Intel Corporation
5  */
6
7 #include <linux/nl80211.h>
8 #include <linux/export.h>
9 #include <linux/rtnetlink.h>
10 #include <net/cfg80211.h>
11 #include "ieee80211_i.h"
12 #include "driver-ops.h"
13 #include "rate.h"
14
15 static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
16                                           struct ieee80211_chanctx *ctx)
17 {
18         struct ieee80211_link_data *link;
19         int num = 0;
20
21         lockdep_assert_wiphy(local->hw.wiphy);
22
23         list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list)
24                 num++;
25
26         return num;
27 }
28
29 static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
30                                           struct ieee80211_chanctx *ctx)
31 {
32         struct ieee80211_link_data *link;
33         int num = 0;
34
35         lockdep_assert_wiphy(local->hw.wiphy);
36
37         list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list)
38                 num++;
39
40         return num;
41 }
42
43 int ieee80211_chanctx_refcount(struct ieee80211_local *local,
44                                struct ieee80211_chanctx *ctx)
45 {
46         return ieee80211_chanctx_num_assigned(local, ctx) +
47                ieee80211_chanctx_num_reserved(local, ctx);
48 }
49
50 static int ieee80211_num_chanctx(struct ieee80211_local *local, int radio_idx)
51 {
52         struct ieee80211_chanctx *ctx;
53         int num = 0;
54
55         lockdep_assert_wiphy(local->hw.wiphy);
56
57         list_for_each_entry(ctx, &local->chanctx_list, list) {
58                 if (radio_idx >= 0 && ctx->conf.radio_idx != radio_idx)
59                         continue;
60                 num++;
61         }
62
63         return num;
64 }
65
66 static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local,
67                                              int radio_idx)
68 {
69         lockdep_assert_wiphy(local->hw.wiphy);
70
71         return ieee80211_num_chanctx(local, radio_idx) <
72                ieee80211_max_num_channels(local, radio_idx);
73 }
74
75 static struct ieee80211_chanctx *
76 ieee80211_link_get_chanctx(struct ieee80211_link_data *link)
77 {
78         struct ieee80211_local *local __maybe_unused = link->sdata->local;
79         struct ieee80211_chanctx_conf *conf;
80
81         conf = rcu_dereference_protected(link->conf->chanctx_conf,
82                                          lockdep_is_held(&local->hw.wiphy->mtx));
83         if (!conf)
84                 return NULL;
85
86         return container_of(conf, struct ieee80211_chanctx, conf);
87 }
88
89 bool ieee80211_chanreq_identical(const struct ieee80211_chan_req *a,
90                                  const struct ieee80211_chan_req *b)
91 {
92         if (!cfg80211_chandef_identical(&a->oper, &b->oper))
93                 return false;
94         if (!a->ap.chan && !b->ap.chan)
95                 return true;
96         return cfg80211_chandef_identical(&a->ap, &b->ap);
97 }
98
99 static const struct ieee80211_chan_req *
100 ieee80211_chanreq_compatible(const struct ieee80211_chan_req *a,
101                              const struct ieee80211_chan_req *b,
102                              struct ieee80211_chan_req *tmp)
103 {
104         const struct cfg80211_chan_def *compat;
105
106         if (a->ap.chan && b->ap.chan &&
107             !cfg80211_chandef_identical(&a->ap, &b->ap))
108                 return NULL;
109
110         compat = cfg80211_chandef_compatible(&a->oper, &b->oper);
111         if (!compat)
112                 return NULL;
113
114         /* Note: later code assumes this always fills & returns tmp if compat */
115         tmp->oper = *compat;
116         tmp->ap = a->ap.chan ? a->ap : b->ap;
117         return tmp;
118 }
119
120 static const struct ieee80211_chan_req *
121 ieee80211_chanctx_compatible(struct ieee80211_chanctx *ctx,
122                              const struct ieee80211_chan_req *req,
123                              struct ieee80211_chan_req *tmp)
124 {
125         const struct ieee80211_chan_req *ret;
126         struct ieee80211_chan_req tmp2;
127
128         *tmp = (struct ieee80211_chan_req){
129                 .oper = ctx->conf.def,
130                 .ap = ctx->conf.ap,
131         };
132
133         ret = ieee80211_chanreq_compatible(tmp, req, &tmp2);
134         if (!ret)
135                 return NULL;
136         *tmp = *ret;
137         return tmp;
138 }
139
140 static const struct ieee80211_chan_req *
141 ieee80211_chanctx_reserved_chanreq(struct ieee80211_local *local,
142                                    struct ieee80211_chanctx *ctx,
143                                    const struct ieee80211_chan_req *req,
144                                    struct ieee80211_chan_req *tmp)
145 {
146         struct ieee80211_link_data *link;
147
148         lockdep_assert_wiphy(local->hw.wiphy);
149
150         if (WARN_ON(!req))
151                 return NULL;
152
153         list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) {
154                 req = ieee80211_chanreq_compatible(&link->reserved, req, tmp);
155                 if (!req)
156                         break;
157         }
158
159         return req;
160 }
161
162 static const struct ieee80211_chan_req *
163 ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
164                                        struct ieee80211_chanctx *ctx,
165                                        const struct ieee80211_chan_req *compat,
166                                        struct ieee80211_chan_req *tmp)
167 {
168         struct ieee80211_link_data *link;
169         const struct ieee80211_chan_req *comp_def = compat;
170
171         lockdep_assert_wiphy(local->hw.wiphy);
172
173         list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) {
174                 struct ieee80211_bss_conf *link_conf = link->conf;
175
176                 if (link->reserved_chanctx)
177                         continue;
178
179                 comp_def = ieee80211_chanreq_compatible(&link_conf->chanreq,
180                                                         comp_def, tmp);
181                 if (!comp_def)
182                         break;
183         }
184
185         return comp_def;
186 }
187
188 static bool
189 ieee80211_chanctx_can_reserve(struct ieee80211_local *local,
190                               struct ieee80211_chanctx *ctx,
191                               const struct ieee80211_chan_req *req)
192 {
193         struct ieee80211_chan_req tmp;
194
195         lockdep_assert_wiphy(local->hw.wiphy);
196
197         if (!ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
198                 return false;
199
200         if (!ieee80211_chanctx_non_reserved_chandef(local, ctx, req, &tmp))
201                 return false;
202
203         if (!list_empty(&ctx->reserved_links) &&
204             ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
205                 return true;
206
207         return false;
208 }
209
210 static struct ieee80211_chanctx *
211 ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
212                                    const struct ieee80211_chan_req *chanreq,
213                                    enum ieee80211_chanctx_mode mode)
214 {
215         struct ieee80211_chanctx *ctx;
216
217         lockdep_assert_wiphy(local->hw.wiphy);
218
219         if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
220                 return NULL;
221
222         list_for_each_entry(ctx, &local->chanctx_list, list) {
223                 if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
224                         continue;
225
226                 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
227                         continue;
228
229                 if (!ieee80211_chanctx_can_reserve(local, ctx, chanreq))
230                         continue;
231
232                 return ctx;
233         }
234
235         return NULL;
236 }
237
238 static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta,
239                                                     unsigned int link_id)
240 {
241         enum ieee80211_sta_rx_bandwidth width;
242         struct link_sta_info *link_sta;
243
244         link_sta = wiphy_dereference(sta->local->hw.wiphy, sta->link[link_id]);
245
246         /* no effect if this STA has no presence on this link */
247         if (!link_sta)
248                 return NL80211_CHAN_WIDTH_20_NOHT;
249
250         width = ieee80211_sta_cap_rx_bw(link_sta);
251
252         switch (width) {
253         case IEEE80211_STA_RX_BW_20:
254                 if (link_sta->pub->ht_cap.ht_supported)
255                         return NL80211_CHAN_WIDTH_20;
256                 else
257                         return NL80211_CHAN_WIDTH_20_NOHT;
258         case IEEE80211_STA_RX_BW_40:
259                 return NL80211_CHAN_WIDTH_40;
260         case IEEE80211_STA_RX_BW_80:
261                 return NL80211_CHAN_WIDTH_80;
262         case IEEE80211_STA_RX_BW_160:
263                 /*
264                  * This applied for both 160 and 80+80. since we use
265                  * the returned value to consider degradation of
266                  * ctx->conf.min_def, we have to make sure to take
267                  * the bigger one (NL80211_CHAN_WIDTH_160).
268                  * Otherwise we might try degrading even when not
269                  * needed, as the max required sta_bw returned (80+80)
270                  * might be smaller than the configured bw (160).
271                  */
272                 return NL80211_CHAN_WIDTH_160;
273         case IEEE80211_STA_RX_BW_320:
274                 return NL80211_CHAN_WIDTH_320;
275         default:
276                 WARN_ON(1);
277                 return NL80211_CHAN_WIDTH_20;
278         }
279 }
280
281 static enum nl80211_chan_width
282 ieee80211_get_max_required_bw(struct ieee80211_link_data *link)
283 {
284         struct ieee80211_sub_if_data *sdata = link->sdata;
285         unsigned int link_id = link->link_id;
286         enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
287         struct sta_info *sta;
288
289         lockdep_assert_wiphy(sdata->local->hw.wiphy);
290
291         list_for_each_entry(sta, &sdata->local->sta_list, list) {
292                 if (sdata != sta->sdata &&
293                     !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
294                         continue;
295
296                 max_bw = max(max_bw, ieee80211_get_sta_bw(sta, link_id));
297         }
298
299         return max_bw;
300 }
301
302 static enum nl80211_chan_width
303 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
304                                       struct ieee80211_chanctx *ctx,
305                                       struct ieee80211_link_data *rsvd_for,
306                                       bool check_reserved)
307 {
308         struct ieee80211_sub_if_data *sdata;
309         struct ieee80211_link_data *link;
310         enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
311
312         if (WARN_ON(check_reserved && rsvd_for))
313                 return ctx->conf.def.width;
314
315         for_each_sdata_link(local, link) {
316                 enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
317
318                 if (check_reserved) {
319                         if (link->reserved_chanctx != ctx)
320                                 continue;
321                 } else if (link != rsvd_for &&
322                            rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf)
323                         continue;
324
325                 switch (link->sdata->vif.type) {
326                 case NL80211_IFTYPE_STATION:
327                         if (!link->sdata->vif.cfg.assoc) {
328                                 /*
329                                  * The AP's sta->bandwidth may not yet be set
330                                  * at this point (pre-association), so simply
331                                  * take the width from the chandef. We cannot
332                                  * have TDLS peers yet (only after association).
333                                  */
334                                 width = link->conf->chanreq.oper.width;
335                                 break;
336                         }
337                         /*
338                          * otherwise just use min_def like in AP, depending on what
339                          * we currently think the AP STA (and possibly TDLS peers)
340                          * require(s)
341                          */
342                         fallthrough;
343                 case NL80211_IFTYPE_AP:
344                 case NL80211_IFTYPE_AP_VLAN:
345                         width = ieee80211_get_max_required_bw(link);
346                         break;
347                 case NL80211_IFTYPE_P2P_DEVICE:
348                 case NL80211_IFTYPE_NAN:
349                         continue;
350                 case NL80211_IFTYPE_MONITOR:
351                         WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
352                                                          NO_VIRTUAL_MONITOR));
353                         fallthrough;
354                 case NL80211_IFTYPE_ADHOC:
355                 case NL80211_IFTYPE_MESH_POINT:
356                 case NL80211_IFTYPE_OCB:
357                         width = link->conf->chanreq.oper.width;
358                         break;
359                 case NL80211_IFTYPE_WDS:
360                 case NL80211_IFTYPE_UNSPECIFIED:
361                 case NUM_NL80211_IFTYPES:
362                 case NL80211_IFTYPE_P2P_CLIENT:
363                 case NL80211_IFTYPE_P2P_GO:
364                         WARN_ON_ONCE(1);
365                 }
366
367                 max_bw = max(max_bw, width);
368         }
369
370         /* use the configured bandwidth in case of monitor interface */
371         sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
372         if (sdata &&
373             rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &ctx->conf)
374                 max_bw = max(max_bw, ctx->conf.def.width);
375
376         return max_bw;
377 }
378
379 /*
380  * recalc the min required chan width of the channel context, which is
381  * the max of min required widths of all the interfaces bound to this
382  * channel context.
383  */
384 static u32
385 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
386                                   struct ieee80211_chanctx *ctx,
387                                   struct ieee80211_link_data *rsvd_for,
388                                   bool check_reserved)
389 {
390         enum nl80211_chan_width max_bw;
391         struct cfg80211_chan_def min_def;
392
393         lockdep_assert_wiphy(local->hw.wiphy);
394
395         /* don't optimize non-20MHz based and radar_enabled confs */
396         if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
397             ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
398             ctx->conf.def.width == NL80211_CHAN_WIDTH_1 ||
399             ctx->conf.def.width == NL80211_CHAN_WIDTH_2 ||
400             ctx->conf.def.width == NL80211_CHAN_WIDTH_4 ||
401             ctx->conf.def.width == NL80211_CHAN_WIDTH_8 ||
402             ctx->conf.def.width == NL80211_CHAN_WIDTH_16 ||
403             ctx->conf.radar_enabled) {
404                 ctx->conf.min_def = ctx->conf.def;
405                 return 0;
406         }
407
408         max_bw = ieee80211_get_chanctx_max_required_bw(local, ctx, rsvd_for,
409                                                        check_reserved);
410
411         /* downgrade chandef up to max_bw */
412         min_def = ctx->conf.def;
413         while (min_def.width > max_bw)
414                 ieee80211_chandef_downgrade(&min_def, NULL);
415
416         if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
417                 return 0;
418
419         ctx->conf.min_def = min_def;
420         if (!ctx->driver_present)
421                 return 0;
422
423         return IEEE80211_CHANCTX_CHANGE_MIN_DEF;
424 }
425
426 static void ieee80211_chan_bw_change(struct ieee80211_local *local,
427                                      struct ieee80211_chanctx *ctx,
428                                      bool reserved, bool narrowed)
429 {
430         struct sta_info *sta;
431         struct ieee80211_supported_band *sband =
432                 local->hw.wiphy->bands[ctx->conf.def.chan->band];
433
434         rcu_read_lock();
435         list_for_each_entry_rcu(sta, &local->sta_list,
436                                 list) {
437                 struct ieee80211_sub_if_data *sdata = sta->sdata;
438                 enum ieee80211_sta_rx_bandwidth new_sta_bw;
439                 unsigned int link_id;
440
441                 if (!ieee80211_sdata_running(sta->sdata))
442                         continue;
443
444                 for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
445                         struct ieee80211_link_data *link =
446                                 rcu_dereference(sdata->link[link_id]);
447                         struct ieee80211_bss_conf *link_conf;
448                         struct cfg80211_chan_def *new_chandef;
449                         struct link_sta_info *link_sta;
450
451                         if (!link)
452                                 continue;
453
454                         link_conf = link->conf;
455
456                         if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
457                                 continue;
458
459                         link_sta = rcu_dereference(sta->link[link_id]);
460                         if (!link_sta)
461                                 continue;
462
463                         if (reserved)
464                                 new_chandef = &link->reserved.oper;
465                         else
466                                 new_chandef = &link_conf->chanreq.oper;
467
468                         new_sta_bw = _ieee80211_sta_cur_vht_bw(link_sta,
469                                                                new_chandef);
470
471                         /* nothing change */
472                         if (new_sta_bw == link_sta->pub->bandwidth)
473                                 continue;
474
475                         /* vif changed to narrow BW and narrow BW for station wasn't
476                          * requested or vice versa */
477                         if ((new_sta_bw < link_sta->pub->bandwidth) == !narrowed)
478                                 continue;
479
480                         link_sta->pub->bandwidth = new_sta_bw;
481                         rate_control_rate_update(local, sband, link_sta,
482                                                  IEEE80211_RC_BW_CHANGED);
483                 }
484         }
485         rcu_read_unlock();
486 }
487
488 /*
489  * recalc the min required chan width of the channel context, which is
490  * the max of min required widths of all the interfaces bound to this
491  * channel context.
492  */
493 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
494                                       struct ieee80211_chanctx *ctx,
495                                       struct ieee80211_link_data *rsvd_for,
496                                       bool check_reserved)
497 {
498         u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for,
499                                                         check_reserved);
500
501         if (!changed)
502                 return;
503
504         /* check is BW narrowed */
505         ieee80211_chan_bw_change(local, ctx, false, true);
506
507         drv_change_chanctx(local, ctx, changed);
508
509         /* check is BW wider */
510         ieee80211_chan_bw_change(local, ctx, false, false);
511 }
512
513 static void _ieee80211_change_chanctx(struct ieee80211_local *local,
514                                       struct ieee80211_chanctx *ctx,
515                                       struct ieee80211_chanctx *old_ctx,
516                                       const struct ieee80211_chan_req *chanreq,
517                                       struct ieee80211_link_data *rsvd_for)
518 {
519         const struct cfg80211_chan_def *chandef = &chanreq->oper;
520         struct ieee80211_chan_req ctx_req = {
521                 .oper = ctx->conf.def,
522                 .ap = ctx->conf.ap,
523         };
524         u32 changed = 0;
525
526         /* expected to handle only 20/40/80/160/320 channel widths */
527         switch (chandef->width) {
528         case NL80211_CHAN_WIDTH_20_NOHT:
529         case NL80211_CHAN_WIDTH_20:
530         case NL80211_CHAN_WIDTH_40:
531         case NL80211_CHAN_WIDTH_80:
532         case NL80211_CHAN_WIDTH_80P80:
533         case NL80211_CHAN_WIDTH_160:
534         case NL80211_CHAN_WIDTH_320:
535                 break;
536         default:
537                 WARN_ON(1);
538         }
539
540         /* Check maybe BW narrowed - we do this _before_ calling recalc_chanctx_min_def
541          * due to maybe not returning from it, e.g in case new context was added
542          * first time with all parameters up to date.
543          */
544         ieee80211_chan_bw_change(local, old_ctx, false, true);
545
546         if (ieee80211_chanreq_identical(&ctx_req, chanreq)) {
547                 ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
548                 return;
549         }
550
551         WARN_ON(ieee80211_chanctx_refcount(local, ctx) > 1 &&
552                 !cfg80211_chandef_compatible(&ctx->conf.def, &chanreq->oper));
553
554         ieee80211_remove_wbrf(local, &ctx->conf.def);
555
556         if (!cfg80211_chandef_identical(&ctx->conf.def, &chanreq->oper)) {
557                 if (ctx->conf.def.width != chanreq->oper.width)
558                         changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
559                 if (ctx->conf.def.punctured != chanreq->oper.punctured)
560                         changed |= IEEE80211_CHANCTX_CHANGE_PUNCTURING;
561         }
562         if (!cfg80211_chandef_identical(&ctx->conf.ap, &chanreq->ap))
563                 changed |= IEEE80211_CHANCTX_CHANGE_AP;
564         ctx->conf.def = *chandef;
565         ctx->conf.ap = chanreq->ap;
566
567         /* check if min chanctx also changed */
568         changed |= _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
569
570         ieee80211_add_wbrf(local, &ctx->conf.def);
571
572         drv_change_chanctx(local, ctx, changed);
573
574         /* check if BW is wider */
575         ieee80211_chan_bw_change(local, old_ctx, false, false);
576 }
577
578 static void ieee80211_change_chanctx(struct ieee80211_local *local,
579                                      struct ieee80211_chanctx *ctx,
580                                      struct ieee80211_chanctx *old_ctx,
581                                      const struct ieee80211_chan_req *chanreq)
582 {
583         _ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL);
584 }
585
586 /* Note: if successful, the returned chanctx is reserved for the link */
587 static struct ieee80211_chanctx *
588 ieee80211_find_chanctx(struct ieee80211_local *local,
589                        struct ieee80211_link_data *link,
590                        const struct ieee80211_chan_req *chanreq,
591                        enum ieee80211_chanctx_mode mode)
592 {
593         struct ieee80211_chan_req tmp;
594         struct ieee80211_chanctx *ctx;
595
596         lockdep_assert_wiphy(local->hw.wiphy);
597
598         if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
599                 return NULL;
600
601         if (WARN_ON(link->reserved_chanctx))
602                 return NULL;
603
604         list_for_each_entry(ctx, &local->chanctx_list, list) {
605                 const struct ieee80211_chan_req *compat;
606
607                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE)
608                         continue;
609
610                 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
611                         continue;
612
613                 compat = ieee80211_chanctx_compatible(ctx, chanreq, &tmp);
614                 if (!compat)
615                         continue;
616
617                 compat = ieee80211_chanctx_reserved_chanreq(local, ctx,
618                                                             compat, &tmp);
619                 if (!compat)
620                         continue;
621
622                 /*
623                  * Reserve the chanctx temporarily, as the driver might change
624                  * active links during callbacks we make into it below and/or
625                  * later during assignment, which could (otherwise) cause the
626                  * context to actually be removed.
627                  */
628                 link->reserved_chanctx = ctx;
629                 list_add(&link->reserved_chanctx_list,
630                          &ctx->reserved_links);
631
632                 ieee80211_change_chanctx(local, ctx, ctx, compat);
633
634                 return ctx;
635         }
636
637         return NULL;
638 }
639
640 bool ieee80211_is_radar_required(struct ieee80211_local *local)
641 {
642         struct ieee80211_link_data *link;
643
644         lockdep_assert_wiphy(local->hw.wiphy);
645
646         for_each_sdata_link(local, link) {
647                 if (link->radar_required)
648                         return true;
649         }
650
651         return false;
652 }
653
654 static bool
655 ieee80211_chanctx_radar_required(struct ieee80211_local *local,
656                                  struct ieee80211_chanctx *ctx)
657 {
658         struct ieee80211_chanctx_conf *conf = &ctx->conf;
659         struct ieee80211_link_data *link;
660
661         lockdep_assert_wiphy(local->hw.wiphy);
662
663         for_each_sdata_link(local, link) {
664                 if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
665                         continue;
666                 if (!link->radar_required)
667                         continue;
668                 return true;
669         }
670
671         return false;
672 }
673
674 static struct ieee80211_chanctx *
675 ieee80211_alloc_chanctx(struct ieee80211_local *local,
676                         const struct ieee80211_chan_req *chanreq,
677                         enum ieee80211_chanctx_mode mode,
678                         int radio_idx)
679 {
680         struct ieee80211_chanctx *ctx;
681
682         lockdep_assert_wiphy(local->hw.wiphy);
683
684         ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
685         if (!ctx)
686                 return NULL;
687
688         INIT_LIST_HEAD(&ctx->assigned_links);
689         INIT_LIST_HEAD(&ctx->reserved_links);
690         ctx->conf.def = chanreq->oper;
691         ctx->conf.ap = chanreq->ap;
692         ctx->conf.rx_chains_static = 1;
693         ctx->conf.rx_chains_dynamic = 1;
694         ctx->mode = mode;
695         ctx->conf.radar_enabled = false;
696         ctx->conf.radio_idx = radio_idx;
697         ctx->radar_detected = false;
698         _ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
699
700         return ctx;
701 }
702
703 static int ieee80211_add_chanctx(struct ieee80211_local *local,
704                                  struct ieee80211_chanctx *ctx)
705 {
706         u32 changed;
707         int err;
708
709         lockdep_assert_wiphy(local->hw.wiphy);
710
711         ieee80211_add_wbrf(local, &ctx->conf.def);
712
713         /* turn idle off *before* setting channel -- some drivers need that */
714         changed = ieee80211_idle_off(local);
715         if (changed)
716                 ieee80211_hw_config(local, changed);
717
718         err = drv_add_chanctx(local, ctx);
719         if (err) {
720                 ieee80211_recalc_idle(local);
721                 return err;
722         }
723
724         return 0;
725 }
726
727 static struct ieee80211_chanctx *
728 ieee80211_new_chanctx(struct ieee80211_local *local,
729                       const struct ieee80211_chan_req *chanreq,
730                       enum ieee80211_chanctx_mode mode,
731                       bool assign_on_failure,
732                       int radio_idx)
733 {
734         struct ieee80211_chanctx *ctx;
735         int err;
736
737         lockdep_assert_wiphy(local->hw.wiphy);
738
739         ctx = ieee80211_alloc_chanctx(local, chanreq, mode, radio_idx);
740         if (!ctx)
741                 return ERR_PTR(-ENOMEM);
742
743         err = ieee80211_add_chanctx(local, ctx);
744         if (!assign_on_failure && err) {
745                 kfree(ctx);
746                 return ERR_PTR(err);
747         }
748         /* We ignored a driver error, see _ieee80211_set_active_links */
749         WARN_ON_ONCE(err && !local->in_reconfig);
750
751         list_add_rcu(&ctx->list, &local->chanctx_list);
752         return ctx;
753 }
754
755 static void ieee80211_del_chanctx(struct ieee80211_local *local,
756                                   struct ieee80211_chanctx *ctx,
757                                   bool skip_idle_recalc)
758 {
759         lockdep_assert_wiphy(local->hw.wiphy);
760
761         drv_remove_chanctx(local, ctx);
762
763         if (!skip_idle_recalc)
764                 ieee80211_recalc_idle(local);
765
766         ieee80211_remove_wbrf(local, &ctx->conf.def);
767 }
768
769 static void ieee80211_free_chanctx(struct ieee80211_local *local,
770                                    struct ieee80211_chanctx *ctx,
771                                    bool skip_idle_recalc)
772 {
773         lockdep_assert_wiphy(local->hw.wiphy);
774
775         WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
776
777         list_del_rcu(&ctx->list);
778         ieee80211_del_chanctx(local, ctx, skip_idle_recalc);
779         kfree_rcu(ctx, rcu_head);
780 }
781
782 void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
783                                        struct ieee80211_chanctx *ctx)
784 {
785         struct ieee80211_chanctx_conf *conf = &ctx->conf;
786         const struct ieee80211_chan_req *compat = NULL;
787         struct ieee80211_link_data *link;
788         struct ieee80211_chan_req tmp;
789         struct sta_info *sta;
790
791         lockdep_assert_wiphy(local->hw.wiphy);
792
793         for_each_sdata_link(local, link) {
794                 struct ieee80211_bss_conf *link_conf;
795
796                 if (link->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
797                         continue;
798
799                 link_conf = link->conf;
800
801                 if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
802                         continue;
803
804                 if (!compat)
805                         compat = &link_conf->chanreq;
806
807                 compat = ieee80211_chanreq_compatible(&link_conf->chanreq,
808                                                       compat, &tmp);
809                 if (WARN_ON_ONCE(!compat))
810                         return;
811         }
812
813         if (WARN_ON_ONCE(!compat))
814                 return;
815
816         /* TDLS peers can sometimes affect the chandef width */
817         list_for_each_entry(sta, &local->sta_list, list) {
818                 struct ieee80211_sub_if_data *sdata = sta->sdata;
819                 struct ieee80211_chan_req tdls_chanreq = {};
820                 int tdls_link_id;
821
822                 if (!sta->uploaded ||
823                     !test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) ||
824                     !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
825                     !sta->tdls_chandef.chan)
826                         continue;
827
828                 tdls_link_id = ieee80211_tdls_sta_link_id(sta);
829                 link = sdata_dereference(sdata->link[tdls_link_id], sdata);
830                 if (!link)
831                         continue;
832
833                 if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
834                         continue;
835
836                 tdls_chanreq.oper = sta->tdls_chandef;
837
838                 /* note this always fills and returns &tmp if compat */
839                 compat = ieee80211_chanreq_compatible(&tdls_chanreq,
840                                                       compat, &tmp);
841                 if (WARN_ON_ONCE(!compat))
842                         return;
843         }
844
845         ieee80211_change_chanctx(local, ctx, ctx, compat);
846 }
847
848 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
849                                            struct ieee80211_chanctx *chanctx)
850 {
851         bool radar_enabled;
852
853         lockdep_assert_wiphy(local->hw.wiphy);
854
855         radar_enabled = ieee80211_chanctx_radar_required(local, chanctx);
856
857         if (radar_enabled == chanctx->conf.radar_enabled)
858                 return;
859
860         chanctx->conf.radar_enabled = radar_enabled;
861
862         drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
863 }
864
865 static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
866                                          struct ieee80211_chanctx *new_ctx,
867                                          bool assign_on_failure)
868 {
869         struct ieee80211_sub_if_data *sdata = link->sdata;
870         struct ieee80211_local *local = sdata->local;
871         struct ieee80211_chanctx_conf *conf;
872         struct ieee80211_chanctx *curr_ctx = NULL;
873         bool new_idle;
874         int ret;
875
876         if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
877                 return -EOPNOTSUPP;
878
879         conf = rcu_dereference_protected(link->conf->chanctx_conf,
880                                          lockdep_is_held(&local->hw.wiphy->mtx));
881
882         if (conf) {
883                 curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
884
885                 drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx);
886                 conf = NULL;
887                 list_del(&link->assigned_chanctx_list);
888         }
889
890         if (new_ctx) {
891                 /* recalc considering the link we'll use it for now */
892                 ieee80211_recalc_chanctx_min_def(local, new_ctx, link, false);
893
894                 ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx);
895                 if (assign_on_failure || !ret) {
896                         /* Need to continue, see _ieee80211_set_active_links */
897                         WARN_ON_ONCE(ret && !local->in_reconfig);
898                         ret = 0;
899
900                         /* succeeded, so commit it to the data structures */
901                         conf = &new_ctx->conf;
902                         list_add(&link->assigned_chanctx_list,
903                                  &new_ctx->assigned_links);
904                 }
905         } else {
906                 ret = 0;
907         }
908
909         rcu_assign_pointer(link->conf->chanctx_conf, conf);
910
911         if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
912                 ieee80211_recalc_chanctx_chantype(local, curr_ctx);
913                 ieee80211_recalc_smps_chanctx(local, curr_ctx);
914                 ieee80211_recalc_radar_chanctx(local, curr_ctx);
915                 ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL, false);
916         }
917
918         if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
919                 ieee80211_recalc_txpower(link, false);
920                 ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
921         }
922
923         if (conf) {
924                 new_idle = false;
925         } else {
926                 struct ieee80211_link_data *tmp;
927
928                 new_idle = true;
929                 for_each_sdata_link(local, tmp) {
930                         if (rcu_access_pointer(tmp->conf->chanctx_conf)) {
931                                 new_idle = false;
932                                 break;
933                         }
934                 }
935         }
936
937         if (new_idle != sdata->vif.cfg.idle) {
938                 sdata->vif.cfg.idle = new_idle;
939
940                 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
941                     sdata->vif.type != NL80211_IFTYPE_MONITOR)
942                         ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
943         }
944
945         ieee80211_check_fast_xmit_iface(sdata);
946
947         return ret;
948 }
949
950 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
951                                    struct ieee80211_chanctx *chanctx)
952 {
953         struct ieee80211_sub_if_data *sdata;
954         u8 rx_chains_static, rx_chains_dynamic;
955         struct ieee80211_link_data *link;
956
957         lockdep_assert_wiphy(local->hw.wiphy);
958
959         rx_chains_static = 1;
960         rx_chains_dynamic = 1;
961
962         for_each_sdata_link(local, link) {
963                 u8 needed_static, needed_dynamic;
964
965                 switch (link->sdata->vif.type) {
966                 case NL80211_IFTYPE_STATION:
967                         if (!link->sdata->u.mgd.associated)
968                                 continue;
969                         break;
970                 case NL80211_IFTYPE_MONITOR:
971                         if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
972                                 continue;
973                         break;
974                 case NL80211_IFTYPE_AP:
975                 case NL80211_IFTYPE_ADHOC:
976                 case NL80211_IFTYPE_MESH_POINT:
977                 case NL80211_IFTYPE_OCB:
978                         break;
979                 default:
980                         continue;
981                 }
982
983                 if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
984                         continue;
985
986                 if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) {
987                         rx_chains_dynamic = rx_chains_static = local->rx_chains;
988                         break;
989                 }
990
991                 switch (link->smps_mode) {
992                 default:
993                         WARN_ONCE(1, "Invalid SMPS mode %d\n",
994                                   link->smps_mode);
995                         fallthrough;
996                 case IEEE80211_SMPS_OFF:
997                         needed_static = link->needed_rx_chains;
998                         needed_dynamic = link->needed_rx_chains;
999                         break;
1000                 case IEEE80211_SMPS_DYNAMIC:
1001                         needed_static = 1;
1002                         needed_dynamic = link->needed_rx_chains;
1003                         break;
1004                 case IEEE80211_SMPS_STATIC:
1005                         needed_static = 1;
1006                         needed_dynamic = 1;
1007                         break;
1008                 }
1009
1010                 rx_chains_static = max(rx_chains_static, needed_static);
1011                 rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
1012         }
1013
1014         /* Disable SMPS for the monitor interface */
1015         sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
1016         if (sdata &&
1017             rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf)
1018                 rx_chains_dynamic = rx_chains_static = local->rx_chains;
1019
1020         if (rx_chains_static == chanctx->conf.rx_chains_static &&
1021             rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
1022                 return;
1023
1024         chanctx->conf.rx_chains_static = rx_chains_static;
1025         chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
1026         drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
1027 }
1028
1029 static void
1030 __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
1031                                        bool clear)
1032 {
1033         struct ieee80211_sub_if_data *sdata = link->sdata;
1034         unsigned int link_id = link->link_id;
1035         struct ieee80211_bss_conf *link_conf = link->conf;
1036         struct ieee80211_local *local __maybe_unused = sdata->local;
1037         struct ieee80211_sub_if_data *vlan;
1038         struct ieee80211_chanctx_conf *conf;
1039
1040         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
1041                 return;
1042
1043         lockdep_assert_wiphy(local->hw.wiphy);
1044
1045         /* Check that conf exists, even when clearing this function
1046          * must be called with the AP's channel context still there
1047          * as it would otherwise cause VLANs to have an invalid
1048          * channel context pointer for a while, possibly pointing
1049          * to a channel context that has already been freed.
1050          */
1051         conf = rcu_dereference_protected(link_conf->chanctx_conf,
1052                                          lockdep_is_held(&local->hw.wiphy->mtx));
1053         WARN_ON(!conf);
1054
1055         if (clear)
1056                 conf = NULL;
1057
1058         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
1059                 struct ieee80211_bss_conf *vlan_conf;
1060
1061                 vlan_conf = wiphy_dereference(local->hw.wiphy,
1062                                               vlan->vif.link_conf[link_id]);
1063                 if (WARN_ON(!vlan_conf))
1064                         continue;
1065
1066                 rcu_assign_pointer(vlan_conf->chanctx_conf, conf);
1067         }
1068 }
1069
1070 void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
1071                                           bool clear)
1072 {
1073         struct ieee80211_local *local = link->sdata->local;
1074
1075         lockdep_assert_wiphy(local->hw.wiphy);
1076
1077         __ieee80211_link_copy_chanctx_to_vlans(link, clear);
1078 }
1079
1080 int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)
1081 {
1082         struct ieee80211_sub_if_data *sdata = link->sdata;
1083         struct ieee80211_chanctx *ctx = link->reserved_chanctx;
1084
1085         lockdep_assert_wiphy(sdata->local->hw.wiphy);
1086
1087         if (WARN_ON(!ctx))
1088                 return -EINVAL;
1089
1090         list_del(&link->reserved_chanctx_list);
1091         link->reserved_chanctx = NULL;
1092
1093         if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
1094                 if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
1095                         if (WARN_ON(!ctx->replace_ctx))
1096                                 return -EINVAL;
1097
1098                         WARN_ON(ctx->replace_ctx->replace_state !=
1099                                 IEEE80211_CHANCTX_WILL_BE_REPLACED);
1100                         WARN_ON(ctx->replace_ctx->replace_ctx != ctx);
1101
1102                         ctx->replace_ctx->replace_ctx = NULL;
1103                         ctx->replace_ctx->replace_state =
1104                                         IEEE80211_CHANCTX_REPLACE_NONE;
1105
1106                         list_del_rcu(&ctx->list);
1107                         kfree_rcu(ctx, rcu_head);
1108                 } else {
1109                         ieee80211_free_chanctx(sdata->local, ctx, false);
1110                 }
1111         }
1112
1113         return 0;
1114 }
1115
1116 static struct ieee80211_chanctx *
1117 ieee80211_replace_chanctx(struct ieee80211_local *local,
1118                           const struct ieee80211_chan_req *chanreq,
1119                           enum ieee80211_chanctx_mode mode,
1120                           struct ieee80211_chanctx *curr_ctx)
1121 {
1122         struct ieee80211_chanctx *new_ctx, *ctx;
1123         struct wiphy *wiphy = local->hw.wiphy;
1124         const struct wiphy_radio *radio;
1125
1126         if (!curr_ctx || (curr_ctx->replace_state ==
1127                           IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1128             !list_empty(&curr_ctx->reserved_links)) {
1129                 /*
1130                  * Another link already requested this context for a
1131                  * reservation. Find another one hoping all links assigned
1132                  * to it will also switch soon enough.
1133                  *
1134                  * TODO: This needs a little more work as some cases
1135                  * (more than 2 chanctx capable devices) may fail which could
1136                  * otherwise succeed provided some channel context juggling was
1137                  * performed.
1138                  *
1139                  * Consider ctx1..3, link1..6, each ctx has 2 links. link1 and
1140                  * link2 from ctx1 request new different chandefs starting 2
1141                  * in-place reservations with ctx4 and ctx5 replacing ctx1 and
1142                  * ctx2 respectively. Next link5 and link6 from ctx3 reserve
1143                  * ctx4. If link3 and link4 remain on ctx2 as they are then this
1144                  * fails unless `replace_ctx` from ctx5 is replaced with ctx3.
1145                  */
1146                 list_for_each_entry(ctx, &local->chanctx_list, list) {
1147                         if (ctx->replace_state !=
1148                             IEEE80211_CHANCTX_REPLACE_NONE)
1149                                 continue;
1150
1151                         if (!list_empty(&ctx->reserved_links))
1152                                 continue;
1153
1154                         if (ctx->conf.radio_idx >= 0) {
1155                                 radio = &wiphy->radio[ctx->conf.radio_idx];
1156                                 if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
1157                                         continue;
1158                         }
1159
1160                         curr_ctx = ctx;
1161                         break;
1162                 }
1163         }
1164
1165         /*
1166          * If that's true then all available contexts already have reservations
1167          * and cannot be used.
1168          */
1169         if (!curr_ctx || (curr_ctx->replace_state ==
1170                           IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1171             !list_empty(&curr_ctx->reserved_links))
1172                 return ERR_PTR(-EBUSY);
1173
1174         new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
1175         if (!new_ctx)
1176                 return ERR_PTR(-ENOMEM);
1177
1178         new_ctx->replace_ctx = curr_ctx;
1179         new_ctx->replace_state = IEEE80211_CHANCTX_REPLACES_OTHER;
1180
1181         curr_ctx->replace_ctx = new_ctx;
1182         curr_ctx->replace_state = IEEE80211_CHANCTX_WILL_BE_REPLACED;
1183
1184         list_add_rcu(&new_ctx->list, &local->chanctx_list);
1185
1186         return new_ctx;
1187 }
1188
1189 static bool
1190 ieee80211_find_available_radio(struct ieee80211_local *local,
1191                                const struct ieee80211_chan_req *chanreq,
1192                                u32 radio_mask, int *radio_idx)
1193 {
1194         struct wiphy *wiphy = local->hw.wiphy;
1195         const struct wiphy_radio *radio;
1196         int i;
1197
1198         *radio_idx = -1;
1199         if (!wiphy->n_radio)
1200                 return true;
1201
1202         for (i = 0; i < wiphy->n_radio; i++) {
1203                 if (!(radio_mask & BIT(i)))
1204                         continue;
1205
1206                 radio = &wiphy->radio[i];
1207                 if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
1208                         continue;
1209
1210                 if (!ieee80211_can_create_new_chanctx(local, i))
1211                         continue;
1212
1213                 *radio_idx = i;
1214                 return true;
1215         }
1216
1217         return false;
1218 }
1219
1220 int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
1221                                    const struct ieee80211_chan_req *chanreq,
1222                                    enum ieee80211_chanctx_mode mode,
1223                                    bool radar_required)
1224 {
1225         struct ieee80211_sub_if_data *sdata = link->sdata;
1226         struct ieee80211_local *local = sdata->local;
1227         struct ieee80211_chanctx *new_ctx, *curr_ctx;
1228         int radio_idx;
1229
1230         lockdep_assert_wiphy(local->hw.wiphy);
1231
1232         curr_ctx = ieee80211_link_get_chanctx(link);
1233         if (curr_ctx && !local->ops->switch_vif_chanctx)
1234                 return -EOPNOTSUPP;
1235
1236         new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode);
1237         if (!new_ctx) {
1238                 if (ieee80211_can_create_new_chanctx(local, -1) &&
1239                     ieee80211_find_available_radio(local, chanreq,
1240                                                    sdata->wdev.radio_mask,
1241                                                    &radio_idx))
1242                         new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
1243                                                         false, radio_idx);
1244                 else
1245                         new_ctx = ieee80211_replace_chanctx(local, chanreq,
1246                                                             mode, curr_ctx);
1247                 if (IS_ERR(new_ctx))
1248                         return PTR_ERR(new_ctx);
1249         }
1250
1251         list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links);
1252         link->reserved_chanctx = new_ctx;
1253         link->reserved = *chanreq;
1254         link->reserved_radar_required = radar_required;
1255         link->reserved_ready = false;
1256
1257         return 0;
1258 }
1259
1260 static void
1261 ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
1262 {
1263         struct ieee80211_sub_if_data *sdata = link->sdata;
1264
1265         switch (sdata->vif.type) {
1266         case NL80211_IFTYPE_ADHOC:
1267         case NL80211_IFTYPE_AP:
1268         case NL80211_IFTYPE_MESH_POINT:
1269         case NL80211_IFTYPE_OCB:
1270                 wiphy_work_queue(sdata->local->hw.wiphy,
1271                                  &link->csa.finalize_work);
1272                 break;
1273         case NL80211_IFTYPE_STATION:
1274                 wiphy_delayed_work_queue(sdata->local->hw.wiphy,
1275                                          &link->u.mgd.csa.switch_work, 0);
1276                 break;
1277         case NL80211_IFTYPE_UNSPECIFIED:
1278         case NL80211_IFTYPE_AP_VLAN:
1279         case NL80211_IFTYPE_WDS:
1280         case NL80211_IFTYPE_MONITOR:
1281         case NL80211_IFTYPE_P2P_CLIENT:
1282         case NL80211_IFTYPE_P2P_GO:
1283         case NL80211_IFTYPE_P2P_DEVICE:
1284         case NL80211_IFTYPE_NAN:
1285         case NUM_NL80211_IFTYPES:
1286                 WARN_ON(1);
1287                 break;
1288         }
1289 }
1290
1291 static void
1292 ieee80211_link_update_chanreq(struct ieee80211_link_data *link,
1293                               const struct ieee80211_chan_req *chanreq)
1294 {
1295         struct ieee80211_sub_if_data *sdata = link->sdata;
1296         unsigned int link_id = link->link_id;
1297         struct ieee80211_sub_if_data *vlan;
1298
1299         link->conf->chanreq = *chanreq;
1300
1301         if (sdata->vif.type != NL80211_IFTYPE_AP)
1302                 return;
1303
1304         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
1305                 struct ieee80211_bss_conf *vlan_conf;
1306
1307                 vlan_conf = wiphy_dereference(sdata->local->hw.wiphy,
1308                                               vlan->vif.link_conf[link_id]);
1309                 if (WARN_ON(!vlan_conf))
1310                         continue;
1311
1312                 vlan_conf->chanreq = *chanreq;
1313         }
1314 }
1315
1316 static int
1317 ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
1318 {
1319         struct ieee80211_sub_if_data *sdata = link->sdata;
1320         struct ieee80211_bss_conf *link_conf = link->conf;
1321         struct ieee80211_local *local = sdata->local;
1322         struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
1323         struct ieee80211_chanctx *old_ctx, *new_ctx;
1324         const struct ieee80211_chan_req *chanreq;
1325         struct ieee80211_chan_req tmp;
1326         u64 changed = 0;
1327         int err;
1328
1329         lockdep_assert_wiphy(local->hw.wiphy);
1330
1331         new_ctx = link->reserved_chanctx;
1332         old_ctx = ieee80211_link_get_chanctx(link);
1333
1334         if (WARN_ON(!link->reserved_ready))
1335                 return -EBUSY;
1336
1337         if (WARN_ON(!new_ctx))
1338                 return -EINVAL;
1339
1340         if (WARN_ON(!old_ctx))
1341                 return -EINVAL;
1342
1343         if (WARN_ON(new_ctx->replace_state ==
1344                     IEEE80211_CHANCTX_REPLACES_OTHER))
1345                 return -EINVAL;
1346
1347         chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1348                                                          &link->reserved,
1349                                                          &tmp);
1350         if (WARN_ON(!chanreq))
1351                 return -EINVAL;
1352
1353         if (link_conf->chanreq.oper.width != link->reserved.oper.width)
1354                 changed = BSS_CHANGED_BANDWIDTH;
1355
1356         ieee80211_link_update_chanreq(link, &link->reserved);
1357
1358         _ieee80211_change_chanctx(local, new_ctx, old_ctx, chanreq, link);
1359
1360         vif_chsw[0].vif = &sdata->vif;
1361         vif_chsw[0].old_ctx = &old_ctx->conf;
1362         vif_chsw[0].new_ctx = &new_ctx->conf;
1363         vif_chsw[0].link_conf = link->conf;
1364
1365         list_del(&link->reserved_chanctx_list);
1366         link->reserved_chanctx = NULL;
1367
1368         err = drv_switch_vif_chanctx(local, vif_chsw, 1,
1369                                      CHANCTX_SWMODE_REASSIGN_VIF);
1370         if (err) {
1371                 if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1372                         ieee80211_free_chanctx(local, new_ctx, false);
1373
1374                 goto out;
1375         }
1376
1377         list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
1378         rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf);
1379
1380         if (sdata->vif.type == NL80211_IFTYPE_AP)
1381                 __ieee80211_link_copy_chanctx_to_vlans(link, false);
1382
1383         ieee80211_check_fast_xmit_iface(sdata);
1384
1385         if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
1386                 ieee80211_free_chanctx(local, old_ctx, false);
1387
1388         ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
1389         ieee80211_recalc_smps_chanctx(local, new_ctx);
1390         ieee80211_recalc_radar_chanctx(local, new_ctx);
1391
1392         if (changed)
1393                 ieee80211_link_info_change_notify(sdata, link, changed);
1394
1395 out:
1396         ieee80211_link_chanctx_reservation_complete(link);
1397         return err;
1398 }
1399
1400 static int
1401 ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
1402 {
1403         struct ieee80211_sub_if_data *sdata = link->sdata;
1404         struct ieee80211_local *local = sdata->local;
1405         struct ieee80211_chanctx *old_ctx, *new_ctx;
1406         const struct ieee80211_chan_req *chanreq;
1407         struct ieee80211_chan_req tmp;
1408         int err;
1409
1410         old_ctx = ieee80211_link_get_chanctx(link);
1411         new_ctx = link->reserved_chanctx;
1412
1413         if (WARN_ON(!link->reserved_ready))
1414                 return -EINVAL;
1415
1416         if (WARN_ON(old_ctx))
1417                 return -EINVAL;
1418
1419         if (WARN_ON(!new_ctx))
1420                 return -EINVAL;
1421
1422         if (WARN_ON(new_ctx->replace_state ==
1423                     IEEE80211_CHANCTX_REPLACES_OTHER))
1424                 return -EINVAL;
1425
1426         chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1427                                                          &link->reserved,
1428                                                          &tmp);
1429         if (WARN_ON(!chanreq))
1430                 return -EINVAL;
1431
1432         ieee80211_change_chanctx(local, new_ctx, new_ctx, chanreq);
1433
1434         list_del(&link->reserved_chanctx_list);
1435         link->reserved_chanctx = NULL;
1436
1437         err = ieee80211_assign_link_chanctx(link, new_ctx, false);
1438         if (err) {
1439                 if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1440                         ieee80211_free_chanctx(local, new_ctx, false);
1441
1442                 goto out;
1443         }
1444
1445 out:
1446         ieee80211_link_chanctx_reservation_complete(link);
1447         return err;
1448 }
1449
1450 static bool
1451 ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link)
1452 {
1453         struct ieee80211_sub_if_data *sdata = link->sdata;
1454         struct ieee80211_chanctx *old_ctx, *new_ctx;
1455
1456         lockdep_assert_wiphy(sdata->local->hw.wiphy);
1457
1458         new_ctx = link->reserved_chanctx;
1459         old_ctx = ieee80211_link_get_chanctx(link);
1460
1461         if (!old_ctx)
1462                 return false;
1463
1464         if (WARN_ON(!new_ctx))
1465                 return false;
1466
1467         if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1468                 return false;
1469
1470         if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1471                 return false;
1472
1473         return true;
1474 }
1475
1476 static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
1477                                       int n_vifs)
1478 {
1479         struct ieee80211_vif_chanctx_switch *vif_chsw;
1480         struct ieee80211_link_data *link;
1481         struct ieee80211_chanctx *ctx, *old_ctx;
1482         int i, err;
1483
1484         lockdep_assert_wiphy(local->hw.wiphy);
1485
1486         vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL);
1487         if (!vif_chsw)
1488                 return -ENOMEM;
1489
1490         i = 0;
1491         list_for_each_entry(ctx, &local->chanctx_list, list) {
1492                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1493                         continue;
1494
1495                 if (WARN_ON(!ctx->replace_ctx)) {
1496                         err = -EINVAL;
1497                         goto out;
1498                 }
1499
1500                 list_for_each_entry(link, &ctx->reserved_links,
1501                                     reserved_chanctx_list) {
1502                         if (!ieee80211_link_has_in_place_reservation(link))
1503                                 continue;
1504
1505                         old_ctx = ieee80211_link_get_chanctx(link);
1506                         vif_chsw[i].vif = &link->sdata->vif;
1507                         vif_chsw[i].old_ctx = &old_ctx->conf;
1508                         vif_chsw[i].new_ctx = &ctx->conf;
1509                         vif_chsw[i].link_conf = link->conf;
1510
1511                         i++;
1512                 }
1513         }
1514
1515         err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
1516                                      CHANCTX_SWMODE_SWAP_CONTEXTS);
1517
1518 out:
1519         kfree(vif_chsw);
1520         return err;
1521 }
1522
1523 static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
1524 {
1525         struct ieee80211_chanctx *ctx;
1526         int err;
1527
1528         lockdep_assert_wiphy(local->hw.wiphy);
1529
1530         list_for_each_entry(ctx, &local->chanctx_list, list) {
1531                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1532                         continue;
1533
1534                 if (!list_empty(&ctx->replace_ctx->assigned_links))
1535                         continue;
1536
1537                 ieee80211_del_chanctx(local, ctx->replace_ctx, false);
1538                 err = ieee80211_add_chanctx(local, ctx);
1539                 if (err)
1540                         goto err;
1541         }
1542
1543         return 0;
1544
1545 err:
1546         WARN_ON(ieee80211_add_chanctx(local, ctx));
1547         list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
1548                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1549                         continue;
1550
1551                 if (!list_empty(&ctx->replace_ctx->assigned_links))
1552                         continue;
1553
1554                 ieee80211_del_chanctx(local, ctx, false);
1555                 WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
1556         }
1557
1558         return err;
1559 }
1560
1561 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
1562 {
1563         struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
1564         int err, n_assigned, n_reserved, n_ready;
1565         int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
1566
1567         lockdep_assert_wiphy(local->hw.wiphy);
1568
1569         /*
1570          * If there are 2 independent pairs of channel contexts performing
1571          * cross-switch of their vifs this code will still wait until both are
1572          * ready even though it could be possible to switch one before the
1573          * other is ready.
1574          *
1575          * For practical reasons and code simplicity just do a single huge
1576          * switch.
1577          */
1578
1579         /*
1580          * Verify if the reservation is still feasible.
1581          *  - if it's not then disconnect
1582          *  - if it is but not all vifs necessary are ready then defer
1583          */
1584
1585         list_for_each_entry(ctx, &local->chanctx_list, list) {
1586                 struct ieee80211_link_data *link;
1587
1588                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1589                         continue;
1590
1591                 if (WARN_ON(!ctx->replace_ctx)) {
1592                         err = -EINVAL;
1593                         goto err;
1594                 }
1595
1596                 n_ctx++;
1597
1598                 n_assigned = 0;
1599                 n_reserved = 0;
1600                 n_ready = 0;
1601
1602                 list_for_each_entry(link, &ctx->replace_ctx->assigned_links,
1603                                     assigned_chanctx_list) {
1604                         n_assigned++;
1605                         if (link->reserved_chanctx) {
1606                                 n_reserved++;
1607                                 if (link->reserved_ready)
1608                                         n_ready++;
1609                         }
1610                 }
1611
1612                 if (n_assigned != n_reserved) {
1613                         if (n_ready == n_reserved) {
1614                                 wiphy_info(local->hw.wiphy,
1615                                            "channel context reservation cannot be finalized because some interfaces aren't switching\n");
1616                                 err = -EBUSY;
1617                                 goto err;
1618                         }
1619
1620                         return -EAGAIN;
1621                 }
1622
1623                 ctx->conf.radar_enabled = false;
1624                 list_for_each_entry(link, &ctx->reserved_links,
1625                                     reserved_chanctx_list) {
1626                         if (ieee80211_link_has_in_place_reservation(link) &&
1627                             !link->reserved_ready)
1628                                 return -EAGAIN;
1629
1630                         old_ctx = ieee80211_link_get_chanctx(link);
1631                         if (old_ctx) {
1632                                 if (old_ctx->replace_state ==
1633                                     IEEE80211_CHANCTX_WILL_BE_REPLACED)
1634                                         n_vifs_switch++;
1635                                 else
1636                                         n_vifs_assign++;
1637                         } else {
1638                                 n_vifs_ctxless++;
1639                         }
1640
1641                         if (link->reserved_radar_required)
1642                                 ctx->conf.radar_enabled = true;
1643                 }
1644         }
1645
1646         if (WARN_ON(n_ctx == 0) ||
1647             WARN_ON(n_vifs_switch == 0 &&
1648                     n_vifs_assign == 0 &&
1649                     n_vifs_ctxless == 0)) {
1650                 err = -EINVAL;
1651                 goto err;
1652         }
1653
1654         /* update station rate control and min width before switch */
1655         list_for_each_entry(ctx, &local->chanctx_list, list) {
1656                 struct ieee80211_link_data *link;
1657
1658                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1659                         continue;
1660
1661                 if (WARN_ON(!ctx->replace_ctx)) {
1662                         err = -EINVAL;
1663                         goto err;
1664                 }
1665
1666                 list_for_each_entry(link, &ctx->reserved_links,
1667                                     reserved_chanctx_list) {
1668                         if (!ieee80211_link_has_in_place_reservation(link))
1669                                 continue;
1670
1671                         ieee80211_chan_bw_change(local,
1672                                                  ieee80211_link_get_chanctx(link),
1673                                                  true, true);
1674                 }
1675
1676                 ieee80211_recalc_chanctx_min_def(local, ctx, NULL, true);
1677         }
1678
1679         /*
1680          * All necessary vifs are ready. Perform the switch now depending on
1681          * reservations and driver capabilities.
1682          */
1683
1684         if (n_vifs_switch > 0) {
1685                 err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
1686                 if (err)
1687                         goto err;
1688         }
1689
1690         if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
1691                 err = ieee80211_chsw_switch_ctxs(local);
1692                 if (err)
1693                         goto err;
1694         }
1695
1696         /*
1697          * Update all structures, values and pointers to point to new channel
1698          * context(s).
1699          */
1700         list_for_each_entry(ctx, &local->chanctx_list, list) {
1701                 struct ieee80211_link_data *link, *link_tmp;
1702
1703                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1704                         continue;
1705
1706                 if (WARN_ON(!ctx->replace_ctx)) {
1707                         err = -EINVAL;
1708                         goto err;
1709                 }
1710
1711                 list_for_each_entry(link, &ctx->reserved_links,
1712                                     reserved_chanctx_list) {
1713                         struct ieee80211_sub_if_data *sdata = link->sdata;
1714                         struct ieee80211_bss_conf *link_conf = link->conf;
1715                         u64 changed = 0;
1716
1717                         if (!ieee80211_link_has_in_place_reservation(link))
1718                                 continue;
1719
1720                         rcu_assign_pointer(link_conf->chanctx_conf,
1721                                            &ctx->conf);
1722
1723                         if (sdata->vif.type == NL80211_IFTYPE_AP)
1724                                 __ieee80211_link_copy_chanctx_to_vlans(link,
1725                                                                        false);
1726
1727                         ieee80211_check_fast_xmit_iface(sdata);
1728
1729                         link->radar_required = link->reserved_radar_required;
1730
1731                         if (link_conf->chanreq.oper.width != link->reserved.oper.width)
1732                                 changed = BSS_CHANGED_BANDWIDTH;
1733
1734                         ieee80211_link_update_chanreq(link, &link->reserved);
1735                         if (changed)
1736                                 ieee80211_link_info_change_notify(sdata,
1737                                                                   link,
1738                                                                   changed);
1739
1740                         ieee80211_recalc_txpower(link, false);
1741                 }
1742
1743                 ieee80211_recalc_chanctx_chantype(local, ctx);
1744                 ieee80211_recalc_smps_chanctx(local, ctx);
1745                 ieee80211_recalc_radar_chanctx(local, ctx);
1746                 ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
1747
1748                 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1749                                          reserved_chanctx_list) {
1750                         if (ieee80211_link_get_chanctx(link) != ctx)
1751                                 continue;
1752
1753                         list_del(&link->reserved_chanctx_list);
1754                         list_move(&link->assigned_chanctx_list,
1755                                   &ctx->assigned_links);
1756                         link->reserved_chanctx = NULL;
1757
1758                         ieee80211_link_chanctx_reservation_complete(link);
1759                         ieee80211_chan_bw_change(local, ctx, false, false);
1760                 }
1761
1762                 /*
1763                  * This context might have been a dependency for an already
1764                  * ready re-assign reservation interface that was deferred. Do
1765                  * not propagate error to the caller though. The in-place
1766                  * reservation for originally requested interface has already
1767                  * succeeded at this point.
1768                  */
1769                 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1770                                          reserved_chanctx_list) {
1771                         if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
1772                                 continue;
1773
1774                         if (WARN_ON(link->reserved_chanctx != ctx))
1775                                 continue;
1776
1777                         if (!link->reserved_ready)
1778                                 continue;
1779
1780                         if (ieee80211_link_get_chanctx(link))
1781                                 err = ieee80211_link_use_reserved_reassign(link);
1782                         else
1783                                 err = ieee80211_link_use_reserved_assign(link);
1784
1785                         if (err) {
1786                                 link_info(link,
1787                                           "failed to finalize (re-)assign reservation (err=%d)\n",
1788                                           err);
1789                                 ieee80211_link_unreserve_chanctx(link);
1790                                 cfg80211_stop_iface(local->hw.wiphy,
1791                                                     &link->sdata->wdev,
1792                                                     GFP_KERNEL);
1793                         }
1794                 }
1795         }
1796
1797         /*
1798          * Finally free old contexts
1799          */
1800
1801         list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
1802                 if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1803                         continue;
1804
1805                 ctx->replace_ctx->replace_ctx = NULL;
1806                 ctx->replace_ctx->replace_state =
1807                                 IEEE80211_CHANCTX_REPLACE_NONE;
1808
1809                 list_del_rcu(&ctx->list);
1810                 kfree_rcu(ctx, rcu_head);
1811         }
1812
1813         return 0;
1814
1815 err:
1816         list_for_each_entry(ctx, &local->chanctx_list, list) {
1817                 struct ieee80211_link_data *link, *link_tmp;
1818
1819                 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1820                         continue;
1821
1822                 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
1823                                          reserved_chanctx_list) {
1824                         ieee80211_link_unreserve_chanctx(link);
1825                         ieee80211_link_chanctx_reservation_complete(link);
1826                 }
1827         }
1828
1829         return err;
1830 }
1831
1832 void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
1833                                       bool skip_idle_recalc)
1834 {
1835         struct ieee80211_sub_if_data *sdata = link->sdata;
1836         struct ieee80211_bss_conf *link_conf = link->conf;
1837         struct ieee80211_local *local = sdata->local;
1838         struct ieee80211_chanctx_conf *conf;
1839         struct ieee80211_chanctx *ctx;
1840         bool use_reserved_switch = false;
1841
1842         lockdep_assert_wiphy(local->hw.wiphy);
1843
1844         conf = rcu_dereference_protected(link_conf->chanctx_conf,
1845                                          lockdep_is_held(&local->hw.wiphy->mtx));
1846         if (!conf)
1847                 return;
1848
1849         ctx = container_of(conf, struct ieee80211_chanctx, conf);
1850
1851         if (link->reserved_chanctx) {
1852                 if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
1853                     ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1)
1854                         use_reserved_switch = true;
1855
1856                 ieee80211_link_unreserve_chanctx(link);
1857         }
1858
1859         ieee80211_assign_link_chanctx(link, NULL, false);
1860         if (ieee80211_chanctx_refcount(local, ctx) == 0)
1861                 ieee80211_free_chanctx(local, ctx, skip_idle_recalc);
1862
1863         link->radar_required = false;
1864
1865         /* Unreserving may ready an in-place reservation. */
1866         if (use_reserved_switch)
1867                 ieee80211_vif_use_reserved_switch(local);
1868 }
1869
1870 int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
1871                                 const struct ieee80211_chan_req *chanreq,
1872                                 enum ieee80211_chanctx_mode mode,
1873                                 bool assign_on_failure)
1874 {
1875         struct ieee80211_sub_if_data *sdata = link->sdata;
1876         struct ieee80211_local *local = sdata->local;
1877         struct ieee80211_chanctx *ctx;
1878         u8 radar_detect_width = 0;
1879         bool reserved = false;
1880         int radio_idx;
1881         int ret;
1882
1883         lockdep_assert_wiphy(local->hw.wiphy);
1884
1885         if (!ieee80211_vif_link_active(&sdata->vif, link->link_id)) {
1886                 ieee80211_link_update_chanreq(link, chanreq);
1887                 return 0;
1888         }
1889
1890         ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
1891                                             &chanreq->oper,
1892                                             sdata->wdev.iftype);
1893         if (ret < 0)
1894                 goto out;
1895         if (ret > 0)
1896                 radar_detect_width = BIT(chanreq->oper.width);
1897
1898         link->radar_required = ret;
1899
1900         ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode,
1901                                            radar_detect_width, -1);
1902         if (ret < 0)
1903                 goto out;
1904
1905         __ieee80211_link_release_channel(link, false);
1906
1907         ctx = ieee80211_find_chanctx(local, link, chanreq, mode);
1908         /* Note: context is now reserved */
1909         if (ctx)
1910                 reserved = true;
1911         else if (!ieee80211_find_available_radio(local, chanreq,
1912                                                  sdata->wdev.radio_mask,
1913                                                  &radio_idx))
1914                 ctx = ERR_PTR(-EBUSY);
1915         else
1916                 ctx = ieee80211_new_chanctx(local, chanreq, mode,
1917                                             assign_on_failure, radio_idx);
1918         if (IS_ERR(ctx)) {
1919                 ret = PTR_ERR(ctx);
1920                 goto out;
1921         }
1922
1923         ieee80211_link_update_chanreq(link, chanreq);
1924
1925         ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
1926
1927         if (reserved) {
1928                 /* remove reservation */
1929                 WARN_ON(link->reserved_chanctx != ctx);
1930                 link->reserved_chanctx = NULL;
1931                 list_del(&link->reserved_chanctx_list);
1932         }
1933
1934         if (ret) {
1935                 /* if assign fails refcount stays the same */
1936                 if (ieee80211_chanctx_refcount(local, ctx) == 0)
1937                         ieee80211_free_chanctx(local, ctx, false);
1938                 goto out;
1939         }
1940
1941         ieee80211_recalc_smps_chanctx(local, ctx);
1942         ieee80211_recalc_radar_chanctx(local, ctx);
1943  out:
1944         if (ret)
1945                 link->radar_required = false;
1946
1947         return ret;
1948 }
1949
1950 int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
1951 {
1952         struct ieee80211_sub_if_data *sdata = link->sdata;
1953         struct ieee80211_local *local = sdata->local;
1954         struct ieee80211_chanctx *new_ctx;
1955         struct ieee80211_chanctx *old_ctx;
1956         int err;
1957
1958         lockdep_assert_wiphy(local->hw.wiphy);
1959
1960         new_ctx = link->reserved_chanctx;
1961         old_ctx = ieee80211_link_get_chanctx(link);
1962
1963         if (WARN_ON(!new_ctx))
1964                 return -EINVAL;
1965
1966         if (WARN_ON(new_ctx->replace_state ==
1967                     IEEE80211_CHANCTX_WILL_BE_REPLACED))
1968                 return -EINVAL;
1969
1970         if (WARN_ON(link->reserved_ready))
1971                 return -EINVAL;
1972
1973         link->reserved_ready = true;
1974
1975         if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
1976                 if (old_ctx)
1977                         return ieee80211_link_use_reserved_reassign(link);
1978
1979                 return ieee80211_link_use_reserved_assign(link);
1980         }
1981
1982         /*
1983          * In-place reservation may need to be finalized now either if:
1984          *  a) sdata is taking part in the swapping itself and is the last one
1985          *  b) sdata has switched with a re-assign reservation to an existing
1986          *     context readying in-place switching of old_ctx
1987          *
1988          * In case of (b) do not propagate the error up because the requested
1989          * sdata already switched successfully. Just spill an extra warning.
1990          * The ieee80211_vif_use_reserved_switch() already stops all necessary
1991          * interfaces upon failure.
1992          */
1993         if ((old_ctx &&
1994              old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1995             new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
1996                 err = ieee80211_vif_use_reserved_switch(local);
1997                 if (err && err != -EAGAIN) {
1998                         if (new_ctx->replace_state ==
1999                             IEEE80211_CHANCTX_REPLACES_OTHER)
2000                                 return err;
2001
2002                         wiphy_info(local->hw.wiphy,
2003                                    "depending in-place reservation failed (err=%d)\n",
2004                                    err);
2005                 }
2006         }
2007
2008         return 0;
2009 }
2010
2011 /*
2012  * This is similar to ieee80211_chanctx_compatible(), but rechecks
2013  * against all the links actually using it (except the one that's
2014  * passed, since that one is changing).
2015  * This is done in order to allow changes to the AP's bandwidth for
2016  * wider bandwidth OFDMA purposes, which wouldn't be treated as
2017  * compatible by ieee80211_chanctx_recheck() but is OK if the link
2018  * requesting the update is the only one using it.
2019  */
2020 static const struct ieee80211_chan_req *
2021 ieee80211_chanctx_recheck(struct ieee80211_local *local,
2022                           struct ieee80211_link_data *skip_link,
2023                           struct ieee80211_chanctx *ctx,
2024                           const struct ieee80211_chan_req *req,
2025                           struct ieee80211_chan_req *tmp)
2026 {
2027         const struct ieee80211_chan_req *ret = req;
2028         struct ieee80211_link_data *link;
2029
2030         lockdep_assert_wiphy(local->hw.wiphy);
2031
2032         for_each_sdata_link(local, link) {
2033                 if (link == skip_link)
2034                         continue;
2035
2036                 if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
2037                         ret = ieee80211_chanreq_compatible(ret,
2038                                                            &link->conf->chanreq,
2039                                                            tmp);
2040                         if (!ret)
2041                                 return NULL;
2042                 }
2043
2044                 if (link->reserved_chanctx == ctx) {
2045                         ret = ieee80211_chanreq_compatible(ret,
2046                                                            &link->reserved,
2047                                                            tmp);
2048                         if (!ret)
2049                                 return NULL;
2050                 }
2051         }
2052
2053         *tmp = *ret;
2054         return tmp;
2055 }
2056
2057 int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
2058                                   const struct ieee80211_chan_req *chanreq,
2059                                   u64 *changed)
2060 {
2061         struct ieee80211_sub_if_data *sdata = link->sdata;
2062         struct ieee80211_bss_conf *link_conf = link->conf;
2063         struct ieee80211_local *local = sdata->local;
2064         struct ieee80211_chanctx_conf *conf;
2065         struct ieee80211_chanctx *ctx;
2066         const struct ieee80211_chan_req *compat;
2067         struct ieee80211_chan_req tmp;
2068
2069         lockdep_assert_wiphy(local->hw.wiphy);
2070
2071         if (!cfg80211_chandef_usable(sdata->local->hw.wiphy,
2072                                      &chanreq->oper,
2073                                      IEEE80211_CHAN_DISABLED))
2074                 return -EINVAL;
2075
2076         /* for non-HT 20 MHz the rest doesn't matter */
2077         if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT &&
2078             cfg80211_chandef_identical(&chanreq->oper, &link_conf->chanreq.oper))
2079                 return 0;
2080
2081         /* but you cannot switch to/from it */
2082         if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT ||
2083             link_conf->chanreq.oper.width == NL80211_CHAN_WIDTH_20_NOHT)
2084                 return -EINVAL;
2085
2086         conf = rcu_dereference_protected(link_conf->chanctx_conf,
2087                                          lockdep_is_held(&local->hw.wiphy->mtx));
2088         if (!conf)
2089                 return -EINVAL;
2090
2091         ctx = container_of(conf, struct ieee80211_chanctx, conf);
2092
2093         compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp);
2094         if (!compat)
2095                 return -EINVAL;
2096
2097         switch (ctx->replace_state) {
2098         case IEEE80211_CHANCTX_REPLACE_NONE:
2099                 if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat,
2100                                                         &tmp))
2101                         return -EBUSY;
2102                 break;
2103         case IEEE80211_CHANCTX_WILL_BE_REPLACED:
2104                 /* TODO: Perhaps the bandwidth change could be treated as a
2105                  * reservation itself? */
2106                 return -EBUSY;
2107         case IEEE80211_CHANCTX_REPLACES_OTHER:
2108                 /* channel context that is going to replace another channel
2109                  * context doesn't really exist and shouldn't be assigned
2110                  * anywhere yet */
2111                 WARN_ON(1);
2112                 break;
2113         }
2114
2115         ieee80211_link_update_chanreq(link, chanreq);
2116
2117         ieee80211_recalc_chanctx_chantype(local, ctx);
2118
2119         *changed |= BSS_CHANGED_BANDWIDTH;
2120         return 0;
2121 }
2122
2123 void ieee80211_link_release_channel(struct ieee80211_link_data *link)
2124 {
2125         struct ieee80211_sub_if_data *sdata = link->sdata;
2126
2127         lockdep_assert_wiphy(sdata->local->hw.wiphy);
2128
2129         if (rcu_access_pointer(link->conf->chanctx_conf))
2130                 __ieee80211_link_release_channel(link, false);
2131 }
2132
2133 void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
2134 {
2135         struct ieee80211_sub_if_data *sdata = link->sdata;
2136         unsigned int link_id = link->link_id;
2137         struct ieee80211_bss_conf *link_conf = link->conf;
2138         struct ieee80211_bss_conf *ap_conf;
2139         struct ieee80211_local *local = sdata->local;
2140         struct ieee80211_sub_if_data *ap;
2141         struct ieee80211_chanctx_conf *conf;
2142
2143         lockdep_assert_wiphy(local->hw.wiphy);
2144
2145         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
2146                 return;
2147
2148         ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
2149
2150         ap_conf = wiphy_dereference(local->hw.wiphy,
2151                                     ap->vif.link_conf[link_id]);
2152         conf = wiphy_dereference(local->hw.wiphy,
2153                                  ap_conf->chanctx_conf);
2154         rcu_assign_pointer(link_conf->chanctx_conf, conf);
2155 }
2156
2157 void ieee80211_iter_chan_contexts_atomic(
2158         struct ieee80211_hw *hw,
2159         void (*iter)(struct ieee80211_hw *hw,
2160                      struct ieee80211_chanctx_conf *chanctx_conf,
2161                      void *data),
2162         void *iter_data)
2163 {
2164         struct ieee80211_local *local = hw_to_local(hw);
2165         struct ieee80211_chanctx *ctx;
2166
2167         rcu_read_lock();
2168         list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
2169                 if (ctx->driver_present)
2170                         iter(hw, &ctx->conf, iter_data);
2171         rcu_read_unlock();
2172 }
2173 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
This page took 0.150645 seconds and 4 git commands to generate.