Linux Audio

Check our new training course

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