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