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