Linux Audio

Check our new training course

Yocto / OpenEmbedded training

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