aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2011-04-27 22:13:12 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-28 14:53:23 -0400
commita46b7b5c13b9ecfe2b4e045e06aaec644dcf55d8 (patch)
treed74c4482678c0221d1b006cee48a56e8d962a557 /drivers/net/wireless/mwifiex
parentadc89595732b92f78940fc0ccdb52afaec582a48 (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.c102
-rw-r--r--drivers/net/wireless/mwifiex/11n.h2
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c42
-rw-r--r--drivers/net/wireless/mwifiex/scan.c4
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 */
54void 37void
55mwifiex_fill_cap_info(struct mwifiex_private *priv, 38mwifiex_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);
39void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, 39void mwifiex_cfg_tx_buf(struct mwifiex_private *priv,
40 struct mwifiex_bssdescriptor *bss_desc); 40 struct mwifiex_bssdescriptor *bss_desc);
41void mwifiex_fill_cap_info(struct mwifiex_private *, 41void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type,
42 struct mwifiex_ie_types_htcap *); 42 struct mwifiex_ie_types_htcap *);
43int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, 43int 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