aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h10
-rw-r--r--net/mac80211/ieee80211.c73
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/ieee80211_sta.c33
4 files changed, 75 insertions, 47 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 48428a6b9109..5174eaa89500 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -178,11 +178,13 @@ struct ieee80211_low_level_stats {
178 * also implies a change in the AID. 178 * also implies a change in the AID.
179 * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed 179 * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed
180 * @BSS_CHANGED_ERP_PREAMBLE: preamble changed 180 * @BSS_CHANGED_ERP_PREAMBLE: preamble changed
181 * @BSS_CHANGED_HT: 802.11n parameters changed
181 */ 182 */
182enum ieee80211_bss_change { 183enum ieee80211_bss_change {
183 BSS_CHANGED_ASSOC = 1<<0, 184 BSS_CHANGED_ASSOC = 1<<0,
184 BSS_CHANGED_ERP_CTS_PROT = 1<<1, 185 BSS_CHANGED_ERP_CTS_PROT = 1<<1,
185 BSS_CHANGED_ERP_PREAMBLE = 1<<2, 186 BSS_CHANGED_ERP_PREAMBLE = 1<<2,
187 BSS_CHANGED_HT = 1<<4,
186}; 188};
187 189
188/** 190/**
@@ -195,6 +197,9 @@ enum ieee80211_bss_change {
195 * @aid: association ID number, valid only when @assoc is true 197 * @aid: association ID number, valid only when @assoc is true
196 * @use_cts_prot: use CTS protection 198 * @use_cts_prot: use CTS protection
197 * @use_short_preamble: use 802.11b short preamble 199 * @use_short_preamble: use 802.11b short preamble
200 * @assoc_ht: association in HT mode
201 * @ht_conf: ht capabilities
202 * @ht_bss_conf: ht extended capabilities
198 */ 203 */
199struct ieee80211_bss_conf { 204struct ieee80211_bss_conf {
200 /* association related data */ 205 /* association related data */
@@ -203,6 +208,10 @@ struct ieee80211_bss_conf {
203 /* erp related data */ 208 /* erp related data */
204 bool use_cts_prot; 209 bool use_cts_prot;
205 bool use_short_preamble; 210 bool use_short_preamble;
211 /* ht related data */
212 bool assoc_ht;
213 struct ieee80211_ht_info *ht_conf;
214 struct ieee80211_ht_bss_info *ht_bss_conf;
206}; 215};
207 216
208/** 217/**
@@ -1132,7 +1141,6 @@ struct ieee80211_ops {
1132 struct sk_buff *skb, 1141 struct sk_buff *skb,
1133 struct ieee80211_tx_control *control); 1142 struct ieee80211_tx_control *control);
1134 int (*tx_last_beacon)(struct ieee80211_hw *hw); 1143 int (*tx_last_beacon)(struct ieee80211_hw *hw);
1135 int (*conf_ht)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
1136 int (*ampdu_action)(struct ieee80211_hw *hw, 1144 int (*ampdu_action)(struct ieee80211_hw *hw,
1137 enum ieee80211_ampdu_mlme_action action, 1145 enum ieee80211_ampdu_mlme_action action,
1138 const u8 *addr, u16 tid, u16 *ssn); 1146 const u8 *addr, u16 tid, u16 *ssn);
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index aaa5480e204a..5d30dd463f22 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -1046,54 +1046,69 @@ int ieee80211_hw_config(struct ieee80211_local *local)
1046} 1046}
1047 1047
1048/** 1048/**
1049 * ieee80211_hw_config_ht should be used only after legacy configuration 1049 * ieee80211_handle_ht should be used only after legacy configuration
1050 * has been determined, as ht configuration depends upon the hardware's 1050 * has been determined namely band, as ht configuration depends upon
1051 * HT abilities for a _specific_ band. 1051 * the hardware's HT abilities for a _specific_ band.
1052 */ 1052 */
1053int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, 1053u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
1054 struct ieee80211_ht_info *req_ht_cap, 1054 struct ieee80211_ht_info *req_ht_cap,
1055 struct ieee80211_ht_bss_info *req_bss_cap) 1055 struct ieee80211_ht_bss_info *req_bss_cap)
1056{ 1056{
1057 struct ieee80211_conf *conf = &local->hw.conf; 1057 struct ieee80211_conf *conf = &local->hw.conf;
1058 struct ieee80211_supported_band *sband; 1058 struct ieee80211_supported_band *sband;
1059 struct ieee80211_ht_info ht_conf;
1060 struct ieee80211_ht_bss_info ht_bss_conf;
1059 int i; 1061 int i;
1062 u32 changed = 0;
1060 1063
1061 sband = local->hw.wiphy->bands[conf->channel->band]; 1064 sband = local->hw.wiphy->bands[conf->channel->band];
1062 1065
1063 /* HT is not supported */ 1066 /* HT is not supported */
1064 if (!sband->ht_info.ht_supported) { 1067 if (!sband->ht_info.ht_supported) {
1065 conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 1068 conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
1066 return -EOPNOTSUPP; 1069 return 0;
1067 } 1070 }
1068 1071
1069 /* disable HT */ 1072 memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
1070 if (!enable_ht) { 1073 memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
1071 conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; 1074
1072 } else { 1075 if (enable_ht) {
1076 if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
1077 changed |= BSS_CHANGED_HT;
1078
1073 conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; 1079 conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
1074 conf->ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; 1080 ht_conf.ht_supported = 1;
1075 conf->ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); 1081
1076 conf->ht_conf.cap |= 1082 ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
1077 sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; 1083 ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
1078 conf->ht_bss_conf.primary_channel = 1084 ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
1079 req_bss_cap->primary_channel; 1085
1080 conf->ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
1081 conf->ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
1082 for (i = 0; i < SUPP_MCS_SET_LEN; i++) 1086 for (i = 0; i < SUPP_MCS_SET_LEN; i++)
1083 conf->ht_conf.supp_mcs_set[i] = 1087 ht_conf.supp_mcs_set[i] =
1084 sband->ht_info.supp_mcs_set[i] & 1088 sband->ht_info.supp_mcs_set[i] &
1085 req_ht_cap->supp_mcs_set[i]; 1089 req_ht_cap->supp_mcs_set[i];
1086 1090
1087 /* In STA mode, this gives us indication 1091 ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
1088 * to the AP's mode of operation */ 1092 ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
1089 conf->ht_conf.ht_supported = 1; 1093 ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
1090 conf->ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; 1094
1091 conf->ht_conf.ampdu_density = req_ht_cap->ampdu_density; 1095 ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
1096 ht_conf.ampdu_density = req_ht_cap->ampdu_density;
1097
1098 /* if bss configuration changed store the new one */
1099 if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
1100 memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
1101 changed |= BSS_CHANGED_HT;
1102 memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
1103 memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
1104 }
1105 } else {
1106 if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
1107 changed |= BSS_CHANGED_HT;
1108 conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
1092 } 1109 }
1093 1110
1094 local->ops->conf_ht(local_to_hw(local), &local->hw.conf); 1111 return changed;
1095
1096 return 0;
1097} 1112}
1098 1113
1099void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, 1114void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0997a0f96203..377c448a0556 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -865,9 +865,9 @@ int ieee80211_if_config(struct net_device *dev);
865int ieee80211_if_config_beacon(struct net_device *dev); 865int ieee80211_if_config_beacon(struct net_device *dev);
866void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); 866void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
867void ieee80211_if_setup(struct net_device *dev); 867void ieee80211_if_setup(struct net_device *dev);
868int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, 868u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
869 struct ieee80211_ht_info *req_ht_cap, 869 struct ieee80211_ht_info *req_ht_cap,
870 struct ieee80211_ht_bss_info *req_bss_cap); 870 struct ieee80211_ht_bss_info *req_bss_cap);
871 871
872/* ieee80211_ioctl.c */ 872/* ieee80211_ioctl.c */
873extern const struct iw_handler_def ieee80211_iw_handler_def; 873extern const struct iw_handler_def ieee80211_iw_handler_def;
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 1ee07f0b02e2..0e936233dac5 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -493,6 +493,7 @@ static void ieee80211_set_associated(struct net_device *dev,
493{ 493{
494 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 494 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
495 struct ieee80211_local *local = sdata->local; 495 struct ieee80211_local *local = sdata->local;
496 struct ieee80211_conf *conf = &local_to_hw(local)->conf;
496 union iwreq_data wrqu; 497 union iwreq_data wrqu;
497 u32 changed = BSS_CHANGED_ASSOC; 498 u32 changed = BSS_CHANGED_ASSOC;
498 499
@@ -505,7 +506,7 @@ static void ieee80211_set_associated(struct net_device *dev,
505 return; 506 return;
506 507
507 bss = ieee80211_rx_bss_get(dev, ifsta->bssid, 508 bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
508 local->hw.conf.channel->center_freq, 509 conf->channel->center_freq,
509 ifsta->ssid, ifsta->ssid_len); 510 ifsta->ssid, ifsta->ssid_len);
510 if (bss) { 511 if (bss) {
511 if (bss->has_erp_value) 512 if (bss->has_erp_value)
@@ -514,6 +515,13 @@ static void ieee80211_set_associated(struct net_device *dev,
514 ieee80211_rx_bss_put(dev, bss); 515 ieee80211_rx_bss_put(dev, bss);
515 } 516 }
516 517
518 if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
519 changed |= BSS_CHANGED_HT;
520 sdata->bss_conf.assoc_ht = 1;
521 sdata->bss_conf.ht_conf = &conf->ht_conf;
522 sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf;
523 }
524
517 netif_carrier_on(dev); 525 netif_carrier_on(dev);
518 ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; 526 ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
519 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); 527 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -524,6 +532,11 @@ static void ieee80211_set_associated(struct net_device *dev,
524 ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; 532 ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
525 netif_carrier_off(dev); 533 netif_carrier_off(dev);
526 ieee80211_reset_erp_info(dev); 534 ieee80211_reset_erp_info(dev);
535
536 sdata->bss_conf.assoc_ht = 0;
537 sdata->bss_conf.ht_conf = NULL;
538 sdata->bss_conf.ht_bss_conf = NULL;
539
527 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 540 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
528 } 541 }
529 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 542 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -1999,17 +2012,15 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1999 else 2012 else
2000 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 2013 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
2001 2014
2002 if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && 2015 if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
2003 local->ops->conf_ht) {
2004 struct ieee80211_ht_bss_info bss_info; 2016 struct ieee80211_ht_bss_info bss_info;
2005
2006 ieee80211_ht_cap_ie_to_ht_info( 2017 ieee80211_ht_cap_ie_to_ht_info(
2007 (struct ieee80211_ht_cap *) 2018 (struct ieee80211_ht_cap *)
2008 elems.ht_cap_elem, &sta->ht_info); 2019 elems.ht_cap_elem, &sta->ht_info);
2009 ieee80211_ht_addt_info_ie_to_ht_bss_info( 2020 ieee80211_ht_addt_info_ie_to_ht_bss_info(
2010 (struct ieee80211_ht_addt_info *) 2021 (struct ieee80211_ht_addt_info *)
2011 elems.ht_info_elem, &bss_info); 2022 elems.ht_info_elem, &bss_info);
2012 ieee80211_hw_config_ht(local, 1, &sta->ht_info, &bss_info); 2023 ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info);
2013 } 2024 }
2014 2025
2015 rate_control_rate_init(sta, local); 2026 rate_control_rate_init(sta, local);
@@ -2760,20 +2771,14 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
2760 changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); 2771 changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
2761 2772
2762 if (elems.ht_cap_elem && elems.ht_info_elem && 2773 if (elems.ht_cap_elem && elems.ht_info_elem &&
2763 elems.wmm_param && local->ops->conf_ht && 2774 elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
2764 conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
2765 struct ieee80211_ht_bss_info bss_info; 2775 struct ieee80211_ht_bss_info bss_info;
2766 2776
2767 ieee80211_ht_addt_info_ie_to_ht_bss_info( 2777 ieee80211_ht_addt_info_ie_to_ht_bss_info(
2768 (struct ieee80211_ht_addt_info *) 2778 (struct ieee80211_ht_addt_info *)
2769 elems.ht_info_elem, &bss_info); 2779 elems.ht_info_elem, &bss_info);
2770 /* check if AP changed bss inforamation */ 2780 changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,
2771 if ((conf->ht_bss_conf.primary_channel != 2781 &bss_info);
2772 bss_info.primary_channel) ||
2773 (conf->ht_bss_conf.bss_cap != bss_info.bss_cap) ||
2774 (conf->ht_bss_conf.bss_op_mode != bss_info.bss_op_mode))
2775 ieee80211_hw_config_ht(local, 1, &conf->ht_conf,
2776 &bss_info);
2777 } 2782 }
2778 2783
2779 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { 2784 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {