diff options
author | Ben Greear <greearb@candelatech.com> | 2011-11-18 14:32:00 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-21 16:22:06 -0500 |
commit | ef96a84202ccfb48a4569256ffba45e32308f7ee (patch) | |
tree | 708275d21455ecbf3b5408241b73f95fa4c484e0 /net/mac80211/ht.c | |
parent | 7e7c8926b2f4e3453b8aeb39cd814d2af3fec24f (diff) |
mac80211: Support ht-cap over-rides.
This implements ht-cap over-rides for mac80211 drivers.
HT may be disabled, making an /a/b/g/n station act like an
a/b/g station. HT40 may be disabled forcing the station to
be HT20 even if the AP and local hardware support HT40.
MAX-AMSDU may be disabled.
AMPDU-Density may be increased.
AMPDU-Factor may be decreased.
This has been successfully tested with ath9k using patched
wpa_supplicant and iw.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ht.c')
-rw-r--r-- | net/mac80211/ht.c | 83 |
1 files changed, 82 insertions, 1 deletions
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) |