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                if (!sta->uploaded)
 235                        continue;
 236
 237                max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
 238        }
 239        rcu_read_unlock();
 240
 241        return max_bw;
 242}
 243
 244static enum nl80211_chan_width
 245ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
 246                                      struct ieee80211_chanctx_conf *conf)
 247{
 248        struct ieee80211_sub_if_data *sdata;
 249        enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
 250
 251        rcu_read_lock();
 252        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 253                struct ieee80211_vif *vif = &sdata->vif;
 254                enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
 255
 256                if (!ieee80211_sdata_running(sdata))
 257                        continue;
 258
 259                if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
 260                        continue;
 261
 262                switch (vif->type) {
 263                case NL80211_IFTYPE_AP:
 264                case NL80211_IFTYPE_AP_VLAN:
 265                        width = ieee80211_get_max_required_bw(sdata);
 266                        break;
 267                case NL80211_IFTYPE_STATION:
 268                        /*
 269                         * The ap's sta->bandwidth is not set yet at this
 270                         * point, so take the width from the chandef, but
 271                         * account also for TDLS peers
 272                         */
 273                        width = max(vif->bss_conf.chandef.width,
 274                                    ieee80211_get_max_required_bw(sdata));
 275                        break;
 276                case NL80211_IFTYPE_P2P_DEVICE:
 277                        continue;
 278                case NL80211_IFTYPE_ADHOC:
 279                case NL80211_IFTYPE_WDS:
 280                case NL80211_IFTYPE_MESH_POINT:
 281                case NL80211_IFTYPE_OCB:
 282                        width = vif->bss_conf.chandef.width;
 283                        break;
 284                case NL80211_IFTYPE_UNSPECIFIED:
 285                case NUM_NL80211_IFTYPES:
 286                case NL80211_IFTYPE_MONITOR:
 287                case NL80211_IFTYPE_P2P_CLIENT:
 288                case NL80211_IFTYPE_P2P_GO:
 289                        WARN_ON_ONCE(1);
 290                }
 291                max_bw = max(max_bw, width);
 292        }
 293
 294        /* use the configured bandwidth in case of monitor interface */
 295        sdata = rcu_dereference(local->monitor_sdata);
 296        if (sdata && rcu_access_pointer(sdata->vif.chanctx_conf) == conf)
 297                max_bw = max(max_bw, conf->def.width);
 298
 299        rcu_read_unlock();
 300
 301        return max_bw;
 302}
 303
 304/*
 305 * recalc the min required chan width of the channel context, which is
 306 * the max of min required widths of all the interfaces bound to this
 307 * channel context.
 308 */
 309void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
 310                                      struct ieee80211_chanctx *ctx)
 311{
 312        enum nl80211_chan_width max_bw;
 313        struct cfg80211_chan_def min_def;
 314
 315        lockdep_assert_held(&local->chanctx_mtx);
 316
 317        /* don't optimize 5MHz, 10MHz, and radar_enabled confs */
 318        if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
 319            ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
 320            ctx->conf.radar_enabled) {
 321                ctx->conf.min_def = ctx->conf.def;
 322                return;
 323        }
 324
 325        max_bw = ieee80211_get_chanctx_max_required_bw(local, &ctx->conf);
 326
 327        /* downgrade chandef up to max_bw */
 328        min_def = ctx->conf.def;
 329        while (min_def.width > max_bw)
 330                ieee80211_chandef_downgrade(&min_def);
 331
 332        if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
 333                return;
 334
 335        ctx->conf.min_def = min_def;
 336        if (!ctx->driver_present)
 337                return;
 338
 339        drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_MIN_WIDTH);
 340}
 341
 342static void ieee80211_change_chanctx(struct ieee80211_local *local,
 343                                     struct ieee80211_chanctx *ctx,
 344                                     const struct cfg80211_chan_def *chandef)
 345{
 346        if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
 347                return;
 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        conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
 648                                         lockdep_is_held(&local->chanctx_mtx));
 649
 650        if (conf) {
 651                curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
 652
 653                drv_unassign_vif_chanctx(local, sdata, curr_ctx);
 654                conf = NULL;
 655                list_del(&sdata->assigned_chanctx_list);
 656        }
 657
 658        if (new_ctx) {
 659                ret = drv_assign_vif_chanctx(local, sdata, new_ctx);
 660                if (ret)
 661                        goto out;
 662
 663                conf = &new_ctx->conf;
 664                list_add(&sdata->assigned_chanctx_list,
 665                         &new_ctx->assigned_vifs);
 666        }
 667
 668out:
 669        rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
 670
 671        sdata->vif.bss_conf.idle = !conf;
 672
 673        if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
 674                ieee80211_recalc_chanctx_chantype(local, curr_ctx);
 675                ieee80211_recalc_smps_chanctx(local, curr_ctx);
 676                ieee80211_recalc_radar_chanctx(local, curr_ctx);
 677                ieee80211_recalc_chanctx_min_def(local, curr_ctx);
 678        }
 679
 680        if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
 681                ieee80211_recalc_txpower(sdata, false);
 682                ieee80211_recalc_chanctx_min_def(local, new_ctx);
 683        }
 684
 685        if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
 686            sdata->vif.type != NL80211_IFTYPE_MONITOR)
 687                ieee80211_bss_info_change_notify(sdata,
 688                                                 BSS_CHANGED_IDLE);
 689
 690        ieee80211_check_fast_xmit_iface(sdata);
 691
 692        return ret;
 693}
 694
 695void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
 696                                   struct ieee80211_chanctx *chanctx)
 697{
 698        struct ieee80211_sub_if_data *sdata;
 699        u8 rx_chains_static, rx_chains_dynamic;
 700
 701        lockdep_assert_held(&local->chanctx_mtx);
 702
 703        rx_chains_static = 1;
 704        rx_chains_dynamic = 1;
 705
 706        rcu_read_lock();
 707        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 708                u8 needed_static, needed_dynamic;
 709
 710                if (!ieee80211_sdata_running(sdata))
 711                        continue;
 712
 713                if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
 714                                                &chanctx->conf)
 715                        continue;
 716
 717                switch (sdata->vif.type) {
 718                case NL80211_IFTYPE_P2P_DEVICE:
 719                        continue;
 720                case NL80211_IFTYPE_STATION:
 721                        if (!sdata->u.mgd.associated)
 722                                continue;
 723                        break;
 724                case NL80211_IFTYPE_AP_VLAN:
 725                        continue;
 726                case NL80211_IFTYPE_AP:
 727                case NL80211_IFTYPE_ADHOC:
 728                case NL80211_IFTYPE_WDS:
 729                case NL80211_IFTYPE_MESH_POINT:
 730                case NL80211_IFTYPE_OCB:
 731                        break;
 732                default:
 733                        WARN_ON_ONCE(1);
 734                }
 735
 736                switch (sdata->smps_mode) {
 737                default:
 738                        WARN_ONCE(1, "Invalid SMPS mode %d\n",
 739                                  sdata->smps_mode);
 740                        /* fall through */
 741                case IEEE80211_SMPS_OFF:
 742                        needed_static = sdata->needed_rx_chains;
 743                        needed_dynamic = sdata->needed_rx_chains;
 744                        break;
 745                case IEEE80211_SMPS_DYNAMIC:
 746                        needed_static = 1;
 747                        needed_dynamic = sdata->needed_rx_chains;
 748                        break;
 749                case IEEE80211_SMPS_STATIC:
 750                        needed_static = 1;
 751                        needed_dynamic = 1;
 752                        break;
 753                }
 754
 755                rx_chains_static = max(rx_chains_static, needed_static);
 756                rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
 757        }
 758
 759        /* Disable SMPS for the monitor interface */
 760        sdata = rcu_dereference(local->monitor_sdata);
 761        if (sdata &&
 762            rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf)
 763                rx_chains_dynamic = rx_chains_static = local->rx_chains;
 764
 765        rcu_read_unlock();
 766
 767        if (!local->use_chanctx) {
 768                if (rx_chains_static > 1)
 769                        local->smps_mode = IEEE80211_SMPS_OFF;
 770                else if (rx_chains_dynamic > 1)
 771                        local->smps_mode = IEEE80211_SMPS_DYNAMIC;
 772                else
 773                        local->smps_mode = IEEE80211_SMPS_STATIC;
 774                ieee80211_hw_config(local, 0);
 775        }
 776
 777        if (rx_chains_static == chanctx->conf.rx_chains_static &&
 778            rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
 779                return;
 780
 781        chanctx->conf.rx_chains_static = rx_chains_static;
 782        chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
 783        drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
 784}
 785
 786static void
 787__ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
 788                                      bool clear)
 789{
 790        struct ieee80211_local *local __maybe_unused = sdata->local;
 791        struct ieee80211_sub_if_data *vlan;
 792        struct ieee80211_chanctx_conf *conf;
 793
 794        if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
 795                return;
 796
 797        lockdep_assert_held(&local->mtx);
 798
 799        /* Check that conf exists, even when clearing this function
 800         * must be called with the AP's channel context still there
 801         * as it would otherwise cause VLANs to have an invalid
 802         * channel context pointer for a while, possibly pointing
 803         * to a channel context that has already been freed.
 804         */
 805        conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
 806                                         lockdep_is_held(&local->chanctx_mtx));
 807        WARN_ON(!conf);
 808
 809        if (clear)
 810                conf = NULL;
 811
 812        list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
 813                rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
 814}
 815
 816void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
 817                                         bool clear)
 818{
 819        struct ieee80211_local *local = sdata->local;
 820
 821        mutex_lock(&local->chanctx_mtx);
 822
 823        __ieee80211_vif_copy_chanctx_to_vlans(sdata, clear);
 824
 825        mutex_unlock(&local->chanctx_mtx);
 826}
 827
 828int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata)
 829{
 830        struct ieee80211_chanctx *ctx = sdata->reserved_chanctx;
 831
 832        lockdep_assert_held(&sdata->local->chanctx_mtx);
 833
 834        if (WARN_ON(!ctx))
 835                return -EINVAL;
 836
 837        list_del(&sdata->reserved_chanctx_list);
 838        sdata->reserved_chanctx = NULL;
 839
 840        if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
 841                if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
 842                        if (WARN_ON(!ctx->replace_ctx))
 843                                return -EINVAL;
 844
 845                        WARN_ON(ctx->replace_ctx->replace_state !=
 846                                IEEE80211_CHANCTX_WILL_BE_REPLACED);
 847                        WARN_ON(ctx->replace_ctx->replace_ctx != ctx);
 848
 849                        ctx->replace_ctx->replace_ctx = NULL;
 850                        ctx->replace_ctx->replace_state =
 851                                        IEEE80211_CHANCTX_REPLACE_NONE;
 852
 853                        list_del_rcu(&ctx->list);
 854                        kfree_rcu(ctx, rcu_head);
 855                } else {
 856                        ieee80211_free_chanctx(sdata->local, ctx);
 857                }
 858        }
 859
 860        return 0;
 861}
 862
 863int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
 864                                  const struct cfg80211_chan_def *chandef,
 865                                  enum ieee80211_chanctx_mode mode,
 866                                  bool radar_required)
 867{
 868        struct ieee80211_local *local = sdata->local;
 869        struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx;
 870
 871        lockdep_assert_held(&local->chanctx_mtx);
 872
 873        curr_ctx = ieee80211_vif_get_chanctx(sdata);
 874        if (curr_ctx && local->use_chanctx && !local->ops->switch_vif_chanctx)
 875                return -ENOTSUPP;
 876
 877        new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode);
 878        if (!new_ctx) {
 879                if (ieee80211_can_create_new_chanctx(local)) {
 880                        new_ctx = ieee80211_new_chanctx(local, chandef, mode);
 881                        if (IS_ERR(new_ctx))
 882                                return PTR_ERR(new_ctx);
 883                } else {
 884                        if (!curr_ctx ||
 885                            (curr_ctx->replace_state ==
 886                             IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
 887                            !list_empty(&curr_ctx->reserved_vifs)) {
 888                                /*
 889                                 * Another vif already requested this context
 890                                 * for a reservation. Find another one hoping
 891                                 * all vifs assigned to it will also switch
 892                                 * soon enough.
 893                                 *
 894                                 * TODO: This needs a little more work as some
 895                                 * cases (more than 2 chanctx capable devices)
 896                                 * may fail which could otherwise succeed
 897                                 * provided some channel context juggling was
 898                                 * performed.
 899                                 *
 900                                 * Consider ctx1..3, vif1..6, each ctx has 2
 901                                 * vifs. vif1 and vif2 from ctx1 request new
 902                                 * different chandefs starting 2 in-place
 903                                 * reserations with ctx4 and ctx5 replacing
 904                                 * ctx1 and ctx2 respectively. Next vif5 and
 905                                 * vif6 from ctx3 reserve ctx4. If vif3 and
 906                                 * vif4 remain on ctx2 as they are then this
 907                                 * fails unless `replace_ctx` from ctx5 is
 908                                 * replaced with ctx3.
 909                                 */
 910                                list_for_each_entry(ctx, &local->chanctx_list,
 911                                                    list) {
 912                                        if (ctx->replace_state !=
 913                                            IEEE80211_CHANCTX_REPLACE_NONE)
 914                                                continue;
 915
 916                                        if (!list_empty(&ctx->reserved_vifs))
 917                                                continue;
 918
 919                                        curr_ctx = ctx;
 920                                        break;
 921                                }
 922                        }
 923
 924                        /*
 925                         * If that's true then all available contexts already
 926                         * have reservations and cannot be used.
 927                         */
 928                        if (!curr_ctx ||
 929                            (curr_ctx->replace_state ==
 930                             IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
 931                            !list_empty(&curr_ctx->reserved_vifs))
 932                                return -EBUSY;
 933
 934                        new_ctx = ieee80211_alloc_chanctx(local, chandef, mode);
 935                        if (!new_ctx)
 936                                return -ENOMEM;
 937
 938                        new_ctx->replace_ctx = curr_ctx;
 939                        new_ctx->replace_state =
 940                                        IEEE80211_CHANCTX_REPLACES_OTHER;
 941
 942                        curr_ctx->replace_ctx = new_ctx;
 943                        curr_ctx->replace_state =
 944                                        IEEE80211_CHANCTX_WILL_BE_REPLACED;
 945
 946                        list_add_rcu(&new_ctx->list, &local->chanctx_list);
 947                }
 948        }
 949
 950        list_add(&sdata->reserved_chanctx_list, &new_ctx->reserved_vifs);
 951        sdata->reserved_chanctx = new_ctx;
 952        sdata->reserved_chandef = *chandef;
 953        sdata->reserved_radar_required = radar_required;
 954        sdata->reserved_ready = false;
 955
 956        return 0;
 957}
 958
 959static void
 960ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata)
 961{
 962        switch (sdata->vif.type) {
 963        case NL80211_IFTYPE_ADHOC:
 964        case NL80211_IFTYPE_AP:
 965        case NL80211_IFTYPE_MESH_POINT:
 966        case NL80211_IFTYPE_OCB:
 967                ieee80211_queue_work(&sdata->local->hw,
 968                                     &sdata->csa_finalize_work);
 969                break;
 970        case NL80211_IFTYPE_STATION:
 971                ieee80211_queue_work(&sdata->local->hw,
 972                                     &sdata->u.mgd.chswitch_work);
 973                break;
 974        case NL80211_IFTYPE_UNSPECIFIED:
 975        case NL80211_IFTYPE_AP_VLAN:
 976        case NL80211_IFTYPE_WDS:
 977        case NL80211_IFTYPE_MONITOR:
 978        case NL80211_IFTYPE_P2P_CLIENT:
 979        case NL80211_IFTYPE_P2P_GO:
 980        case NL80211_IFTYPE_P2P_DEVICE:
 981        case NUM_NL80211_IFTYPES:
 982                WARN_ON(1);
 983                break;
 984        }
 985}
 986
 987static void
 988ieee80211_vif_update_chandef(struct ieee80211_sub_if_data *sdata,
 989                             const struct cfg80211_chan_def *chandef)
 990{
 991        struct ieee80211_sub_if_data *vlan;
 992
 993        sdata->vif.bss_conf.chandef = *chandef;
 994
 995        if (sdata->vif.type != NL80211_IFTYPE_AP)
 996                return;
 997
 998        list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
 999                vlan->vif.bss_conf.chandef = *chandef;
1000}
1001
1002static int
1003ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
1004{
1005        struct ieee80211_local *local = sdata->local;
1006        struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
1007        struct ieee80211_chanctx *old_ctx, *new_ctx;
1008        const struct cfg80211_chan_def *chandef;
1009        u32 changed = 0;
1010        int err;
1011
1012        lockdep_assert_held(&local->mtx);
1013        lockdep_assert_held(&local->chanctx_mtx);
1014
1015        new_ctx = sdata->reserved_chanctx;
1016        old_ctx = ieee80211_vif_get_chanctx(sdata);
1017
1018        if (WARN_ON(!sdata->reserved_ready))
1019                return -EBUSY;
1020
1021        if (WARN_ON(!new_ctx))
1022                return -EINVAL;
1023
1024        if (WARN_ON(!old_ctx))
1025                return -EINVAL;
1026
1027        if (WARN_ON(new_ctx->replace_state ==
1028                    IEEE80211_CHANCTX_REPLACES_OTHER))
1029                return -EINVAL;
1030
1031        chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1032                                &sdata->reserved_chandef);
1033        if (WARN_ON(!chandef))
1034                return -EINVAL;
1035
1036        ieee80211_change_chanctx(local, new_ctx, chandef);
1037
1038        vif_chsw[0].vif = &sdata->vif;
1039        vif_chsw[0].old_ctx = &old_ctx->conf;
1040        vif_chsw[0].new_ctx = &new_ctx->conf;
1041
1042        list_del(&sdata->reserved_chanctx_list);
1043        sdata->reserved_chanctx = NULL;
1044
1045        err = drv_switch_vif_chanctx(local, vif_chsw, 1,
1046                                     CHANCTX_SWMODE_REASSIGN_VIF);
1047        if (err) {
1048                if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1049                        ieee80211_free_chanctx(local, new_ctx);
1050
1051                goto out;
1052        }
1053
1054        list_move(&sdata->assigned_chanctx_list, &new_ctx->assigned_vifs);
1055        rcu_assign_pointer(sdata->vif.chanctx_conf, &new_ctx->conf);
1056
1057        if (sdata->vif.type == NL80211_IFTYPE_AP)
1058                __ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
1059
1060        ieee80211_check_fast_xmit_iface(sdata);
1061
1062        if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
1063                ieee80211_free_chanctx(local, old_ctx);
1064
1065        if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width)
1066                changed = BSS_CHANGED_BANDWIDTH;
1067
1068        ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
1069
1070        ieee80211_recalc_smps_chanctx(local, new_ctx);
1071        ieee80211_recalc_radar_chanctx(local, new_ctx);
1072        ieee80211_recalc_chanctx_min_def(local, new_ctx);
1073
1074        if (changed)
1075                ieee80211_bss_info_change_notify(sdata, changed);
1076
1077out:
1078        ieee80211_vif_chanctx_reservation_complete(sdata);
1079        return err;
1080}
1081
1082static int
1083ieee80211_vif_use_reserved_assign(struct ieee80211_sub_if_data *sdata)
1084{
1085        struct ieee80211_local *local = sdata->local;
1086        struct ieee80211_chanctx *old_ctx, *new_ctx;
1087        const struct cfg80211_chan_def *chandef;
1088        int err;
1089
1090        old_ctx = ieee80211_vif_get_chanctx(sdata);
1091        new_ctx = sdata->reserved_chanctx;
1092
1093        if (WARN_ON(!sdata->reserved_ready))
1094                return -EINVAL;
1095
1096        if (WARN_ON(old_ctx))
1097                return -EINVAL;
1098
1099        if (WARN_ON(!new_ctx))
1100                return -EINVAL;
1101
1102        if (WARN_ON(new_ctx->replace_state ==
1103                    IEEE80211_CHANCTX_REPLACES_OTHER))
1104                return -EINVAL;
1105
1106        chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
1107                                &sdata->reserved_chandef);
1108        if (WARN_ON(!chandef))
1109                return -EINVAL;
1110
1111        ieee80211_change_chanctx(local, new_ctx, chandef);
1112
1113        list_del(&sdata->reserved_chanctx_list);
1114        sdata->reserved_chanctx = NULL;
1115
1116        err = ieee80211_assign_vif_chanctx(sdata, new_ctx);
1117        if (err) {
1118                if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
1119                        ieee80211_free_chanctx(local, new_ctx);
1120
1121                goto out;
1122        }
1123
1124out:
1125        ieee80211_vif_chanctx_reservation_complete(sdata);
1126        return err;
1127}
1128
1129static bool
1130ieee80211_vif_has_in_place_reservation(struct ieee80211_sub_if_data *sdata)
1131{
1132        struct ieee80211_chanctx *old_ctx, *new_ctx;
1133
1134        lockdep_assert_held(&sdata->local->chanctx_mtx);
1135
1136        new_ctx = sdata->reserved_chanctx;
1137        old_ctx = ieee80211_vif_get_chanctx(sdata);
1138
1139        if (!old_ctx)
1140                return false;
1141
1142        if (WARN_ON(!new_ctx))
1143                return false;
1144
1145        if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1146                return false;
1147
1148        if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1149                return false;
1150
1151        return true;
1152}
1153
1154static int ieee80211_chsw_switch_hwconf(struct ieee80211_local *local,
1155                                        struct ieee80211_chanctx *new_ctx)
1156{
1157        const struct cfg80211_chan_def *chandef;
1158
1159        lockdep_assert_held(&local->mtx);
1160        lockdep_assert_held(&local->chanctx_mtx);
1161
1162        chandef = ieee80211_chanctx_reserved_chandef(local, new_ctx, NULL);
1163        if (WARN_ON(!chandef))
1164                return -EINVAL;
1165
1166        local->hw.conf.radar_enabled = new_ctx->conf.radar_enabled;
1167        local->_oper_chandef = *chandef;
1168        ieee80211_hw_config(local, 0);
1169
1170        return 0;
1171}
1172
1173static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
1174                                      int n_vifs)
1175{
1176        struct ieee80211_vif_chanctx_switch *vif_chsw;
1177        struct ieee80211_sub_if_data *sdata;
1178        struct ieee80211_chanctx *ctx, *old_ctx;
1179        int i, err;
1180
1181        lockdep_assert_held(&local->mtx);
1182        lockdep_assert_held(&local->chanctx_mtx);
1183
1184        vif_chsw = kzalloc(sizeof(vif_chsw[0]) * n_vifs, GFP_KERNEL);
1185        if (!vif_chsw)
1186                return -ENOMEM;
1187
1188        i = 0;
1189        list_for_each_entry(ctx, &local->chanctx_list, list) {
1190                if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1191                        continue;
1192
1193                if (WARN_ON(!ctx->replace_ctx)) {
1194                        err = -EINVAL;
1195                        goto out;
1196                }
1197
1198                list_for_each_entry(sdata, &ctx->reserved_vifs,
1199                                    reserved_chanctx_list) {
1200                        if (!ieee80211_vif_has_in_place_reservation(
1201                                        sdata))
1202                                continue;
1203
1204                        old_ctx = ieee80211_vif_get_chanctx(sdata);
1205                        vif_chsw[i].vif = &sdata->vif;
1206                        vif_chsw[i].old_ctx = &old_ctx->conf;
1207                        vif_chsw[i].new_ctx = &ctx->conf;
1208
1209                        i++;
1210                }
1211        }
1212
1213        err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
1214                                     CHANCTX_SWMODE_SWAP_CONTEXTS);
1215
1216out:
1217        kfree(vif_chsw);
1218        return err;
1219}
1220
1221static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
1222{
1223        struct ieee80211_chanctx *ctx;
1224        int err;
1225
1226        lockdep_assert_held(&local->mtx);
1227        lockdep_assert_held(&local->chanctx_mtx);
1228
1229        list_for_each_entry(ctx, &local->chanctx_list, list) {
1230                if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1231                        continue;
1232
1233                if (!list_empty(&ctx->replace_ctx->assigned_vifs))
1234                        continue;
1235
1236                ieee80211_del_chanctx(local, ctx->replace_ctx);
1237                err = ieee80211_add_chanctx(local, ctx);
1238                if (err)
1239                        goto err;
1240        }
1241
1242        return 0;
1243
1244err:
1245        WARN_ON(ieee80211_add_chanctx(local, ctx));
1246        list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
1247                if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1248                        continue;
1249
1250                if (!list_empty(&ctx->replace_ctx->assigned_vifs))
1251                        continue;
1252
1253                ieee80211_del_chanctx(local, ctx);
1254                WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
1255        }
1256
1257        return err;
1258}
1259
1260static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
1261{
1262        struct ieee80211_sub_if_data *sdata, *sdata_tmp;
1263        struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
1264        struct ieee80211_chanctx *new_ctx = NULL;
1265        int i, err, n_assigned, n_reserved, n_ready;
1266        int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
1267
1268        lockdep_assert_held(&local->mtx);
1269        lockdep_assert_held(&local->chanctx_mtx);
1270
1271        /*
1272         * If there are 2 independent pairs of channel contexts performing
1273         * cross-switch of their vifs this code will still wait until both are
1274         * ready even though it could be possible to switch one before the
1275         * other is ready.
1276         *
1277         * For practical reasons and code simplicity just do a single huge
1278         * switch.
1279         */
1280
1281        /*
1282         * Verify if the reservation is still feasible.
1283         *  - if it's not then disconnect
1284         *  - if it is but not all vifs necessary are ready then defer
1285         */
1286
1287        list_for_each_entry(ctx, &local->chanctx_list, list) {
1288                if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1289                        continue;
1290
1291                if (WARN_ON(!ctx->replace_ctx)) {
1292                        err = -EINVAL;
1293                        goto err;
1294                }
1295
1296                if (!local->use_chanctx)
1297                        new_ctx = ctx;
1298
1299                n_ctx++;
1300
1301                n_assigned = 0;
1302                n_reserved = 0;
1303                n_ready = 0;
1304
1305                list_for_each_entry(sdata, &ctx->replace_ctx->assigned_vifs,
1306                                    assigned_chanctx_list) {
1307                        n_assigned++;
1308                        if (sdata->reserved_chanctx) {
1309                                n_reserved++;
1310                                if (sdata->reserved_ready)
1311                                        n_ready++;
1312                        }
1313                }
1314
1315                if (n_assigned != n_reserved) {
1316                        if (n_ready == n_reserved) {
1317                                wiphy_info(local->hw.wiphy,
1318                                           "channel context reservation cannot be finalized because some interfaces aren't switching\n");
1319                                err = -EBUSY;
1320                                goto err;
1321                        }
1322
1323                        return -EAGAIN;
1324                }
1325
1326                ctx->conf.radar_enabled = false;
1327                list_for_each_entry(sdata, &ctx->reserved_vifs,
1328                                    reserved_chanctx_list) {
1329                        if (ieee80211_vif_has_in_place_reservation(sdata) &&
1330                            !sdata->reserved_ready)
1331                                return -EAGAIN;
1332
1333                        old_ctx = ieee80211_vif_get_chanctx(sdata);
1334                        if (old_ctx) {
1335                                if (old_ctx->replace_state ==
1336                                    IEEE80211_CHANCTX_WILL_BE_REPLACED)
1337                                        n_vifs_switch++;
1338                                else
1339                                        n_vifs_assign++;
1340                        } else {
1341                                n_vifs_ctxless++;
1342                        }
1343
1344                        if (sdata->reserved_radar_required)
1345                                ctx->conf.radar_enabled = true;
1346                }
1347        }
1348
1349        if (WARN_ON(n_ctx == 0) ||
1350            WARN_ON(n_vifs_switch == 0 &&
1351                    n_vifs_assign == 0 &&
1352                    n_vifs_ctxless == 0) ||
1353            WARN_ON(n_ctx > 1 && !local->use_chanctx) ||
1354            WARN_ON(!new_ctx && !local->use_chanctx)) {
1355                err = -EINVAL;
1356                goto err;
1357        }
1358
1359        /*
1360         * All necessary vifs are ready. Perform the switch now depending on
1361         * reservations and driver capabilities.
1362         */
1363
1364        if (local->use_chanctx) {
1365                if (n_vifs_switch > 0) {
1366                        err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
1367                        if (err)
1368                                goto err;
1369                }
1370
1371                if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
1372                        err = ieee80211_chsw_switch_ctxs(local);
1373                        if (err)
1374                                goto err;
1375                }
1376        } else {
1377                err = ieee80211_chsw_switch_hwconf(local, new_ctx);
1378                if (err)
1379                        goto err;
1380        }
1381
1382        /*
1383         * Update all structures, values and pointers to point to new channel
1384         * context(s).
1385         */
1386
1387        i = 0;
1388        list_for_each_entry(ctx, &local->chanctx_list, list) {
1389                if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1390                        continue;
1391
1392                if (WARN_ON(!ctx->replace_ctx)) {
1393                        err = -EINVAL;
1394                        goto err;
1395                }
1396
1397                list_for_each_entry(sdata, &ctx->reserved_vifs,
1398                                    reserved_chanctx_list) {
1399                        u32 changed = 0;
1400
1401                        if (!ieee80211_vif_has_in_place_reservation(sdata))
1402                                continue;
1403
1404                        rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
1405
1406                        if (sdata->vif.type == NL80211_IFTYPE_AP)
1407                                __ieee80211_vif_copy_chanctx_to_vlans(sdata,
1408                                                                      false);
1409
1410                        ieee80211_check_fast_xmit_iface(sdata);
1411
1412                        sdata->radar_required = sdata->reserved_radar_required;
1413
1414                        if (sdata->vif.bss_conf.chandef.width !=
1415                            sdata->reserved_chandef.width)
1416                                changed = BSS_CHANGED_BANDWIDTH;
1417
1418                        ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
1419                        if (changed)
1420                                ieee80211_bss_info_change_notify(sdata,
1421                                                                 changed);
1422
1423                        ieee80211_recalc_txpower(sdata, false);
1424                }
1425
1426                ieee80211_recalc_chanctx_chantype(local, ctx);
1427                ieee80211_recalc_smps_chanctx(local, ctx);
1428                ieee80211_recalc_radar_chanctx(local, ctx);
1429                ieee80211_recalc_chanctx_min_def(local, ctx);
1430
1431                list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
1432                                         reserved_chanctx_list) {
1433                        if (ieee80211_vif_get_chanctx(sdata) != ctx)
1434                                continue;
1435
1436                        list_del(&sdata->reserved_chanctx_list);
1437                        list_move(&sdata->assigned_chanctx_list,
1438                                  &ctx->assigned_vifs);
1439                        sdata->reserved_chanctx = NULL;
1440
1441                        ieee80211_vif_chanctx_reservation_complete(sdata);
1442                }
1443
1444                /*
1445                 * This context might have been a dependency for an already
1446                 * ready re-assign reservation interface that was deferred. Do
1447                 * not propagate error to the caller though. The in-place
1448                 * reservation for originally requested interface has already
1449                 * succeeded at this point.
1450                 */
1451                list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
1452                                         reserved_chanctx_list) {
1453                        if (WARN_ON(ieee80211_vif_has_in_place_reservation(
1454                                        sdata)))
1455                                continue;
1456
1457                        if (WARN_ON(sdata->reserved_chanctx != ctx))
1458                                continue;
1459
1460                        if (!sdata->reserved_ready)
1461                                continue;
1462
1463                        if (ieee80211_vif_get_chanctx(sdata))
1464                                err = ieee80211_vif_use_reserved_reassign(
1465                                                sdata);
1466                        else
1467                                err = ieee80211_vif_use_reserved_assign(sdata);
1468
1469                        if (err) {
1470                                sdata_info(sdata,
1471                                           "failed to finalize (re-)assign reservation (err=%d)\n",
1472                                           err);
1473                                ieee80211_vif_unreserve_chanctx(sdata);
1474                                cfg80211_stop_iface(local->hw.wiphy,
1475                                                    &sdata->wdev,
1476                                                    GFP_KERNEL);
1477                        }
1478                }
1479        }
1480
1481        /*
1482         * Finally free old contexts
1483         */
1484
1485        list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
1486                if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
1487                        continue;
1488
1489                ctx->replace_ctx->replace_ctx = NULL;
1490                ctx->replace_ctx->replace_state =
1491                                IEEE80211_CHANCTX_REPLACE_NONE;
1492
1493                list_del_rcu(&ctx->list);
1494                kfree_rcu(ctx, rcu_head);
1495        }
1496
1497        return 0;
1498
1499err:
1500        list_for_each_entry(ctx, &local->chanctx_list, list) {
1501                if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
1502                        continue;
1503
1504                list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
1505                                         reserved_chanctx_list) {
1506                        ieee80211_vif_unreserve_chanctx(sdata);
1507                        ieee80211_vif_chanctx_reservation_complete(sdata);
1508                }
1509        }
1510
1511        return err;
1512}
1513
1514static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
1515{
1516        struct ieee80211_local *local = sdata->local;
1517        struct ieee80211_chanctx_conf *conf;
1518        struct ieee80211_chanctx *ctx;
1519        bool use_reserved_switch = false;
1520
1521        lockdep_assert_held(&local->chanctx_mtx);
1522
1523        conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
1524                                         lockdep_is_held(&local->chanctx_mtx));
1525        if (!conf)
1526                return;
1527
1528        ctx = container_of(conf, struct ieee80211_chanctx, conf);
1529
1530        if (sdata->reserved_chanctx) {
1531                if (sdata->reserved_chanctx->replace_state ==
1532                    IEEE80211_CHANCTX_REPLACES_OTHER &&
1533                    ieee80211_chanctx_num_reserved(local,
1534                                                   sdata->reserved_chanctx) > 1)
1535                        use_reserved_switch = true;
1536
1537                ieee80211_vif_unreserve_chanctx(sdata);
1538        }
1539
1540        ieee80211_assign_vif_chanctx(sdata, NULL);
1541        if (ieee80211_chanctx_refcount(local, ctx) == 0)
1542                ieee80211_free_chanctx(local, ctx);
1543
1544        sdata->radar_required = false;
1545
1546        /* Unreserving may ready an in-place reservation. */
1547        if (use_reserved_switch)
1548                ieee80211_vif_use_reserved_switch(local);
1549}
1550
1551int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
1552                              const struct cfg80211_chan_def *chandef,
1553                              enum ieee80211_chanctx_mode mode)
1554{
1555        struct ieee80211_local *local = sdata->local;
1556        struct ieee80211_chanctx *ctx;
1557        u8 radar_detect_width = 0;
1558        int ret;
1559
1560        lockdep_assert_held(&local->mtx);
1561
1562        WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
1563
1564        mutex_lock(&local->chanctx_mtx);
1565
1566        ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
1567                                            chandef,
1568                                            sdata->wdev.iftype);
1569        if (ret < 0)
1570                goto out;
1571        if (ret > 0)
1572                radar_detect_width = BIT(chandef->width);
1573
1574        sdata->radar_required = ret;
1575
1576        ret = ieee80211_check_combinations(sdata, chandef, mode,
1577                                           radar_detect_width);
1578        if (ret < 0)
1579                goto out;
1580
1581        __ieee80211_vif_release_channel(sdata);
1582
1583        ctx = ieee80211_find_chanctx(local, chandef, mode);
1584        if (!ctx)
1585                ctx = ieee80211_new_chanctx(local, chandef, mode);
1586        if (IS_ERR(ctx)) {
1587                ret = PTR_ERR(ctx);
1588                goto out;
1589        }
1590
1591        ieee80211_vif_update_chandef(sdata, chandef);
1592
1593        ret = ieee80211_assign_vif_chanctx(sdata, ctx);
1594        if (ret) {
1595                /* if assign fails refcount stays the same */
1596                if (ieee80211_chanctx_refcount(local, ctx) == 0)
1597                        ieee80211_free_chanctx(local, ctx);
1598                goto out;
1599        }
1600
1601        ieee80211_recalc_smps_chanctx(local, ctx);
1602        ieee80211_recalc_radar_chanctx(local, ctx);
1603 out:
1604        if (ret)
1605                sdata->radar_required = false;
1606
1607        mutex_unlock(&local->chanctx_mtx);
1608        return ret;
1609}
1610
1611int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
1612{
1613        struct ieee80211_local *local = sdata->local;
1614        struct ieee80211_chanctx *new_ctx;
1615        struct ieee80211_chanctx *old_ctx;
1616        int err;
1617
1618        lockdep_assert_held(&local->mtx);
1619        lockdep_assert_held(&local->chanctx_mtx);
1620
1621        new_ctx = sdata->reserved_chanctx;
1622        old_ctx = ieee80211_vif_get_chanctx(sdata);
1623
1624        if (WARN_ON(!new_ctx))
1625                return -EINVAL;
1626
1627        if (WARN_ON(new_ctx->replace_state ==
1628                    IEEE80211_CHANCTX_WILL_BE_REPLACED))
1629                return -EINVAL;
1630
1631        if (WARN_ON(sdata->reserved_ready))
1632                return -EINVAL;
1633
1634        sdata->reserved_ready = true;
1635
1636        if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
1637                if (old_ctx)
1638                        err = ieee80211_vif_use_reserved_reassign(sdata);
1639                else
1640                        err = ieee80211_vif_use_reserved_assign(sdata);
1641
1642                if (err)
1643                        return err;
1644        }
1645
1646        /*
1647         * In-place reservation may need to be finalized now either if:
1648         *  a) sdata is taking part in the swapping itself and is the last one
1649         *  b) sdata has switched with a re-assign reservation to an existing
1650         *     context readying in-place switching of old_ctx
1651         *
1652         * In case of (b) do not propagate the error up because the requested
1653         * sdata already switched successfully. Just spill an extra warning.
1654         * The ieee80211_vif_use_reserved_switch() already stops all necessary
1655         * interfaces upon failure.
1656         */
1657        if ((old_ctx &&
1658             old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
1659            new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
1660                err = ieee80211_vif_use_reserved_switch(local);
1661                if (err && err != -EAGAIN) {
1662                        if (new_ctx->replace_state ==
1663                            IEEE80211_CHANCTX_REPLACES_OTHER)
1664                                return err;
1665
1666                        wiphy_info(local->hw.wiphy,
1667                                   "depending in-place reservation failed (err=%d)\n",
1668                                   err);
1669                }
1670        }
1671
1672        return 0;
1673}
1674
1675int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
1676                                   const struct cfg80211_chan_def *chandef,
1677                                   u32 *changed)
1678{
1679        struct ieee80211_local *local = sdata->local;
1680        struct ieee80211_chanctx_conf *conf;
1681        struct ieee80211_chanctx *ctx;
1682        const struct cfg80211_chan_def *compat;
1683        int ret;
1684
1685        if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
1686                                     IEEE80211_CHAN_DISABLED))
1687                return -EINVAL;
1688
1689        mutex_lock(&local->chanctx_mtx);
1690        if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
1691                ret = 0;
1692                goto out;
1693        }
1694
1695        if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
1696            sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
1697                ret = -EINVAL;
1698                goto out;
1699        }
1700
1701        conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
1702                                         lockdep_is_held(&local->chanctx_mtx));
1703        if (!conf) {
1704                ret = -EINVAL;
1705                goto out;
1706        }
1707
1708        ctx = container_of(conf, struct ieee80211_chanctx, conf);
1709
1710        compat = cfg80211_chandef_compatible(&conf->def, chandef);
1711        if (!compat) {
1712                ret = -EINVAL;
1713                goto out;
1714        }
1715
1716        switch (ctx->replace_state) {
1717        case IEEE80211_CHANCTX_REPLACE_NONE:
1718                if (!ieee80211_chanctx_reserved_chandef(local, ctx, compat)) {
1719                        ret = -EBUSY;
1720                        goto out;
1721                }
1722                break;
1723        case IEEE80211_CHANCTX_WILL_BE_REPLACED:
1724                /* TODO: Perhaps the bandwidth change could be treated as a
1725                 * reservation itself? */
1726                ret = -EBUSY;
1727                goto out;
1728        case IEEE80211_CHANCTX_REPLACES_OTHER:
1729                /* channel context that is going to replace another channel
1730                 * context doesn't really exist and shouldn't be assigned
1731                 * anywhere yet */
1732                WARN_ON(1);
1733                break;
1734        }
1735
1736        ieee80211_vif_update_chandef(sdata, chandef);
1737
1738        ieee80211_recalc_chanctx_chantype(local, ctx);
1739
1740        *changed |= BSS_CHANGED_BANDWIDTH;
1741        ret = 0;
1742 out:
1743        mutex_unlock(&local->chanctx_mtx);
1744        return ret;
1745}
1746
1747void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
1748{
1749        WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
1750
1751        lockdep_assert_held(&sdata->local->mtx);
1752
1753        mutex_lock(&sdata->local->chanctx_mtx);
1754        __ieee80211_vif_release_channel(sdata);
1755        mutex_unlock(&sdata->local->chanctx_mtx);
1756}
1757
1758void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
1759{
1760        struct ieee80211_local *local = sdata->local;
1761        struct ieee80211_sub_if_data *ap;
1762        struct ieee80211_chanctx_conf *conf;
1763
1764        if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
1765                return;
1766
1767        ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
1768
1769        mutex_lock(&local->chanctx_mtx);
1770
1771        conf = rcu_dereference_protected(ap->vif.chanctx_conf,
1772                                         lockdep_is_held(&local->chanctx_mtx));
1773        rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
1774        mutex_unlock(&local->chanctx_mtx);
1775}
1776
1777void ieee80211_iter_chan_contexts_atomic(
1778        struct ieee80211_hw *hw,
1779        void (*iter)(struct ieee80211_hw *hw,
1780                     struct ieee80211_chanctx_conf *chanctx_conf,
1781                     void *data),
1782        void *iter_data)
1783{
1784        struct ieee80211_local *local = hw_to_local(hw);
1785        struct ieee80211_chanctx *ctx;
1786
1787        rcu_read_lock();
1788        list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
1789                if (ctx->driver_present)
1790                        iter(hw, &ctx->conf, iter_data);
1791        rcu_read_unlock();
1792}
1793EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);
1794