aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/main.c22
-rw-r--r--net/mac80211/mlme.c12
-rw-r--r--net/mac80211/vht.c98
4 files changed, 135 insertions, 1 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 388580a1bada..8da53a067306 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -479,6 +479,8 @@ struct ieee80211_if_managed {
479 479
480 struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ 480 struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */
481 struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ 481 struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */
482 struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */
483 struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */
482}; 484};
483 485
484struct ieee80211_if_ibss { 486struct ieee80211_if_ibss {
@@ -1441,6 +1443,8 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta);
1441void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, 1443void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
1442 struct sta_info *sta, u8 opmode, 1444 struct sta_info *sta, u8 opmode,
1443 enum ieee80211_band band, bool nss_only); 1445 enum ieee80211_band band, bool nss_only);
1446void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
1447 struct ieee80211_sta_vht_cap *vht_cap);
1444 1448
1445/* Spectrum management */ 1449/* Spectrum management */
1446void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, 1450void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1a8591b77a13..78554724f815 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -501,6 +501,27 @@ static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = {
501 }, 501 },
502}; 502};
503 503
504static const struct ieee80211_vht_cap mac80211_vht_capa_mod_mask = {
505 .vht_cap_info =
506 cpu_to_le32(IEEE80211_VHT_CAP_RXLDPC |
507 IEEE80211_VHT_CAP_SHORT_GI_80 |
508 IEEE80211_VHT_CAP_SHORT_GI_160 |
509 IEEE80211_VHT_CAP_RXSTBC_1 |
510 IEEE80211_VHT_CAP_RXSTBC_2 |
511 IEEE80211_VHT_CAP_RXSTBC_3 |
512 IEEE80211_VHT_CAP_RXSTBC_4 |
513 IEEE80211_VHT_CAP_TXSTBC |
514 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
515 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
516 IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN |
517 IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
518 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK),
519 .supp_mcs = {
520 .rx_mcs_map = cpu_to_le16(~0),
521 .tx_mcs_map = cpu_to_le16(~0),
522 },
523};
524
504static const u8 extended_capabilities[] = { 525static const u8 extended_capabilities[] = {
505 0, 0, 0, 0, 0, 0, 0, 526 0, 0, 0, 0, 0, 0, 0,
506 WLAN_EXT_CAPA8_OPMODE_NOTIF, 527 WLAN_EXT_CAPA8_OPMODE_NOTIF,
@@ -609,6 +630,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
609 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; 630 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
610 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; 631 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
611 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; 632 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
633 wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
612 634
613 INIT_LIST_HEAD(&local->interfaces); 635 INIT_LIST_HEAD(&local->interfaces);
614 636
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 141577412d84..9784622cd3d1 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -609,6 +609,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
609 BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); 609 BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));
610 610
611 memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); 611 memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
612 ieee80211_apply_vhtcap_overrides(sdata, &vht_cap);
612 613
613 /* determine capability flags */ 614 /* determine capability flags */
614 cap = vht_cap.cap; 615 cap = vht_cap.cap;
@@ -1802,9 +1803,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1802 sdata->vif.bss_conf.p2p_ctwindow = 0; 1803 sdata->vif.bss_conf.p2p_ctwindow = 0;
1803 sdata->vif.bss_conf.p2p_oppps = false; 1804 sdata->vif.bss_conf.p2p_oppps = false;
1804 1805
1805 /* on the next assoc, re-program HT parameters */ 1806 /* on the next assoc, re-program HT/VHT parameters */
1806 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); 1807 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
1807 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); 1808 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1809 memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
1810 memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
1808 1811
1809 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; 1812 sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
1810 1813
@@ -4071,6 +4074,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4071 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; 4074 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
4072 } 4075 }
4073 4076
4077 if (req->flags & ASSOC_REQ_DISABLE_VHT)
4078 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
4079
4074 /* Also disable HT if we don't support it or the AP doesn't use WMM */ 4080 /* Also disable HT if we don't support it or the AP doesn't use WMM */
4075 sband = local->hw.wiphy->bands[req->bss->channel->band]; 4081 sband = local->hw.wiphy->bands[req->bss->channel->band];
4076 if (!sband->ht_cap.ht_supported || 4082 if (!sband->ht_cap.ht_supported ||
@@ -4094,6 +4100,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4094 memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, 4100 memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
4095 sizeof(ifmgd->ht_capa_mask)); 4101 sizeof(ifmgd->ht_capa_mask));
4096 4102
4103 memcpy(&ifmgd->vht_capa, &req->vht_capa, sizeof(ifmgd->vht_capa));
4104 memcpy(&ifmgd->vht_capa_mask, &req->vht_capa_mask,
4105 sizeof(ifmgd->vht_capa_mask));
4106
4097 if (req->ie && req->ie_len) { 4107 if (req->ie && req->ie_len) {
4098 memcpy(assoc_data->ie, req->ie, req->ie_len); 4108 memcpy(assoc_data->ie, req->ie, req->ie_len);
4099 assoc_data->ie_len = req->ie_len; 4109 assoc_data->ie_len = req->ie_len;
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index a2c2258bc84e..cacc1c74556a 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -13,6 +13,104 @@
13#include "rate.h" 13#include "rate.h"
14 14
15 15
16static void __check_vhtcap_disable(struct ieee80211_sub_if_data *sdata,
17 struct ieee80211_sta_vht_cap *vht_cap,
18 u32 flag)
19{
20 __le32 le_flag = cpu_to_le32(flag);
21
22 if (sdata->u.mgd.vht_capa_mask.vht_cap_info & le_flag &&
23 !(sdata->u.mgd.vht_capa.vht_cap_info & le_flag))
24 vht_cap->cap &= ~flag;
25}
26
27void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
28 struct ieee80211_sta_vht_cap *vht_cap)
29{
30 int i;
31 u16 rxmcs_mask, rxmcs_cap, rxmcs_n, txmcs_mask, txmcs_cap, txmcs_n;
32
33 if (!vht_cap->vht_supported)
34 return;
35
36 if (sdata->vif.type != NL80211_IFTYPE_STATION)
37 return;
38
39 __check_vhtcap_disable(sdata, vht_cap,
40 IEEE80211_VHT_CAP_RXLDPC);
41 __check_vhtcap_disable(sdata, vht_cap,
42 IEEE80211_VHT_CAP_SHORT_GI_80);
43 __check_vhtcap_disable(sdata, vht_cap,
44 IEEE80211_VHT_CAP_SHORT_GI_160);
45 __check_vhtcap_disable(sdata, vht_cap,
46 IEEE80211_VHT_CAP_TXSTBC);
47 __check_vhtcap_disable(sdata, vht_cap,
48 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
49 __check_vhtcap_disable(sdata, vht_cap,
50 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
51 __check_vhtcap_disable(sdata, vht_cap,
52 IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN);
53 __check_vhtcap_disable(sdata, vht_cap,
54 IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN);
55
56 /* Allow user to decrease AMPDU length exponent */
57 if (sdata->u.mgd.vht_capa_mask.vht_cap_info &
58 cpu_to_le32(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK)) {
59 u32 cap, n;
60
61 n = le32_to_cpu(sdata->u.mgd.vht_capa.vht_cap_info) &
62 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
63 n >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
64 cap = vht_cap->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
65 cap >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
66
67 if (n < cap) {
68 vht_cap->cap &=
69 ~IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
70 vht_cap->cap |=
71 n << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
72 }
73 }
74
75 /* Allow the user to decrease MCSes */
76 rxmcs_mask =
77 le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.rx_mcs_map);
78 rxmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.rx_mcs_map);
79 rxmcs_n &= rxmcs_mask;
80 rxmcs_cap = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
81
82 txmcs_mask =
83 le16_to_cpu(sdata->u.mgd.vht_capa_mask.supp_mcs.tx_mcs_map);
84 txmcs_n = le16_to_cpu(sdata->u.mgd.vht_capa.supp_mcs.tx_mcs_map);
85 txmcs_n &= txmcs_mask;
86 txmcs_cap = le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map);
87 for (i = 0; i < 8; i++) {
88 u8 m, n, c;
89
90 m = (rxmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
91 n = (rxmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
92 c = (rxmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
93
94 if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) ||
95 n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) {
96 rxmcs_cap &= ~(3 << 2*i);
97 rxmcs_cap |= (rxmcs_n & (3 << 2*i));
98 }
99
100 m = (txmcs_mask >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
101 n = (txmcs_n >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
102 c = (txmcs_cap >> 2*i) & IEEE80211_VHT_MCS_NOT_SUPPORTED;
103
104 if (m && ((c != IEEE80211_VHT_MCS_NOT_SUPPORTED && n < c) ||
105 n == IEEE80211_VHT_MCS_NOT_SUPPORTED)) {
106 txmcs_cap &= ~(3 << 2*i);
107 txmcs_cap |= (txmcs_n & (3 << 2*i));
108 }
109 }
110 vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(rxmcs_cap);
111 vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(txmcs_cap);
112}
113
16void 114void
17ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, 115ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
18 struct ieee80211_supported_band *sband, 116 struct ieee80211_supported_band *sband,