aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorYogesh Ashok Powar <yogeshp@marvell.com>2013-02-16 00:44:30 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-02-18 15:30:39 -0500
commita5f390562a375a315292648e2da865a12b42f280 (patch)
tree4df3a0938102374e0a9208b5296ced9e7590d340 /drivers/net/wireless
parent073c9e6f86e58ba652c694b340f0460fc8156268 (diff)
mwifiex: add 802.11AC support
For STA mode, collect VHT realated IEs from the Beacons or Probe Responses and append similar VHT related IEs to association requests. For AP mode, get VHT related capability information and share it with cfg80211 at the time of wiphy register. This information is further used by cfg80211 and hostapd to start an AP with 802.11AC support. Currently only 8897 supports 802.11AC. Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com> Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Nishant Sarmukadam <nishants@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: Frank Huang <frankh@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mwifiex/11ac.c261
-rw-r--r--drivers/net/wireless/mwifiex/11ac.h26
-rw-r--r--drivers/net/wireless/mwifiex/11n.c7
-rw-r--r--drivers/net/wireless/mwifiex/11n.h4
-rw-r--r--drivers/net/wireless/mwifiex/Makefile1
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c177
-rw-r--r--drivers/net/wireless/mwifiex/cfp.c159
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c19
-rw-r--r--drivers/net/wireless/mwifiex/fw.h127
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h4
-rw-r--r--drivers/net/wireless/mwifiex/join.c8
-rw-r--r--drivers/net/wireless/mwifiex/main.h23
-rw-r--r--drivers/net/wireless/mwifiex/scan.c48
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c1
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c5
16 files changed, 830 insertions, 42 deletions
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c
new file mode 100644
index 000000000000..cf43b3c29250
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/11ac.c
@@ -0,0 +1,261 @@
1/*
2 * Marvell Wireless LAN device driver: 802.11ac
3 *
4 * Copyright (C) 2013, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include "decl.h"
21#include "ioctl.h"
22#include "fw.h"
23#include "main.h"
24#include "11ac.h"
25
26/* This function converts the 2-bit MCS map to the highest long GI
27 * VHT data rate.
28 */
29static u16
30mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
31 u8 bands, u16 mcs_map)
32{
33 u8 i, nss, max_mcs;
34 u16 max_rate = 0;
35 u32 usr_vht_cap_info = 0;
36 struct mwifiex_adapter *adapter = priv->adapter;
37 /* tables of the MCS map to the highest data rate (in Mbps)
38 * supported for long GI
39 */
40 u16 max_rate_lgi_80MHZ[8][3] = {
41 {0x124, 0x15F, 0x186}, /* NSS = 1 */
42 {0x249, 0x2BE, 0x30C}, /* NSS = 2 */
43 {0x36D, 0x41D, 0x492}, /* NSS = 3 */
44 {0x492, 0x57C, 0x618}, /* NSS = 4 */
45 {0x5B6, 0x6DB, 0x79E}, /* NSS = 5 */
46 {0x6DB, 0x83A, 0x0}, /* NSS = 6 */
47 {0x7FF, 0x999, 0xAAA}, /* NSS = 7 */
48 {0x924, 0xAF8, 0xC30} /* NSS = 8 */
49 };
50 u16 max_rate_lgi_160MHZ[8][3] = {
51 {0x249, 0x2BE, 0x30C}, /* NSS = 1 */
52 {0x492, 0x57C, 0x618}, /* NSS = 2 */
53 {0x6DB, 0x83A, 0x0}, /* NSS = 3 */
54 {0x924, 0xAF8, 0xC30}, /* NSS = 4 */
55 {0xB6D, 0xDB6, 0xF3C}, /* NSS = 5 */
56 {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
57 {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
58 {0x1248, 0x15F0, 0x1860} /* NSS = 8 */
59 };
60
61 if (bands & BAND_AAC)
62 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
63 else
64 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
65
66 /* find the max NSS supported */
67 nss = 0;
68 for (i = 0; i < 8; i++) {
69 max_mcs = (mcs_map >> (2 * i)) & 0x3;
70 if (max_mcs < 3)
71 nss = i;
72 }
73 max_mcs = (mcs_map >> (2 * nss)) & 0x3;
74
75 /* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9 */
76 if (max_mcs >= 3)
77 max_mcs = 2;
78
79 if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
80 /* support 160 MHz */
81 max_rate = max_rate_lgi_160MHZ[nss][max_mcs];
82 if (!max_rate)
83 /* MCS9 is not supported in NSS6 */
84 max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1];
85 } else {
86 max_rate = max_rate_lgi_80MHZ[nss][max_mcs];
87 if (!max_rate)
88 /* MCS9 is not supported in NSS3 */
89 max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1];
90 }
91
92 return max_rate;
93}
94
95static void
96mwifiex_fill_vht_cap_info(struct mwifiex_private *priv,
97 struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands)
98{
99 struct mwifiex_adapter *adapter = priv->adapter;
100
101 if (bands & BAND_A)
102 vht_cap->vht_cap.vht_cap_info =
103 cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a);
104 else
105 vht_cap->vht_cap.vht_cap_info =
106 cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg);
107}
108
109static void
110mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
111 struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands)
112{
113 struct mwifiex_adapter *adapter = priv->adapter;
114 u16 mcs_map_user, mcs_map_resp, mcs_map_result;
115 u16 mcs_user, mcs_resp, nss, tmp;
116
117 /* Fill VHT cap info */
118 mwifiex_fill_vht_cap_info(priv, vht_cap, bands);
119
120 /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */
121 mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
122 mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.rx_mcs_map);
123 mcs_map_result = 0;
124
125 for (nss = 1; nss <= 8; nss++) {
126 mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
127 mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
128
129 if ((mcs_user == NO_NSS_SUPPORT) ||
130 (mcs_resp == NO_NSS_SUPPORT))
131 SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
132 else
133 SET_VHTNSSMCS(mcs_map_result, nss,
134 min(mcs_user, mcs_resp));
135 }
136
137 vht_cap->vht_cap.supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result);
138
139 tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
140 vht_cap->vht_cap.supp_mcs.rx_highest = cpu_to_le16(tmp);
141
142 /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */
143 mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support);
144 mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.tx_mcs_map);
145 mcs_map_result = 0;
146
147 for (nss = 1; nss <= 8; nss++) {
148 mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
149 mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
150 if ((mcs_user == NO_NSS_SUPPORT) ||
151 (mcs_resp == NO_NSS_SUPPORT))
152 SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
153 else
154 SET_VHTNSSMCS(mcs_map_result, nss,
155 min(mcs_user, mcs_resp));
156 }
157
158 vht_cap->vht_cap.supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result);
159
160 tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
161 vht_cap->vht_cap.supp_mcs.tx_highest = cpu_to_le16(tmp);
162
163 return;
164}
165
166int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
167 struct mwifiex_bssdescriptor *bss_desc,
168 u8 **buffer)
169{
170 struct mwifiex_ie_types_vhtcap *vht_cap;
171 struct mwifiex_ie_types_oper_mode_ntf *oper_ntf;
172 struct ieee_types_oper_mode_ntf *ieee_oper_ntf;
173 struct mwifiex_ie_types_vht_oper *vht_op;
174 struct mwifiex_adapter *adapter = priv->adapter;
175 u8 supp_chwd_set;
176 u32 usr_vht_cap_info;
177 int ret_len = 0;
178
179 if (bss_desc->bss_band & BAND_A)
180 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
181 else
182 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
183
184 /* VHT Capabilities IE */
185 if (bss_desc->bcn_vht_cap) {
186 vht_cap = (struct mwifiex_ie_types_vhtcap *)*buffer;
187 memset(vht_cap, 0, sizeof(*vht_cap));
188 vht_cap->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
189 vht_cap->header.len =
190 cpu_to_le16(sizeof(struct ieee80211_vht_cap));
191 memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header),
192 (u8 *)bss_desc->bcn_vht_cap +
193 sizeof(struct ieee_types_header),
194 le16_to_cpu(vht_cap->header.len));
195
196 mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band);
197 *buffer += sizeof(*vht_cap);
198 ret_len += sizeof(*vht_cap);
199 }
200
201 /* VHT Operation IE */
202 if (bss_desc->bcn_vht_oper) {
203 if (priv->bss_mode == HostCmd_BSS_MODE_IBSS) {
204 vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
205 memset(vht_op, 0, sizeof(*vht_op));
206 vht_op->header.type =
207 cpu_to_le16(WLAN_EID_VHT_OPERATION);
208 vht_op->header.len = cpu_to_le16(sizeof(*vht_op) -
209 sizeof(struct mwifiex_ie_types_header));
210 memcpy((u8 *)vht_op +
211 sizeof(struct mwifiex_ie_types_header),
212 (u8 *)bss_desc->bcn_vht_oper +
213 sizeof(struct ieee_types_header),
214 le16_to_cpu(vht_op->header.len));
215
216 /* negotiate the channel width and central freq
217 * and keep the central freq as the peer suggests
218 */
219 supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
220
221 switch (supp_chwd_set) {
222 case 0:
223 vht_op->chan_width =
224 min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ,
225 bss_desc->bcn_vht_oper->chan_width);
226 break;
227 case 1:
228 vht_op->chan_width =
229 min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ,
230 bss_desc->bcn_vht_oper->chan_width);
231 break;
232 case 2:
233 vht_op->chan_width =
234 min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ,
235 bss_desc->bcn_vht_oper->chan_width);
236 break;
237 default:
238 vht_op->chan_width =
239 IEEE80211_VHT_CHANWIDTH_USE_HT;
240 break;
241 }
242
243 *buffer += sizeof(*vht_op);
244 ret_len += sizeof(*vht_op);
245 }
246 }
247
248 /* Operating Mode Notification IE */
249 if (bss_desc->oper_mode) {
250 ieee_oper_ntf = bss_desc->oper_mode;
251 oper_ntf = (void *)*buffer;
252 memset(oper_ntf, 0, sizeof(*oper_ntf));
253 oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF);
254 oper_ntf->header.len = cpu_to_le16(sizeof(u8));
255 oper_ntf->oper_mode = ieee_oper_ntf->oper_mode;
256 *buffer += sizeof(*oper_ntf);
257 ret_len += sizeof(*oper_ntf);
258 }
259
260 return ret_len;
261}
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h
new file mode 100644
index 000000000000..80fd1ba46200
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/11ac.h
@@ -0,0 +1,26 @@
1/*
2 * Marvell Wireless LAN device driver: 802.11ac
3 *
4 * Copyright (C) 2013, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#ifndef _MWIFIEX_11AC_H_
21#define _MWIFIEX_11AC_H_
22
23int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
24 struct mwifiex_bssdescriptor *bss_desc,
25 u8 **buffer);
26#endif /* _MWIFIEX_11AC_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 48cc46bc152f..5e4e51a18b80 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -250,7 +250,8 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
250 * - Setting HT Tx capability and HT Tx information fields 250 * - Setting HT Tx capability and HT Tx information fields
251 * - Ensuring correct endian-ness 251 * - Ensuring correct endian-ness
252 */ 252 */
253int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, 253int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
254 struct host_cmd_ds_command *cmd, u16 cmd_action,
254 struct mwifiex_ds_11n_tx_cfg *txcfg) 255 struct mwifiex_ds_11n_tx_cfg *txcfg)
255{ 256{
256 struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; 257 struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
@@ -260,6 +261,10 @@ int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
260 htcfg->action = cpu_to_le16(cmd_action); 261 htcfg->action = cpu_to_le16(cmd_action);
261 htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap); 262 htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap);
262 htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo); 263 htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo);
264
265 if (priv->adapter->is_hw_11ac_capable)
266 htcfg->misc_config = cpu_to_le16(txcfg->misc_config);
267
263 return 0; 268 return 0;
264} 269}
265 270
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 29a4c02479d6..375db01442bf 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -28,9 +28,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
28 struct host_cmd_ds_command *resp); 28 struct host_cmd_ds_command *resp);
29int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, 29int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
30 struct host_cmd_ds_command *resp); 30 struct host_cmd_ds_command *resp);
31int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, 31int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv,
32 struct host_cmd_ds_command *cmd, u16 cmd_action,
32 struct mwifiex_ds_11n_tx_cfg *txcfg); 33 struct mwifiex_ds_11n_tx_cfg *txcfg);
33
34int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, 34int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
35 struct mwifiex_bssdescriptor *bss_desc, 35 struct mwifiex_bssdescriptor *bss_desc,
36 u8 **buffer); 36 u8 **buffer);
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index dd0410d2d465..97b245cbafd8 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -23,6 +23,7 @@ mwifiex-y += util.o
23mwifiex-y += txrx.o 23mwifiex-y += txrx.o
24mwifiex-y += wmm.o 24mwifiex-y += wmm.o
25mwifiex-y += 11n.o 25mwifiex-y += 11n.o
26mwifiex-y += 11ac.o
26mwifiex-y += 11n_aggr.o 27mwifiex-y += 11n_aggr.o
27mwifiex-y += 11n_rxreorder.o 28mwifiex-y += 11n_rxreorder.o
28mwifiex-y += scan.o 29mwifiex-y += scan.o
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 81c84a29308f..9667425362ed 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -834,6 +834,66 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
834 return ret; 834 return ret;
835} 835}
836 836
837static void
838mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
839 struct rate_info *rate)
840{
841 struct mwifiex_adapter *adapter = priv->adapter;
842
843 if (adapter->is_hw_11ac_capable) {
844 /* bit[1-0]: 00=LG 01=HT 10=VHT */
845 if (tx_htinfo & BIT(0)) {
846 /* HT */
847 rate->mcs = priv->tx_rate;
848 rate->flags |= RATE_INFO_FLAGS_MCS;
849 }
850 if (tx_htinfo & BIT(1)) {
851 /* VHT */
852 rate->mcs = priv->tx_rate & 0x0F;
853 rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
854 }
855
856 if (tx_htinfo & (BIT(1) | BIT(0))) {
857 /* HT or VHT */
858 switch (tx_htinfo & (BIT(3) | BIT(2))) {
859 case 0:
860 /* This will be 20MHz */
861 break;
862 case (BIT(2)):
863 rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
864 break;
865 case (BIT(3)):
866 rate->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
867 break;
868 case (BIT(3) | BIT(2)):
869 rate->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
870 break;
871 }
872
873 if (tx_htinfo & BIT(4))
874 rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
875
876 if ((priv->tx_rate >> 4) == 1)
877 rate->nss = 2;
878 else
879 rate->nss = 1;
880 }
881 } else {
882 /*
883 * Bit 0 in tx_htinfo indicates that current Tx rate
884 * is 11n rate. Valid MCS index values for us are 0 to 15.
885 */
886 if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
887 rate->mcs = priv->tx_rate;
888 rate->flags |= RATE_INFO_FLAGS_MCS;
889 if (tx_htinfo & BIT(1))
890 rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
891 if (tx_htinfo & BIT(2))
892 rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
893 }
894 }
895}
896
837/* 897/*
838 * This function dumps the station information on a buffer. 898 * This function dumps the station information on a buffer.
839 * 899 *
@@ -873,20 +933,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
873 HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, 933 HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,
874 &priv->dtim_period); 934 &priv->dtim_period);
875 935
876 /* 936 mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate);
877 * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid
878 * MCS index values for us are 0 to 15.
879 */
880 if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
881 sinfo->txrate.mcs = priv->tx_rate;
882 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
883 /* 40MHz rate */
884 if (priv->tx_htinfo & BIT(1))
885 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
886 /* SGI enabled */
887 if (priv->tx_htinfo & BIT(2))
888 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
889 }
890 937
891 sinfo->signal_avg = priv->bcn_rssi_avg; 938 sinfo->signal_avg = priv->bcn_rssi_avg;
892 sinfo->rx_bytes = priv->stats.rx_bytes; 939 sinfo->rx_bytes = priv->stats.rx_bytes;
@@ -1295,20 +1342,22 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
1295 /* Set appropriate bands */ 1342 /* Set appropriate bands */
1296 if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { 1343 if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
1297 bss_cfg->band_cfg = BAND_CONFIG_BG; 1344 bss_cfg->band_cfg = BAND_CONFIG_BG;
1345 config_bands = BAND_B | BAND_G;
1298 1346
1299 if (cfg80211_get_chandef_type(&params->chandef) == 1347 if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
1300 NL80211_CHAN_NO_HT) 1348 config_bands |= BAND_GN;
1301 config_bands = BAND_B | BAND_G; 1349
1302 else 1350 if (params->chandef.width > NL80211_CHAN_WIDTH_40)
1303 config_bands = BAND_B | BAND_G | BAND_GN; 1351 config_bands |= BAND_GAC;
1304 } else { 1352 } else {
1305 bss_cfg->band_cfg = BAND_CONFIG_A; 1353 bss_cfg->band_cfg = BAND_CONFIG_A;
1354 config_bands = BAND_A;
1306 1355
1307 if (cfg80211_get_chandef_type(&params->chandef) == 1356 if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT)
1308 NL80211_CHAN_NO_HT) 1357 config_bands |= BAND_AN;
1309 config_bands = BAND_A; 1358
1310 else 1359 if (params->chandef.width > NL80211_CHAN_WIDTH_40)
1311 config_bands = BAND_AN | BAND_A; 1360 config_bands |= BAND_AAC;
1312 } 1361 }
1313 1362
1314 if (!((config_bands | priv->adapter->fw_bands) & 1363 if (!((config_bands | priv->adapter->fw_bands) &
@@ -1881,6 +1930,79 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
1881 return 0; 1930 return 0;
1882} 1931}
1883 1932
1933static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
1934 struct mwifiex_private *priv)
1935{
1936 struct mwifiex_adapter *adapter = priv->adapter;
1937 u32 vht_cap = 0, cap = adapter->hw_dot_11ac_dev_cap;
1938
1939 vht_info->vht_supported = true;
1940
1941 switch (GET_VHTCAP_MAXMPDULEN(cap)) {
1942 case 0x00:
1943 vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
1944 break;
1945 case 0x01:
1946 vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
1947 break;
1948 case 0x10:
1949 vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
1950 break;
1951 default:
1952 dev_err(adapter->dev, "unsupported MAX MPDU len\n");
1953 break;
1954 }
1955
1956 if (ISSUPP_11ACVHTHTCVHT(cap))
1957 vht_cap |= IEEE80211_VHT_CAP_HTC_VHT;
1958
1959 if (ISSUPP_11ACVHTTXOPPS(cap))
1960 vht_cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS;
1961
1962 if (ISSUPP_11ACMURXBEAMFORMEE(cap))
1963 vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
1964
1965 if (ISSUPP_11ACMUTXBEAMFORMEE(cap))
1966 vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
1967
1968 if (ISSUPP_11ACSUBEAMFORMER(cap))
1969 vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
1970
1971 if (ISSUPP_11ACSUBEAMFORMEE(cap))
1972 vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
1973
1974 if (ISSUPP_11ACRXSTBC(cap))
1975 vht_cap |= IEEE80211_VHT_CAP_RXSTBC_1;
1976
1977 if (ISSUPP_11ACTXSTBC(cap))
1978 vht_cap |= IEEE80211_VHT_CAP_TXSTBC;
1979
1980 if (ISSUPP_11ACSGI160(cap))
1981 vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
1982
1983 if (ISSUPP_11ACSGI80(cap))
1984 vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
1985
1986 if (ISSUPP_11ACLDPC(cap))
1987 vht_cap |= IEEE80211_VHT_CAP_RXLDPC;
1988
1989 if (ISSUPP_11ACBW8080(cap))
1990 vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1991
1992 if (ISSUPP_11ACBW160(cap))
1993 vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
1994
1995 vht_info->cap = vht_cap;
1996
1997 /* Update MCS support for VHT */
1998 vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(
1999 adapter->hw_dot_11ac_mcs_support & 0xFFFF);
2000 vht_info->vht_mcs.rx_highest = 0;
2001 vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(
2002 adapter->hw_dot_11ac_mcs_support >> 16);
2003 vht_info->vht_mcs.tx_highest = 0;
2004}
2005
1884/* 2006/*
1885 * This function sets up the CFG802.11 specific HT capability fields 2007 * This function sets up the CFG802.11 specific HT capability fields
1886 * with default values. 2008 * with default values.
@@ -2094,11 +2216,18 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
2094 priv->netdev = dev; 2216 priv->netdev = dev;
2095 2217
2096 mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); 2218 mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
2219 if (adapter->is_hw_11ac_capable)
2220 mwifiex_setup_vht_caps(
2221 &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv);
2097 2222
2098 if (adapter->config_bands & BAND_A) 2223 if (adapter->config_bands & BAND_A)
2099 mwifiex_setup_ht_caps( 2224 mwifiex_setup_ht_caps(
2100 &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); 2225 &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
2101 2226
2227 if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)
2228 mwifiex_setup_vht_caps(
2229 &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv);
2230
2102 dev_net_set(dev, wiphy_net(wiphy)); 2231 dev_net_set(dev, wiphy_net(wiphy));
2103 dev->ieee80211_ptr = priv->wdev; 2232 dev->ieee80211_ptr = priv->wdev;
2104 dev->ieee80211_ptr->iftype = priv->bss_mode; 2233 dev->ieee80211_ptr->iftype = priv->bss_mode;
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c
index f69300f93f42..988552dece75 100644
--- a/drivers/net/wireless/mwifiex/cfp.c
+++ b/drivers/net/wireless/mwifiex/cfp.c
@@ -106,8 +106,8 @@ u8 *mwifiex_11d_code_2_region(u8 code)
106 * This function maps an index in supported rates table into 106 * This function maps an index in supported rates table into
107 * the corresponding data rate. 107 * the corresponding data rate.
108 */ 108 */
109u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index, 109u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
110 u8 ht_info) 110 u8 index, u8 ht_info)
111{ 111{
112 /* 112 /*
113 * For every mcs_rate line, the first 8 bytes are for stream 1x1, 113 * For every mcs_rate line, the first 8 bytes are for stream 1x1,
@@ -130,10 +130,155 @@ u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index,
130 { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 130 { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
131 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } 131 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
132 }; 132 };
133 /* AC rates */
134 u16 ac_mcs_rate_nss1[8][10] = {
135 /* LG 160M */
136 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
137 0x492, 0x57C, 0x618 },
138
139 /* SG 160M */
140 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
141 0x514, 0x618, 0x6C6 },
142
143 /* LG 80M */
144 { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F,
145 0x249, 0x2BE, 0x30C },
146
147 /* SG 80M */
148 { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249,
149 0x28A, 0x30C, 0x363 },
150
151 /* LG 40M */
152 { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3,
153 0x10E, 0x144, 0x168 },
154
155 /* SG 40M */
156 { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E,
157 0x12C, 0x168, 0x190 },
158
159 /* LG 20M */
160 { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 },
161
162 /* SG 20M */
163 { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 },
164 };
165 /* NSS2 note: the value in the table is 2 multiplier of the actual
166 * rate
167 */
168 u16 ac_mcs_rate_nss2[8][10] = {
169 /* LG 160M */
170 { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A,
171 0x924, 0xAF8, 0xC30 },
172
173 /* SG 160M */
174 { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924,
175 0xA28, 0xC30, 0xD8B },
176
177 /* LG 80M */
178 { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D,
179 0x492, 0x57C, 0x618 },
180
181 /* SG 80M */
182 { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492,
183 0x514, 0x618, 0x6C6 },
184
185 /* LG 40M */
186 { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6,
187 0x21C, 0x288, 0x2D0 },
188
189 /* SG 40M */
190 { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C,
191 0x258, 0x2D0, 0x320 },
192
193 /* LG 20M */
194 { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104,
195 0x138, 0x00 },
196
197 /* SG 20M */
198 { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121,
199 0x15B, 0x00 },
200 };
201 u32 rate = 0;
202 u8 mcs_index = 0;
203 u8 bw = 0;
204 u8 gi = 0;
205
206 if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) {
207 mcs_index = min(index & 0xF, 9);
208
209 /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */
210 bw = (ht_info & 0xC) >> 2;
211
212 /* LGI: gi =0, SGI: gi = 1 */
213 gi = (ht_info & 0x10) >> 4;
214
215 if ((index >> 4) == 1) /* NSS = 2 */
216 rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index];
217 else /* NSS = 1 */
218 rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index];
219 } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) {
220 /* 20M: bw=0, 40M: bw=1 */
221 bw = (ht_info & 0xC) >> 2;
222
223 /* LGI: gi =0, SGI: gi = 1 */
224 gi = (ht_info & 0x10) >> 4;
225
226 if (index == MWIFIEX_RATE_BITMAP_MCS0) {
227 if (gi == 1)
228 rate = 0x0D; /* MCS 32 SGI rate */
229 else
230 rate = 0x0C; /* MCS 32 LGI rate */
231 } else if (index < 16) {
232 if ((bw == 1) || (bw == 0))
233 rate = mcs_rate[2 * (1 - bw) + gi][index];
234 else
235 rate = mwifiex_data_rates[0];
236 } else {
237 rate = mwifiex_data_rates[0];
238 }
239 } else {
240 /* 11n non-HT rates */
241 if (index >= MWIFIEX_SUPPORTED_RATES_EXT)
242 index = 0;
243 rate = mwifiex_data_rates[index];
244 }
245
246 return rate;
247}
248
249/* This function maps an index in supported rates table into
250 * the corresponding data rate.
251 */
252u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
253 u8 index, u8 ht_info)
254{
255 /* For every mcs_rate line, the first 8 bytes are for stream 1x1,
256 * and all 16 bytes are for stream 2x2.
257 */
258 u16 mcs_rate[4][16] = {
259 /* LGI 40M */
260 { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e,
261 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c },
262
263 /* SGI 40M */
264 { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c,
265 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 },
266
267 /* LGI 20M */
268 { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82,
269 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 },
270
271 /* SGI 20M */
272 { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90,
273 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 }
274 };
133 u32 mcs_num_supp = 275 u32 mcs_num_supp =
134 (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8; 276 (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8;
135 u32 rate; 277 u32 rate;
136 278
279 if (priv->adapter->is_hw_11ac_capable)
280 return mwifiex_index_to_acs_data_rate(priv, index, ht_info);
281
137 if (ht_info & BIT(0)) { 282 if (ht_info & BIT(0)) {
138 if (index == MWIFIEX_RATE_BITMAP_MCS0) { 283 if (index == MWIFIEX_RATE_BITMAP_MCS0) {
139 if (ht_info & BIT(2)) 284 if (ht_info & BIT(2))
@@ -269,6 +414,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
269{ 414{
270 u32 k = 0; 415 u32 k = 0;
271 struct mwifiex_adapter *adapter = priv->adapter; 416 struct mwifiex_adapter *adapter = priv->adapter;
417
272 if (priv->bss_mode == NL80211_IFTYPE_STATION) { 418 if (priv->bss_mode == NL80211_IFTYPE_STATION) {
273 switch (adapter->config_bands) { 419 switch (adapter->config_bands) {
274 case BAND_B: 420 case BAND_B:
@@ -279,6 +425,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
279 break; 425 break;
280 case BAND_G: 426 case BAND_G:
281 case BAND_G | BAND_GN: 427 case BAND_G | BAND_GN:
428 case BAND_G | BAND_GN | BAND_GAC:
282 dev_dbg(adapter->dev, "info: infra band=%d " 429 dev_dbg(adapter->dev, "info: infra band=%d "
283 "supported_rates_g\n", adapter->config_bands); 430 "supported_rates_g\n", adapter->config_bands);
284 k = mwifiex_copy_rates(rates, k, supported_rates_g, 431 k = mwifiex_copy_rates(rates, k, supported_rates_g,
@@ -288,7 +435,11 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
288 case BAND_A | BAND_B | BAND_G: 435 case BAND_A | BAND_B | BAND_G:
289 case BAND_A | BAND_B: 436 case BAND_A | BAND_B:
290 case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: 437 case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN:
438 case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC:
439 case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN |
440 BAND_AAC | BAND_GAC:
291 case BAND_B | BAND_G | BAND_GN: 441 case BAND_B | BAND_G | BAND_GN:
442 case BAND_B | BAND_G | BAND_GN | BAND_GAC:
292 dev_dbg(adapter->dev, "info: infra band=%d " 443 dev_dbg(adapter->dev, "info: infra band=%d "
293 "supported_rates_bg\n", adapter->config_bands); 444 "supported_rates_bg\n", adapter->config_bands);
294 k = mwifiex_copy_rates(rates, k, supported_rates_bg, 445 k = mwifiex_copy_rates(rates, k, supported_rates_bg,
@@ -301,14 +452,18 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates)
301 k = mwifiex_copy_rates(rates, k, supported_rates_a, 452 k = mwifiex_copy_rates(rates, k, supported_rates_a,
302 sizeof(supported_rates_a)); 453 sizeof(supported_rates_a));
303 break; 454 break;
455 case BAND_AN:
304 case BAND_A | BAND_AN: 456 case BAND_A | BAND_AN:
457 case BAND_A | BAND_AN | BAND_AAC:
305 case BAND_A | BAND_G | BAND_AN | BAND_GN: 458 case BAND_A | BAND_G | BAND_AN | BAND_GN:
459 case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC:
306 dev_dbg(adapter->dev, "info: infra band=%d " 460 dev_dbg(adapter->dev, "info: infra band=%d "
307 "supported_rates_a\n", adapter->config_bands); 461 "supported_rates_a\n", adapter->config_bands);
308 k = mwifiex_copy_rates(rates, k, supported_rates_a, 462 k = mwifiex_copy_rates(rates, k, supported_rates_a,
309 sizeof(supported_rates_a)); 463 sizeof(supported_rates_a));
310 break; 464 break;
311 case BAND_GN: 465 case BAND_GN:
466 case BAND_GN | BAND_GAC:
312 dev_dbg(adapter->dev, "info: infra band=%d " 467 dev_dbg(adapter->dev, "info: infra band=%d "
313 "supported_rates_n\n", adapter->config_bands); 468 "supported_rates_n\n", adapter->config_bands);
314 k = mwifiex_copy_rates(rates, k, supported_rates_n, 469 k = mwifiex_copy_rates(rates, k, supported_rates_n,
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 5f438e6c2155..5019f1f2e01c 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -24,6 +24,7 @@
24#include "main.h" 24#include "main.h"
25#include "wmm.h" 25#include "wmm.h"
26#include "11n.h" 26#include "11n.h"
27#include "11ac.h"
27 28
28/* 29/*
29 * This function initializes a command node. 30 * This function initializes a command node.
@@ -1470,6 +1471,24 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
1470 adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); 1471 adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
1471 adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); 1472 adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna);
1472 1473
1474 if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
1475 adapter->is_hw_11ac_capable = true;
1476
1477 /* Copy 11AC cap */
1478 adapter->hw_dot_11ac_dev_cap =
1479 le32_to_cpu(hw_spec->dot_11ac_dev_cap);
1480 adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap;
1481 adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap;
1482
1483 /* Copy 11AC mcs */
1484 adapter->hw_dot_11ac_mcs_support =
1485 le32_to_cpu(hw_spec->dot_11ac_mcs_support);
1486 adapter->usr_dot_11ac_mcs_support =
1487 adapter->hw_dot_11ac_mcs_support;
1488 } else {
1489 adapter->is_hw_11ac_capable = false;
1490 }
1491
1473 dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", 1492 dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n",
1474 adapter->fw_release_number); 1493 adapter->fw_release_number);
1475 dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", 1494 dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n",
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index ebe2f6a7984c..25acb0682c56 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -49,13 +49,23 @@ struct tx_packet_hdr {
49#define A_SUPPORTED_RATES 9 49#define A_SUPPORTED_RATES 9
50#define HOSTCMD_SUPPORTED_RATES 14 50#define HOSTCMD_SUPPORTED_RATES 14
51#define N_SUPPORTED_RATES 3 51#define N_SUPPORTED_RATES 3
52#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN) 52#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN | \
53 BAND_AN | BAND_GAC | BAND_AAC)
53 54
54#define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11)) 55#define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \
56 BIT(12) | BIT(13))
55#define IS_SUPPORT_MULTI_BANDS(adapter) \ 57#define IS_SUPPORT_MULTI_BANDS(adapter) \
56 (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) 58 (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT)
59
60/* shift bit 12 and bit 13 in fw_cap_info from the firmware to bit 13 and 14
61 * for 11ac so that bit 11 is for GN, bit 12 for AN, bit 13 for GAC, and bit
62 * bit 14 for AAC, in order to be compatible with the band capability
63 * defined in the driver after right shift of 8 bits.
64 */
57#define GET_FW_DEFAULT_BANDS(adapter) \ 65#define GET_FW_DEFAULT_BANDS(adapter) \
58 ((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS) 66 (((((adapter->fw_cap_info & 0x3000) << 1) | \
67 (adapter->fw_cap_info & ~0xF000)) >> 8) & \
68 ALL_802_11_BANDS)
59 69
60#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff 70#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff
61 71
@@ -216,6 +226,47 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
216 226
217#define LLC_SNAP_LEN 8 227#define LLC_SNAP_LEN 8
218 228
229/* HW_SPEC fw_cap_info */
230
231#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14)))
232
233#define GET_VHTCAP_MAXMPDULEN(vht_cap_info) (vht_cap_info & 0x3)
234#define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3)
235#define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3)
236#define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \
237 (2 * (nss - 1)))
238#define NO_NSS_SUPPORT 0x3
239
240/* HW_SPEC: HTC-VHT supported */
241#define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & BIT(22))
242/* HW_SPEC: VHT TXOP PS support */
243#define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & BIT(21))
244/* HW_SPEC: MU RX beamformee support */
245#define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(20))
246/* HW_SPEC: MU TX beamformee support */
247#define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(19))
248/* HW_SPEC: SU Beamformee support */
249#define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(10))
250/* HW_SPEC: SU Beamformer support */
251#define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & BIT(9))
252/* HW_SPEC: Rx STBC support */
253#define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(8))
254/* HW_SPEC: Tx STBC support */
255#define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(7))
256/* HW_SPEC: Short GI support for 160MHz BW */
257#define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & BIT(6))
258/* HW_SPEC: Short GI support for 80MHz BW */
259#define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & BIT(5))
260/* HW_SPEC: LDPC coding support */
261#define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & BIT(4))
262/* HW_SPEC: Channel BW 20/40/80/160/80+80 MHz support */
263#define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & BIT(3))
264/* HW_SPEC: Channel BW 20/40/80/160 MHz support */
265#define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & BIT(2))
266
267#define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16)
268#define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF)
269
219#define MOD_CLASS_HR_DSSS 0x03 270#define MOD_CLASS_HR_DSSS 0x03
220#define MOD_CLASS_OFDM 0x07 271#define MOD_CLASS_OFDM 0x07
221#define MOD_CLASS_HT 0x08 272#define MOD_CLASS_HT 0x08
@@ -455,9 +506,22 @@ struct rxpd {
455 u8 rx_rate; 506 u8 rx_rate;
456 s8 snr; 507 s8 snr;
457 s8 nf; 508 s8 nf;
458 /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 509
510 /* For: Non-802.11 AC cards
511 *
512 * Ht Info [Bit 0] RxRate format: LG=0, HT=1
459 * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 513 * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1
460 * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ 514 * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1
515 *
516 * For: 802.11 AC cards
517 * [Bit 1] [Bit 0] RxRate format: legacy rate = 00 HT = 01 VHT = 10
518 * [Bit 3] [Bit 2] HT/VHT Bandwidth BW20 = 00 BW40 = 01
519 * BW80 = 10 BW160 = 11
520 * [Bit 4] HT/VHT Guard interval LGI = 0 SGI = 1
521 * [Bit 5] STBC support Enabled = 1
522 * [Bit 6] LDPC support Enabled = 1
523 * [Bit 7] Reserved
524 */
461 u8 ht_info; 525 u8 ht_info;
462 u8 reserved; 526 u8 reserved;
463} __packed; 527} __packed;
@@ -680,7 +744,11 @@ struct host_cmd_ds_get_hw_spec {
680 __le32 dot_11n_dev_cap; 744 __le32 dot_11n_dev_cap;
681 u8 dev_mcs_support; 745 u8 dev_mcs_support;
682 __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ 746 __le16 mp_end_port; /* SDIO only, reserved for other interfacces */
683 __le16 reserved_4; 747 __le16 mgmt_buf_count; /* mgmt IE buffer count */
748 __le32 reserved_5;
749 __le32 reserved_6;
750 __le32 dot_11ac_dev_cap;
751 __le32 dot_11ac_mcs_support;
684} __packed; 752} __packed;
685 753
686struct host_cmd_ds_802_11_rssi_info { 754struct host_cmd_ds_802_11_rssi_info {
@@ -786,6 +854,12 @@ union ieee_types_phy_param_set {
786 struct ieee_types_ds_param_set ds_param_set; 854 struct ieee_types_ds_param_set ds_param_set;
787} __packed; 855} __packed;
788 856
857struct ieee_types_oper_mode_ntf {
858 u8 element_id;
859 u8 len;
860 u8 oper_mode;
861} __packed;
862
789struct host_cmd_ds_802_11_ad_hoc_start { 863struct host_cmd_ds_802_11_ad_hoc_start {
790 u8 ssid[IEEE80211_MAX_SSID_LEN]; 864 u8 ssid[IEEE80211_MAX_SSID_LEN];
791 u8 bss_mode; 865 u8 bss_mode;
@@ -846,11 +920,27 @@ struct host_cmd_ds_802_11_get_log {
846 __le32 wep_icv_err_cnt[4]; 920 __le32 wep_icv_err_cnt[4];
847}; 921};
848 922
923/* Enumeration for rate format */
924enum _mwifiex_rate_format {
925 MWIFIEX_RATE_FORMAT_LG = 0,
926 MWIFIEX_RATE_FORMAT_HT,
927 MWIFIEX_RATE_FORMAT_VHT,
928 MWIFIEX_RATE_FORMAT_AUTO = 0xFF,
929};
930
849struct host_cmd_ds_tx_rate_query { 931struct host_cmd_ds_tx_rate_query {
850 u8 tx_rate; 932 u8 tx_rate;
851 /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 933 /* Tx Rate Info: For 802.11 AC cards
934 *
935 * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2
936 * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3
937 * [Bit 4] HT/VHT Guard Interval: LGI = 0, SGI = 1
938 *
939 * For non-802.11 AC cards
940 * Ht Info [Bit 0] RxRate format: LG=0, HT=1
852 * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 941 * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1
853 * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ 942 * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1
943 */
854 u8 ht_info; 944 u8 ht_info;
855} __packed; 945} __packed;
856 946
@@ -1096,6 +1186,7 @@ struct host_cmd_ds_11n_cfg {
1096 __le16 action; 1186 __le16 action;
1097 __le16 ht_tx_cap; 1187 __le16 ht_tx_cap;
1098 __le16 ht_tx_info; 1188 __le16 ht_tx_info;
1189 __le16 misc_config; /* Needed for 802.11AC cards only */
1099} __packed; 1190} __packed;
1100 1191
1101struct host_cmd_ds_txbuf_cfg { 1192struct host_cmd_ds_txbuf_cfg {
@@ -1183,6 +1274,26 @@ struct mwifiex_ie_types_htcap {
1183 struct ieee80211_ht_cap ht_cap; 1274 struct ieee80211_ht_cap ht_cap;
1184} __packed; 1275} __packed;
1185 1276
1277struct mwifiex_ie_types_vhtcap {
1278 struct mwifiex_ie_types_header header;
1279 struct ieee80211_vht_cap vht_cap;
1280} __packed;
1281
1282struct mwifiex_ie_types_oper_mode_ntf {
1283 struct mwifiex_ie_types_header header;
1284 u8 oper_mode;
1285} __packed;
1286
1287/* VHT Operations IE */
1288struct mwifiex_ie_types_vht_oper {
1289 struct mwifiex_ie_types_header header;
1290 u8 chan_width;
1291 u8 chan_center_freq_1;
1292 u8 chan_center_freq_2;
1293 /* Basic MCS set map, each 2 bits stands for a NSS */
1294 u16 basic_mcs_map;
1295} __packed;
1296
1186struct mwifiex_ie_types_wmmcap { 1297struct mwifiex_ie_types_wmmcap {
1187 struct mwifiex_ie_types_header header; 1298 struct mwifiex_ie_types_header header;
1188 struct mwifiex_types_wmm_info wmm_info; 1299 struct mwifiex_types_wmm_info wmm_info;
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index f3d9d0445529..d85e6eb1f58a 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -60,6 +60,8 @@ enum {
60 BAND_A = 4, 60 BAND_A = 4,
61 BAND_GN = 8, 61 BAND_GN = 8,
62 BAND_AN = 16, 62 BAND_AN = 16,
63 BAND_GAC = 32,
64 BAND_AAC = 64,
63}; 65};
64 66
65#define MWIFIEX_WPA_PASSHPHRASE_LEN 64 67#define MWIFIEX_WPA_PASSHPHRASE_LEN 64
@@ -103,6 +105,7 @@ struct mwifiex_uap_bss_param {
103 struct wpa_param wpa_cfg; 105 struct wpa_param wpa_cfg;
104 struct wep_key wep_cfg[NUM_WEP_KEYS]; 106 struct wep_key wep_cfg[NUM_WEP_KEYS];
105 struct ieee80211_ht_cap ht_cap; 107 struct ieee80211_ht_cap ht_cap;
108 struct ieee80211_vht_cap vht_cap;
106 u8 rates[MWIFIEX_SUPPORTED_RATES]; 109 u8 rates[MWIFIEX_SUPPORTED_RATES];
107 u32 sta_ao_timer; 110 u32 sta_ao_timer;
108 u32 ps_sta_ao_timer; 111 u32 ps_sta_ao_timer;
@@ -272,6 +275,7 @@ struct mwifiex_ds_pm_cfg {
272struct mwifiex_ds_11n_tx_cfg { 275struct mwifiex_ds_11n_tx_cfg {
273 u16 tx_htcap; 276 u16 tx_htcap;
274 u16 tx_htinfo; 277 u16 tx_htinfo;
278 u16 misc_config; /* Needed for 802.11AC cards only */
275}; 279};
276 280
277struct mwifiex_ds_11n_amsdu_aggr_ctrl { 281struct mwifiex_ds_11n_amsdu_aggr_ctrl {
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index a537297866c6..246aa62a4817 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -24,6 +24,7 @@
24#include "main.h" 24#include "main.h"
25#include "wmm.h" 25#include "wmm.h"
26#include "11n.h" 26#include "11n.h"
27#include "11ac.h"
27 28
28#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) 29#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9)))
29 30
@@ -512,6 +513,12 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
512 priv->adapter->config_bands & BAND_AN)) 513 priv->adapter->config_bands & BAND_AN))
513 mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); 514 mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos);
514 515
516 if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) &&
517 !bss_desc->disable_11n && !bss_desc->disable_11ac &&
518 (priv->adapter->config_bands & BAND_GAC ||
519 priv->adapter->config_bands & BAND_AAC))
520 mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos);
521
515 /* Append vendor specific IE TLV */ 522 /* Append vendor specific IE TLV */
516 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); 523 mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos);
517 524
@@ -1421,6 +1428,7 @@ mwifiex_band_to_radio_type(u8 band)
1421 case BAND_A: 1428 case BAND_A:
1422 case BAND_AN: 1429 case BAND_AN:
1423 case BAND_A | BAND_AN: 1430 case BAND_A | BAND_AN:
1431 case BAND_A | BAND_AN | BAND_AAC:
1424 return HostCmd_SCAN_RADIO_TYPE_A; 1432 return HostCmd_SCAN_RADIO_TYPE_A;
1425 case BAND_B: 1433 case BAND_B:
1426 case BAND_G: 1434 case BAND_G:
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index ac799a046eb7..553adfb0aa81 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -295,6 +295,13 @@ struct mwifiex_bssdescriptor {
295 u16 bss_co_2040_offset; 295 u16 bss_co_2040_offset;
296 u8 *bcn_ext_cap; 296 u8 *bcn_ext_cap;
297 u16 ext_cap_offset; 297 u16 ext_cap_offset;
298 struct ieee80211_vht_cap *bcn_vht_cap;
299 u16 vht_cap_offset;
300 struct ieee80211_vht_operation *bcn_vht_oper;
301 u16 vht_info_offset;
302 struct ieee_types_oper_mode_ntf *oper_mode;
303 u16 oper_mode_offset;
304 u8 disable_11ac;
298 struct ieee_types_vendor_specific *bcn_wpa_ie; 305 struct ieee_types_vendor_specific *bcn_wpa_ie;
299 u16 wpa_offset; 306 u16 wpa_offset;
300 struct ieee_types_generic *bcn_rsn_ie; 307 struct ieee_types_generic *bcn_rsn_ie;
@@ -499,6 +506,7 @@ struct mwifiex_private {
499 u16 rsn_idx; 506 u16 rsn_idx;
500 struct timer_list scan_delay_timer; 507 struct timer_list scan_delay_timer;
501 u8 ap_11n_enabled; 508 u8 ap_11n_enabled;
509 u8 ap_11ac_enabled;
502 u32 mgmt_frame_mask; 510 u32 mgmt_frame_mask;
503 struct mwifiex_roc_cfg roc_cfg; 511 struct mwifiex_roc_cfg roc_cfg;
504}; 512};
@@ -722,6 +730,15 @@ struct mwifiex_adapter {
722 u16 max_mgmt_ie_index; 730 u16 max_mgmt_ie_index;
723 u8 scan_delay_cnt; 731 u8 scan_delay_cnt;
724 u8 empty_tx_q_cnt; 732 u8 empty_tx_q_cnt;
733
734 /* 11AC */
735 u32 is_hw_11ac_capable;
736 u32 hw_dot_11ac_dev_cap;
737 u32 hw_dot_11ac_mcs_support;
738 u32 usr_dot_11ac_dev_cap_bg;
739 u32 usr_dot_11ac_dev_cap_a;
740 u32 usr_dot_11ac_mcs_support;
741
725 atomic_t is_tx_received; 742 atomic_t is_tx_received;
726 atomic_t pending_bridged_pkts; 743 atomic_t pending_bridged_pkts;
727}; 744};
@@ -864,8 +881,10 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
864int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); 881int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
865struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv, 882struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv,
866 u8 band, u16 channel, u32 freq); 883 u8 band, u16 channel, u32 freq);
867u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index, 884u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv,
868 u8 ht_info); 885 u8 index, u8 ht_info);
886u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv,
887 u8 index, u8 ht_info);
869u32 mwifiex_find_freq_from_band_chan(u8, u8); 888u32 mwifiex_find_freq_from_band_chan(u8, u8);
870int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, 889int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,
871 u8 **buffer); 890 u8 **buffer);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index e275aec5a17a..db4d5ae3ff96 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1250,6 +1250,23 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1250 sizeof(struct ieee_types_header) - 1250 sizeof(struct ieee_types_header) -
1251 bss_entry->beacon_buf); 1251 bss_entry->beacon_buf);
1252 break; 1252 break;
1253 case WLAN_EID_VHT_CAPABILITY:
1254 bss_entry->disable_11ac = false;
1255 bss_entry->bcn_vht_cap =
1256 (void *)(current_ptr +
1257 sizeof(struct ieee_types_header));
1258 bss_entry->vht_cap_offset =
1259 (u16)((u8 *)bss_entry->bcn_vht_cap -
1260 bss_entry->beacon_buf);
1261 break;
1262 case WLAN_EID_VHT_OPERATION:
1263 bss_entry->bcn_vht_oper =
1264 (void *)(current_ptr +
1265 sizeof(struct ieee_types_header));
1266 bss_entry->vht_info_offset =
1267 (u16)((u8 *)bss_entry->bcn_vht_oper -
1268 bss_entry->beacon_buf);
1269 break;
1253 case WLAN_EID_BSS_COEX_2040: 1270 case WLAN_EID_BSS_COEX_2040:
1254 bss_entry->bcn_bss_co_2040 = current_ptr + 1271 bss_entry->bcn_bss_co_2040 = current_ptr +
1255 sizeof(struct ieee_types_header); 1272 sizeof(struct ieee_types_header);
@@ -1264,6 +1281,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1264 sizeof(struct ieee_types_header) - 1281 sizeof(struct ieee_types_header) -
1265 bss_entry->beacon_buf); 1282 bss_entry->beacon_buf);
1266 break; 1283 break;
1284 case WLAN_EID_OPMODE_NOTIF:
1285 bss_entry->oper_mode =
1286 (void *)(current_ptr +
1287 sizeof(struct ieee_types_header));
1288 bss_entry->oper_mode_offset =
1289 (u16)((u8 *)bss_entry->oper_mode -
1290 bss_entry->beacon_buf);
1291 break;
1267 default: 1292 default:
1268 break; 1293 break;
1269 } 1294 }
@@ -1494,6 +1519,17 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1494 priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; 1519 priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
1495 priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; 1520 priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
1496 priv->curr_bss_params.bss_descriptor.beacon_buf_size = 0; 1521 priv->curr_bss_params.bss_descriptor.beacon_buf_size = 0;
1522 priv->curr_bss_params.bss_descriptor.bcn_vht_cap = NULL;
1523 priv->curr_bss_params.bss_descriptor.vht_cap_offset = 0;
1524 priv->curr_bss_params.bss_descriptor.bcn_vht_oper = NULL;
1525 priv->curr_bss_params.bss_descriptor.vht_info_offset = 0;
1526 priv->curr_bss_params.bss_descriptor.oper_mode = NULL;
1527 priv->curr_bss_params.bss_descriptor.oper_mode_offset = 0;
1528
1529 /* Disable 11ac by default. Enable it only where there
1530 * exist VHT_CAP IE in AP beacon
1531 */
1532 priv->curr_bss_params.bss_descriptor.disable_11ac = true;
1497 1533
1498 /* Make a copy of current BSSID descriptor */ 1534 /* Make a copy of current BSSID descriptor */
1499 memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, 1535 memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
@@ -2028,6 +2064,14 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2028 (curr_bss->beacon_buf + 2064 (curr_bss->beacon_buf +
2029 curr_bss->ht_info_offset); 2065 curr_bss->ht_info_offset);
2030 2066
2067 if (curr_bss->bcn_vht_cap)
2068 curr_bss->bcn_ht_cap = (void *)(curr_bss->beacon_buf +
2069 curr_bss->vht_cap_offset);
2070
2071 if (curr_bss->bcn_vht_oper)
2072 curr_bss->bcn_ht_oper = (void *)(curr_bss->beacon_buf +
2073 curr_bss->vht_info_offset);
2074
2031 if (curr_bss->bcn_bss_co_2040) 2075 if (curr_bss->bcn_bss_co_2040)
2032 curr_bss->bcn_bss_co_2040 = 2076 curr_bss->bcn_bss_co_2040 =
2033 (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset); 2077 (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
@@ -2035,6 +2079,10 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
2035 if (curr_bss->bcn_ext_cap) 2079 if (curr_bss->bcn_ext_cap)
2036 curr_bss->bcn_ext_cap = curr_bss->beacon_buf + 2080 curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
2037 curr_bss->ext_cap_offset; 2081 curr_bss->ext_cap_offset;
2082
2083 if (curr_bss->oper_mode)
2084 curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
2085 curr_bss->oper_mode_offset);
2038} 2086}
2039 2087
2040/* 2088/*
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index c4607859d59d..c55c5bb93134 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1230,7 +1230,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
1230 data_buf); 1230 data_buf);
1231 break; 1231 break;
1232 case HostCmd_CMD_11N_CFG: 1232 case HostCmd_CMD_11N_CFG:
1233 ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action, data_buf); 1233 ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, data_buf);
1234 break; 1234 break;
1235 case HostCmd_CMD_WMM_GET_STATUS: 1235 case HostCmd_CMD_WMM_GET_STATUS:
1236 dev_dbg(priv->adapter->dev, 1236 dev_dbg(priv->adapter->dev,
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 847056415ac9..4669f8d9389f 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -24,6 +24,7 @@
24#include "main.h" 24#include "main.h"
25#include "wmm.h" 25#include "wmm.h"
26#include "11n.h" 26#include "11n.h"
27#include "11ac.h"
27 28
28 29
29/* 30/*
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 0d018460daf9..7ce72e93260d 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -283,9 +283,10 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
283 283
284 if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) 284 if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band)
285 == HostCmd_SCAN_RADIO_TYPE_BG) 285 == HostCmd_SCAN_RADIO_TYPE_BG)
286 config_bands = BAND_B | BAND_G | BAND_GN; 286 config_bands = BAND_B | BAND_G | BAND_GN |
287 BAND_GAC;
287 else 288 else
288 config_bands = BAND_A | BAND_AN; 289 config_bands = BAND_A | BAND_AN | BAND_AAC;
289 290
290 if (!((config_bands | adapter->fw_bands) & 291 if (!((config_bands | adapter->fw_bands) &
291 ~adapter->fw_bands)) 292 ~adapter->fw_bands))