diff options
author | Amitkumar Karwar <akarwar@marvell.com> | 2011-04-27 22:13:12 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-28 14:53:23 -0400 |
commit | a46b7b5c13b9ecfe2b4e045e06aaec644dcf55d8 (patch) | |
tree | d74c4482678c0221d1b006cee48a56e8d962a557 /drivers/net/wireless/mwifiex | |
parent | adc89595732b92f78940fc0ccdb52afaec582a48 (diff) |
mwifiex: HT capability information handling
1) Initialise HT capabilities in cfg80211 properly.
2) Cfg80211 stack may modify "sband->ht_cap" to disable
40Mhz operation in 2.4GHz band (after recent patch
"cfg80211: module_param to disable HT40 in 2.4GHz band")
Therefore read "sband->ht_cap" instead of an adapter variable
"hw_dot_11n_dev_cap" to get HT capabilities.
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/11n.c | 102 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/11n.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/scan.c | 4 |
4 files changed, 64 insertions, 86 deletions
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index e22d761f2ef2..1d294cfa6c9b 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -29,95 +29,38 @@ | |||
29 | * Fills HT capability information field, AMPDU Parameters field, HT extended | 29 | * Fills HT capability information field, AMPDU Parameters field, HT extended |
30 | * capability field, and supported MCS set fields. | 30 | * capability field, and supported MCS set fields. |
31 | * | 31 | * |
32 | * Only the following HT capability information fields are used, all other | 32 | * HT capability information field, AMPDU Parameters field, supported MCS set |
33 | * fields are always turned off. | 33 | * fields are retrieved from cfg80211 stack |
34 | * | 34 | * |
35 | * Bit 1 : Supported channel width (0: 20MHz, 1: Both 20 and 40 MHz) | 35 | * RD responder bit to set to clear in the extended capability header. |
36 | * Bit 4 : Greenfield support (0: Not supported, 1: Supported) | ||
37 | * Bit 5 : Short GI for 20 MHz support (0: Not supported, 1: Supported) | ||
38 | * Bit 6 : Short GI for 40 MHz support (0: Not supported, 1: Supported) | ||
39 | * Bit 7 : Tx STBC (0: Not supported, 1: Supported) | ||
40 | * Bit 8-9 : Rx STBC (0: Not supported, X: Support for up to X spatial streams) | ||
41 | * Bit 10 : Delayed BA support (0: Not supported, 1: Supported) | ||
42 | * Bit 11 : Maximum AMSDU length (0: 3839 octets, 1: 7935 octets) | ||
43 | * Bit 14 : 40-Mhz intolerant support (0: Not supported, 1: Supported) | ||
44 | * | ||
45 | * In addition, the following AMPDU Parameters are set - | ||
46 | * - Maximum AMPDU length exponent (set to 3) | ||
47 | * - Minimum AMPDU start spacing (set to 0 - No restrictions) | ||
48 | * | ||
49 | * MCS is set for 1x1, with MSC32 for infra mode or ad-hoc mode with 40 MHz | ||
50 | * support. | ||
51 | * | ||
52 | * RD responder bit to set to clear in the extended capability header. | ||
53 | */ | 36 | */ |
54 | void | 37 | void |
55 | mwifiex_fill_cap_info(struct mwifiex_private *priv, | 38 | mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, |
56 | struct mwifiex_ie_types_htcap *ht_cap) | 39 | struct mwifiex_ie_types_htcap *ht_cap) |
57 | { | 40 | { |
58 | struct mwifiex_adapter *adapter = priv->adapter; | ||
59 | u8 *mcs; | ||
60 | int rx_mcs_supp; | ||
61 | uint16_t ht_cap_info = le16_to_cpu(ht_cap->ht_cap.cap_info); | ||
62 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); | 41 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); |
42 | struct ieee80211_supported_band *sband = | ||
43 | priv->wdev->wiphy->bands[radio_type]; | ||
63 | 44 | ||
64 | /* Convert dev_cap to IEEE80211_HT_CAP */ | 45 | ht_cap->ht_cap.ampdu_params_info = |
65 | if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) | 46 | (sband->ht_cap.ampdu_factor & |
66 | ht_cap_info |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 47 | IEEE80211_HT_AMPDU_PARM_FACTOR)| |
67 | else | 48 | ((sband->ht_cap.ampdu_density << |
68 | ht_cap_info &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 49 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & |
69 | 50 | IEEE80211_HT_AMPDU_PARM_DENSITY); | |
70 | if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) | ||
71 | ht_cap_info |= IEEE80211_HT_CAP_SGI_20; | ||
72 | else | ||
73 | ht_cap_info &= ~IEEE80211_HT_CAP_SGI_20; | ||
74 | |||
75 | if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) | ||
76 | ht_cap_info |= IEEE80211_HT_CAP_SGI_40; | ||
77 | else | ||
78 | ht_cap_info &= ~IEEE80211_HT_CAP_SGI_40; | ||
79 | |||
80 | if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) | ||
81 | ht_cap_info |= IEEE80211_HT_CAP_TX_STBC; | ||
82 | else | ||
83 | ht_cap_info &= ~IEEE80211_HT_CAP_TX_STBC; | ||
84 | |||
85 | if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) | ||
86 | ht_cap_info |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; | ||
87 | else | ||
88 | ht_cap_info &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | ||
89 | |||
90 | if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap)) | ||
91 | ht_cap_info |= IEEE80211_HT_CAP_GRN_FLD; | ||
92 | else | ||
93 | ht_cap_info &= ~IEEE80211_HT_CAP_GRN_FLD; | ||
94 | |||
95 | ht_cap_info &= ~IEEE80211_HT_CAP_MAX_AMSDU; | ||
96 | ht_cap_info |= IEEE80211_HT_CAP_SM_PS; | ||
97 | 51 | ||
98 | ht_cap->ht_cap.ampdu_params_info |= IEEE80211_HT_AMPDU_PARM_FACTOR; | 52 | memcpy((u8 *) &ht_cap->ht_cap.mcs, &sband->ht_cap.mcs, |
99 | ht_cap->ht_cap.ampdu_params_info &= ~IEEE80211_HT_AMPDU_PARM_DENSITY; | 53 | sizeof(sband->ht_cap.mcs)); |
100 | |||
101 | rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); | ||
102 | |||
103 | mcs = (u8 *)&ht_cap->ht_cap.mcs; | ||
104 | |||
105 | /* Set MCS for 1x1 */ | ||
106 | memset(mcs, 0xff, rx_mcs_supp); | ||
107 | |||
108 | /* Clear all the other values */ | ||
109 | memset(&mcs[rx_mcs_supp], 0, | ||
110 | sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); | ||
111 | 54 | ||
112 | if (priv->bss_mode == NL80211_IFTYPE_STATION || | 55 | if (priv->bss_mode == NL80211_IFTYPE_STATION || |
113 | (ht_cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) | 56 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
114 | /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ | 57 | /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ |
115 | SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); | 58 | SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); |
116 | 59 | ||
117 | /* Clear RD responder bit */ | 60 | /* Clear RD responder bit */ |
118 | ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; | 61 | ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; |
119 | 62 | ||
120 | ht_cap->ht_cap.cap_info = cpu_to_le16(ht_cap_info); | 63 | ht_cap->ht_cap.cap_info = cpu_to_le16(sband->ht_cap.cap); |
121 | ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); | 64 | ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); |
122 | } | 65 | } |
123 | 66 | ||
@@ -391,10 +334,15 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
391 | struct mwifiex_ie_types_2040bssco *bss_co_2040; | 334 | struct mwifiex_ie_types_2040bssco *bss_co_2040; |
392 | struct mwifiex_ie_types_extcap *ext_cap; | 335 | struct mwifiex_ie_types_extcap *ext_cap; |
393 | int ret_len = 0; | 336 | int ret_len = 0; |
337 | struct ieee80211_supported_band *sband; | ||
338 | u8 radio_type; | ||
394 | 339 | ||
395 | if (!buffer || !*buffer) | 340 | if (!buffer || !*buffer) |
396 | return ret_len; | 341 | return ret_len; |
397 | 342 | ||
343 | radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); | ||
344 | sband = priv->wdev->wiphy->bands[radio_type]; | ||
345 | |||
398 | if (bss_desc->bcn_ht_cap) { | 346 | if (bss_desc->bcn_ht_cap) { |
399 | ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; | 347 | ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; |
400 | memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); | 348 | memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); |
@@ -406,7 +354,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
406 | sizeof(struct ieee_types_header), | 354 | sizeof(struct ieee_types_header), |
407 | le16_to_cpu(ht_cap->header.len)); | 355 | le16_to_cpu(ht_cap->header.len)); |
408 | 356 | ||
409 | mwifiex_fill_cap_info(priv, ht_cap); | 357 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); |
410 | 358 | ||
411 | *buffer += sizeof(struct mwifiex_ie_types_htcap); | 359 | *buffer += sizeof(struct mwifiex_ie_types_htcap); |
412 | ret_len += sizeof(struct mwifiex_ie_types_htcap); | 360 | ret_len += sizeof(struct mwifiex_ie_types_htcap); |
@@ -428,8 +376,8 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
428 | sizeof(struct ieee_types_header), | 376 | sizeof(struct ieee_types_header), |
429 | le16_to_cpu(ht_info->header.len)); | 377 | le16_to_cpu(ht_info->header.len)); |
430 | 378 | ||
431 | if (!ISSUPP_CHANWIDTH40 | 379 | if (!(sband->ht_cap.cap & |
432 | (priv->adapter->hw_dot_11n_dev_cap)) | 380 | IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
433 | ht_info->ht_info.ht_param &= | 381 | ht_info->ht_info.ht_param &= |
434 | ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | | 382 | ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | |
435 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET); | 383 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET); |
@@ -451,7 +399,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
451 | chan_list->chan_scan_param[0].radio_type = | 399 | chan_list->chan_scan_param[0].radio_type = |
452 | mwifiex_band_to_radio_type((u8) bss_desc->bss_band); | 400 | mwifiex_band_to_radio_type((u8) bss_desc->bss_band); |
453 | 401 | ||
454 | if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) | 402 | if ((sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
455 | && (bss_desc->bcn_ht_info->ht_param & | 403 | && (bss_desc->bcn_ht_info->ht_param & |
456 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | 404 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) |
457 | SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. | 405 | SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 02602ff30cbf..a4390a1a2a9f 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
@@ -38,7 +38,7 @@ int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
38 | u8 **buffer); | 38 | u8 **buffer); |
39 | void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, | 39 | void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, |
40 | struct mwifiex_bssdescriptor *bss_desc); | 40 | struct mwifiex_bssdescriptor *bss_desc); |
41 | void mwifiex_fill_cap_info(struct mwifiex_private *, | 41 | void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, |
42 | struct mwifiex_ie_types_htcap *); | 42 | struct mwifiex_ie_types_htcap *); |
43 | int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, | 43 | int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, |
44 | u16 action, int *htcap_cfg); | 44 | u16 action, int *htcap_cfg); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 585575562127..98009e2194c5 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1150,9 +1150,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, | |||
1150 | * | 1150 | * |
1151 | * The following default values are set - | 1151 | * The following default values are set - |
1152 | * - HT Supported = True | 1152 | * - HT Supported = True |
1153 | * - Maximum AMPDU length factor = 0x3 | 1153 | * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K |
1154 | * - Minimum AMPDU spacing = 0x6 | 1154 | * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE |
1155 | * - HT Capabilities map = IEEE80211_HT_CAP_SUP_WIDTH_20_40 (0x0002) | 1155 | * - HT Capabilities supported by firmware |
1156 | * - MCS information, Rx mask = 0xff | 1156 | * - MCS information, Rx mask = 0xff |
1157 | * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) | 1157 | * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) |
1158 | */ | 1158 | */ |
@@ -1166,13 +1166,41 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
1166 | struct mwifiex_adapter *adapter = priv->adapter; | 1166 | struct mwifiex_adapter *adapter = priv->adapter; |
1167 | 1167 | ||
1168 | ht_info->ht_supported = true; | 1168 | ht_info->ht_supported = true; |
1169 | ht_info->ampdu_factor = 0x3; | 1169 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
1170 | ht_info->ampdu_density = 0x6; | 1170 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; |
1171 | 1171 | ||
1172 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | 1172 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); |
1173 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1174 | 1173 | ||
1175 | rx_mcs_supp = GET_RXMCSSUPP(priv->adapter->hw_dev_mcs_support); | 1174 | /* Fill HT capability information */ |
1175 | if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) | ||
1176 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1177 | else | ||
1178 | ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1179 | |||
1180 | if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) | ||
1181 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
1182 | else | ||
1183 | ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20; | ||
1184 | |||
1185 | if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) | ||
1186 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
1187 | else | ||
1188 | ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
1189 | |||
1190 | if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) | ||
1191 | ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; | ||
1192 | else | ||
1193 | ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | ||
1194 | |||
1195 | if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) | ||
1196 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; | ||
1197 | else | ||
1198 | ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; | ||
1199 | |||
1200 | ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; | ||
1201 | ht_info->cap |= IEEE80211_HT_CAP_SM_PS; | ||
1202 | |||
1203 | rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); | ||
1176 | /* Set MCS for 1x1 */ | 1204 | /* Set MCS for 1x1 */ |
1177 | memset(mcs, 0xff, rx_mcs_supp); | 1205 | memset(mcs, 0xff, rx_mcs_supp); |
1178 | /* Clear all the other values */ | 1206 | /* Clear all the other values */ |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 68d905d58606..be708ad8c44d 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1007,7 +1007,9 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv, | |||
1007 | ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); | 1007 | ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); |
1008 | ht_cap->header.len = | 1008 | ht_cap->header.len = |
1009 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); | 1009 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); |
1010 | mwifiex_fill_cap_info(priv, ht_cap); | 1010 | radio_type = |
1011 | mwifiex_band_to_radio_type(priv->adapter->config_bands); | ||
1012 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); | ||
1011 | tlv_pos += sizeof(struct mwifiex_ie_types_htcap); | 1013 | tlv_pos += sizeof(struct mwifiex_ie_types_htcap); |
1012 | } | 1014 | } |
1013 | 1015 | ||