]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/mac80211/chan.c
Merge remote-tracking branch 'net-next/master'
[karo-tx-linux.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 void ieee80211_change_chanctx(struct ieee80211_local *local,
13                                      struct ieee80211_chanctx *ctx,
14                                      const struct cfg80211_chan_def *chandef)
15 {
16         if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
17                 return;
18
19         WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
20
21         ctx->conf.def = *chandef;
22         drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
23
24         if (!local->use_chanctx) {
25                 local->_oper_chandef = *chandef;
26                 ieee80211_hw_config(local, 0);
27         }
28 }
29
30 static struct ieee80211_chanctx *
31 ieee80211_find_chanctx(struct ieee80211_local *local,
32                        const struct cfg80211_chan_def *chandef,
33                        enum ieee80211_chanctx_mode mode)
34 {
35         struct ieee80211_chanctx *ctx;
36
37         lockdep_assert_held(&local->chanctx_mtx);
38
39         if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
40                 return NULL;
41
42         list_for_each_entry(ctx, &local->chanctx_list, list) {
43                 const struct cfg80211_chan_def *compat;
44
45                 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
46                         continue;
47
48                 compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
49                 if (!compat)
50                         continue;
51
52                 ieee80211_change_chanctx(local, ctx, compat);
53
54                 return ctx;
55         }
56
57         return NULL;
58 }
59
60 static bool ieee80211_is_radar_required(struct ieee80211_local *local)
61 {
62         struct ieee80211_sub_if_data *sdata;
63
64         rcu_read_lock();
65         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
66                 if (sdata->radar_required) {
67                         rcu_read_unlock();
68                         return true;
69                 }
70         }
71         rcu_read_unlock();
72
73         return false;
74 }
75
76 static struct ieee80211_chanctx *
77 ieee80211_new_chanctx(struct ieee80211_local *local,
78                       const struct cfg80211_chan_def *chandef,
79                       enum ieee80211_chanctx_mode mode)
80 {
81         struct ieee80211_chanctx *ctx;
82         u32 changed;
83         int err;
84
85         lockdep_assert_held(&local->chanctx_mtx);
86
87         ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
88         if (!ctx)
89                 return ERR_PTR(-ENOMEM);
90
91         ctx->conf.def = *chandef;
92         ctx->conf.rx_chains_static = 1;
93         ctx->conf.rx_chains_dynamic = 1;
94         ctx->mode = mode;
95         ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
96         if (!local->use_chanctx)
97                 local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
98
99         /* acquire mutex to prevent idle from changing */
100         mutex_lock(&local->mtx);
101         /* turn idle off *before* setting channel -- some drivers need that */
102         changed = ieee80211_idle_off(local);
103         if (changed)
104                 ieee80211_hw_config(local, changed);
105
106         if (!local->use_chanctx) {
107                 local->_oper_chandef = *chandef;
108                 ieee80211_hw_config(local, 0);
109         } else {
110                 err = drv_add_chanctx(local, ctx);
111                 if (err) {
112                         kfree(ctx);
113                         ctx = ERR_PTR(err);
114
115                         ieee80211_recalc_idle(local);
116                         goto out;
117                 }
118         }
119
120         /* and keep the mutex held until the new chanctx is on the list */
121         list_add_rcu(&ctx->list, &local->chanctx_list);
122
123  out:
124         mutex_unlock(&local->mtx);
125
126         return ctx;
127 }
128
129 static void ieee80211_free_chanctx(struct ieee80211_local *local,
130                                    struct ieee80211_chanctx *ctx)
131 {
132         bool check_single_channel = false;
133         lockdep_assert_held(&local->chanctx_mtx);
134
135         WARN_ON_ONCE(ctx->refcount != 0);
136
137         if (!local->use_chanctx) {
138                 struct cfg80211_chan_def *chandef = &local->_oper_chandef;
139                 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
140                 chandef->center_freq1 = chandef->chan->center_freq;
141                 chandef->center_freq2 = 0;
142
143                 /* NOTE: Disabling radar is only valid here for
144                  * single channel context. To be sure, check it ...
145                  */
146                 if (local->hw.conf.radar_enabled)
147                         check_single_channel = true;
148                 local->hw.conf.radar_enabled = false;
149
150                 ieee80211_hw_config(local, 0);
151         } else {
152                 drv_remove_chanctx(local, ctx);
153         }
154
155         list_del_rcu(&ctx->list);
156         kfree_rcu(ctx, rcu_head);
157
158         /* throw a warning if this wasn't the only channel context. */
159         WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
160
161         mutex_lock(&local->mtx);
162         ieee80211_recalc_idle(local);
163         mutex_unlock(&local->mtx);
164 }
165
166 static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
167                                         struct ieee80211_chanctx *ctx)
168 {
169         struct ieee80211_local *local = sdata->local;
170         int ret;
171
172         lockdep_assert_held(&local->chanctx_mtx);
173
174         ret = drv_assign_vif_chanctx(local, sdata, ctx);
175         if (ret)
176                 return ret;
177
178         rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
179         ctx->refcount++;
180
181         ieee80211_recalc_txpower(sdata);
182         sdata->vif.bss_conf.idle = false;
183
184         if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
185             sdata->vif.type != NL80211_IFTYPE_MONITOR)
186                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
187
188         return 0;
189 }
190
191 static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
192                                               struct ieee80211_chanctx *ctx)
193 {
194         struct ieee80211_chanctx_conf *conf = &ctx->conf;
195         struct ieee80211_sub_if_data *sdata;
196         const struct cfg80211_chan_def *compat = NULL;
197
198         lockdep_assert_held(&local->chanctx_mtx);
199
200         rcu_read_lock();
201         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
202
203                 if (!ieee80211_sdata_running(sdata))
204                         continue;
205                 if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
206                         continue;
207
208                 if (!compat)
209                         compat = &sdata->vif.bss_conf.chandef;
210
211                 compat = cfg80211_chandef_compatible(
212                                 &sdata->vif.bss_conf.chandef, compat);
213                 if (!compat)
214                         break;
215         }
216         rcu_read_unlock();
217
218         if (WARN_ON_ONCE(!compat))
219                 return;
220
221         ieee80211_change_chanctx(local, ctx, compat);
222 }
223
224 static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
225                                            struct ieee80211_chanctx *ctx)
226 {
227         struct ieee80211_local *local = sdata->local;
228
229         lockdep_assert_held(&local->chanctx_mtx);
230
231         ctx->refcount--;
232         rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
233
234         sdata->vif.bss_conf.idle = true;
235
236         if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
237             sdata->vif.type != NL80211_IFTYPE_MONITOR)
238                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
239
240         drv_unassign_vif_chanctx(local, sdata, ctx);
241
242         if (ctx->refcount > 0) {
243                 ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
244                 ieee80211_recalc_smps_chanctx(local, ctx);
245                 ieee80211_recalc_radar_chanctx(local, ctx);
246         }
247 }
248
249 static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
250 {
251         struct ieee80211_local *local = sdata->local;
252         struct ieee80211_chanctx_conf *conf;
253         struct ieee80211_chanctx *ctx;
254
255         lockdep_assert_held(&local->chanctx_mtx);
256
257         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
258                                          lockdep_is_held(&local->chanctx_mtx));
259         if (!conf)
260                 return;
261
262         ctx = container_of(conf, struct ieee80211_chanctx, conf);
263
264         ieee80211_unassign_vif_chanctx(sdata, ctx);
265         if (ctx->refcount == 0)
266                 ieee80211_free_chanctx(local, ctx);
267 }
268
269 void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
270                                     struct ieee80211_chanctx *chanctx)
271 {
272         bool radar_enabled;
273
274         lockdep_assert_held(&local->chanctx_mtx);
275
276         radar_enabled = ieee80211_is_radar_required(local);
277
278         if (radar_enabled == chanctx->conf.radar_enabled)
279                 return;
280
281         chanctx->conf.radar_enabled = radar_enabled;
282         local->radar_detect_enabled = chanctx->conf.radar_enabled;
283
284         if (!local->use_chanctx) {
285                 local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
286                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
287         }
288
289         drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
290 }
291
292 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
293                                    struct ieee80211_chanctx *chanctx)
294 {
295         struct ieee80211_sub_if_data *sdata;
296         u8 rx_chains_static, rx_chains_dynamic;
297
298         lockdep_assert_held(&local->chanctx_mtx);
299
300         rx_chains_static = 1;
301         rx_chains_dynamic = 1;
302
303         rcu_read_lock();
304         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
305                 u8 needed_static, needed_dynamic;
306
307                 if (!ieee80211_sdata_running(sdata))
308                         continue;
309
310                 if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
311                                                 &chanctx->conf)
312                         continue;
313
314                 switch (sdata->vif.type) {
315                 case NL80211_IFTYPE_P2P_DEVICE:
316                         continue;
317                 case NL80211_IFTYPE_STATION:
318                         if (!sdata->u.mgd.associated)
319                                 continue;
320                         break;
321                 case NL80211_IFTYPE_AP_VLAN:
322                         continue;
323                 case NL80211_IFTYPE_AP:
324                 case NL80211_IFTYPE_ADHOC:
325                 case NL80211_IFTYPE_WDS:
326                 case NL80211_IFTYPE_MESH_POINT:
327                         break;
328                 default:
329                         WARN_ON_ONCE(1);
330                 }
331
332                 switch (sdata->smps_mode) {
333                 default:
334                         WARN_ONCE(1, "Invalid SMPS mode %d\n",
335                                   sdata->smps_mode);
336                         /* fall through */
337                 case IEEE80211_SMPS_OFF:
338                         needed_static = sdata->needed_rx_chains;
339                         needed_dynamic = sdata->needed_rx_chains;
340                         break;
341                 case IEEE80211_SMPS_DYNAMIC:
342                         needed_static = 1;
343                         needed_dynamic = sdata->needed_rx_chains;
344                         break;
345                 case IEEE80211_SMPS_STATIC:
346                         needed_static = 1;
347                         needed_dynamic = 1;
348                         break;
349                 }
350
351                 rx_chains_static = max(rx_chains_static, needed_static);
352                 rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
353         }
354         rcu_read_unlock();
355
356         if (!local->use_chanctx) {
357                 if (rx_chains_static > 1)
358                         local->smps_mode = IEEE80211_SMPS_OFF;
359                 else if (rx_chains_dynamic > 1)
360                         local->smps_mode = IEEE80211_SMPS_DYNAMIC;
361                 else
362                         local->smps_mode = IEEE80211_SMPS_STATIC;
363                 ieee80211_hw_config(local, 0);
364         }
365
366         if (rx_chains_static == chanctx->conf.rx_chains_static &&
367             rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
368                 return;
369
370         chanctx->conf.rx_chains_static = rx_chains_static;
371         chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
372         drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
373 }
374
375 int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
376                               const struct cfg80211_chan_def *chandef,
377                               enum ieee80211_chanctx_mode mode)
378 {
379         struct ieee80211_local *local = sdata->local;
380         struct ieee80211_chanctx *ctx;
381         int ret;
382
383         WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
384
385         mutex_lock(&local->chanctx_mtx);
386         __ieee80211_vif_release_channel(sdata);
387
388         ctx = ieee80211_find_chanctx(local, chandef, mode);
389         if (!ctx)
390                 ctx = ieee80211_new_chanctx(local, chandef, mode);
391         if (IS_ERR(ctx)) {
392                 ret = PTR_ERR(ctx);
393                 goto out;
394         }
395
396         sdata->vif.bss_conf.chandef = *chandef;
397
398         ret = ieee80211_assign_vif_chanctx(sdata, ctx);
399         if (ret) {
400                 /* if assign fails refcount stays the same */
401                 if (ctx->refcount == 0)
402                         ieee80211_free_chanctx(local, ctx);
403                 goto out;
404         }
405
406         ieee80211_recalc_smps_chanctx(local, ctx);
407         ieee80211_recalc_radar_chanctx(local, ctx);
408  out:
409         mutex_unlock(&local->chanctx_mtx);
410         return ret;
411 }
412
413 int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
414                                  const struct cfg80211_chan_def *chandef,
415                                  u32 *changed)
416 {
417         struct ieee80211_local *local = sdata->local;
418         struct ieee80211_chanctx_conf *conf;
419         struct ieee80211_chanctx *ctx;
420         int ret;
421         u32 chanctx_changed = 0;
422
423         /* should never be called if not performing a channel switch. */
424         if (WARN_ON(!sdata->vif.csa_active))
425                 return -EINVAL;
426
427         if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
428                                      IEEE80211_CHAN_DISABLED))
429                 return -EINVAL;
430
431         mutex_lock(&local->chanctx_mtx);
432         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
433                                          lockdep_is_held(&local->chanctx_mtx));
434         if (!conf) {
435                 ret = -EINVAL;
436                 goto out;
437         }
438
439         ctx = container_of(conf, struct ieee80211_chanctx, conf);
440         if (ctx->refcount != 1) {
441                 ret = -EINVAL;
442                 goto out;
443         }
444
445         if (sdata->vif.bss_conf.chandef.width != chandef->width) {
446                 chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH;
447                 *changed |= BSS_CHANGED_BANDWIDTH;
448         }
449
450         sdata->vif.bss_conf.chandef = *chandef;
451         ctx->conf.def = *chandef;
452
453         chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL;
454         drv_change_chanctx(local, ctx, chanctx_changed);
455
456         ieee80211_recalc_chanctx_chantype(local, ctx);
457         ieee80211_recalc_smps_chanctx(local, ctx);
458         ieee80211_recalc_radar_chanctx(local, ctx);
459
460         ret = 0;
461  out:
462         mutex_unlock(&local->chanctx_mtx);
463         return ret;
464 }
465
466 int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
467                                    const struct cfg80211_chan_def *chandef,
468                                    u32 *changed)
469 {
470         struct ieee80211_local *local = sdata->local;
471         struct ieee80211_chanctx_conf *conf;
472         struct ieee80211_chanctx *ctx;
473         int ret;
474
475         if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
476                                      IEEE80211_CHAN_DISABLED))
477                 return -EINVAL;
478
479         mutex_lock(&local->chanctx_mtx);
480         if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
481                 ret = 0;
482                 goto out;
483         }
484
485         if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
486             sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
487                 ret = -EINVAL;
488                 goto out;
489         }
490
491         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
492                                          lockdep_is_held(&local->chanctx_mtx));
493         if (!conf) {
494                 ret = -EINVAL;
495                 goto out;
496         }
497
498         ctx = container_of(conf, struct ieee80211_chanctx, conf);
499         if (!cfg80211_chandef_compatible(&conf->def, chandef)) {
500                 ret = -EINVAL;
501                 goto out;
502         }
503
504         sdata->vif.bss_conf.chandef = *chandef;
505
506         ieee80211_recalc_chanctx_chantype(local, ctx);
507
508         *changed |= BSS_CHANGED_BANDWIDTH;
509         ret = 0;
510  out:
511         mutex_unlock(&local->chanctx_mtx);
512         return ret;
513 }
514
515 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
516 {
517         WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
518
519         mutex_lock(&sdata->local->chanctx_mtx);
520         __ieee80211_vif_release_channel(sdata);
521         mutex_unlock(&sdata->local->chanctx_mtx);
522 }
523
524 void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
525 {
526         struct ieee80211_local *local = sdata->local;
527         struct ieee80211_sub_if_data *ap;
528         struct ieee80211_chanctx_conf *conf;
529
530         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
531                 return;
532
533         ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
534
535         mutex_lock(&local->chanctx_mtx);
536
537         conf = rcu_dereference_protected(ap->vif.chanctx_conf,
538                                          lockdep_is_held(&local->chanctx_mtx));
539         rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
540         mutex_unlock(&local->chanctx_mtx);
541 }
542
543 void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
544                                          bool clear)
545 {
546         struct ieee80211_local *local = sdata->local;
547         struct ieee80211_sub_if_data *vlan;
548         struct ieee80211_chanctx_conf *conf;
549
550         ASSERT_RTNL();
551
552         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
553                 return;
554
555         mutex_lock(&local->chanctx_mtx);
556
557         /*
558          * Check that conf exists, even when clearing this function
559          * must be called with the AP's channel context still there
560          * as it would otherwise cause VLANs to have an invalid
561          * channel context pointer for a while, possibly pointing
562          * to a channel context that has already been freed.
563          */
564         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
565                                 lockdep_is_held(&local->chanctx_mtx));
566         WARN_ON(!conf);
567
568         if (clear)
569                 conf = NULL;
570
571         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
572                 rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
573
574         mutex_unlock(&local->chanctx_mtx);
575 }
576
577 void ieee80211_iter_chan_contexts_atomic(
578         struct ieee80211_hw *hw,
579         void (*iter)(struct ieee80211_hw *hw,
580                      struct ieee80211_chanctx_conf *chanctx_conf,
581                      void *data),
582         void *iter_data)
583 {
584         struct ieee80211_local *local = hw_to_local(hw);
585         struct ieee80211_chanctx *ctx;
586
587         rcu_read_lock();
588         list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
589                 if (ctx->driver_present)
590                         iter(hw, &ctx->conf, iter_data);
591         rcu_read_unlock();
592 }
593 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);