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