diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 96 |
1 files changed, 61 insertions, 35 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 36016363d225..b0fddb7de549 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -35,8 +35,6 @@ | |||
35 | #include "debugfs.h" | 35 | #include "debugfs.h" |
36 | #include "debugfs_netdev.h" | 36 | #include "debugfs_netdev.h" |
37 | 37 | ||
38 | #define SUPP_MCS_SET_LEN 16 | ||
39 | |||
40 | /* | 38 | /* |
41 | * For seeing transmitted packets on monitor interfaces | 39 | * For seeing transmitted packets on monitor interfaces |
42 | * we have a radiotap header too. | 40 | * we have a radiotap header too. |
@@ -1068,56 +1066,84 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | |||
1068 | struct ieee80211_supported_band *sband; | 1066 | struct ieee80211_supported_band *sband; |
1069 | struct ieee80211_ht_info ht_conf; | 1067 | struct ieee80211_ht_info ht_conf; |
1070 | struct ieee80211_ht_bss_info ht_bss_conf; | 1068 | struct ieee80211_ht_bss_info ht_bss_conf; |
1071 | int i; | ||
1072 | u32 changed = 0; | 1069 | u32 changed = 0; |
1070 | int i; | ||
1071 | u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS; | ||
1072 | u8 tx_mcs_set_cap; | ||
1073 | 1073 | ||
1074 | sband = local->hw.wiphy->bands[conf->channel->band]; | 1074 | sband = local->hw.wiphy->bands[conf->channel->band]; |
1075 | 1075 | ||
1076 | memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); | ||
1077 | memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); | ||
1078 | |||
1076 | /* HT is not supported */ | 1079 | /* HT is not supported */ |
1077 | if (!sband->ht_info.ht_supported) { | 1080 | if (!sband->ht_info.ht_supported) { |
1078 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | 1081 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; |
1079 | return 0; | 1082 | goto out; |
1080 | } | 1083 | } |
1081 | 1084 | ||
1082 | memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); | 1085 | /* disable HT */ |
1083 | memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); | 1086 | if (!enable_ht) { |
1084 | 1087 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) | |
1085 | if (enable_ht) { | ||
1086 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) | ||
1087 | changed |= BSS_CHANGED_HT; | 1088 | changed |= BSS_CHANGED_HT; |
1089 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1090 | conf->ht_conf.ht_supported = 0; | ||
1091 | goto out; | ||
1092 | } | ||
1088 | 1093 | ||
1089 | conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1090 | ht_conf.ht_supported = 1; | ||
1091 | 1094 | ||
1092 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; | 1095 | if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) |
1093 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); | 1096 | changed |= BSS_CHANGED_HT; |
1094 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; | ||
1095 | 1097 | ||
1096 | for (i = 0; i < SUPP_MCS_SET_LEN; i++) | 1098 | conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; |
1097 | ht_conf.supp_mcs_set[i] = | 1099 | ht_conf.ht_supported = 1; |
1098 | sband->ht_info.supp_mcs_set[i] & | ||
1099 | req_ht_cap->supp_mcs_set[i]; | ||
1100 | 1100 | ||
1101 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | 1101 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; |
1102 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | 1102 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); |
1103 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | 1103 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; |
1104 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | ||
1105 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | ||
1106 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | ||
1104 | 1107 | ||
1105 | ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; | 1108 | ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; |
1106 | ht_conf.ampdu_density = req_ht_cap->ampdu_density; | 1109 | ht_conf.ampdu_density = req_ht_cap->ampdu_density; |
1107 | 1110 | ||
1108 | /* if bss configuration changed store the new one */ | 1111 | /* Bits 96-100 */ |
1109 | if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || | 1112 | tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12]; |
1110 | memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { | ||
1111 | changed |= BSS_CHANGED_HT; | ||
1112 | memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); | ||
1113 | memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); | ||
1114 | } | ||
1115 | } else { | ||
1116 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) | ||
1117 | changed |= BSS_CHANGED_HT; | ||
1118 | conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; | ||
1119 | } | ||
1120 | 1113 | ||
1114 | /* configure suppoerted Tx MCS according to requested MCS | ||
1115 | * (based in most cases on Rx capabilities of peer) and self | ||
1116 | * Tx MCS capabilities (as defined by low level driver HW | ||
1117 | * Tx capabilities) */ | ||
1118 | if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED)) | ||
1119 | goto check_changed; | ||
1120 | |||
1121 | /* Counting from 0 therfore + 1 */ | ||
1122 | if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF) | ||
1123 | max_tx_streams = ((tx_mcs_set_cap & | ||
1124 | IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1; | ||
1125 | |||
1126 | for (i = 0; i < max_tx_streams; i++) | ||
1127 | ht_conf.supp_mcs_set[i] = | ||
1128 | sband->ht_info.supp_mcs_set[i] & | ||
1129 | req_ht_cap->supp_mcs_set[i]; | ||
1130 | |||
1131 | if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM) | ||
1132 | for (i = IEEE80211_SUPP_MCS_SET_UEQM; | ||
1133 | i < IEEE80211_SUPP_MCS_SET_LEN; i++) | ||
1134 | ht_conf.supp_mcs_set[i] = | ||
1135 | sband->ht_info.supp_mcs_set[i] & | ||
1136 | req_ht_cap->supp_mcs_set[i]; | ||
1137 | |||
1138 | check_changed: | ||
1139 | /* if bss configuration changed store the new one */ | ||
1140 | if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || | ||
1141 | memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { | ||
1142 | changed |= BSS_CHANGED_HT; | ||
1143 | memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); | ||
1144 | memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); | ||
1145 | } | ||
1146 | out: | ||
1121 | return changed; | 1147 | return changed; |
1122 | } | 1148 | } |
1123 | 1149 | ||