OSDN Git Service

mac80211: track assigned vifs in chanctx
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / net / mac80211 / chan.c
1 /*
2  * mac80211 - channel management
3  */
4
5 #include <linux/nl80211.h>
6 #include <linux/export.h>
7 #include <linux/rtnetlink.h>
8 #include <net/cfg80211.h>
9 #include "ieee80211_i.h"
10 #include "driver-ops.h"
11
12 static int ieee80211_num_chanctx(struct ieee80211_local *local)
13 {
14         struct ieee80211_chanctx *ctx;
15         int num = 0;
16
17         lockdep_assert_held(&local->chanctx_mtx);
18
19         list_for_each_entry(ctx, &local->chanctx_list, list)
20                 num++;
21
22         return num;
23 }
24
25 static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
26 {
27         lockdep_assert_held(&local->chanctx_mtx);
28         return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local);
29 }
30
31 static enum nl80211_chan_width ieee80211_get_sta_bw(struct ieee80211_sta *sta)
32 {
33         switch (sta->bandwidth) {
34         case IEEE80211_STA_RX_BW_20:
35                 if (sta->ht_cap.ht_supported)
36                         return NL80211_CHAN_WIDTH_20;
37                 else
38                         return NL80211_CHAN_WIDTH_20_NOHT;
39         case IEEE80211_STA_RX_BW_40:
40                 return NL80211_CHAN_WIDTH_40;
41         case IEEE80211_STA_RX_BW_80:
42                 return NL80211_CHAN_WIDTH_80;
43         case IEEE80211_STA_RX_BW_160:
44                 /*
45                  * This applied for both 160 and 80+80. since we use
46                  * the returned value to consider degradation of
47                  * ctx->conf.min_def, we have to make sure to take
48                  * the bigger one (NL80211_CHAN_WIDTH_160).
49                  * Otherwise we might try degrading even when not
50                  * needed, as the max required sta_bw returned (80+80)
51                  * might be smaller than the configured bw (160).
52                  */
53                 return NL80211_CHAN_WIDTH_160;
54         default:
55                 WARN_ON(1);
56                 return NL80211_CHAN_WIDTH_20;
57         }
58 }
59
60 static enum nl80211_chan_width
61 ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
62 {
63         enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
64         struct sta_info *sta;
65
66         rcu_read_lock();
67         list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
68                 if (sdata != sta->sdata &&
69                     !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
70                         continue;
71
72                 if (!sta->uploaded)
73                         continue;
74
75                 max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
76         }
77         rcu_read_unlock();
78
79         return max_bw;
80 }
81
82 static enum nl80211_chan_width
83 ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
84                                       struct ieee80211_chanctx_conf *conf)
85 {
86         struct ieee80211_sub_if_data *sdata;
87         enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
88
89         rcu_read_lock();
90         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
91                 struct ieee80211_vif *vif = &sdata->vif;
92                 enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
93
94                 if (!ieee80211_sdata_running(sdata))
95                         continue;
96
97                 if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
98                         continue;
99
100                 switch (vif->type) {
101                 case NL80211_IFTYPE_AP:
102                 case NL80211_IFTYPE_AP_VLAN:
103                         width = ieee80211_get_max_required_bw(sdata);
104                         break;
105                 case NL80211_IFTYPE_P2P_DEVICE:
106                         continue;
107                 case NL80211_IFTYPE_STATION:
108                 case NL80211_IFTYPE_ADHOC:
109                 case NL80211_IFTYPE_WDS:
110                 case NL80211_IFTYPE_MESH_POINT:
111                         width = vif->bss_conf.chandef.width;
112                         break;
113                 case NL80211_IFTYPE_UNSPECIFIED:
114                 case NUM_NL80211_IFTYPES:
115                 case NL80211_IFTYPE_MONITOR:
116                 case NL80211_IFTYPE_P2P_CLIENT:
117                 case NL80211_IFTYPE_P2P_GO:
118                         WARN_ON_ONCE(1);
119                 }
120                 max_bw = max(max_bw, width);
121         }
122
123         /* use the configured bandwidth in case of monitor interface */
124         sdata = rcu_dereference(local->monitor_sdata);
125         if (sdata && rcu_access_pointer(sdata->vif.chanctx_conf) == conf)
126                 max_bw = max(max_bw, conf->def.width);
127
128         rcu_read_unlock();
129
130         return max_bw;
131 }
132
133 /*
134  * recalc the min required chan width of the channel context, which is
135  * the max of min required widths of all the interfaces bound to this
136  * channel context.
137  */
138 void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
139                                       struct ieee80211_chanctx *ctx)
140 {
141         enum nl80211_chan_width max_bw;
142         struct cfg80211_chan_def min_def;
143
144         lockdep_assert_held(&local->chanctx_mtx);
145
146         /* don't optimize 5MHz, 10MHz, and radar_enabled confs */
147         if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
148             ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
149             ctx->conf.radar_enabled) {
150                 ctx->conf.min_def = ctx->conf.def;
151                 return;
152         }
153
154         max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf);
155
156         /* downgrade chandef up to max_bw */
157         min_def = ctx->conf.def;
158         while (min_def.width > max_bw)
159                 ieee80211_chandef_downgrade(&min_def);
160
161         if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
162                 return;
163
164         ctx->conf.min_def = min_def;
165         if (!ctx->driver_present)
166                 return;
167
168         drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH);
169 }
170
171 static void ieee80211_change_chanctx(struct ieee80211_local *local,
172                                      struct ieee80211_chanctx *ctx,
173                                      const struct cfg80211_chan_def *chandef)
174 {
175         if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
176                 return;
177
178         WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
179
180         ctx->conf.def = *chandef;
181         drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
182         ieee80211_recalc_chanctx_min_def(local, ctx);
183
184         if (!local->use_chanctx) {
185                 local->_oper_chandef = *chandef;
186                 ieee80211_hw_config(local, 0);
187         }
188 }
189
190 static bool ieee80211_chanctx_is_reserved(struct ieee80211_local *local,
191                                           struct ieee80211_chanctx *ctx)
192 {
193         struct ieee80211_sub_if_data *sdata;
194         bool ret = false;
195
196         lockdep_assert_held(&local->chanctx_mtx);
197         rcu_read_lock();
198         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
199                 if (!ieee80211_sdata_running(sdata))
200                         continue;
201                 if (sdata->reserved_chanctx == ctx) {
202                         ret = true;
203                         break;
204                 }
205         }
206
207         rcu_read_unlock();
208         return ret;
209 }
210
211 static struct ieee80211_chanctx *
212 ieee80211_find_chanctx(struct ieee80211_local *local,
213                        const struct cfg80211_chan_def *chandef,
214                        enum ieee80211_chanctx_mode mode)
215 {
216         struct ieee80211_chanctx *ctx;
217
218         lockdep_assert_held(&local->chanctx_mtx);
219
220         if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
221                 return NULL;
222
223         list_for_each_entry(ctx, &local->chanctx_list, list) {
224                 const struct cfg80211_chan_def *compat;
225
226                 /* We don't support chanctx reservation for multiple
227                  * vifs yet, so don't allow reserved chanctxs to be
228                  * reused.
229                  */
230                 if ((ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) ||
231                     ieee80211_chanctx_is_reserved(local, ctx))
232                         continue;
233
234                 compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
235                 if (!compat)
236                         continue;
237
238                 ieee80211_change_chanctx(local, ctx, compat);
239
240                 return ctx;
241         }
242
243         return NULL;
244 }
245
246 static bool ieee80211_is_radar_required(struct ieee80211_local *local)
247 {
248         struct ieee80211_sub_if_data *sdata;
249
250         lockdep_assert_held(&local->mtx);
251
252         rcu_read_lock();
253         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
254                 if (sdata->radar_required) {
255                         rcu_read_unlock();
256                         return true;
257                 }
258         }
259         rcu_read_unlock();
260
261         return false;
262 }
263
264 static struct ieee80211_chanctx *
265 ieee80211_new_chanctx(struct ieee80211_local *local,
266                       const struct cfg80211_chan_def *chandef,
267                       enum ieee80211_chanctx_mode mode)
268 {
269         struct ieee80211_chanctx *ctx;
270         u32 changed;
271         int err;
272
273         lockdep_assert_held(&local->chanctx_mtx);
274
275         ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
276         if (!ctx)
277                 return ERR_PTR(-ENOMEM);
278
279         INIT_LIST_HEAD(&ctx->assigned_vifs);
280         ctx->conf.def = *chandef;
281         ctx->conf.rx_chains_static = 1;
282         ctx->conf.rx_chains_dynamic = 1;
283         ctx->mode = mode;
284         ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
285         ieee80211_recalc_chanctx_min_def(local, ctx);
286         if (!local->use_chanctx)
287                 local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
288
289         /* we hold the mutex to prevent idle from changing */
290         lockdep_assert_held(&local->mtx);
291         /* turn idle off *before* setting channel -- some drivers need that */
292         changed = ieee80211_idle_off(local);
293         if (changed)
294                 ieee80211_hw_config(local, changed);
295
296         if (!local->use_chanctx) {
297                 local->_oper_chandef = *chandef;
298                 ieee80211_hw_config(local, 0);
299         } else {
300                 err = drv_add_chanctx(local, ctx);
301                 if (err) {
302                         kfree(ctx);
303                         ieee80211_recalc_idle(local);
304                         return ERR_PTR(err);
305                 }
306         }
307
308         /* and keep the mutex held until the new chanctx is on the list */
309         list_add_rcu(&ctx->list, &local->chanctx_list);
310
311         return ctx;
312 }
313
314 static void ieee80211_free_chanctx(struct ieee80211_local *local,
315                                    struct ieee80211_chanctx *ctx)
316 {
317         bool check_single_channel = false;
318         lockdep_assert_held(&local->chanctx_mtx);
319
320         WARN_ON_ONCE(ctx->refcount != 0);
321
322         if (!local->use_chanctx) {
323                 struct cfg80211_chan_def *chandef = &local->_oper_chandef;
324                 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
325                 chandef->center_freq1 = chandef->chan->center_freq;
326                 chandef->center_freq2 = 0;
327
328                 /* NOTE: Disabling radar is only valid here for
329                  * single channel context. To be sure, check it ...
330                  */
331                 if (local->hw.conf.radar_enabled)
332                         check_single_channel = true;
333                 local->hw.conf.radar_enabled = false;
334
335                 ieee80211_hw_config(local, 0);
336         } else {
337                 drv_remove_chanctx(local, ctx);
338         }
339
340         list_del_rcu(&ctx->list);
341         kfree_rcu(ctx, rcu_head);
342
343         /* throw a warning if this wasn't the only channel context. */
344         WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
345
346         ieee80211_recalc_idle(local);
347 }
348
349 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
350                                               struct ieee80211_chanctx *ctx)
351 {
352         struct ieee80211_chanctx_conf *conf = &ctx->conf;
353         struct ieee80211_sub_if_data *sdata;
354         const struct cfg80211_chan_def *compat = NULL;
355
356         lockdep_assert_held(&local->chanctx_mtx);
357
358         rcu_read_lock();
359         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
360
361                 if (!ieee80211_sdata_running(sdata))
362                         continue;
363                 if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
364                         continue;
365
366                 if (!compat)
367                         compat = &sdata->vif.bss_conf.chandef;
368
369                 compat = cfg80211_chandef_compatible(
370                                 &sdata->vif.bss_conf.chandef, compat);
371                 if (!compat)
372                         break;
373         }
374         rcu_read_unlock();
375
376         if (WARN_ON_ONCE(!compat))
377                 return;
378
379         ieee80211_change_chanctx(local, ctx, compat);
380 }
381
382 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
383                                            struct ieee80211_chanctx *chanctx)
384 {
385         bool radar_enabled;
386
387         lockdep_assert_held(&local->chanctx_mtx);
388         /* for setting local->radar_detect_enabled */
389         lockdep_assert_held(&local->mtx);
390
391         radar_enabled = ieee80211_is_radar_required(local);
392
393         if (radar_enabled == chanctx->conf.radar_enabled)
394                 return;
395
396         chanctx->conf.radar_enabled = radar_enabled;
397         local->radar_detect_enabled = chanctx->conf.radar_enabled;
398
399         if (!local->use_chanctx) {
400                 local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
401                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
402         }
403
404         drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
405 }
406
407 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
408                                         struct ieee80211_chanctx *new_ctx)
409 {
410         struct ieee80211_local *local = sdata->local;
411         struct ieee80211_chanctx_conf *conf;
412         struct ieee80211_chanctx *curr_ctx = NULL;
413         int ret = 0;
414
415         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
416                                          lockdep_is_held(&local->chanctx_mtx));
417
418         if (conf) {
419                 curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
420
421                 curr_ctx->refcount--;
422                 drv_unassign_vif_chanctx(local, sdata, curr_ctx);
423                 conf = NULL;
424                 list_del(&sdata->assigned_chanctx_list);
425         }
426
427         if (new_ctx) {
428                 ret = drv_assign_vif_chanctx(local, sdata, new_ctx);
429                 if (ret)
430                         goto out;
431
432                 new_ctx->refcount++;
433                 conf = &new_ctx->conf;
434                 list_add(&sdata->assigned_chanctx_list,
435                          &new_ctx->assigned_vifs);
436         }
437
438 out:
439         rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
440
441         sdata->vif.bss_conf.idle = !conf;
442
443         if (curr_ctx && curr_ctx->refcount > 0) {
444                 ieee80211_recalc_chanctx_chantype(local, curr_ctx);
445                 ieee80211_recalc_smps_chanctx(local, curr_ctx);
446                 ieee80211_recalc_radar_chanctx(local, curr_ctx);
447                 ieee80211_recalc_chanctx_min_def(local, curr_ctx);
448         }
449
450         if (new_ctx && new_ctx->refcount > 0) {
451                 ieee80211_recalc_txpower(sdata);
452                 ieee80211_recalc_chanctx_min_def(local, new_ctx);
453         }
454
455         if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
456             sdata->vif.type != NL80211_IFTYPE_MONITOR)
457                 ieee80211_bss_info_change_notify(sdata,
458                                                  BSS_CHANGED_IDLE);
459
460         return ret;
461 }
462
463 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
464 {
465         struct ieee80211_local *local = sdata->local;
466         struct ieee80211_chanctx_conf *conf;
467         struct ieee80211_chanctx *ctx;
468
469         lockdep_assert_held(&local->chanctx_mtx);
470
471         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
472                                          lockdep_is_held(&local->chanctx_mtx));
473         if (!conf)
474                 return;
475
476         ctx = container_of(conf, struct ieee80211_chanctx, conf);
477
478         if (sdata->reserved_chanctx)
479                 ieee80211_vif_unreserve_chanctx(sdata);
480
481         ieee80211_assign_vif_chanctx(sdata, NULL);
482         if (ctx->refcount == 0)
483                 ieee80211_free_chanctx(local, ctx);
484 }
485
486 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
487                                    struct ieee80211_chanctx *chanctx)
488 {
489         struct ieee80211_sub_if_data *sdata;
490         u8 rx_chains_static, rx_chains_dynamic;
491
492         lockdep_assert_held(&local->chanctx_mtx);
493
494         rx_chains_static = 1;
495         rx_chains_dynamic = 1;
496
497         rcu_read_lock();
498         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
499                 u8 needed_static, needed_dynamic;
500
501                 if (!ieee80211_sdata_running(sdata))
502                         continue;
503
504                 if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
505                                                 &chanctx->conf)
506                         continue;
507
508                 switch (sdata->vif.type) {
509                 case NL80211_IFTYPE_P2P_DEVICE:
510                         continue;
511                 case NL80211_IFTYPE_STATION:
512                         if (!sdata->u.mgd.associated)
513                                 continue;
514                         break;
515                 case NL80211_IFTYPE_AP_VLAN:
516                         continue;
517                 case NL80211_IFTYPE_AP:
518                 case NL80211_IFTYPE_ADHOC:
519                 case NL80211_IFTYPE_WDS:
520                 case NL80211_IFTYPE_MESH_POINT:
521                         break;
522                 default:
523                         WARN_ON_ONCE(1);
524                 }
525
526                 switch (sdata->smps_mode) {
527                 default:
528                         WARN_ONCE(1, "Invalid SMPS mode %d\n",
529                                   sdata->smps_mode);
530                         /* fall through */
531                 case IEEE80211_SMPS_OFF:
532                         needed_static = sdata->needed_rx_chains;
533                         needed_dynamic = sdata->needed_rx_chains;
534                         break;
535                 case IEEE80211_SMPS_DYNAMIC:
536                         needed_static = 1;
537                         needed_dynamic = sdata->needed_rx_chains;
538                         break;
539                 case IEEE80211_SMPS_STATIC:
540                         needed_static = 1;
541                         needed_dynamic = 1;
542                         break;
543                 }
544
545                 rx_chains_static = max(rx_chains_static, needed_static);
546                 rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
547         }
548         rcu_read_unlock();
549
550         if (!local->use_chanctx) {
551                 if (rx_chains_static > 1)
552                         local->smps_mode = IEEE80211_SMPS_OFF;
553                 else if (rx_chains_dynamic > 1)
554                         local->smps_mode = IEEE80211_SMPS_DYNAMIC;
555                 else
556                         local->smps_mode = IEEE80211_SMPS_STATIC;
557                 ieee80211_hw_config(local, 0);
558         }
559
560         if (rx_chains_static == chanctx->conf.rx_chains_static &&
561             rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
562                 return;
563
564         chanctx->conf.rx_chains_static = rx_chains_static;
565         chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
566         drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
567 }
568
569 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
570                               const struct cfg80211_chan_def *chandef,
571                               enum ieee80211_chanctx_mode mode)
572 {
573         struct ieee80211_local *local = sdata->local;
574         struct ieee80211_chanctx *ctx;
575         u8 radar_detect_width = 0;
576         int ret;
577
578         lockdep_assert_held(&local->mtx);
579
580         WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
581
582         mutex_lock(&local->chanctx_mtx);
583
584         ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
585                                             chandef,
586                                             sdata->wdev.iftype);
587         if (ret < 0)
588                 goto out;
589         if (ret > 0)
590                 radar_detect_width = BIT(chandef->width);
591
592         sdata->radar_required = ret;
593
594         ret = ieee80211_check_combinations(sdata, chandef, mode,
595                                            radar_detect_width);
596         if (ret < 0)
597                 goto out;
598
599         __ieee80211_vif_release_channel(sdata);
600
601         ctx = ieee80211_find_chanctx(local, chandef, mode);
602         if (!ctx)
603                 ctx = ieee80211_new_chanctx(local, chandef, mode);
604         if (IS_ERR(ctx)) {
605                 ret = PTR_ERR(ctx);
606                 goto out;
607         }
608
609         sdata->vif.bss_conf.chandef = *chandef;
610
611         ret = ieee80211_assign_vif_chanctx(sdata, ctx);
612         if (ret) {
613                 /* if assign fails refcount stays the same */
614                 if (ctx->refcount == 0)
615                         ieee80211_free_chanctx(local, ctx);
616                 goto out;
617         }
618
619         ieee80211_recalc_smps_chanctx(local, ctx);
620         ieee80211_recalc_radar_chanctx(local, ctx);
621  out:
622         mutex_unlock(&local->chanctx_mtx);
623         return ret;
624 }
625
626 static int __ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
627                                           struct ieee80211_chanctx *ctx,
628                                           u32 *changed)
629 {
630         struct ieee80211_local *local = sdata->local;
631         const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
632         u32 chanctx_changed = 0;
633
634         if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
635                                      IEEE80211_CHAN_DISABLED))
636                 return -EINVAL;
637
638         if (ctx->refcount != 1)
639                 return -EINVAL;
640
641         if (sdata->vif.bss_conf.chandef.width != chandef->width) {
642                 chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH;
643                 *changed |= BSS_CHANGED_BANDWIDTH;
644         }
645
646         sdata->vif.bss_conf.chandef = *chandef;
647         ctx->conf.def = *chandef;
648
649         chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL;
650         drv_change_chanctx(local, ctx, chanctx_changed);
651
652         ieee80211_recalc_chanctx_chantype(local, ctx);
653         ieee80211_recalc_smps_chanctx(local, ctx);
654         ieee80211_recalc_radar_chanctx(local, ctx);
655         ieee80211_recalc_chanctx_min_def(local, ctx);
656
657         return 0;
658 }
659
660 int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
661                                  u32 *changed)
662 {
663         struct ieee80211_local *local = sdata->local;
664         struct ieee80211_chanctx_conf *conf;
665         struct ieee80211_chanctx *ctx;
666         int ret;
667
668         lockdep_assert_held(&local->mtx);
669
670         /* should never be called if not performing a channel switch. */
671         if (WARN_ON(!sdata->vif.csa_active))
672                 return -EINVAL;
673
674         mutex_lock(&local->chanctx_mtx);
675         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
676                                          lockdep_is_held(&local->chanctx_mtx));
677         if (!conf) {
678                 ret = -EINVAL;
679                 goto out;
680         }
681
682         ctx = container_of(conf, struct ieee80211_chanctx, conf);
683
684         ret = __ieee80211_vif_change_channel(sdata, ctx, changed);
685  out:
686         mutex_unlock(&local->chanctx_mtx);
687         return ret;
688 }
689
690 static void
691 __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
692                                       bool clear)
693 {
694         struct ieee80211_local *local = sdata->local;
695         struct ieee80211_sub_if_data *vlan;
696         struct ieee80211_chanctx_conf *conf;
697
698         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
699                 return;
700
701         lockdep_assert_held(&local->mtx);
702
703         /* Check that conf exists, even when clearing this function
704          * must be called with the AP's channel context still there
705          * as it would otherwise cause VLANs to have an invalid
706          * channel context pointer for a while, possibly pointing
707          * to a channel context that has already been freed.
708          */
709         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
710                                 lockdep_is_held(&local->chanctx_mtx));
711         WARN_ON(!conf);
712
713         if (clear)
714                 conf = NULL;
715
716         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
717                 rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
718 }
719
720 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
721                                          bool clear)
722 {
723         struct ieee80211_local *local = sdata->local;
724
725         mutex_lock(&local->chanctx_mtx);
726
727         __ieee80211_vif_copy_chanctx_to_vlans(sdata, clear);
728
729         mutex_unlock(&local->chanctx_mtx);
730 }
731
732 int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata)
733 {
734         lockdep_assert_held(&sdata->local->chanctx_mtx);
735
736         if (WARN_ON(!sdata->reserved_chanctx))
737                 return -EINVAL;
738
739         if (--sdata->reserved_chanctx->refcount == 0)
740                 ieee80211_free_chanctx(sdata->local, sdata->reserved_chanctx);
741
742         sdata->reserved_chanctx = NULL;
743
744         return 0;
745 }
746
747 int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
748                                   const struct cfg80211_chan_def *chandef,
749                                   enum ieee80211_chanctx_mode mode,
750                                   bool radar_required)
751 {
752         struct ieee80211_local *local = sdata->local;
753         struct ieee80211_chanctx_conf *conf;
754         struct ieee80211_chanctx *new_ctx, *curr_ctx;
755         int ret = 0;
756
757         mutex_lock(&local->chanctx_mtx);
758
759         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
760                                          lockdep_is_held(&local->chanctx_mtx));
761         if (!conf) {
762                 ret = -EINVAL;
763                 goto out;
764         }
765
766         curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
767
768         /* try to find another context with the chandef we want */
769         new_ctx = ieee80211_find_chanctx(local, chandef, mode);
770         if (!new_ctx) {
771                 if (curr_ctx->refcount == 1 &&
772                     (local->hw.flags & IEEE80211_HW_CHANGE_RUNNING_CHANCTX)) {
773                         /* if we're the only users of the chanctx and
774                          * the driver supports changing a running
775                          * context, reserve our current context
776                          */
777                         new_ctx = curr_ctx;
778                 } else if (ieee80211_can_create_new_chanctx(local)) {
779                         /* create a new context and reserve it */
780                         new_ctx = ieee80211_new_chanctx(local, chandef, mode);
781                         if (IS_ERR(new_ctx)) {
782                                 ret = PTR_ERR(new_ctx);
783                                 goto out;
784                         }
785                 } else {
786                         ret = -EBUSY;
787                         goto out;
788                 }
789         }
790
791         new_ctx->refcount++;
792         sdata->reserved_chanctx = new_ctx;
793         sdata->reserved_chandef = *chandef;
794         sdata->reserved_radar_required = radar_required;
795 out:
796         mutex_unlock(&local->chanctx_mtx);
797         return ret;
798 }
799
800 int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata,
801                                        u32 *changed)
802 {
803         struct ieee80211_local *local = sdata->local;
804         struct ieee80211_chanctx *ctx;
805         struct ieee80211_chanctx *old_ctx;
806         struct ieee80211_chanctx_conf *conf;
807         int ret;
808         u32 tmp_changed = *changed;
809
810         /* TODO: need to recheck if the chandef is usable etc.? */
811
812         lockdep_assert_held(&local->mtx);
813
814         mutex_lock(&local->chanctx_mtx);
815
816         ctx = sdata->reserved_chanctx;
817         if (WARN_ON(!ctx)) {
818                 ret = -EINVAL;
819                 goto out;
820         }
821
822         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
823                                          lockdep_is_held(&local->chanctx_mtx));
824         if (!conf) {
825                 ret = -EINVAL;
826                 goto out;
827         }
828
829         old_ctx = container_of(conf, struct ieee80211_chanctx, conf);
830
831         if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width)
832                 tmp_changed |= BSS_CHANGED_BANDWIDTH;
833
834         sdata->vif.bss_conf.chandef = sdata->reserved_chandef;
835
836         /* unref our reservation */
837         ctx->refcount--;
838         sdata->reserved_chanctx = NULL;
839         sdata->radar_required = sdata->reserved_radar_required;
840
841         if (old_ctx == ctx) {
842                 /* This is our own context, just change it */
843                 ret = __ieee80211_vif_change_channel(sdata, old_ctx,
844                                                      &tmp_changed);
845                 if (ret)
846                         goto out;
847         } else {
848                 ret = ieee80211_assign_vif_chanctx(sdata, ctx);
849                 if (old_ctx->refcount == 0)
850                         ieee80211_free_chanctx(local, old_ctx);
851                 if (ret) {
852                         /* if assign fails refcount stays the same */
853                         if (ctx->refcount == 0)
854                                 ieee80211_free_chanctx(local, ctx);
855                         goto out;
856                 }
857
858                 if (sdata->vif.type == NL80211_IFTYPE_AP)
859                         __ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
860         }
861
862         *changed = tmp_changed;
863
864         ieee80211_recalc_chanctx_chantype(local, ctx);
865         ieee80211_recalc_smps_chanctx(local, ctx);
866         ieee80211_recalc_radar_chanctx(local, ctx);
867         ieee80211_recalc_chanctx_min_def(local, ctx);
868 out:
869         mutex_unlock(&local->chanctx_mtx);
870         return ret;
871 }
872
873 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
874                                    const struct cfg80211_chan_def *chandef,
875                                    u32 *changed)
876 {
877         struct ieee80211_local *local = sdata->local;
878         struct ieee80211_chanctx_conf *conf;
879         struct ieee80211_chanctx *ctx;
880         int ret;
881
882         if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
883                                      IEEE80211_CHAN_DISABLED))
884                 return -EINVAL;
885
886         mutex_lock(&local->chanctx_mtx);
887         if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
888                 ret = 0;
889                 goto out;
890         }
891
892         if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
893             sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
894                 ret = -EINVAL;
895                 goto out;
896         }
897
898         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
899                                          lockdep_is_held(&local->chanctx_mtx));
900         if (!conf) {
901                 ret = -EINVAL;
902                 goto out;
903         }
904
905         ctx = container_of(conf, struct ieee80211_chanctx, conf);
906         if (!cfg80211_chandef_compatible(&conf->def, chandef)) {
907                 ret = -EINVAL;
908                 goto out;
909         }
910
911         sdata->vif.bss_conf.chandef = *chandef;
912
913         ieee80211_recalc_chanctx_chantype(local, ctx);
914
915         *changed |= BSS_CHANGED_BANDWIDTH;
916         ret = 0;
917  out:
918         mutex_unlock(&local->chanctx_mtx);
919         return ret;
920 }
921
922 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
923 {
924         WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
925
926         lockdep_assert_held(&sdata->local->mtx);
927
928         mutex_lock(&sdata->local->chanctx_mtx);
929         __ieee80211_vif_release_channel(sdata);
930         mutex_unlock(&sdata->local->chanctx_mtx);
931 }
932
933 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
934 {
935         struct ieee80211_local *local = sdata->local;
936         struct ieee80211_sub_if_data *ap;
937         struct ieee80211_chanctx_conf *conf;
938
939         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
940                 return;
941
942         ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
943
944         mutex_lock(&local->chanctx_mtx);
945
946         conf = rcu_dereference_protected(ap->vif.chanctx_conf,
947                                          lockdep_is_held(&local->chanctx_mtx));
948         rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
949         mutex_unlock(&local->chanctx_mtx);
950 }
951
952 void ieee80211_iter_chan_contexts_atomic(
953         struct ieee80211_hw *hw,
954         void (*iter)(struct ieee80211_hw *hw,
955                      struct ieee80211_chanctx_conf *chanctx_conf,
956                      void *data),
957         void *iter_data)
958 {
959         struct ieee80211_local *local = hw_to_local(hw);
960         struct ieee80211_chanctx *ctx;
961
962         rcu_read_lock();
963         list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
964                 if (ctx->driver_present)
965                         iter(hw, &ctx->conf, iter_data);
966         rcu_read_unlock();
967 }
968 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);