aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2008-05-15 01:53:55 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:47:52 -0400
commitedcdf8b21ac920e06b4180246123fe43b022e020 (patch)
treef24622a574e9f8a2746339ae0460f555a6bdd3b0 /net/mac80211/main.c
parent0b794d63c5db8d010d1584c694eba97f0391fca6 (diff)
mac80211: separate Tx and Rx MCS when configuring HT
This patch follows the 11n spec in separation between Tx and Rx MCS capabilities. Up until now, when configuring the HT possible set of Tx MCS only Rx MCS were considered, assuming they are the same as the Tx MCS. This patch fixed this by looking at low level driver Tx capabilities. Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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