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