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