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