linux/net/mac80211/vht.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * VHT handling
   4 *
   5 * Portions of this file
   6 * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
   7 * Copyright (C) 2018 - 2020 Intel Corporation
   8 */
   9
  10#include <linux/ieee80211.h>
  11#include <linux/export.h>
  12#include <net/mac80211.h>
  13#include "ieee80211_i.h"
  14#include "rate.h"
  15
  16
  17static void __check_vhtcap_disable(struct ieee80211_sub_if_data *sdata,
  18                                   struct ieee80211_sta_vht_cap *vht_cap,
  19                                   u32 flag)
  20{
  21        __le32 le_flag = cpu_to_le32(flag);
  22
  23        if (sdata->u.mgd.vht_capa_mask.vht_cap_info & le_flag &&
  24            !(sdata->u.mgd.vht_capa.vht_cap_info & le_flag))
  25                vht_cap->cap &= ~flag;
  26}
  27
  28void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
  29                                      struct ieee80211_sta_vht_cap *vht_cap)
  30{
  31        int i;
  32        u16 rxmcs_mask, rxmcs_cap, rxmcs_n, txmcs_mask, txmcs_cap, txmcs_n;
  33
  34        if (!vht_cap->vht_supported)
  35                return;
  36
  37        if (sdata->vif.type != NL80211_IFTYPE_STATION)
  38                return;
  39
  40        __check_vhtcap_disable(sdata, vht_cap,
  41                               IEEE80211_VHT_CAP_RXLDPC);
  42        __check_vhtcap_disable(sdata, vht_cap,
  43                               IEEE80211_VHT_CAP_SHORT_GI_80);
  44        __check_vhtcap_disable(sdata, vht_cap,
  45                               IEEE80211_VHT_CAP_SHORT_GI_160);
  46        __check_vhtcap_disable(sdata, vht_cap,
  47                               IEEE80211_VHT_CAP_TXSTBC);
  48        __check_vhtcap_disable(sdata, vht_cap,
  49                               IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
  50        __check_vhtcap_disable(sdata, vht_cap,
  51                               IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
  52        __check_vhtcap_disable(sdata, vht_cap,
  53                               IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN);
  54        __check_vhtcap_disable(sdata, vht_cap,
  55                               IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN);
  56
  57        /* Allow user to decrease AMPDU length exponent */
  58        if (sdata->u.mgd.vht_capa_mask.vht_cap_info &
  59            cpu_to_le32(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK)) {
  60                u32 cap, n;
  61
  62                n = le32_to_cpu(sdata->u.mgd.vht_capa.vht_cap_info) &
  63                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
  64                n >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
  65                cap = vht_cap->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
  66                cap >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
  67
  68                if (n < cap) {
  69                        vht_cap->cap &=
  70                                ~IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
  71                        vht_cap->cap |=
  72                                n << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
  73                }
  74        }
  75
  76        /* Allow the user to decrease MCSes */
  77        rxmcs_mask =
  78                le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.rx_mcs_map);
  79        rxmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.rx_mcs_map);
  80        rxmcs_n &= rxmcs_mask;
  81        rxmcs_cap = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
  82
  83        txmcs_mask =
  84                le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.tx_mcs_map);
  85        txmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.tx_mcs_map);
  86        txmcs_n &= txmcs_mask;
  87        txmcs_cap = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
  88        for (i = 0; i < 8; i++) {
  89                u8 m, n, c;
  90
  91                m = (rxmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
  92                n = (rxmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
  93                c = (rxmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
  94
  95                if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) ||
  96                          n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) {
  97                        rxmcs_cap &= ~(3 << 2*i);
  98                        rxmcs_cap |= (rxmcs_n & (3 << 2*i));
  99                }
 100
 101                m = (txmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 102                n = (txmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 103                c = (txmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 104
 105                if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) ||
 106                          n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) {
 107                        txmcs_cap &= ~(3 << 2*i);
 108                        txmcs_cap |= (txmcs_n & (3 << 2*i));
 109                }
 110        }
 111        vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_cap);
 112        vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_cap);
 113}
 114
 115void
 116ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 117                                    struct ieee80211_supported_band *sband,
 118                                    const struct ieee80211_vht_cap *vht_cap_ie,
 119                                    struct sta_info *sta)
 120{
 121        struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
 122        struct ieee80211_sta_vht_cap own_cap;
 123        u32 cap_info, i;
 124        bool have_80mhz;
 125
 126        memset(vht_cap, 0, sizeof(*vht_cap));
 127
 128        if (!sta->sta.ht_cap.ht_supported)
 129                return;
 130
 131        if (!vht_cap_ie || !sband->vht_cap.vht_supported)
 132                return;
 133
 134        /* Allow VHT if at least one channel on the sband supports 80 MHz */
 135        have_80mhz = false;
 136        for (i = 0; i < sband->n_channels; i++) {
 137                if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
 138                                                IEEE80211_CHAN_NO_80MHZ))
 139                        continue;
 140
 141                have_80mhz = true;
 142                break;
 143        }
 144
 145        if (!have_80mhz)
 146                return;
 147
 148        /*
 149         * A VHT STA must support 40 MHz, but if we verify that here
 150         * then we break a few things - some APs (e.g. Netgear R6300v2
 151         * and others based on the BCM4360 chipset) will unset this
 152         * capability bit when operating in 20 MHz.
 153         */
 154
 155        vht_cap->vht_supported = true;
 156
 157        own_cap = sband->vht_cap;
 158        /*
 159         * If user has specified capability overrides, take care
 160         * of that if the station we're setting up is the AP that
 161         * we advertised a restricted capability set to. Override
 162         * our own capabilities and then use those below.
 163         */
 164        if (sdata->vif.type == NL80211_IFTYPE_STATION &&
 165            !test_sta_flag(sta, WLAN_STA_TDLS_PEER))
 166                ieee80211_apply_vhtcap_overrides(sdata, &own_cap);
 167
 168        /* take some capabilities as-is */
 169        cap_info = le32_to_cpu(vht_cap_ie->vht_cap_info);
 170        vht_cap->cap = cap_info;
 171        vht_cap->cap &= IEEE80211_VHT_CAP_RXLDPC |
 172                        IEEE80211_VHT_CAP_VHT_TXOP_PS |
 173                        IEEE80211_VHT_CAP_HTC_VHT |
 174                        IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
 175                        IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB |
 176                        IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB |
 177                        IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
 178                        IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
 179
 180        vht_cap->cap |= min_t(u32, cap_info & IEEE80211_VHT_CAP_MAX_MPDU_MASK,
 181                              own_cap.cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK);
 182
 183        /* and some based on our own capabilities */
 184        switch (own_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
 185        case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
 186                vht_cap->cap |= cap_info &
 187                                IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
 188                break;
 189        case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
 190                vht_cap->cap |= cap_info &
 191                                IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
 192                break;
 193        default:
 194                /* nothing */
 195                break;
 196        }
 197
 198        /* symmetric capabilities */
 199        vht_cap->cap |= cap_info & own_cap.cap &
 200                        (IEEE80211_VHT_CAP_SHORT_GI_80 |
 201                         IEEE80211_VHT_CAP_SHORT_GI_160);
 202
 203        /* remaining ones */
 204        if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
 205                vht_cap->cap |= cap_info &
 206                                (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
 207                                 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK);
 208
 209        if (own_cap.cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
 210                vht_cap->cap |= cap_info &
 211                                (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
 212                                 IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK);
 213
 214        if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
 215                vht_cap->cap |= cap_info &
 216                                IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
 217
 218        if (own_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
 219                vht_cap->cap |= cap_info &
 220                                IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
 221
 222        if (own_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
 223                vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_RXSTBC_MASK;
 224
 225        if (own_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
 226                vht_cap->cap |= cap_info & IEEE80211_VHT_CAP_TXSTBC;
 227
 228        /* Copy peer MCS info, the driver might need them. */
 229        memcpy(&vht_cap->vht_mcs, &vht_cap_ie->supp_mcs,
 230               sizeof(struct ieee80211_vht_mcs_info));
 231
 232        /* copy EXT_NSS_BW Support value or remove the capability */
 233        if (ieee80211_hw_check(&sdata->local->hw, SUPPORTS_VHT_EXT_NSS_BW))
 234                vht_cap->cap |= (cap_info & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK);
 235        else
 236                vht_cap->vht_mcs.tx_highest &=
 237                        ~cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
 238
 239        /* but also restrict MCSes */
 240        for (i = 0; i < 8; i++) {
 241                u16 own_rx, own_tx, peer_rx, peer_tx;
 242
 243                own_rx = le16_to_cpu(own_cap.vht_mcs.rx_mcs_map);
 244                own_rx = (own_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 245
 246                own_tx = le16_to_cpu(own_cap.vht_mcs.tx_mcs_map);
 247                own_tx = (own_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 248
 249                peer_rx = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
 250                peer_rx = (peer_rx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 251
 252                peer_tx = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
 253                peer_tx = (peer_tx >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 254
 255                if (peer_tx != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
 256                        if (own_rx == IEEE80211_VHT_MCS_NOT_SUPPORTED)
 257                                peer_tx = IEEE80211_VHT_MCS_NOT_SUPPORTED;
 258                        else if (own_rx < peer_tx)
 259                                peer_tx = own_rx;
 260                }
 261
 262                if (peer_rx != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
 263                        if (own_tx == IEEE80211_VHT_MCS_NOT_SUPPORTED)
 264                                peer_rx = IEEE80211_VHT_MCS_NOT_SUPPORTED;
 265                        else if (own_tx < peer_rx)
 266                                peer_rx = own_tx;
 267                }
 268
 269                vht_cap->vht_mcs.rx_mcs_map &=
 270                        ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2);
 271                vht_cap->vht_mcs.rx_mcs_map |= cpu_to_le16(peer_rx << i * 2);
 272
 273                vht_cap->vht_mcs.tx_mcs_map &=
 274                        ~cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << i * 2);
 275                vht_cap->vht_mcs.tx_mcs_map |= cpu_to_le16(peer_tx << i * 2);
 276        }
 277
 278        /*
 279         * This is a workaround for VHT-enabled STAs which break the spec
 280         * and have the VHT-MCS Rx map filled in with value 3 for all eight
 281         * spacial streams, an example is AR9462.
 282         *
 283         * As per spec, in section 22.1.1 Introduction to the VHT PHY
 284         * A VHT STA shall support at least single spactial stream VHT-MCSs
 285         * 0 to 7 (transmit and receive) in all supported channel widths.
 286         */
 287        if (vht_cap->vht_mcs.rx_mcs_map == cpu_to_le16(0xFFFF)) {
 288                vht_cap->vht_supported = false;
 289                sdata_info(sdata, "Ignoring VHT IE from %pM due to invalid rx_mcs_map\n",
 290                           sta->addr);
 291                return;
 292        }
 293
 294        /* finally set up the bandwidth */
 295        switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
 296        case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
 297        case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
 298                sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 299                break;
 300        default:
 301                sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
 302
 303                if (!(vht_cap->vht_mcs.tx_highest &
 304                                cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))
 305                        break;
 306
 307                /*
 308                 * If this is non-zero, then it does support 160 MHz after all,
 309                 * in one form or the other. We don't distinguish here (or even
 310                 * above) between 160 and 80+80 yet.
 311                 */
 312                if (cap_info & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)
 313                        sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 314        }
 315
 316        sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta);
 317
 318        switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
 319        case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
 320                sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454;
 321                break;
 322        case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
 323                sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_7991;
 324                break;
 325        case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
 326        default:
 327                sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_3895;
 328                break;
 329        }
 330}
 331
 332/* FIXME: move this to some better location - parses HE now */
 333enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
 334{
 335        struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
 336        struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap;
 337        u32 cap_width;
 338
 339        if (he_cap->has_he) {
 340                u8 info = he_cap->he_cap_elem.phy_cap_info[0];
 341
 342                if (sta->sdata->vif.bss_conf.chandef.chan->band ==
 343                                NL80211_BAND_2GHZ) {
 344                        if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)
 345                                return IEEE80211_STA_RX_BW_40;
 346                        else
 347                                return IEEE80211_STA_RX_BW_20;
 348                }
 349
 350                if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G ||
 351                    info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
 352                        return IEEE80211_STA_RX_BW_160;
 353                else if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)
 354                        return IEEE80211_STA_RX_BW_80;
 355
 356                return IEEE80211_STA_RX_BW_20;
 357        }
 358
 359        if (!vht_cap->vht_supported)
 360                return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
 361                                IEEE80211_STA_RX_BW_40 :
 362                                IEEE80211_STA_RX_BW_20;
 363
 364        cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
 365
 366        if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
 367            cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
 368                return IEEE80211_STA_RX_BW_160;
 369
 370        /*
 371         * If this is non-zero, then it does support 160 MHz after all,
 372         * in one form or the other. We don't distinguish here (or even
 373         * above) between 160 and 80+80 yet.
 374         */
 375        if (vht_cap->cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)
 376                return IEEE80211_STA_RX_BW_160;
 377
 378        return IEEE80211_STA_RX_BW_80;
 379}
 380
 381enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta)
 382{
 383        struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
 384        u32 cap_width;
 385
 386        if (!vht_cap->vht_supported) {
 387                if (!sta->sta.ht_cap.ht_supported)
 388                        return NL80211_CHAN_WIDTH_20_NOHT;
 389
 390                return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
 391                                NL80211_CHAN_WIDTH_40 : NL80211_CHAN_WIDTH_20;
 392        }
 393
 394        cap_width = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
 395
 396        if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
 397                return NL80211_CHAN_WIDTH_160;
 398        else if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
 399                return NL80211_CHAN_WIDTH_80P80;
 400
 401        return NL80211_CHAN_WIDTH_80;
 402}
 403
 404enum nl80211_chan_width
 405ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta)
 406{
 407        enum ieee80211_sta_rx_bandwidth cur_bw = sta->sta.bandwidth;
 408        struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap;
 409        u32 cap_width;
 410
 411        switch (cur_bw) {
 412        case IEEE80211_STA_RX_BW_20:
 413                if (!sta->sta.ht_cap.ht_supported)
 414                        return NL80211_CHAN_WIDTH_20_NOHT;
 415                else
 416                        return NL80211_CHAN_WIDTH_20;
 417        case IEEE80211_STA_RX_BW_40:
 418                return NL80211_CHAN_WIDTH_40;
 419        case IEEE80211_STA_RX_BW_80:
 420                return NL80211_CHAN_WIDTH_80;
 421        case IEEE80211_STA_RX_BW_160:
 422                cap_width =
 423                        vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
 424
 425                if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
 426                        return NL80211_CHAN_WIDTH_160;
 427
 428                return NL80211_CHAN_WIDTH_80P80;
 429        default:
 430                return NL80211_CHAN_WIDTH_20;
 431        }
 432}
 433
 434enum ieee80211_sta_rx_bandwidth
 435ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
 436{
 437        switch (width) {
 438        case NL80211_CHAN_WIDTH_20_NOHT:
 439        case NL80211_CHAN_WIDTH_20:
 440                return IEEE80211_STA_RX_BW_20;
 441        case NL80211_CHAN_WIDTH_40:
 442                return IEEE80211_STA_RX_BW_40;
 443        case NL80211_CHAN_WIDTH_80:
 444                return IEEE80211_STA_RX_BW_80;
 445        case NL80211_CHAN_WIDTH_160:
 446        case NL80211_CHAN_WIDTH_80P80:
 447                return IEEE80211_STA_RX_BW_160;
 448        default:
 449                WARN_ON_ONCE(1);
 450                return IEEE80211_STA_RX_BW_20;
 451        }
 452}
 453
 454/* FIXME: rename/move - this deals with everything not just VHT */
 455enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
 456{
 457        struct ieee80211_sub_if_data *sdata = sta->sdata;
 458        enum ieee80211_sta_rx_bandwidth bw;
 459        enum nl80211_chan_width bss_width = sdata->vif.bss_conf.chandef.width;
 460
 461        bw = ieee80211_sta_cap_rx_bw(sta);
 462        bw = min(bw, sta->cur_max_bandwidth);
 463
 464        /* Don't consider AP's bandwidth for TDLS peers, section 11.23.1 of
 465         * IEEE80211-2016 specification makes higher bandwidth operation
 466         * possible on the TDLS link if the peers have wider bandwidth
 467         * capability.
 468         *
 469         * However, in this case, and only if the TDLS peer is authorized,
 470         * limit to the tdls_chandef so that the configuration here isn't
 471         * wider than what's actually requested on the channel context.
 472         */
 473        if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
 474            test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) &&
 475            test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
 476            sta->tdls_chandef.chan)
 477                bw = min(bw, ieee80211_chan_width_to_rx_bw(sta->tdls_chandef.width));
 478        else
 479                bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width));
 480
 481        return bw;
 482}
 483
 484void ieee80211_sta_set_rx_nss(struct sta_info *sta)
 485{
 486        u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, rx_nss;
 487        bool support_160;
 488
 489        /* if we received a notification already don't overwrite it */
 490        if (sta->sta.rx_nss)
 491                return;
 492
 493        if (sta->sta.he_cap.has_he) {
 494                int i;
 495                u8 rx_mcs_80 = 0, rx_mcs_160 = 0;
 496                const struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap;
 497                u16 mcs_160_map =
 498                        le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
 499                u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
 500
 501                for (i = 7; i >= 0; i--) {
 502                        u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
 503
 504                        if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
 505                                rx_mcs_160 = i + 1;
 506                                break;
 507                        }
 508                }
 509                for (i = 7; i >= 0; i--) {
 510                        u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
 511
 512                        if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
 513                                rx_mcs_80 = i + 1;
 514                                break;
 515                        }
 516                }
 517
 518                support_160 = he_cap->he_cap_elem.phy_cap_info[0] &
 519                              IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
 520
 521                if (support_160)
 522                        he_rx_nss = min(rx_mcs_80, rx_mcs_160);
 523                else
 524                        he_rx_nss = rx_mcs_80;
 525        }
 526
 527        if (sta->sta.ht_cap.ht_supported) {
 528                if (sta->sta.ht_cap.mcs.rx_mask[0])
 529                        ht_rx_nss++;
 530                if (sta->sta.ht_cap.mcs.rx_mask[1])
 531                        ht_rx_nss++;
 532                if (sta->sta.ht_cap.mcs.rx_mask[2])
 533                        ht_rx_nss++;
 534                if (sta->sta.ht_cap.mcs.rx_mask[3])
 535                        ht_rx_nss++;
 536                /* FIXME: consider rx_highest? */
 537        }
 538
 539        if (sta->sta.vht_cap.vht_supported) {
 540                int i;
 541                u16 rx_mcs_map;
 542
 543                rx_mcs_map = le16_to_cpu(sta->sta.vht_cap.vht_mcs.rx_mcs_map);
 544
 545                for (i = 7; i >= 0; i--) {
 546                        u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
 547
 548                        if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
 549                                vht_rx_nss = i + 1;
 550                                break;
 551                        }
 552                }
 553                /* FIXME: consider rx_highest? */
 554        }
 555
 556        rx_nss = max(vht_rx_nss, ht_rx_nss);
 557        rx_nss = max(he_rx_nss, rx_nss);
 558        sta->sta.rx_nss = max_t(u8, 1, rx_nss);
 559}
 560
 561u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 562                                  struct sta_info *sta, u8 opmode,
 563                                  enum nl80211_band band)
 564{
 565        enum ieee80211_sta_rx_bandwidth new_bw;
 566        struct sta_opmode_info sta_opmode = {};
 567        u32 changed = 0;
 568        u8 nss;
 569
 570        /* ignore - no support for BF yet */
 571        if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)
 572                return 0;
 573
 574        nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK;
 575        nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
 576        nss += 1;
 577
 578        if (sta->sta.rx_nss != nss) {
 579                sta->sta.rx_nss = nss;
 580                sta_opmode.rx_nss = nss;
 581                changed |= IEEE80211_RC_NSS_CHANGED;
 582                sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
 583        }
 584
 585        switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
 586        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
 587                /* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
 588                sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
 589                break;
 590        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ:
 591                /* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
 592                sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
 593                break;
 594        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ:
 595                if (opmode & IEEE80211_OPMODE_NOTIF_BW_160_80P80)
 596                        sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 597                else
 598                        sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
 599                break;
 600        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ:
 601                /* legacy only, no longer used by newer spec */
 602                sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 603                break;
 604        }
 605
 606        new_bw = ieee80211_sta_cur_vht_bw(sta);
 607        if (new_bw != sta->sta.bandwidth) {
 608                sta->sta.bandwidth = new_bw;
 609                sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta);
 610                changed |= IEEE80211_RC_BW_CHANGED;
 611                sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
 612        }
 613
 614        if (sta_opmode.changed)
 615                cfg80211_sta_opmode_change_notify(sdata->dev, sta->addr,
 616                                                  &sta_opmode, GFP_KERNEL);
 617
 618        return changed;
 619}
 620
 621void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
 622                                 struct ieee80211_mgmt *mgmt)
 623{
 624        struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 625
 626        if (!sdata->vif.mu_mimo_owner)
 627                return;
 628
 629        if (!memcmp(mgmt->u.action.u.vht_group_notif.position,
 630                    bss_conf->mu_group.position, WLAN_USER_POSITION_LEN) &&
 631            !memcmp(mgmt->u.action.u.vht_group_notif.membership,
 632                    bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN))
 633                return;
 634
 635        memcpy(bss_conf->mu_group.membership,
 636               mgmt->u.action.u.vht_group_notif.membership,
 637               WLAN_MEMBERSHIP_LEN);
 638        memcpy(bss_conf->mu_group.position,
 639               mgmt->u.action.u.vht_group_notif.position,
 640               WLAN_USER_POSITION_LEN);
 641
 642        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS);
 643}
 644
 645void ieee80211_update_mu_groups(struct ieee80211_vif *vif,
 646                                const u8 *membership, const u8 *position)
 647{
 648        struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 649
 650        if (WARN_ON_ONCE(!vif->mu_mimo_owner))
 651                return;
 652
 653        memcpy(bss_conf->mu_group.membership, membership, WLAN_MEMBERSHIP_LEN);
 654        memcpy(bss_conf->mu_group.position, position, WLAN_USER_POSITION_LEN);
 655}
 656EXPORT_SYMBOL_GPL(ieee80211_update_mu_groups);
 657
 658void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 659                                 struct sta_info *sta, u8 opmode,
 660                                 enum nl80211_band band)
 661{
 662        struct ieee80211_local *local = sdata->local;
 663        struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
 664
 665        u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
 666
 667        if (changed > 0) {
 668                ieee80211_recalc_min_chandef(sdata);
 669                rate_control_rate_update(local, sband, sta, changed);
 670        }
 671}
 672
 673void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
 674                                     u16 vht_mask[NL80211_VHT_NSS_MAX])
 675{
 676        int i;
 677        u16 mask, cap = le16_to_cpu(vht_cap);
 678
 679        for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
 680                mask = (cap >> i * 2) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
 681                switch (mask) {
 682                case IEEE80211_VHT_MCS_SUPPORT_0_7:
 683                        vht_mask[i] = 0x00FF;
 684                        break;
 685                case IEEE80211_VHT_MCS_SUPPORT_0_8:
 686                        vht_mask[i] = 0x01FF;
 687                        break;
 688                case IEEE80211_VHT_MCS_SUPPORT_0_9:
 689                        vht_mask[i] = 0x03FF;
 690                        break;
 691                case IEEE80211_VHT_MCS_NOT_SUPPORTED:
 692                default:
 693                        vht_mask[i] = 0;
 694                        break;
 695                }
 696        }
 697}
 698