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