Linux Audio

Check our new training course

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