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