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