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 static struct ieee80211_chanctx * 551 ieee80211_find_chanctx(struct ieee80211_local *local, 552 const struct ieee80211_chan_req *chanreq, 553 enum ieee80211_chanctx_mode mode) 554 { 555 struct ieee80211_chan_req tmp; 556 struct ieee80211_chanctx *ctx; 557 558 lockdep_assert_wiphy(local->hw.wiphy); 559 560 if (mode == IEEE80211_CHANCTX_EXCLUSIVE) 561 return NULL; 562 563 list_for_each_entry(ctx, &local->chanctx_list, list) { 564 const struct ieee80211_chan_req *compat; 565 566 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE) 567 continue; 568 569 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) 570 continue; 571 572 compat = ieee80211_chanctx_compatible(ctx, chanreq, &tmp); 573 if (!compat) 574 continue; 575 576 compat = ieee80211_chanctx_reserved_chanreq(local, ctx, 577 compat, &tmp); 578 if (!compat) 579 continue; 580 581 ieee80211_change_chanctx(local, ctx, ctx, compat); 582 583 return ctx; 584 } 585 586 return NULL; 587 } 588 589 bool ieee80211_is_radar_required(struct ieee80211_local *local) 590 { 591 struct ieee80211_link_data *link; 592 593 lockdep_assert_wiphy(local->hw.wiphy); 594 595 for_each_sdata_link(local, link) { 596 if (link->radar_required) 597 return true; 598 } 599 600 return false; 601 } 602 603 static bool 604 ieee80211_chanctx_radar_required(struct ieee80211_local *local, 605 struct ieee80211_chanctx *ctx) 606 { 607 struct ieee80211_chanctx_conf *conf = &ctx->conf; 608 struct ieee80211_link_data *link; 609 610 lockdep_assert_wiphy(local->hw.wiphy); 611 612 for_each_sdata_link(local, link) { 613 if (rcu_access_pointer(link->conf->chanctx_conf) != conf) 614 continue; 615 if (!link->radar_required) 616 continue; 617 return true; 618 } 619 620 return false; 621 } 622 623 static struct ieee80211_chanctx * 624 ieee80211_alloc_chanctx(struct ieee80211_local *local, 625 const struct ieee80211_chan_req *chanreq, 626 enum ieee80211_chanctx_mode mode) 627 { 628 struct ieee80211_chanctx *ctx; 629 630 lockdep_assert_wiphy(local->hw.wiphy); 631 632 ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL); 633 if (!ctx) 634 return NULL; 635 636 INIT_LIST_HEAD(&ctx->assigned_links); 637 INIT_LIST_HEAD(&ctx->reserved_links); 638 ctx->conf.def = chanreq->oper; 639 ctx->conf.ap = chanreq->ap; 640 ctx->conf.rx_chains_static = 1; 641 ctx->conf.rx_chains_dynamic = 1; 642 ctx->mode = mode; 643 ctx->conf.radar_enabled = false; 644 _ieee80211_recalc_chanctx_min_def(local, ctx, NULL); 645 646 return ctx; 647 } 648 649 static int ieee80211_add_chanctx(struct ieee80211_local *local, 650 struct ieee80211_chanctx *ctx) 651 { 652 u32 changed; 653 int err; 654 655 lockdep_assert_wiphy(local->hw.wiphy); 656 657 ieee80211_add_wbrf(local, &ctx->conf.def); 658 659 /* turn idle off *before* setting channel -- some drivers need that */ 660 changed = ieee80211_idle_off(local); 661 if (changed) 662 ieee80211_hw_config(local, changed); 663 664 err = drv_add_chanctx(local, ctx); 665 if (err) { 666 ieee80211_recalc_idle(local); 667 return err; 668 } 669 670 return 0; 671 } 672 673 static struct ieee80211_chanctx * 674 ieee80211_new_chanctx(struct ieee80211_local *local, 675 const struct ieee80211_chan_req *chanreq, 676 enum ieee80211_chanctx_mode mode) 677 { 678 struct ieee80211_chanctx *ctx; 679 int err; 680 681 lockdep_assert_wiphy(local->hw.wiphy); 682 683 ctx = ieee80211_alloc_chanctx(local, chanreq, mode); 684 if (!ctx) 685 return ERR_PTR(-ENOMEM); 686 687 err = ieee80211_add_chanctx(local, ctx); 688 if (err) { 689 kfree(ctx); 690 return ERR_PTR(err); 691 } 692 693 list_add_rcu(&ctx->list, &local->chanctx_list); 694 return ctx; 695 } 696 697 static void ieee80211_del_chanctx(struct ieee80211_local *local, 698 struct ieee80211_chanctx *ctx) 699 { 700 lockdep_assert_wiphy(local->hw.wiphy); 701 702 drv_remove_chanctx(local, ctx); 703 704 ieee80211_recalc_idle(local); 705 706 ieee80211_remove_wbrf(local, &ctx->conf.def); 707 } 708 709 static void ieee80211_free_chanctx(struct ieee80211_local *local, 710 struct ieee80211_chanctx *ctx) 711 { 712 lockdep_assert_wiphy(local->hw.wiphy); 713 714 WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0); 715 716 list_del_rcu(&ctx->list); 717 ieee80211_del_chanctx(local, ctx); 718 kfree_rcu(ctx, rcu_head); 719 } 720 721 void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, 722 struct ieee80211_chanctx *ctx) 723 { 724 struct ieee80211_chanctx_conf *conf = &ctx->conf; 725 const struct ieee80211_chan_req *compat = NULL; 726 struct ieee80211_link_data *link; 727 struct ieee80211_chan_req tmp; 728 struct sta_info *sta; 729 730 lockdep_assert_wiphy(local->hw.wiphy); 731 732 for_each_sdata_link(local, link) { 733 struct ieee80211_bss_conf *link_conf; 734 735 if (link->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 736 continue; 737 738 link_conf = link->conf; 739 740 if (rcu_access_pointer(link_conf->chanctx_conf) != conf) 741 continue; 742 743 if (!compat) 744 compat = &link_conf->chanreq; 745 746 compat = ieee80211_chanreq_compatible(&link_conf->chanreq, 747 compat, &tmp); 748 if (WARN_ON_ONCE(!compat)) 749 return; 750 } 751 752 if (WARN_ON_ONCE(!compat)) 753 return; 754 755 /* TDLS peers can sometimes affect the chandef width */ 756 list_for_each_entry(sta, &local->sta_list, list) { 757 struct ieee80211_chan_req tdls_chanreq = {}; 758 if (!sta->uploaded || 759 !test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) || 760 !test_sta_flag(sta, WLAN_STA_AUTHORIZED) || 761 !sta->tdls_chandef.chan) 762 continue; 763 764 tdls_chanreq.oper = sta->tdls_chandef; 765 766 /* note this always fills and returns &tmp if compat */ 767 compat = ieee80211_chanreq_compatible(&tdls_chanreq, 768 compat, &tmp); 769 if (WARN_ON_ONCE(!compat)) 770 return; 771 } 772 773 ieee80211_change_chanctx(local, ctx, ctx, compat); 774 } 775 776 static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, 777 struct ieee80211_chanctx *chanctx) 778 { 779 bool radar_enabled; 780 781 lockdep_assert_wiphy(local->hw.wiphy); 782 783 radar_enabled = ieee80211_chanctx_radar_required(local, chanctx); 784 785 if (radar_enabled == chanctx->conf.radar_enabled) 786 return; 787 788 chanctx->conf.radar_enabled = radar_enabled; 789 790 drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR); 791 } 792 793 static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, 794 struct ieee80211_chanctx *new_ctx) 795 { 796 struct ieee80211_sub_if_data *sdata = link->sdata; 797 struct ieee80211_local *local = sdata->local; 798 struct ieee80211_chanctx_conf *conf; 799 struct ieee80211_chanctx *curr_ctx = NULL; 800 bool new_idle; 801 int ret = 0; 802 803 if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN)) 804 return -EOPNOTSUPP; 805 806 conf = rcu_dereference_protected(link->conf->chanctx_conf, 807 lockdep_is_held(&local->hw.wiphy->mtx)); 808 809 if (conf) { 810 curr_ctx = container_of(conf, struct ieee80211_chanctx, conf); 811 812 drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx); 813 conf = NULL; 814 list_del(&link->assigned_chanctx_list); 815 } 816 817 if (new_ctx) { 818 /* recalc considering the link we'll use it for now */ 819 ieee80211_recalc_chanctx_min_def(local, new_ctx, link); 820 821 ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx); 822 if (ret) 823 goto out; 824 825 conf = &new_ctx->conf; 826 list_add(&link->assigned_chanctx_list, 827 &new_ctx->assigned_links); 828 } 829 830 out: 831 rcu_assign_pointer(link->conf->chanctx_conf, conf); 832 833 if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) { 834 ieee80211_recalc_chanctx_chantype(local, curr_ctx); 835 ieee80211_recalc_smps_chanctx(local, curr_ctx); 836 ieee80211_recalc_radar_chanctx(local, curr_ctx); 837 ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL); 838 } 839 840 if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) { 841 ieee80211_recalc_txpower(sdata, false); 842 ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL); 843 } 844 845 if (conf) { 846 new_idle = false; 847 } else { 848 struct ieee80211_link_data *tmp; 849 850 new_idle = true; 851 for_each_sdata_link(local, tmp) { 852 if (rcu_access_pointer(tmp->conf->chanctx_conf)) { 853 new_idle = false; 854 break; 855 } 856 } 857 } 858 859 if (new_idle != sdata->vif.cfg.idle) { 860 sdata->vif.cfg.idle = new_idle; 861 862 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && 863 sdata->vif.type != NL80211_IFTYPE_MONITOR) 864 ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE); 865 } 866 867 ieee80211_check_fast_xmit_iface(sdata); 868 869 return ret; 870 } 871 872 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, 873 struct ieee80211_chanctx *chanctx) 874 { 875 struct ieee80211_sub_if_data *sdata; 876 u8 rx_chains_static, rx_chains_dynamic; 877 struct ieee80211_link_data *link; 878 879 lockdep_assert_wiphy(local->hw.wiphy); 880 881 rx_chains_static = 1; 882 rx_chains_dynamic = 1; 883 884 for_each_sdata_link(local, link) { 885 u8 needed_static, needed_dynamic; 886 887 switch (link->sdata->vif.type) { 888 case NL80211_IFTYPE_STATION: 889 if (!link->sdata->u.mgd.associated) 890 continue; 891 break; 892 case NL80211_IFTYPE_AP: 893 case NL80211_IFTYPE_ADHOC: 894 case NL80211_IFTYPE_MESH_POINT: 895 case NL80211_IFTYPE_OCB: 896 break; 897 default: 898 continue; 899 } 900 901 if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf) 902 continue; 903 904 switch (link->smps_mode) { 905 default: 906 WARN_ONCE(1, "Invalid SMPS mode %d\n", 907 link->smps_mode); 908 fallthrough; 909 case IEEE80211_SMPS_OFF: 910 needed_static = link->needed_rx_chains; 911 needed_dynamic = link->needed_rx_chains; 912 break; 913 case IEEE80211_SMPS_DYNAMIC: 914 needed_static = 1; 915 needed_dynamic = link->needed_rx_chains; 916 break; 917 case IEEE80211_SMPS_STATIC: 918 needed_static = 1; 919 needed_dynamic = 1; 920 break; 921 } 922 923 rx_chains_static = max(rx_chains_static, needed_static); 924 rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic); 925 } 926 927 /* Disable SMPS for the monitor interface */ 928 sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata); 929 if (sdata && 930 rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf) 931 rx_chains_dynamic = rx_chains_static = local->rx_chains; 932 933 if (rx_chains_static == chanctx->conf.rx_chains_static && 934 rx_chains_dynamic == chanctx->conf.rx_chains_dynamic) 935 return; 936 937 chanctx->conf.rx_chains_static = rx_chains_static; 938 chanctx->conf.rx_chains_dynamic = rx_chains_dynamic; 939 drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS); 940 } 941 942 static void 943 __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link, 944 bool clear) 945 { 946 struct ieee80211_sub_if_data *sdata = link->sdata; 947 unsigned int link_id = link->link_id; 948 struct ieee80211_bss_conf *link_conf = link->conf; 949 struct ieee80211_local *local __maybe_unused = sdata->local; 950 struct ieee80211_sub_if_data *vlan; 951 struct ieee80211_chanctx_conf *conf; 952 953 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP)) 954 return; 955 956 lockdep_assert_wiphy(local->hw.wiphy); 957 958 /* Check that conf exists, even when clearing this function 959 * must be called with the AP's channel context still there 960 * as it would otherwise cause VLANs to have an invalid 961 * channel context pointer for a while, possibly pointing 962 * to a channel context that has already been freed. 963 */ 964 conf = rcu_dereference_protected(link_conf->chanctx_conf, 965 lockdep_is_held(&local->hw.wiphy->mtx)); 966 WARN_ON(!conf); 967 968 if (clear) 969 conf = NULL; 970 971 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { 972 struct ieee80211_bss_conf *vlan_conf; 973 974 vlan_conf = wiphy_dereference(local->hw.wiphy, 975 vlan->vif.link_conf[link_id]); 976 if (WARN_ON(!vlan_conf)) 977 continue; 978 979 rcu_assign_pointer(vlan_conf->chanctx_conf, conf); 980 } 981 } 982 983 void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link, 984 bool clear) 985 { 986 struct ieee80211_local *local = link->sdata->local; 987 988 lockdep_assert_wiphy(local->hw.wiphy); 989 990 __ieee80211_link_copy_chanctx_to_vlans(link, clear); 991 } 992 993 int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link) 994 { 995 struct ieee80211_sub_if_data *sdata = link->sdata; 996 struct ieee80211_chanctx *ctx = link->reserved_chanctx; 997 998 lockdep_assert_wiphy(sdata->local->hw.wiphy); 999 1000 if (WARN_ON(!ctx)) 1001 return -EINVAL; 1002 1003 list_del(&link->reserved_chanctx_list); 1004 link->reserved_chanctx = NULL; 1005 1006 if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) { 1007 if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) { 1008 if (WARN_ON(!ctx->replace_ctx)) 1009 return -EINVAL; 1010 1011 WARN_ON(ctx->replace_ctx->replace_state != 1012 IEEE80211_CHANCTX_WILL_BE_REPLACED); 1013 WARN_ON(ctx->replace_ctx->replace_ctx != ctx); 1014 1015 ctx->replace_ctx->replace_ctx = NULL; 1016 ctx->replace_ctx->replace_state = 1017 IEEE80211_CHANCTX_REPLACE_NONE; 1018 1019 list_del_rcu(&ctx->list); 1020 kfree_rcu(ctx, rcu_head); 1021 } else { 1022 ieee80211_free_chanctx(sdata->local, ctx); 1023 } 1024 } 1025 1026 return 0; 1027 } 1028 1029 int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link, 1030 const struct ieee80211_chan_req *chanreq, 1031 enum ieee80211_chanctx_mode mode, 1032 bool radar_required) 1033 { 1034 struct ieee80211_sub_if_data *sdata = link->sdata; 1035 struct ieee80211_local *local = sdata->local; 1036 struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx; 1037 1038 lockdep_assert_wiphy(local->hw.wiphy); 1039 1040 curr_ctx = ieee80211_link_get_chanctx(link); 1041 if (curr_ctx && !local->ops->switch_vif_chanctx) 1042 return -EOPNOTSUPP; 1043 1044 new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode); 1045 if (!new_ctx) { 1046 if (ieee80211_can_create_new_chanctx(local)) { 1047 new_ctx = ieee80211_new_chanctx(local, chanreq, mode); 1048 if (IS_ERR(new_ctx)) 1049 return PTR_ERR(new_ctx); 1050 } else { 1051 if (!curr_ctx || 1052 (curr_ctx->replace_state == 1053 IEEE80211_CHANCTX_WILL_BE_REPLACED) || 1054 !list_empty(&curr_ctx->reserved_links)) { 1055 /* 1056 * Another link already requested this context 1057 * for a reservation. Find another one hoping 1058 * all links assigned to it will also switch 1059 * soon enough. 1060 * 1061 * TODO: This needs a little more work as some 1062 * cases (more than 2 chanctx capable devices) 1063 * may fail which could otherwise succeed 1064 * provided some channel context juggling was 1065 * performed. 1066 * 1067 * Consider ctx1..3, link1..6, each ctx has 2 1068 * links. link1 and link2 from ctx1 request new 1069 * different chandefs starting 2 in-place 1070 * reserations with ctx4 and ctx5 replacing 1071 * ctx1 and ctx2 respectively. Next link5 and 1072 * link6 from ctx3 reserve ctx4. If link3 and 1073 * link4 remain on ctx2 as they are then this 1074 * fails unless `replace_ctx` from ctx5 is 1075 * replaced with ctx3. 1076 */ 1077 list_for_each_entry(ctx, &local->chanctx_list, 1078 list) { 1079 if (ctx->replace_state != 1080 IEEE80211_CHANCTX_REPLACE_NONE) 1081 continue; 1082 1083 if (!list_empty(&ctx->reserved_links)) 1084 continue; 1085 1086 curr_ctx = ctx; 1087 break; 1088 } 1089 } 1090 1091 /* 1092 * If that's true then all available contexts already 1093 * have reservations and cannot be used. 1094 */ 1095 if (!curr_ctx || 1096 (curr_ctx->replace_state == 1097 IEEE80211_CHANCTX_WILL_BE_REPLACED) || 1098 !list_empty(&curr_ctx->reserved_links)) 1099 return -EBUSY; 1100 1101 new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode); 1102 if (!new_ctx) 1103 return -ENOMEM; 1104 1105 new_ctx->replace_ctx = curr_ctx; 1106 new_ctx->replace_state = 1107 IEEE80211_CHANCTX_REPLACES_OTHER; 1108 1109 curr_ctx->replace_ctx = new_ctx; 1110 curr_ctx->replace_state = 1111 IEEE80211_CHANCTX_WILL_BE_REPLACED; 1112 1113 list_add_rcu(&new_ctx->list, &local->chanctx_list); 1114 } 1115 } 1116 1117 list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links); 1118 link->reserved_chanctx = new_ctx; 1119 link->reserved = *chanreq; 1120 link->reserved_radar_required = radar_required; 1121 link->reserved_ready = false; 1122 1123 return 0; 1124 } 1125 1126 static void 1127 ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link) 1128 { 1129 struct ieee80211_sub_if_data *sdata = link->sdata; 1130 1131 switch (sdata->vif.type) { 1132 case NL80211_IFTYPE_ADHOC: 1133 case NL80211_IFTYPE_AP: 1134 case NL80211_IFTYPE_MESH_POINT: 1135 case NL80211_IFTYPE_OCB: 1136 wiphy_work_queue(sdata->local->hw.wiphy, 1137 &link->csa_finalize_work); 1138 break; 1139 case NL80211_IFTYPE_STATION: 1140 wiphy_delayed_work_queue(sdata->local->hw.wiphy, 1141 &link->u.mgd.chswitch_work, 0); 1142 break; 1143 case NL80211_IFTYPE_UNSPECIFIED: 1144 case NL80211_IFTYPE_AP_VLAN: 1145 case NL80211_IFTYPE_WDS: 1146 case NL80211_IFTYPE_MONITOR: 1147 case NL80211_IFTYPE_P2P_CLIENT: 1148 case NL80211_IFTYPE_P2P_GO: 1149 case NL80211_IFTYPE_P2P_DEVICE: 1150 case NL80211_IFTYPE_NAN: 1151 case NUM_NL80211_IFTYPES: 1152 WARN_ON(1); 1153 break; 1154 } 1155 } 1156 1157 static void 1158 ieee80211_link_update_chanreq(struct ieee80211_link_data *link, 1159 const struct ieee80211_chan_req *chanreq) 1160 { 1161 struct ieee80211_sub_if_data *sdata = link->sdata; 1162 unsigned int link_id = link->link_id; 1163 struct ieee80211_sub_if_data *vlan; 1164 1165 link->conf->chanreq = *chanreq; 1166 1167 if (sdata->vif.type != NL80211_IFTYPE_AP) 1168 return; 1169 1170 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { 1171 struct ieee80211_bss_conf *vlan_conf; 1172 1173 vlan_conf = wiphy_dereference(sdata->local->hw.wiphy, 1174 vlan->vif.link_conf[link_id]); 1175 if (WARN_ON(!vlan_conf)) 1176 continue; 1177 1178 vlan_conf->chanreq = *chanreq; 1179 } 1180 } 1181 1182 static int 1183 ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link) 1184 { 1185 struct ieee80211_sub_if_data *sdata = link->sdata; 1186 struct ieee80211_bss_conf *link_conf = link->conf; 1187 struct ieee80211_local *local = sdata->local; 1188 struct ieee80211_vif_chanctx_switch vif_chsw[1] = {}; 1189 struct ieee80211_chanctx *old_ctx, *new_ctx; 1190 const struct ieee80211_chan_req *chanreq; 1191 struct ieee80211_chan_req tmp; 1192 u64 changed = 0; 1193 int err; 1194 1195 lockdep_assert_wiphy(local->hw.wiphy); 1196 1197 new_ctx = link->reserved_chanctx; 1198 old_ctx = ieee80211_link_get_chanctx(link); 1199 1200 if (WARN_ON(!link->reserved_ready)) 1201 return -EBUSY; 1202 1203 if (WARN_ON(!new_ctx)) 1204 return -EINVAL; 1205 1206 if (WARN_ON(!old_ctx)) 1207 return -EINVAL; 1208 1209 if (WARN_ON(new_ctx->replace_state == 1210 IEEE80211_CHANCTX_REPLACES_OTHER)) 1211 return -EINVAL; 1212 1213 chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx, 1214 &link->reserved, 1215 &tmp); 1216 if (WARN_ON(!chanreq)) 1217 return -EINVAL; 1218 1219 if (link_conf->chanreq.oper.width != link->reserved.oper.width) 1220 changed = BSS_CHANGED_BANDWIDTH; 1221 1222 ieee80211_link_update_chanreq(link, &link->reserved); 1223 1224 _ieee80211_change_chanctx(local, new_ctx, old_ctx, chanreq, link); 1225 1226 vif_chsw[0].vif = &sdata->vif; 1227 vif_chsw[0].old_ctx = &old_ctx->conf; 1228 vif_chsw[0].new_ctx = &new_ctx->conf; 1229 vif_chsw[0].link_conf = link->conf; 1230 1231 list_del(&link->reserved_chanctx_list); 1232 link->reserved_chanctx = NULL; 1233 1234 err = drv_switch_vif_chanctx(local, vif_chsw, 1, 1235 CHANCTX_SWMODE_REASSIGN_VIF); 1236 if (err) { 1237 if (ieee80211_chanctx_refcount(local, new_ctx) == 0) 1238 ieee80211_free_chanctx(local, new_ctx); 1239 1240 goto out; 1241 } 1242 1243 list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links); 1244 rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf); 1245 1246 if (sdata->vif.type == NL80211_IFTYPE_AP) 1247 __ieee80211_link_copy_chanctx_to_vlans(link, false); 1248 1249 ieee80211_check_fast_xmit_iface(sdata); 1250 1251 if (ieee80211_chanctx_refcount(local, old_ctx) == 0) 1252 ieee80211_free_chanctx(local, old_ctx); 1253 1254 ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL); 1255 ieee80211_recalc_smps_chanctx(local, new_ctx); 1256 ieee80211_recalc_radar_chanctx(local, new_ctx); 1257 1258 if (changed) 1259 ieee80211_link_info_change_notify(sdata, link, changed); 1260 1261 out: 1262 ieee80211_link_chanctx_reservation_complete(link); 1263 return err; 1264 } 1265 1266 static int 1267 ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link) 1268 { 1269 struct ieee80211_sub_if_data *sdata = link->sdata; 1270 struct ieee80211_local *local = sdata->local; 1271 struct ieee80211_chanctx *old_ctx, *new_ctx; 1272 const struct ieee80211_chan_req *chanreq; 1273 struct ieee80211_chan_req tmp; 1274 int err; 1275 1276 old_ctx = ieee80211_link_get_chanctx(link); 1277 new_ctx = link->reserved_chanctx; 1278 1279 if (WARN_ON(!link->reserved_ready)) 1280 return -EINVAL; 1281 1282 if (WARN_ON(old_ctx)) 1283 return -EINVAL; 1284 1285 if (WARN_ON(!new_ctx)) 1286 return -EINVAL; 1287 1288 if (WARN_ON(new_ctx->replace_state == 1289 IEEE80211_CHANCTX_REPLACES_OTHER)) 1290 return -EINVAL; 1291 1292 chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx, 1293 &link->reserved, 1294 &tmp); 1295 if (WARN_ON(!chanreq)) 1296 return -EINVAL; 1297 1298 ieee80211_change_chanctx(local, new_ctx, new_ctx, chanreq); 1299 1300 list_del(&link->reserved_chanctx_list); 1301 link->reserved_chanctx = NULL; 1302 1303 err = ieee80211_assign_link_chanctx(link, new_ctx); 1304 if (err) { 1305 if (ieee80211_chanctx_refcount(local, new_ctx) == 0) 1306 ieee80211_free_chanctx(local, new_ctx); 1307 1308 goto out; 1309 } 1310 1311 out: 1312 ieee80211_link_chanctx_reservation_complete(link); 1313 return err; 1314 } 1315 1316 static bool 1317 ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link) 1318 { 1319 struct ieee80211_sub_if_data *sdata = link->sdata; 1320 struct ieee80211_chanctx *old_ctx, *new_ctx; 1321 1322 lockdep_assert_wiphy(sdata->local->hw.wiphy); 1323 1324 new_ctx = link->reserved_chanctx; 1325 old_ctx = ieee80211_link_get_chanctx(link); 1326 1327 if (!old_ctx) 1328 return false; 1329 1330 if (WARN_ON(!new_ctx)) 1331 return false; 1332 1333 if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED) 1334 return false; 1335 1336 if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1337 return false; 1338 1339 return true; 1340 } 1341 1342 static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local, 1343 int n_vifs) 1344 { 1345 struct ieee80211_vif_chanctx_switch *vif_chsw; 1346 struct ieee80211_link_data *link; 1347 struct ieee80211_chanctx *ctx, *old_ctx; 1348 int i, err; 1349 1350 lockdep_assert_wiphy(local->hw.wiphy); 1351 1352 vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL); 1353 if (!vif_chsw) 1354 return -ENOMEM; 1355 1356 i = 0; 1357 list_for_each_entry(ctx, &local->chanctx_list, list) { 1358 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1359 continue; 1360 1361 if (WARN_ON(!ctx->replace_ctx)) { 1362 err = -EINVAL; 1363 goto out; 1364 } 1365 1366 list_for_each_entry(link, &ctx->reserved_links, 1367 reserved_chanctx_list) { 1368 if (!ieee80211_link_has_in_place_reservation(link)) 1369 continue; 1370 1371 old_ctx = ieee80211_link_get_chanctx(link); 1372 vif_chsw[i].vif = &link->sdata->vif; 1373 vif_chsw[i].old_ctx = &old_ctx->conf; 1374 vif_chsw[i].new_ctx = &ctx->conf; 1375 vif_chsw[i].link_conf = link->conf; 1376 1377 i++; 1378 } 1379 } 1380 1381 err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs, 1382 CHANCTX_SWMODE_SWAP_CONTEXTS); 1383 1384 out: 1385 kfree(vif_chsw); 1386 return err; 1387 } 1388 1389 static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local) 1390 { 1391 struct ieee80211_chanctx *ctx; 1392 int err; 1393 1394 lockdep_assert_wiphy(local->hw.wiphy); 1395 1396 list_for_each_entry(ctx, &local->chanctx_list, list) { 1397 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1398 continue; 1399 1400 if (!list_empty(&ctx->replace_ctx->assigned_links)) 1401 continue; 1402 1403 ieee80211_del_chanctx(local, ctx->replace_ctx); 1404 err = ieee80211_add_chanctx(local, ctx); 1405 if (err) 1406 goto err; 1407 } 1408 1409 return 0; 1410 1411 err: 1412 WARN_ON(ieee80211_add_chanctx(local, ctx)); 1413 list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) { 1414 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1415 continue; 1416 1417 if (!list_empty(&ctx->replace_ctx->assigned_links)) 1418 continue; 1419 1420 ieee80211_del_chanctx(local, ctx); 1421 WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx)); 1422 } 1423 1424 return err; 1425 } 1426 1427 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) 1428 { 1429 struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx; 1430 int err, n_assigned, n_reserved, n_ready; 1431 int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0; 1432 1433 lockdep_assert_wiphy(local->hw.wiphy); 1434 1435 /* 1436 * If there are 2 independent pairs of channel contexts performing 1437 * cross-switch of their vifs this code will still wait until both are 1438 * ready even though it could be possible to switch one before the 1439 * other is ready. 1440 * 1441 * For practical reasons and code simplicity just do a single huge 1442 * switch. 1443 */ 1444 1445 /* 1446 * Verify if the reservation is still feasible. 1447 * - if it's not then disconnect 1448 * - if it is but not all vifs necessary are ready then defer 1449 */ 1450 1451 list_for_each_entry(ctx, &local->chanctx_list, list) { 1452 struct ieee80211_link_data *link; 1453 1454 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1455 continue; 1456 1457 if (WARN_ON(!ctx->replace_ctx)) { 1458 err = -EINVAL; 1459 goto err; 1460 } 1461 1462 n_ctx++; 1463 1464 n_assigned = 0; 1465 n_reserved = 0; 1466 n_ready = 0; 1467 1468 list_for_each_entry(link, &ctx->replace_ctx->assigned_links, 1469 assigned_chanctx_list) { 1470 n_assigned++; 1471 if (link->reserved_chanctx) { 1472 n_reserved++; 1473 if (link->reserved_ready) 1474 n_ready++; 1475 } 1476 } 1477 1478 if (n_assigned != n_reserved) { 1479 if (n_ready == n_reserved) { 1480 wiphy_info(local->hw.wiphy, 1481 "channel context reservation cannot be finalized because some interfaces aren't switching\n"); 1482 err = -EBUSY; 1483 goto err; 1484 } 1485 1486 return -EAGAIN; 1487 } 1488 1489 ctx->conf.radar_enabled = false; 1490 list_for_each_entry(link, &ctx->reserved_links, 1491 reserved_chanctx_list) { 1492 if (ieee80211_link_has_in_place_reservation(link) && 1493 !link->reserved_ready) 1494 return -EAGAIN; 1495 1496 old_ctx = ieee80211_link_get_chanctx(link); 1497 if (old_ctx) { 1498 if (old_ctx->replace_state == 1499 IEEE80211_CHANCTX_WILL_BE_REPLACED) 1500 n_vifs_switch++; 1501 else 1502 n_vifs_assign++; 1503 } else { 1504 n_vifs_ctxless++; 1505 } 1506 1507 if (link->reserved_radar_required) 1508 ctx->conf.radar_enabled = true; 1509 } 1510 } 1511 1512 if (WARN_ON(n_ctx == 0) || 1513 WARN_ON(n_vifs_switch == 0 && 1514 n_vifs_assign == 0 && 1515 n_vifs_ctxless == 0)) { 1516 err = -EINVAL; 1517 goto err; 1518 } 1519 1520 /* 1521 * All necessary vifs are ready. Perform the switch now depending on 1522 * reservations and driver capabilities. 1523 */ 1524 1525 if (n_vifs_switch > 0) { 1526 err = ieee80211_chsw_switch_vifs(local, n_vifs_switch); 1527 if (err) 1528 goto err; 1529 } 1530 1531 if (n_vifs_assign > 0 || n_vifs_ctxless > 0) { 1532 err = ieee80211_chsw_switch_ctxs(local); 1533 if (err) 1534 goto err; 1535 } 1536 1537 /* 1538 * Update all structures, values and pointers to point to new channel 1539 * context(s). 1540 */ 1541 list_for_each_entry(ctx, &local->chanctx_list, list) { 1542 struct ieee80211_link_data *link, *link_tmp; 1543 1544 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1545 continue; 1546 1547 if (WARN_ON(!ctx->replace_ctx)) { 1548 err = -EINVAL; 1549 goto err; 1550 } 1551 1552 list_for_each_entry(link, &ctx->reserved_links, 1553 reserved_chanctx_list) { 1554 struct ieee80211_sub_if_data *sdata = link->sdata; 1555 struct ieee80211_bss_conf *link_conf = link->conf; 1556 u64 changed = 0; 1557 1558 if (!ieee80211_link_has_in_place_reservation(link)) 1559 continue; 1560 1561 rcu_assign_pointer(link_conf->chanctx_conf, 1562 &ctx->conf); 1563 1564 if (sdata->vif.type == NL80211_IFTYPE_AP) 1565 __ieee80211_link_copy_chanctx_to_vlans(link, 1566 false); 1567 1568 ieee80211_check_fast_xmit_iface(sdata); 1569 1570 link->radar_required = link->reserved_radar_required; 1571 1572 if (link_conf->chanreq.oper.width != link->reserved.oper.width) 1573 changed = BSS_CHANGED_BANDWIDTH; 1574 1575 ieee80211_link_update_chanreq(link, &link->reserved); 1576 if (changed) 1577 ieee80211_link_info_change_notify(sdata, 1578 link, 1579 changed); 1580 1581 ieee80211_recalc_txpower(sdata, false); 1582 } 1583 1584 ieee80211_recalc_chanctx_chantype(local, ctx); 1585 ieee80211_recalc_smps_chanctx(local, ctx); 1586 ieee80211_recalc_radar_chanctx(local, ctx); 1587 ieee80211_recalc_chanctx_min_def(local, ctx, NULL); 1588 1589 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links, 1590 reserved_chanctx_list) { 1591 if (ieee80211_link_get_chanctx(link) != ctx) 1592 continue; 1593 1594 list_del(&link->reserved_chanctx_list); 1595 list_move(&link->assigned_chanctx_list, 1596 &ctx->assigned_links); 1597 link->reserved_chanctx = NULL; 1598 1599 ieee80211_link_chanctx_reservation_complete(link); 1600 } 1601 1602 /* 1603 * This context might have been a dependency for an already 1604 * ready re-assign reservation interface that was deferred. Do 1605 * not propagate error to the caller though. The in-place 1606 * reservation for originally requested interface has already 1607 * succeeded at this point. 1608 */ 1609 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links, 1610 reserved_chanctx_list) { 1611 if (WARN_ON(ieee80211_link_has_in_place_reservation(link))) 1612 continue; 1613 1614 if (WARN_ON(link->reserved_chanctx != ctx)) 1615 continue; 1616 1617 if (!link->reserved_ready) 1618 continue; 1619 1620 if (ieee80211_link_get_chanctx(link)) 1621 err = ieee80211_link_use_reserved_reassign(link); 1622 else 1623 err = ieee80211_link_use_reserved_assign(link); 1624 1625 if (err) { 1626 link_info(link, 1627 "failed to finalize (re-)assign reservation (err=%d)\n", 1628 err); 1629 ieee80211_link_unreserve_chanctx(link); 1630 cfg80211_stop_iface(local->hw.wiphy, 1631 &link->sdata->wdev, 1632 GFP_KERNEL); 1633 } 1634 } 1635 } 1636 1637 /* 1638 * Finally free old contexts 1639 */ 1640 1641 list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) { 1642 if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED) 1643 continue; 1644 1645 ctx->replace_ctx->replace_ctx = NULL; 1646 ctx->replace_ctx->replace_state = 1647 IEEE80211_CHANCTX_REPLACE_NONE; 1648 1649 list_del_rcu(&ctx->list); 1650 kfree_rcu(ctx, rcu_head); 1651 } 1652 1653 return 0; 1654 1655 err: 1656 list_for_each_entry(ctx, &local->chanctx_list, list) { 1657 struct ieee80211_link_data *link, *link_tmp; 1658 1659 if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) 1660 continue; 1661 1662 list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links, 1663 reserved_chanctx_list) { 1664 ieee80211_link_unreserve_chanctx(link); 1665 ieee80211_link_chanctx_reservation_complete(link); 1666 } 1667 } 1668 1669 return err; 1670 } 1671 1672 static void __ieee80211_link_release_channel(struct ieee80211_link_data *link) 1673 { 1674 struct ieee80211_sub_if_data *sdata = link->sdata; 1675 struct ieee80211_bss_conf *link_conf = link->conf; 1676 struct ieee80211_local *local = sdata->local; 1677 struct ieee80211_chanctx_conf *conf; 1678 struct ieee80211_chanctx *ctx; 1679 bool use_reserved_switch = false; 1680 1681 lockdep_assert_wiphy(local->hw.wiphy); 1682 1683 conf = rcu_dereference_protected(link_conf->chanctx_conf, 1684 lockdep_is_held(&local->hw.wiphy->mtx)); 1685 if (!conf) 1686 return; 1687 1688 ctx = container_of(conf, struct ieee80211_chanctx, conf); 1689 1690 if (link->reserved_chanctx) { 1691 if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER && 1692 ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1) 1693 use_reserved_switch = true; 1694 1695 ieee80211_link_unreserve_chanctx(link); 1696 } 1697 1698 ieee80211_assign_link_chanctx(link, NULL); 1699 if (ieee80211_chanctx_refcount(local, ctx) == 0) 1700 ieee80211_free_chanctx(local, ctx); 1701 1702 link->radar_required = false; 1703 1704 /* Unreserving may ready an in-place reservation. */ 1705 if (use_reserved_switch) 1706 ieee80211_vif_use_reserved_switch(local); 1707 } 1708 1709 int ieee80211_link_use_channel(struct ieee80211_link_data *link, 1710 const struct ieee80211_chan_req *chanreq, 1711 enum ieee80211_chanctx_mode mode) 1712 { 1713 struct ieee80211_sub_if_data *sdata = link->sdata; 1714 struct ieee80211_local *local = sdata->local; 1715 struct ieee80211_chanctx *ctx; 1716 u8 radar_detect_width = 0; 1717 int ret; 1718 1719 lockdep_assert_wiphy(local->hw.wiphy); 1720 1721 if (!ieee80211_vif_link_active(&sdata->vif, link->link_id)) { 1722 ieee80211_link_update_chanreq(link, chanreq); 1723 return 0; 1724 } 1725 1726 ret = cfg80211_chandef_dfs_required(local->hw.wiphy, 1727 &chanreq->oper, 1728 sdata->wdev.iftype); 1729 if (ret < 0) 1730 goto out; 1731 if (ret > 0) 1732 radar_detect_width = BIT(chanreq->oper.width); 1733 1734 link->radar_required = ret; 1735 1736 ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode, 1737 radar_detect_width); 1738 if (ret < 0) 1739 goto out; 1740 1741 __ieee80211_link_release_channel(link); 1742 1743 ctx = ieee80211_find_chanctx(local, chanreq, mode); 1744 if (!ctx) 1745 ctx = ieee80211_new_chanctx(local, chanreq, mode); 1746 if (IS_ERR(ctx)) { 1747 ret = PTR_ERR(ctx); 1748 goto out; 1749 } 1750 1751 ieee80211_link_update_chanreq(link, chanreq); 1752 1753 ret = ieee80211_assign_link_chanctx(link, ctx); 1754 if (ret) { 1755 /* if assign fails refcount stays the same */ 1756 if (ieee80211_chanctx_refcount(local, ctx) == 0) 1757 ieee80211_free_chanctx(local, ctx); 1758 goto out; 1759 } 1760 1761 ieee80211_recalc_smps_chanctx(local, ctx); 1762 ieee80211_recalc_radar_chanctx(local, ctx); 1763 out: 1764 if (ret) 1765 link->radar_required = false; 1766 1767 return ret; 1768 } 1769 1770 int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link) 1771 { 1772 struct ieee80211_sub_if_data *sdata = link->sdata; 1773 struct ieee80211_local *local = sdata->local; 1774 struct ieee80211_chanctx *new_ctx; 1775 struct ieee80211_chanctx *old_ctx; 1776 int err; 1777 1778 lockdep_assert_wiphy(local->hw.wiphy); 1779 1780 new_ctx = link->reserved_chanctx; 1781 old_ctx = ieee80211_link_get_chanctx(link); 1782 1783 if (WARN_ON(!new_ctx)) 1784 return -EINVAL; 1785 1786 if (WARN_ON(new_ctx->replace_state == 1787 IEEE80211_CHANCTX_WILL_BE_REPLACED)) 1788 return -EINVAL; 1789 1790 if (WARN_ON(link->reserved_ready)) 1791 return -EINVAL; 1792 1793 link->reserved_ready = true; 1794 1795 if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) { 1796 if (old_ctx) 1797 return ieee80211_link_use_reserved_reassign(link); 1798 1799 return ieee80211_link_use_reserved_assign(link); 1800 } 1801 1802 /* 1803 * In-place reservation may need to be finalized now either if: 1804 * a) sdata is taking part in the swapping itself and is the last one 1805 * b) sdata has switched with a re-assign reservation to an existing 1806 * context readying in-place switching of old_ctx 1807 * 1808 * In case of (b) do not propagate the error up because the requested 1809 * sdata already switched successfully. Just spill an extra warning. 1810 * The ieee80211_vif_use_reserved_switch() already stops all necessary 1811 * interfaces upon failure. 1812 */ 1813 if ((old_ctx && 1814 old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) || 1815 new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) { 1816 err = ieee80211_vif_use_reserved_switch(local); 1817 if (err && err != -EAGAIN) { 1818 if (new_ctx->replace_state == 1819 IEEE80211_CHANCTX_REPLACES_OTHER) 1820 return err; 1821 1822 wiphy_info(local->hw.wiphy, 1823 "depending in-place reservation failed (err=%d)\n", 1824 err); 1825 } 1826 } 1827 1828 return 0; 1829 } 1830 1831 /* 1832 * This is similar to ieee80211_chanctx_compatible(), but rechecks 1833 * against all the links actually using it (except the one that's 1834 * passed, since that one is changing). 1835 * This is done in order to allow changes to the AP's bandwidth for 1836 * wider bandwidth OFDMA purposes, which wouldn't be treated as 1837 * compatible by ieee80211_chanctx_recheck() but is OK if the link 1838 * requesting the update is the only one using it. 1839 */ 1840 static const struct ieee80211_chan_req * 1841 ieee80211_chanctx_recheck(struct ieee80211_local *local, 1842 struct ieee80211_link_data *skip_link, 1843 struct ieee80211_chanctx *ctx, 1844 const struct ieee80211_chan_req *req, 1845 struct ieee80211_chan_req *tmp) 1846 { 1847 const struct ieee80211_chan_req *ret = req; 1848 struct ieee80211_link_data *link; 1849 1850 lockdep_assert_wiphy(local->hw.wiphy); 1851 1852 for_each_sdata_link(local, link) { 1853 if (link == skip_link) 1854 continue; 1855 1856 if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) { 1857 ret = ieee80211_chanreq_compatible(ret, 1858 &link->conf->chanreq, 1859 tmp); 1860 if (!ret) 1861 return NULL; 1862 } 1863 1864 if (link->reserved_chanctx == ctx) { 1865 ret = ieee80211_chanreq_compatible(ret, 1866 &link->reserved, 1867 tmp); 1868 if (!ret) 1869 return NULL; 1870 } 1871 } 1872 1873 *tmp = *ret; 1874 return tmp; 1875 } 1876 1877 int ieee80211_link_change_chanreq(struct ieee80211_link_data *link, 1878 const struct ieee80211_chan_req *chanreq, 1879 u64 *changed) 1880 { 1881 struct ieee80211_sub_if_data *sdata = link->sdata; 1882 struct ieee80211_bss_conf *link_conf = link->conf; 1883 struct ieee80211_local *local = sdata->local; 1884 struct ieee80211_chanctx_conf *conf; 1885 struct ieee80211_chanctx *ctx; 1886 const struct ieee80211_chan_req *compat; 1887 struct ieee80211_chan_req tmp; 1888 1889 lockdep_assert_wiphy(local->hw.wiphy); 1890 1891 if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, 1892 &chanreq->oper, 1893 IEEE80211_CHAN_DISABLED)) 1894 return -EINVAL; 1895 1896 /* for non-HT 20 MHz the rest doesn't matter */ 1897 if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT && 1898 cfg80211_chandef_identical(&chanreq->oper, &link_conf->chanreq.oper)) 1899 return 0; 1900 1901 /* but you cannot switch to/from it */ 1902 if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT || 1903 link_conf->chanreq.oper.width == NL80211_CHAN_WIDTH_20_NOHT) 1904 return -EINVAL; 1905 1906 conf = rcu_dereference_protected(link_conf->chanctx_conf, 1907 lockdep_is_held(&local->hw.wiphy->mtx)); 1908 if (!conf) 1909 return -EINVAL; 1910 1911 ctx = container_of(conf, struct ieee80211_chanctx, conf); 1912 1913 compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp); 1914 if (!compat) 1915 return -EINVAL; 1916 1917 switch (ctx->replace_state) { 1918 case IEEE80211_CHANCTX_REPLACE_NONE: 1919 if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat, 1920 &tmp)) 1921 return -EBUSY; 1922 break; 1923 case IEEE80211_CHANCTX_WILL_BE_REPLACED: 1924 /* TODO: Perhaps the bandwidth change could be treated as a 1925 * reservation itself? */ 1926 return -EBUSY; 1927 case IEEE80211_CHANCTX_REPLACES_OTHER: 1928 /* channel context that is going to replace another channel 1929 * context doesn't really exist and shouldn't be assigned 1930 * anywhere yet */ 1931 WARN_ON(1); 1932 break; 1933 } 1934 1935 ieee80211_link_update_chanreq(link, chanreq); 1936 1937 ieee80211_recalc_chanctx_chantype(local, ctx); 1938 1939 *changed |= BSS_CHANGED_BANDWIDTH; 1940 return 0; 1941 } 1942 1943 void ieee80211_link_release_channel(struct ieee80211_link_data *link) 1944 { 1945 struct ieee80211_sub_if_data *sdata = link->sdata; 1946 1947 lockdep_assert_wiphy(sdata->local->hw.wiphy); 1948 1949 if (rcu_access_pointer(link->conf->chanctx_conf)) 1950 __ieee80211_link_release_channel(link); 1951 } 1952 1953 void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link) 1954 { 1955 struct ieee80211_sub_if_data *sdata = link->sdata; 1956 unsigned int link_id = link->link_id; 1957 struct ieee80211_bss_conf *link_conf = link->conf; 1958 struct ieee80211_bss_conf *ap_conf; 1959 struct ieee80211_local *local = sdata->local; 1960 struct ieee80211_sub_if_data *ap; 1961 struct ieee80211_chanctx_conf *conf; 1962 1963 lockdep_assert_wiphy(local->hw.wiphy); 1964 1965 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss)) 1966 return; 1967 1968 ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); 1969 1970 ap_conf = wiphy_dereference(local->hw.wiphy, 1971 ap->vif.link_conf[link_id]); 1972 conf = wiphy_dereference(local->hw.wiphy, 1973 ap_conf->chanctx_conf); 1974 rcu_assign_pointer(link_conf->chanctx_conf, conf); 1975 } 1976 1977 void ieee80211_iter_chan_contexts_atomic( 1978 struct ieee80211_hw *hw, 1979 void (*iter)(struct ieee80211_hw *hw, 1980 struct ieee80211_chanctx_conf *chanctx_conf, 1981 void *data), 1982 void *iter_data) 1983 { 1984 struct ieee80211_local *local = hw_to_local(hw); 1985 struct ieee80211_chanctx *ctx; 1986 1987 rcu_read_lock(); 1988 list_for_each_entry_rcu(ctx, &local->chanctx_list, list) 1989 if (ctx->driver_present) 1990 iter(hw, &ctx->conf, iter_data); 1991 rcu_read_unlock(); 1992 } 1993 EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic); 1994