diff options
Diffstat (limited to 'net/mac80211/chan.c')
-rw-r--r-- | net/mac80211/chan.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 03e8d2e3270e..3a4764b2869e 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -410,6 +410,64 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
410 | return ret; | 410 | return ret; |
411 | } | 411 | } |
412 | 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 | if (!local->use_chanctx) { | ||
457 | local->_oper_chandef = *chandef; | ||
458 | ieee80211_hw_config(local, 0); | ||
459 | } | ||
460 | |||
461 | ieee80211_recalc_chanctx_chantype(local, ctx); | ||
462 | ieee80211_recalc_smps_chanctx(local, ctx); | ||
463 | ieee80211_recalc_radar_chanctx(local, ctx); | ||
464 | |||
465 | ret = 0; | ||
466 | out: | ||
467 | mutex_unlock(&local->chanctx_mtx); | ||
468 | return ret; | ||
469 | } | ||
470 | |||
413 | int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | 471 | int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, |
414 | const struct cfg80211_chan_def *chandef, | 472 | const struct cfg80211_chan_def *chandef, |
415 | u32 *changed) | 473 | u32 *changed) |