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