diff options
Diffstat (limited to 'net/mac80211')
| -rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
| -rw-r--r-- | net/mac80211/ht.c | 83 | ||||
| -rw-r--r-- | net/mac80211/ieee80211_i.h | 11 | ||||
| -rw-r--r-- | net/mac80211/main.c | 14 | ||||
| -rw-r--r-- | net/mac80211/mesh.c | 2 | ||||
| -rw-r--r-- | net/mac80211/mesh_plink.c | 3 | ||||
| -rw-r--r-- | net/mac80211/mlme.c | 14 | ||||
| -rw-r--r-- | net/mac80211/util.c | 13 | ||||
| -rw-r--r-- | net/mac80211/work.c | 16 |
9 files changed, 140 insertions, 18 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1063a7e57d62..2577c45069e5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -832,7 +832,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
| 832 | } | 832 | } |
| 833 | 833 | ||
| 834 | if (params->ht_capa) | 834 | if (params->ht_capa) |
| 835 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, | 835 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
| 836 | params->ht_capa, | 836 | params->ht_capa, |
| 837 | &sta->sta.ht_cap); | 837 | &sta->sta.ht_cap); |
| 838 | 838 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 988c7ec0898c..7e0ac9791fd6 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
| @@ -18,7 +18,82 @@ | |||
| 18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
| 19 | #include "rate.h" | 19 | #include "rate.h" |
| 20 | 20 | ||
| 21 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 21 | bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata) |
| 22 | { | ||
| 23 | const __le16 flg = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
| 24 | if ((sdata->u.mgd.ht_capa_mask.cap_info & flg) && | ||
| 25 | !(sdata->u.mgd.ht_capa.cap_info & flg)) | ||
| 26 | return true; | ||
| 27 | return false; | ||
| 28 | } | ||
| 29 | |||
| 30 | void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, | ||
| 31 | struct ieee80211_sta_ht_cap *ht_cap, | ||
| 32 | u16 flag) | ||
| 33 | { | ||
| 34 | __le16 le_flag = cpu_to_le16(flag); | ||
| 35 | if (sdata->u.mgd.ht_capa_mask.cap_info & le_flag) { | ||
| 36 | if (!(sdata->u.mgd.ht_capa.cap_info & le_flag)) | ||
| 37 | ht_cap->cap &= ~flag; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
| 42 | struct ieee80211_sta_ht_cap *ht_cap) | ||
| 43 | { | ||
| 44 | u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask); | ||
| 45 | u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask); | ||
| 46 | int i; | ||
| 47 | |||
| 48 | if (sdata->vif.type != NL80211_IFTYPE_STATION) { | ||
| 49 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | |||
| 53 | /* NOTE: If you add more over-rides here, update register_hw | ||
| 54 | * ht_capa_mod_msk logic in main.c as well. | ||
| 55 | * And, if this method can ever change ht_cap.ht_supported, fix | ||
| 56 | * the check in ieee80211_add_ht_ie. | ||
| 57 | */ | ||
| 58 | |||
| 59 | /* check for HT over-rides, MCS rates first. */ | ||
| 60 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { | ||
| 61 | u8 m = smask[i]; | ||
| 62 | ht_cap->mcs.rx_mask[i] &= ~m; /* turn off all masked bits */ | ||
| 63 | /* Add back rates that are supported */ | ||
| 64 | ht_cap->mcs.rx_mask[i] |= (m & scaps[i]); | ||
| 65 | } | ||
| 66 | |||
| 67 | /* Force removal of HT-40 capabilities? */ | ||
| 68 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
| 69 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40); | ||
| 70 | |||
| 71 | /* Allow user to disable the max-AMSDU bit. */ | ||
| 72 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU); | ||
| 73 | |||
| 74 | /* Allow user to decrease AMPDU factor */ | ||
| 75 | if (sdata->u.mgd.ht_capa_mask.ampdu_params_info & | ||
| 76 | IEEE80211_HT_AMPDU_PARM_FACTOR) { | ||
| 77 | u8 n = sdata->u.mgd.ht_capa.ampdu_params_info | ||
| 78 | & IEEE80211_HT_AMPDU_PARM_FACTOR; | ||
| 79 | if (n < ht_cap->ampdu_factor) | ||
| 80 | ht_cap->ampdu_factor = n; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Allow the user to increase AMPDU density. */ | ||
| 84 | if (sdata->u.mgd.ht_capa_mask.ampdu_params_info & | ||
| 85 | IEEE80211_HT_AMPDU_PARM_DENSITY) { | ||
| 86 | u8 n = (sdata->u.mgd.ht_capa.ampdu_params_info & | ||
| 87 | IEEE80211_HT_AMPDU_PARM_DENSITY) | ||
| 88 | >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT; | ||
| 89 | if (n > ht_cap->ampdu_density) | ||
| 90 | ht_cap->ampdu_density = n; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | |||
| 95 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | ||
| 96 | struct ieee80211_supported_band *sband, | ||
| 22 | struct ieee80211_ht_cap *ht_cap_ie, | 97 | struct ieee80211_ht_cap *ht_cap_ie, |
| 23 | struct ieee80211_sta_ht_cap *ht_cap) | 98 | struct ieee80211_sta_ht_cap *ht_cap) |
| 24 | { | 99 | { |
| @@ -102,6 +177,12 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | |||
| 102 | /* handle MCS rate 32 too */ | 177 | /* handle MCS rate 32 too */ |
| 103 | if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) | 178 | if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) |
| 104 | ht_cap->mcs.rx_mask[32/8] |= 1; | 179 | ht_cap->mcs.rx_mask[32/8] |= 1; |
| 180 | |||
| 181 | /* | ||
| 182 | * If user has specified capability over-rides, take care | ||
| 183 | * of that here. | ||
| 184 | */ | ||
| 185 | ieee80211_apply_htcap_overrides(sdata, ht_cap); | ||
| 105 | } | 186 | } |
| 106 | 187 | ||
| 107 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) | 188 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 17661df1515f..762243e469df 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -449,6 +449,9 @@ struct ieee80211_if_managed { | |||
| 449 | */ | 449 | */ |
| 450 | int rssi_min_thold, rssi_max_thold; | 450 | int rssi_min_thold, rssi_max_thold; |
| 451 | int last_ave_beacon_signal; | 451 | int last_ave_beacon_signal; |
| 452 | |||
| 453 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ | ||
| 454 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | ||
| 452 | }; | 455 | }; |
| 453 | 456 | ||
| 454 | struct ieee80211_if_ibss { | 457 | struct ieee80211_if_ibss { |
| @@ -1252,7 +1255,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
| 1252 | struct net_device *dev); | 1255 | struct net_device *dev); |
| 1253 | 1256 | ||
| 1254 | /* HT */ | 1257 | /* HT */ |
| 1255 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 1258 | bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); |
| 1259 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | ||
| 1260 | struct ieee80211_sta_ht_cap *ht_cap); | ||
| 1261 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | ||
| 1262 | struct ieee80211_supported_band *sband, | ||
| 1256 | struct ieee80211_ht_cap *ht_cap_ie, | 1263 | struct ieee80211_ht_cap *ht_cap_ie, |
| 1257 | struct ieee80211_sta_ht_cap *ht_cap); | 1264 | struct ieee80211_sta_ht_cap *ht_cap); |
| 1258 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 1265 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
| @@ -1407,7 +1414,7 @@ void ieee80211_recalc_smps(struct ieee80211_local *local); | |||
| 1407 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | 1414 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, |
| 1408 | const u8 *ids, int n_ids, size_t offset); | 1415 | const u8 *ids, int n_ids, size_t offset); |
| 1409 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); | 1416 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); |
| 1410 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband, | 1417 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
| 1411 | u16 cap); | 1418 | u16 cap); |
| 1412 | u8 *ieee80211_ie_build_ht_info(u8 *pos, | 1419 | u8 *ieee80211_ie_build_ht_info(u8 *pos, |
| 1413 | struct ieee80211_sta_ht_cap *ht_cap, | 1420 | struct ieee80211_sta_ht_cap *ht_cap, |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f0106d331938..dddedfad5404 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -558,6 +558,19 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
| 558 | }, | 558 | }, |
| 559 | }; | 559 | }; |
| 560 | 560 | ||
| 561 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | ||
| 562 | .ampdu_params_info = IEEE80211_HT_AMPDU_PARM_FACTOR | | ||
| 563 | IEEE80211_HT_AMPDU_PARM_DENSITY, | ||
| 564 | |||
| 565 | .cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
| 566 | IEEE80211_HT_CAP_MAX_AMSDU | | ||
| 567 | IEEE80211_HT_CAP_SGI_40), | ||
| 568 | .mcs = { | ||
| 569 | .rx_mask = { 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 570 | 0xff, 0xff, 0xff, 0xff, 0xff, }, | ||
| 571 | }, | ||
| 572 | }; | ||
| 573 | |||
| 561 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 574 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
| 562 | const struct ieee80211_ops *ops) | 575 | const struct ieee80211_ops *ops) |
| 563 | { | 576 | { |
| @@ -631,6 +644,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
| 631 | local->user_power_level = -1; | 644 | local->user_power_level = -1; |
| 632 | local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | 645 | local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; |
| 633 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | 646 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; |
| 647 | wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; | ||
| 634 | 648 | ||
| 635 | INIT_LIST_HEAD(&local->interfaces); | 649 | INIT_LIST_HEAD(&local->interfaces); |
| 636 | 650 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b3a125f60347..ee82d2f7f114 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -366,7 +366,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
| 366 | return -ENOMEM; | 366 | return -ENOMEM; |
| 367 | 367 | ||
| 368 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap)); | 368 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap)); |
| 369 | ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap); | 369 | ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, sband->ht_cap.cap); |
| 370 | 370 | ||
| 371 | return 0; | 371 | return 0; |
| 372 | } | 372 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 0140e88a8220..7314372b12ba 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
| @@ -101,7 +101,8 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
| 101 | set_sta_flag(sta, WLAN_STA_WME); | 101 | set_sta_flag(sta, WLAN_STA_WME); |
| 102 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 102 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
| 103 | if (elems->ht_cap_elem) | 103 | if (elems->ht_cap_elem) |
| 104 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, elems->ht_cap_elem, | 104 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
| 105 | elems->ht_cap_elem, | ||
| 105 | &sta->sta.ht_cap); | 106 | &sta->sta.ht_cap); |
| 106 | rate_control_rate_init(sta); | 107 | rate_control_rate_init(sta); |
| 107 | 108 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0f58122edffa..8925138736ef 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -207,6 +207,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
| 207 | channel_type = NL80211_CHAN_HT20; | 207 | channel_type = NL80211_CHAN_HT20; |
| 208 | 208 | ||
| 209 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | 209 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && |
| 210 | !ieee80111_cfg_override_disables_ht40(sdata) && | ||
| 210 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && | 211 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && |
| 211 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | 212 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { |
| 212 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 213 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
| @@ -1118,6 +1119,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
| 1118 | 1119 | ||
| 1119 | /* on the next assoc, re-program HT parameters */ | 1120 | /* on the next assoc, re-program HT parameters */ |
| 1120 | sdata->ht_opmode_valid = false; | 1121 | sdata->ht_opmode_valid = false; |
| 1122 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | ||
| 1123 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); | ||
| 1121 | 1124 | ||
| 1122 | local->power_constr_level = 0; | 1125 | local->power_constr_level = 0; |
| 1123 | 1126 | ||
| @@ -1611,7 +1614,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
| 1611 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 1614 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
| 1612 | 1615 | ||
| 1613 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 1616 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
| 1614 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, | 1617 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
| 1615 | elems.ht_cap_elem, &sta->sta.ht_cap); | 1618 | elems.ht_cap_elem, &sta->sta.ht_cap); |
| 1616 | 1619 | ||
| 1617 | ap_ht_cap_flags = sta->sta.ht_cap.cap; | 1620 | ap_ht_cap_flags = sta->sta.ht_cap.cap; |
| @@ -1980,7 +1983,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 1980 | 1983 | ||
| 1981 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1984 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
| 1982 | 1985 | ||
| 1983 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, | 1986 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
| 1984 | elems.ht_cap_elem, &sta->sta.ht_cap); | 1987 | elems.ht_cap_elem, &sta->sta.ht_cap); |
| 1985 | 1988 | ||
| 1986 | ap_ht_cap_flags = sta->sta.ht_cap.cap; | 1989 | ap_ht_cap_flags = sta->sta.ht_cap.cap; |
| @@ -2640,6 +2643,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 2640 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 2643 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
| 2641 | 2644 | ||
| 2642 | 2645 | ||
| 2646 | if (req->flags & ASSOC_REQ_DISABLE_HT) | ||
| 2647 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | ||
| 2648 | |||
| 2649 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | ||
| 2650 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | ||
| 2651 | sizeof(ifmgd->ht_capa_mask)); | ||
| 2652 | |||
| 2643 | if (req->ie && req->ie_len) { | 2653 | if (req->ie && req->ie_len) { |
| 2644 | memcpy(wk->ie, req->ie, req->ie_len); | 2654 | memcpy(wk->ie, req->ie, req->ie_len); |
| 2645 | wk->ie_len = req->ie_len; | 2655 | wk->ie_len = req->ie_len; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e2cb00df8c36..1118393d79de 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -979,7 +979,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
| 979 | } | 979 | } |
| 980 | 980 | ||
| 981 | if (sband->ht_cap.ht_supported) | 981 | if (sband->ht_cap.ht_supported) |
| 982 | pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap); | 982 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, |
| 983 | sband->ht_cap.cap); | ||
| 983 | 984 | ||
| 984 | /* | 985 | /* |
| 985 | * If adding more here, adjust code in main.c | 986 | * If adding more here, adjust code in main.c |
| @@ -1518,7 +1519,7 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) | |||
| 1518 | } | 1519 | } |
| 1519 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); | 1520 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); |
| 1520 | 1521 | ||
| 1521 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband, | 1522 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
| 1522 | u16 cap) | 1523 | u16 cap) |
| 1523 | { | 1524 | { |
| 1524 | __le16 tmp; | 1525 | __le16 tmp; |
| @@ -1533,13 +1534,13 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband, | |||
| 1533 | pos += sizeof(u16); | 1534 | pos += sizeof(u16); |
| 1534 | 1535 | ||
| 1535 | /* AMPDU parameters */ | 1536 | /* AMPDU parameters */ |
| 1536 | *pos++ = sband->ht_cap.ampdu_factor | | 1537 | *pos++ = ht_cap->ampdu_factor | |
| 1537 | (sband->ht_cap.ampdu_density << | 1538 | (ht_cap->ampdu_density << |
| 1538 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | 1539 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); |
| 1539 | 1540 | ||
| 1540 | /* MCS set */ | 1541 | /* MCS set */ |
| 1541 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 1542 | memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs)); |
| 1542 | pos += sizeof(sband->ht_cap.mcs); | 1543 | pos += sizeof(ht_cap->mcs); |
| 1543 | 1544 | ||
| 1544 | /* extended capabilities */ | 1545 | /* extended capabilities */ |
| 1545 | pos += sizeof(__le16); | 1546 | pos += sizeof(__le16); |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 3dd5a89e99a7..6884a2d986dc 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
| @@ -94,7 +94,8 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | |||
| 94 | 94 | ||
| 95 | /* frame sending functions */ | 95 | /* frame sending functions */ |
| 96 | 96 | ||
| 97 | static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | 97 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
| 98 | struct sk_buff *skb, const u8 *ht_info_ie, | ||
| 98 | struct ieee80211_supported_band *sband, | 99 | struct ieee80211_supported_band *sband, |
| 99 | struct ieee80211_channel *channel, | 100 | struct ieee80211_channel *channel, |
| 100 | enum ieee80211_smps_mode smps) | 101 | enum ieee80211_smps_mode smps) |
| @@ -102,7 +103,10 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | |||
| 102 | struct ieee80211_ht_info *ht_info; | 103 | struct ieee80211_ht_info *ht_info; |
| 103 | u8 *pos; | 104 | u8 *pos; |
| 104 | u32 flags = channel->flags; | 105 | u32 flags = channel->flags; |
| 105 | u16 cap = sband->ht_cap.cap; | 106 | u16 cap; |
| 107 | struct ieee80211_sta_ht_cap ht_cap; | ||
| 108 | |||
| 109 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | ||
| 106 | 110 | ||
| 107 | if (!sband->ht_cap.ht_supported) | 111 | if (!sband->ht_cap.ht_supported) |
| 108 | return; | 112 | return; |
| @@ -113,9 +117,13 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | |||
| 113 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) | 117 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) |
| 114 | return; | 118 | return; |
| 115 | 119 | ||
| 120 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | ||
| 121 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
| 122 | |||
| 116 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); | 123 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); |
| 117 | 124 | ||
| 118 | /* determine capability flags */ | 125 | /* determine capability flags */ |
| 126 | cap = ht_cap.cap; | ||
| 119 | 127 | ||
| 120 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 128 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
| 121 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 129 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
| @@ -154,7 +162,7 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | |||
| 154 | 162 | ||
| 155 | /* reserve and fill IE */ | 163 | /* reserve and fill IE */ |
| 156 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | 164 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); |
| 157 | ieee80211_ie_build_ht_cap(pos, sband, cap); | 165 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); |
| 158 | } | 166 | } |
| 159 | 167 | ||
| 160 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | 168 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, |
| @@ -329,7 +337,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
| 329 | 337 | ||
| 330 | if (wk->assoc.use_11n && wk->assoc.wmm_used && | 338 | if (wk->assoc.use_11n && wk->assoc.wmm_used && |
| 331 | local->hw.queues >= 4) | 339 | local->hw.queues >= 4) |
| 332 | ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, | 340 | ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie, |
| 333 | sband, wk->chan, wk->assoc.smps); | 341 | sband, wk->chan, wk->assoc.smps); |
| 334 | 342 | ||
| 335 | /* if present, add any custom non-vendor IEs that go after HT */ | 343 | /* if present, add any custom non-vendor IEs that go after HT */ |
