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