cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

chan.c (49079B)


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