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