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