aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c96
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
1138check_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 }
1146out:
1121 return changed; 1147 return changed;
1122} 1148}
1123 1149