diff options
-rw-r--r-- | include/net/mac80211.h | 10 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 73 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 33 |
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 | */ |
182 | enum ieee80211_bss_change { | 183 | enum 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 | */ |
199 | struct ieee80211_bss_conf { | 204 | struct 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 | */ |
1053 | int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, | 1053 | u32 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 | ||
1099 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 1114 | void 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); | |||
865 | int ieee80211_if_config_beacon(struct net_device *dev); | 865 | int ieee80211_if_config_beacon(struct net_device *dev); |
866 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 866 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
867 | void ieee80211_if_setup(struct net_device *dev); | 867 | void ieee80211_if_setup(struct net_device *dev); |
868 | int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, | 868 | u32 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 */ |
873 | extern const struct iw_handler_def ieee80211_iw_handler_def; | 873 | extern 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)) { |