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