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