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