diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-02 23:53:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-02 23:53:45 -0400 |
commit | cd6362befe4cc7bf589a5236d2a780af2d47bcc9 (patch) | |
tree | 3bd4e13ec3f92a00dc4f6c3d65e820b54dbfe46e /drivers/net/wireless/mwifiex | |
parent | 0f1b1e6d73cb989ce2c071edc57deade3b084dfe (diff) | |
parent | b1586f099ba897542ece36e8a23c1a62907261ef (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller:
"Here is my initial pull request for the networking subsystem during
this merge window:
1) Support for ESN in AH (RFC 4302) from Fan Du.
2) Add full kernel doc for ethtool command structures, from Ben
Hutchings.
3) Add BCM7xxx PHY driver, from Florian Fainelli.
4) Export computed TCP rate information in netlink socket dumps, from
Eric Dumazet.
5) Allow IPSEC SA to be dumped partially using a filter, from Nicolas
Dichtel.
6) Convert many drivers to pci_enable_msix_range(), from Alexander
Gordeev.
7) Record SKB timestamps more efficiently, from Eric Dumazet.
8) Switch to microsecond resolution for TCP round trip times, also
from Eric Dumazet.
9) Clean up and fix 6lowpan fragmentation handling by making use of
the existing inet_frag api for it's implementation.
10) Add TX grant mapping to xen-netback driver, from Zoltan Kiss.
11) Auto size SKB lengths when composing netlink messages based upon
past message sizes used, from Eric Dumazet.
12) qdisc dumps can take a long time, add a cond_resched(), From Eric
Dumazet.
13) Sanitize netpoll core and drivers wrt. SKB handling semantics.
Get rid of never-used-in-tree netpoll RX handling. From Eric W
Biederman.
14) Support inter-address-family and namespace changing in VTI tunnel
driver(s). From Steffen Klassert.
15) Add Altera TSE driver, from Vince Bridgers.
16) Optimizing csum_replace2() so that it doesn't adjust the checksum
by checksumming the entire header, from Eric Dumazet.
17) Expand BPF internal implementation for faster interpreting, more
direct translations into JIT'd code, and much cleaner uses of BPF
filtering in non-socket ocntexts. From Daniel Borkmann and Alexei
Starovoitov"
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1976 commits)
netpoll: Use skb_irq_freeable to make zap_completion_queue safe.
net: Add a test to see if a skb is freeable in irq context
qlcnic: Fix build failure due to undefined reference to `vxlan_get_rx_port'
net: ptp: move PTP classifier in its own file
net: sxgbe: make "core_ops" static
net: sxgbe: fix logical vs bitwise operation
net: sxgbe: sxgbe_mdio_register() frees the bus
Call efx_set_channels() before efx->type->dimension_resources()
xen-netback: disable rogue vif in kthread context
net/mlx4: Set proper build dependancy with vxlan
be2net: fix build dependency on VxLAN
mac802154: make csma/cca parameters per-wpan
mac802154: allow only one WPAN to be up at any given time
net: filter: minor: fix kdoc in __sk_run_filter
netlink: don't compare the nul-termination in nla_strcmp
can: c_can: Avoid led toggling for every packet.
can: c_can: Simplify TX interrupt cleanup
can: c_can: Store dlc private
can: c_can: Reduce register access
can: c_can: Make the code readable
...
Diffstat (limited to 'drivers/net/wireless/mwifiex')
41 files changed, 3844 insertions, 1145 deletions
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c index 5d9a8084665d..c92f27aa71ed 100644 --- a/drivers/net/wireless/mwifiex/11ac.c +++ b/drivers/net/wireless/mwifiex/11ac.c | |||
@@ -23,6 +23,31 @@ | |||
23 | #include "main.h" | 23 | #include "main.h" |
24 | #include "11ac.h" | 24 | #include "11ac.h" |
25 | 25 | ||
26 | /* Tables of the MCS map to the highest data rate (in Mbps) supported | ||
27 | * for long GI. | ||
28 | */ | ||
29 | static const u16 max_rate_lgi_80MHZ[8][3] = { | ||
30 | {0x124, 0x15F, 0x186}, /* NSS = 1 */ | ||
31 | {0x249, 0x2BE, 0x30C}, /* NSS = 2 */ | ||
32 | {0x36D, 0x41D, 0x492}, /* NSS = 3 */ | ||
33 | {0x492, 0x57C, 0x618}, /* NSS = 4 */ | ||
34 | {0x5B6, 0x6DB, 0x79E}, /* NSS = 5 */ | ||
35 | {0x6DB, 0x83A, 0x0}, /* NSS = 6 */ | ||
36 | {0x7FF, 0x999, 0xAAA}, /* NSS = 7 */ | ||
37 | {0x924, 0xAF8, 0xC30} /* NSS = 8 */ | ||
38 | }; | ||
39 | |||
40 | static const u16 max_rate_lgi_160MHZ[8][3] = { | ||
41 | {0x249, 0x2BE, 0x30C}, /* NSS = 1 */ | ||
42 | {0x492, 0x57C, 0x618}, /* NSS = 2 */ | ||
43 | {0x6DB, 0x83A, 0x0}, /* NSS = 3 */ | ||
44 | {0x924, 0xAF8, 0xC30}, /* NSS = 4 */ | ||
45 | {0xB6D, 0xDB6, 0xF3C}, /* NSS = 5 */ | ||
46 | {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */ | ||
47 | {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */ | ||
48 | {0x1248, 0x15F0, 0x1860} /* NSS = 8 */ | ||
49 | }; | ||
50 | |||
26 | /* This function converts the 2-bit MCS map to the highest long GI | 51 | /* This function converts the 2-bit MCS map to the highest long GI |
27 | * VHT data rate. | 52 | * VHT data rate. |
28 | */ | 53 | */ |
@@ -30,33 +55,10 @@ static u16 | |||
30 | mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv, | 55 | mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv, |
31 | u8 bands, u16 mcs_map) | 56 | u8 bands, u16 mcs_map) |
32 | { | 57 | { |
33 | u8 i, nss, max_mcs; | 58 | u8 i, nss, mcs; |
34 | u16 max_rate = 0; | 59 | u16 max_rate = 0; |
35 | u32 usr_vht_cap_info = 0; | 60 | u32 usr_vht_cap_info = 0; |
36 | struct mwifiex_adapter *adapter = priv->adapter; | 61 | 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 | 62 | ||
61 | if (bands & BAND_AAC) | 63 | if (bands & BAND_AAC) |
62 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; | 64 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; |
@@ -64,29 +66,29 @@ mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv, | |||
64 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; | 66 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; |
65 | 67 | ||
66 | /* find the max NSS supported */ | 68 | /* find the max NSS supported */ |
67 | nss = 0; | 69 | nss = 1; |
68 | for (i = 0; i < 8; i++) { | 70 | for (i = 1; i <= 8; i++) { |
69 | max_mcs = (mcs_map >> (2 * i)) & 0x3; | 71 | mcs = GET_VHTNSSMCS(mcs_map, i); |
70 | if (max_mcs < 3) | 72 | if (mcs < IEEE80211_VHT_MCS_NOT_SUPPORTED) |
71 | nss = i; | 73 | nss = i; |
72 | } | 74 | } |
73 | max_mcs = (mcs_map >> (2 * nss)) & 0x3; | 75 | mcs = GET_VHTNSSMCS(mcs_map, nss); |
74 | 76 | ||
75 | /* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9 */ | 77 | /* if mcs is 3, nss must be 1 (NSS = 1). Default mcs to MCS 0~9 */ |
76 | if (max_mcs >= 3) | 78 | if (mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED) |
77 | max_mcs = 2; | 79 | mcs = IEEE80211_VHT_MCS_SUPPORT_0_9; |
78 | 80 | ||
79 | if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) { | 81 | if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) { |
80 | /* support 160 MHz */ | 82 | /* support 160 MHz */ |
81 | max_rate = max_rate_lgi_160MHZ[nss][max_mcs]; | 83 | max_rate = max_rate_lgi_160MHZ[nss - 1][mcs]; |
82 | if (!max_rate) | 84 | if (!max_rate) |
83 | /* MCS9 is not supported in NSS6 */ | 85 | /* MCS9 is not supported in NSS6 */ |
84 | max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1]; | 86 | max_rate = max_rate_lgi_160MHZ[nss - 1][mcs - 1]; |
85 | } else { | 87 | } else { |
86 | max_rate = max_rate_lgi_80MHZ[nss][max_mcs]; | 88 | max_rate = max_rate_lgi_80MHZ[nss - 1][mcs]; |
87 | if (!max_rate) | 89 | if (!max_rate) |
88 | /* MCS9 is not supported in NSS3 */ | 90 | /* MCS9 is not supported in NSS3 */ |
89 | max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1]; | 91 | max_rate = max_rate_lgi_80MHZ[nss - 1][mcs - 1]; |
90 | } | 92 | } |
91 | 93 | ||
92 | return max_rate; | 94 | return max_rate; |
@@ -94,21 +96,20 @@ mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv, | |||
94 | 96 | ||
95 | static void | 97 | static void |
96 | mwifiex_fill_vht_cap_info(struct mwifiex_private *priv, | 98 | mwifiex_fill_vht_cap_info(struct mwifiex_private *priv, |
97 | struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands) | 99 | struct ieee80211_vht_cap *vht_cap, u8 bands) |
98 | { | 100 | { |
99 | struct mwifiex_adapter *adapter = priv->adapter; | 101 | struct mwifiex_adapter *adapter = priv->adapter; |
100 | 102 | ||
101 | if (bands & BAND_A) | 103 | if (bands & BAND_A) |
102 | vht_cap->vht_cap.vht_cap_info = | 104 | vht_cap->vht_cap_info = |
103 | cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a); | 105 | cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a); |
104 | else | 106 | else |
105 | vht_cap->vht_cap.vht_cap_info = | 107 | vht_cap->vht_cap_info = |
106 | cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg); | 108 | cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg); |
107 | } | 109 | } |
108 | 110 | ||
109 | static void | 111 | void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv, |
110 | mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv, | 112 | struct ieee80211_vht_cap *vht_cap, u8 bands) |
111 | struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands) | ||
112 | { | 113 | { |
113 | struct mwifiex_adapter *adapter = priv->adapter; | 114 | struct mwifiex_adapter *adapter = priv->adapter; |
114 | u16 mcs_map_user, mcs_map_resp, mcs_map_result; | 115 | u16 mcs_map_user, mcs_map_resp, mcs_map_result; |
@@ -119,46 +120,48 @@ mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv, | |||
119 | 120 | ||
120 | /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */ | 121 | /* 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_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_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map); |
123 | mcs_map_result = 0; | 124 | mcs_map_result = 0; |
124 | 125 | ||
125 | for (nss = 1; nss <= 8; nss++) { | 126 | for (nss = 1; nss <= 8; nss++) { |
126 | mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); | 127 | mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); |
127 | mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); | 128 | mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); |
128 | 129 | ||
129 | if ((mcs_user == NO_NSS_SUPPORT) || | 130 | if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) || |
130 | (mcs_resp == NO_NSS_SUPPORT)) | 131 | (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED)) |
131 | SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT); | 132 | SET_VHTNSSMCS(mcs_map_result, nss, |
133 | IEEE80211_VHT_MCS_NOT_SUPPORTED); | ||
132 | else | 134 | else |
133 | SET_VHTNSSMCS(mcs_map_result, nss, | 135 | SET_VHTNSSMCS(mcs_map_result, nss, |
134 | min(mcs_user, mcs_resp)); | 136 | min(mcs_user, mcs_resp)); |
135 | } | 137 | } |
136 | 138 | ||
137 | vht_cap->vht_cap.supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result); | 139 | vht_cap->supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result); |
138 | 140 | ||
139 | tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); | 141 | tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); |
140 | vht_cap->vht_cap.supp_mcs.rx_highest = cpu_to_le16(tmp); | 142 | vht_cap->supp_mcs.rx_highest = cpu_to_le16(tmp); |
141 | 143 | ||
142 | /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */ | 144 | /* 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); | 145 | 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); | 146 | mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map); |
145 | mcs_map_result = 0; | 147 | mcs_map_result = 0; |
146 | 148 | ||
147 | for (nss = 1; nss <= 8; nss++) { | 149 | for (nss = 1; nss <= 8; nss++) { |
148 | mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); | 150 | mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); |
149 | mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); | 151 | mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); |
150 | if ((mcs_user == NO_NSS_SUPPORT) || | 152 | if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) || |
151 | (mcs_resp == NO_NSS_SUPPORT)) | 153 | (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED)) |
152 | SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT); | 154 | SET_VHTNSSMCS(mcs_map_result, nss, |
155 | IEEE80211_VHT_MCS_NOT_SUPPORTED); | ||
153 | else | 156 | else |
154 | SET_VHTNSSMCS(mcs_map_result, nss, | 157 | SET_VHTNSSMCS(mcs_map_result, nss, |
155 | min(mcs_user, mcs_resp)); | 158 | min(mcs_user, mcs_resp)); |
156 | } | 159 | } |
157 | 160 | ||
158 | vht_cap->vht_cap.supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result); | 161 | vht_cap->supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result); |
159 | 162 | ||
160 | tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); | 163 | tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); |
161 | vht_cap->vht_cap.supp_mcs.tx_highest = cpu_to_le16(tmp); | 164 | vht_cap->supp_mcs.tx_highest = cpu_to_le16(tmp); |
162 | 165 | ||
163 | return; | 166 | return; |
164 | } | 167 | } |
@@ -192,7 +195,8 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | |||
192 | (u8 *)bss_desc->bcn_vht_cap, | 195 | (u8 *)bss_desc->bcn_vht_cap, |
193 | le16_to_cpu(vht_cap->header.len)); | 196 | le16_to_cpu(vht_cap->header.len)); |
194 | 197 | ||
195 | mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band); | 198 | mwifiex_fill_vht_cap_tlv(priv, &vht_cap->vht_cap, |
199 | bss_desc->bss_band); | ||
196 | *buffer += sizeof(*vht_cap); | 200 | *buffer += sizeof(*vht_cap); |
197 | ret_len += sizeof(*vht_cap); | 201 | ret_len += sizeof(*vht_cap); |
198 | } | 202 | } |
@@ -299,3 +303,81 @@ void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv) | |||
299 | 303 | ||
300 | return; | 304 | return; |
301 | } | 305 | } |
306 | |||
307 | bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv) | ||
308 | { | ||
309 | struct mwifiex_bssdescriptor *bss_desc; | ||
310 | struct ieee80211_vht_operation *vht_oper; | ||
311 | |||
312 | bss_desc = &priv->curr_bss_params.bss_descriptor; | ||
313 | vht_oper = bss_desc->bcn_vht_oper; | ||
314 | |||
315 | if (!bss_desc->bcn_vht_cap || !vht_oper) | ||
316 | return false; | ||
317 | |||
318 | if (vht_oper->chan_width == IEEE80211_VHT_CHANWIDTH_USE_HT) | ||
319 | return false; | ||
320 | |||
321 | return true; | ||
322 | } | ||
323 | |||
324 | u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, | ||
325 | u32 pri_chan, u8 chan_bw) | ||
326 | { | ||
327 | u8 center_freq_idx = 0; | ||
328 | |||
329 | if (band & BAND_AAC) { | ||
330 | switch (pri_chan) { | ||
331 | case 36: | ||
332 | case 40: | ||
333 | case 44: | ||
334 | case 48: | ||
335 | if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) | ||
336 | center_freq_idx = 42; | ||
337 | break; | ||
338 | case 52: | ||
339 | case 56: | ||
340 | case 60: | ||
341 | case 64: | ||
342 | if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) | ||
343 | center_freq_idx = 58; | ||
344 | else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ) | ||
345 | center_freq_idx = 50; | ||
346 | break; | ||
347 | case 100: | ||
348 | case 104: | ||
349 | case 108: | ||
350 | case 112: | ||
351 | if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) | ||
352 | center_freq_idx = 106; | ||
353 | break; | ||
354 | case 116: | ||
355 | case 120: | ||
356 | case 124: | ||
357 | case 128: | ||
358 | if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) | ||
359 | center_freq_idx = 122; | ||
360 | else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ) | ||
361 | center_freq_idx = 114; | ||
362 | break; | ||
363 | case 132: | ||
364 | case 136: | ||
365 | case 140: | ||
366 | case 144: | ||
367 | if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) | ||
368 | center_freq_idx = 138; | ||
369 | break; | ||
370 | case 149: | ||
371 | case 153: | ||
372 | case 157: | ||
373 | case 161: | ||
374 | if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) | ||
375 | center_freq_idx = 155; | ||
376 | break; | ||
377 | default: | ||
378 | center_freq_idx = 42; | ||
379 | } | ||
380 | } | ||
381 | |||
382 | return center_freq_idx; | ||
383 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h index 7c2c69b5b3eb..0b02cb6cfcb4 100644 --- a/drivers/net/wireless/mwifiex/11ac.h +++ b/drivers/net/wireless/mwifiex/11ac.h | |||
@@ -40,4 +40,6 @@ int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | |||
40 | int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, | 40 | int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, |
41 | struct host_cmd_ds_command *cmd, u16 cmd_action, | 41 | struct host_cmd_ds_command *cmd, u16 cmd_action, |
42 | struct mwifiex_11ac_vht_cfg *cfg); | 42 | struct mwifiex_11ac_vht_cfg *cfg); |
43 | void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv, | ||
44 | struct ieee80211_vht_cap *vht_cap, u8 bands); | ||
43 | #endif /* _MWIFIEX_11AC_H_ */ | 45 | #endif /* _MWIFIEX_11AC_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c index 8d683070bdb3..e76b0db4e3e6 100644 --- a/drivers/net/wireless/mwifiex/11h.c +++ b/drivers/net/wireless/mwifiex/11h.c | |||
@@ -73,8 +73,8 @@ static int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag) | |||
73 | { | 73 | { |
74 | u32 enable = flag; | 74 | u32 enable = flag; |
75 | 75 | ||
76 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 76 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
77 | HostCmd_ACT_GEN_SET, DOT11H_I, &enable); | 77 | HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true); |
78 | } | 78 | } |
79 | 79 | ||
80 | /* This functions processes TLV buffer for a pending BSS Join command. | 80 | /* This functions processes TLV buffer for a pending BSS Join command. |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 7db1a89fdd95..d14ead8beca8 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -34,22 +34,26 @@ | |||
34 | * | 34 | * |
35 | * RD responder bit to set to clear in the extended capability header. | 35 | * RD responder bit to set to clear in the extended capability header. |
36 | */ | 36 | */ |
37 | void | 37 | int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, |
38 | mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, | 38 | struct ieee80211_ht_cap *ht_cap) |
39 | struct mwifiex_ie_types_htcap *ht_cap) | ||
40 | { | 39 | { |
41 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->ht_cap.extended_ht_cap_info); | 40 | uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info); |
42 | struct ieee80211_supported_band *sband = | 41 | struct ieee80211_supported_band *sband = |
43 | priv->wdev->wiphy->bands[radio_type]; | 42 | priv->wdev->wiphy->bands[radio_type]; |
44 | 43 | ||
45 | ht_cap->ht_cap.ampdu_params_info = | 44 | if (WARN_ON_ONCE(!sband)) { |
45 | dev_err(priv->adapter->dev, "Invalid radio type!\n"); | ||
46 | return -EINVAL; | ||
47 | } | ||
48 | |||
49 | ht_cap->ampdu_params_info = | ||
46 | (sband->ht_cap.ampdu_factor & | 50 | (sband->ht_cap.ampdu_factor & |
47 | IEEE80211_HT_AMPDU_PARM_FACTOR) | | 51 | IEEE80211_HT_AMPDU_PARM_FACTOR) | |
48 | ((sband->ht_cap.ampdu_density << | 52 | ((sband->ht_cap.ampdu_density << |
49 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & | 53 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & |
50 | IEEE80211_HT_AMPDU_PARM_DENSITY); | 54 | IEEE80211_HT_AMPDU_PARM_DENSITY); |
51 | 55 | ||
52 | memcpy((u8 *) &ht_cap->ht_cap.mcs, &sband->ht_cap.mcs, | 56 | memcpy((u8 *)&ht_cap->mcs, &sband->ht_cap.mcs, |
53 | sizeof(sband->ht_cap.mcs)); | 57 | sizeof(sband->ht_cap.mcs)); |
54 | 58 | ||
55 | if (priv->bss_mode == NL80211_IFTYPE_STATION || | 59 | if (priv->bss_mode == NL80211_IFTYPE_STATION || |
@@ -57,13 +61,18 @@ mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, | |||
57 | (priv->adapter->sec_chan_offset != | 61 | (priv->adapter->sec_chan_offset != |
58 | IEEE80211_HT_PARAM_CHA_SEC_NONE))) | 62 | IEEE80211_HT_PARAM_CHA_SEC_NONE))) |
59 | /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ | 63 | /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ |
60 | SETHT_MCS32(ht_cap->ht_cap.mcs.rx_mask); | 64 | SETHT_MCS32(ht_cap->mcs.rx_mask); |
61 | 65 | ||
62 | /* Clear RD responder bit */ | 66 | /* Clear RD responder bit */ |
63 | ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; | 67 | ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; |
64 | 68 | ||
65 | ht_cap->ht_cap.cap_info = cpu_to_le16(sband->ht_cap.cap); | 69 | ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap); |
66 | ht_cap->ht_cap.extended_ht_cap_info = cpu_to_le16(ht_ext_cap); | 70 | ht_cap->extended_ht_cap_info = cpu_to_le16(ht_ext_cap); |
71 | |||
72 | if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap)) | ||
73 | ht_cap->tx_BF_cap_info = cpu_to_le32(MWIFIEX_DEF_11N_TX_BF_CAP); | ||
74 | |||
75 | return 0; | ||
67 | } | 76 | } |
68 | 77 | ||
69 | /* | 78 | /* |
@@ -150,28 +159,34 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
150 | int tid; | 159 | int tid; |
151 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; | 160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; |
152 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; | 161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; |
162 | u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); | ||
153 | 163 | ||
154 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) | 164 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) |
155 | & SSN_MASK); | 165 | & SSN_MASK); |
156 | 166 | ||
157 | tid = (le16_to_cpu(add_ba_rsp->block_ack_param_set) | 167 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) |
158 | & IEEE80211_ADDBA_PARAM_TID_MASK) | 168 | >> BLOCKACKPARAM_TID_POS; |
159 | >> BLOCKACKPARAM_TID_POS; | 169 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { |
160 | if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { | ||
161 | tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, | ||
162 | add_ba_rsp->peer_mac_addr); | ||
163 | if (tx_ba_tbl) { | ||
164 | dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); | ||
165 | tx_ba_tbl->ba_status = BA_SETUP_COMPLETE; | ||
166 | } else { | ||
167 | dev_err(priv->adapter->dev, "BA stream not created\n"); | ||
168 | } | ||
169 | } else { | ||
170 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, | 170 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, |
171 | TYPE_DELBA_SENT, true); | 171 | TYPE_DELBA_SENT, true); |
172 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) | 172 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) |
173 | priv->aggr_prio_tbl[tid].ampdu_ap = | 173 | priv->aggr_prio_tbl[tid].ampdu_ap = |
174 | BA_STREAM_NOT_ALLOWED; | 174 | BA_STREAM_NOT_ALLOWED; |
175 | return 0; | ||
176 | } | ||
177 | |||
178 | tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr); | ||
179 | if (tx_ba_tbl) { | ||
180 | dev_dbg(priv->adapter->dev, "info: BA stream complete\n"); | ||
181 | tx_ba_tbl->ba_status = BA_SETUP_COMPLETE; | ||
182 | if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && | ||
183 | priv->add_ba_param.tx_amsdu && | ||
184 | (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) | ||
185 | tx_ba_tbl->amsdu = true; | ||
186 | else | ||
187 | tx_ba_tbl->amsdu = false; | ||
188 | } else { | ||
189 | dev_err(priv->adapter->dev, "BA stream not created\n"); | ||
175 | } | 190 | } |
176 | 191 | ||
177 | return 0; | 192 | return 0; |
@@ -311,7 +326,7 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
311 | (u8 *)bss_desc->bcn_ht_cap, | 326 | (u8 *)bss_desc->bcn_ht_cap, |
312 | le16_to_cpu(ht_cap->header.len)); | 327 | le16_to_cpu(ht_cap->header.len)); |
313 | 328 | ||
314 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); | 329 | mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); |
315 | 330 | ||
316 | *buffer += sizeof(struct mwifiex_ie_types_htcap); | 331 | *buffer += sizeof(struct mwifiex_ie_types_htcap); |
317 | ret_len += sizeof(struct mwifiex_ie_types_htcap); | 332 | ret_len += sizeof(struct mwifiex_ie_types_htcap); |
@@ -527,16 +542,39 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, | |||
527 | int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) | 542 | int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) |
528 | { | 543 | { |
529 | struct host_cmd_ds_11n_addba_req add_ba_req; | 544 | struct host_cmd_ds_11n_addba_req add_ba_req; |
545 | struct mwifiex_sta_node *sta_ptr; | ||
546 | u32 tx_win_size = priv->add_ba_param.tx_win_size; | ||
530 | static u8 dialog_tok; | 547 | static u8 dialog_tok; |
531 | int ret; | 548 | int ret; |
549 | u16 block_ack_param_set; | ||
532 | 550 | ||
533 | dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); | 551 | dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid); |
534 | 552 | ||
535 | add_ba_req.block_ack_param_set = cpu_to_le16( | 553 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && |
536 | (u16) ((tid << BLOCKACKPARAM_TID_POS) | | 554 | ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && |
537 | (priv->add_ba_param. | 555 | priv->adapter->is_hw_11ac_capable && |
538 | tx_win_size << BLOCKACKPARAM_WINSIZE_POS) | | 556 | memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) { |
539 | IMMEDIATE_BLOCK_ACK)); | 557 | sta_ptr = mwifiex_get_sta_entry(priv, peer_mac); |
558 | if (!sta_ptr) { | ||
559 | dev_warn(priv->adapter->dev, | ||
560 | "BA setup with unknown TDLS peer %pM!\n", | ||
561 | peer_mac); | ||
562 | return -1; | ||
563 | } | ||
564 | if (sta_ptr->is_11ac_enabled) | ||
565 | tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; | ||
566 | } | ||
567 | |||
568 | block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) | | ||
569 | tx_win_size << BLOCKACKPARAM_WINSIZE_POS | | ||
570 | IMMEDIATE_BLOCK_ACK); | ||
571 | |||
572 | /* enable AMSDU inside AMPDU */ | ||
573 | if (priv->add_ba_param.tx_amsdu && | ||
574 | (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) | ||
575 | block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK; | ||
576 | |||
577 | add_ba_req.block_ack_param_set = cpu_to_le16(block_ack_param_set); | ||
540 | add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); | 578 | add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); |
541 | 579 | ||
542 | ++dialog_tok; | 580 | ++dialog_tok; |
@@ -548,8 +586,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) | |||
548 | memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); | 586 | memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); |
549 | 587 | ||
550 | /* We don't wait for the response of this command */ | 588 | /* We don't wait for the response of this command */ |
551 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_REQ, | 589 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, |
552 | 0, 0, &add_ba_req); | 590 | 0, 0, &add_ba_req, false); |
553 | 591 | ||
554 | return ret; | 592 | return ret; |
555 | } | 593 | } |
@@ -576,8 +614,8 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
576 | memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); | 614 | memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); |
577 | 615 | ||
578 | /* We don't wait for the response of this command */ | 616 | /* We don't wait for the response of this command */ |
579 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, | 617 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA, |
580 | HostCmd_ACT_GEN_SET, 0, &delba); | 618 | HostCmd_ACT_GEN_SET, 0, &delba, false); |
581 | 619 | ||
582 | return ret; | 620 | return ret; |
583 | } | 621 | } |
@@ -651,6 +689,7 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, | |||
651 | dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", | 689 | dev_dbg(priv->adapter->dev, "data: %s tid=%d\n", |
652 | __func__, rx_reo_tbl->tid); | 690 | __func__, rx_reo_tbl->tid); |
653 | memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); | 691 | memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); |
692 | rx_reo_tbl->amsdu = tx_ba_tsr_tbl->amsdu; | ||
654 | rx_reo_tbl++; | 693 | rx_reo_tbl++; |
655 | count++; | 694 | count++; |
656 | if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) | 695 | if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) |
@@ -706,5 +745,8 @@ void mwifiex_set_ba_params(struct mwifiex_private *priv) | |||
706 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; | 745 | MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; |
707 | } | 746 | } |
708 | 747 | ||
748 | priv->add_ba_param.tx_amsdu = true; | ||
749 | priv->add_ba_param.rx_amsdu = true; | ||
750 | |||
709 | return; | 751 | return; |
710 | } | 752 | } |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 375db01442bf..40b007a00f4b 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
@@ -34,8 +34,8 @@ int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, | |||
34 | int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | 34 | int 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); |
37 | void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, | 37 | int mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, |
38 | struct mwifiex_ie_types_htcap *); | 38 | struct ieee80211_ht_cap *); |
39 | int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, | 39 | int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, |
40 | u16 action, int *htcap_cfg); | 40 | u16 action, int *htcap_cfg); |
41 | void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, | 41 | void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, |
@@ -64,14 +64,46 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, | |||
64 | struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl); | 64 | struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl); |
65 | void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra); | 65 | void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra); |
66 | 66 | ||
67 | /* | ||
68 | * This function checks whether AMPDU is allowed or not for a particular TID. | ||
69 | */ | ||
70 | static inline u8 | 67 | static inline u8 |
71 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, int tid) | 68 | mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, |
69 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
72 | { | 70 | { |
73 | return ((priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED) | 71 | struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ptr->ra); |
74 | ? true : false); | 72 | |
73 | if (unlikely(!node)) | ||
74 | return false; | ||
75 | |||
76 | return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; | ||
77 | } | ||
78 | |||
79 | /* This function checks whether AMSDU is allowed for BA stream. */ | ||
80 | static inline u8 | ||
81 | mwifiex_is_amsdu_in_ampdu_allowed(struct mwifiex_private *priv, | ||
82 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
83 | { | ||
84 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; | ||
85 | |||
86 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); | ||
87 | if (tx_tbl) | ||
88 | return tx_tbl->amsdu; | ||
89 | |||
90 | return false; | ||
91 | } | ||
92 | |||
93 | /* This function checks whether AMPDU is allowed or not for a particular TID. */ | ||
94 | static inline u8 | ||
95 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, | ||
96 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
97 | { | ||
98 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
99 | return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); | ||
100 | } else { | ||
101 | if (ptr->tdls_link) | ||
102 | return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); | ||
103 | |||
104 | return (priv->aggr_prio_tbl[tid].ampdu_ap != | ||
105 | BA_STREAM_NOT_ALLOWED) ? true : false; | ||
106 | } | ||
75 | } | 107 | } |
76 | 108 | ||
77 | /* | 109 | /* |
@@ -165,4 +197,14 @@ static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, | |||
165 | 197 | ||
166 | return node->is_11n_enabled; | 198 | return node->is_11n_enabled; |
167 | } | 199 | } |
200 | |||
201 | static inline u8 | ||
202 | mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra) | ||
203 | { | ||
204 | struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra); | ||
205 | if (node) | ||
206 | return node->is_11n_enabled; | ||
207 | |||
208 | return false; | ||
209 | } | ||
168 | #endif /* !_MWIFIEX_11N_H_ */ | 210 | #endif /* !_MWIFIEX_11N_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index ada809f576fe..0c3571f830b0 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -26,6 +26,56 @@ | |||
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "11n_rxreorder.h" | 27 | #include "11n_rxreorder.h" |
28 | 28 | ||
29 | /* This function will dispatch amsdu packet and forward it to kernel/upper | ||
30 | * layer. | ||
31 | */ | ||
32 | static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, | ||
33 | struct sk_buff *skb) | ||
34 | { | ||
35 | struct rxpd *local_rx_pd = (struct rxpd *)(skb->data); | ||
36 | int ret; | ||
37 | |||
38 | if (le16_to_cpu(local_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) { | ||
39 | struct sk_buff_head list; | ||
40 | struct sk_buff *rx_skb; | ||
41 | |||
42 | __skb_queue_head_init(&list); | ||
43 | |||
44 | skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset)); | ||
45 | skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); | ||
46 | |||
47 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | ||
48 | priv->wdev->iftype, 0, false); | ||
49 | |||
50 | while (!skb_queue_empty(&list)) { | ||
51 | rx_skb = __skb_dequeue(&list); | ||
52 | ret = mwifiex_recv_packet(priv, rx_skb); | ||
53 | if (ret == -1) | ||
54 | dev_err(priv->adapter->dev, | ||
55 | "Rx of A-MSDU failed"); | ||
56 | } | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | return -1; | ||
61 | } | ||
62 | |||
63 | /* This function will process the rx packet and forward it to kernel/upper | ||
64 | * layer. | ||
65 | */ | ||
66 | static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload) | ||
67 | { | ||
68 | int ret = mwifiex_11n_dispatch_amsdu_pkt(priv, payload); | ||
69 | |||
70 | if (!ret) | ||
71 | return 0; | ||
72 | |||
73 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | ||
74 | return mwifiex_handle_uap_rx_forward(priv, payload); | ||
75 | |||
76 | return mwifiex_process_rx_packet(priv, payload); | ||
77 | } | ||
78 | |||
29 | /* | 79 | /* |
30 | * This function dispatches all packets in the Rx reorder table until the | 80 | * This function dispatches all packets in the Rx reorder table until the |
31 | * start window. | 81 | * start window. |
@@ -35,8 +85,9 @@ | |||
35 | * circular buffer. | 85 | * circular buffer. |
36 | */ | 86 | */ |
37 | static void | 87 | static void |
38 | mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, | 88 | mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, |
39 | struct mwifiex_rx_reorder_tbl *tbl, int start_win) | 89 | struct mwifiex_rx_reorder_tbl *tbl, |
90 | int start_win) | ||
40 | { | 91 | { |
41 | int pkt_to_send, i; | 92 | int pkt_to_send, i; |
42 | void *rx_tmp_ptr; | 93 | void *rx_tmp_ptr; |
@@ -54,12 +105,8 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, | |||
54 | tbl->rx_reorder_ptr[i] = NULL; | 105 | tbl->rx_reorder_ptr[i] = NULL; |
55 | } | 106 | } |
56 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); | 107 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); |
57 | if (rx_tmp_ptr) { | 108 | if (rx_tmp_ptr) |
58 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 109 | mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); |
59 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); | ||
60 | else | ||
61 | mwifiex_process_rx_packet(priv, rx_tmp_ptr); | ||
62 | } | ||
63 | } | 110 | } |
64 | 111 | ||
65 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); | 112 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); |
@@ -101,11 +148,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, | |||
101 | rx_tmp_ptr = tbl->rx_reorder_ptr[i]; | 148 | rx_tmp_ptr = tbl->rx_reorder_ptr[i]; |
102 | tbl->rx_reorder_ptr[i] = NULL; | 149 | tbl->rx_reorder_ptr[i] = NULL; |
103 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); | 150 | spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); |
104 | 151 | mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); | |
105 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | ||
106 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); | ||
107 | else | ||
108 | mwifiex_process_rx_packet(priv, rx_tmp_ptr); | ||
109 | } | 152 | } |
110 | 153 | ||
111 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); | 154 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); |
@@ -135,14 +178,15 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, | |||
135 | struct mwifiex_rx_reorder_tbl *tbl) | 178 | struct mwifiex_rx_reorder_tbl *tbl) |
136 | { | 179 | { |
137 | unsigned long flags; | 180 | unsigned long flags; |
181 | int start_win; | ||
138 | 182 | ||
139 | if (!tbl) | 183 | if (!tbl) |
140 | return; | 184 | return; |
141 | 185 | ||
142 | mwifiex_11n_dispatch_pkt(priv, tbl, (tbl->start_win + tbl->win_size) & | 186 | start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1); |
143 | (MAX_TID_VALUE - 1)); | 187 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); |
144 | 188 | ||
145 | del_timer(&tbl->timer_context.timer); | 189 | del_timer_sync(&tbl->timer_context.timer); |
146 | 190 | ||
147 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); | 191 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); |
148 | list_del(&tbl->list); | 192 | list_del(&tbl->list); |
@@ -228,17 +272,17 @@ mwifiex_flush_data(unsigned long context) | |||
228 | { | 272 | { |
229 | struct reorder_tmr_cnxt *ctx = | 273 | struct reorder_tmr_cnxt *ctx = |
230 | (struct reorder_tmr_cnxt *) context; | 274 | (struct reorder_tmr_cnxt *) context; |
231 | int start_win; | 275 | int start_win, seq_num; |
232 | 276 | ||
233 | start_win = mwifiex_11n_find_last_seq_num(ctx->ptr); | 277 | seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr); |
234 | 278 | ||
235 | if (start_win < 0) | 279 | if (seq_num < 0) |
236 | return; | 280 | return; |
237 | 281 | ||
238 | dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", start_win); | 282 | dev_dbg(ctx->priv->adapter->dev, "info: flush data %d\n", seq_num); |
239 | mwifiex_11n_dispatch_pkt(ctx->priv, ctx->ptr, | 283 | start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1); |
240 | (ctx->ptr->start_win + start_win + 1) & | 284 | mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr, |
241 | (MAX_TID_VALUE - 1)); | 285 | start_win); |
242 | } | 286 | } |
243 | 287 | ||
244 | /* | 288 | /* |
@@ -267,7 +311,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
267 | */ | 311 | */ |
268 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); | 312 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); |
269 | if (tbl) { | 313 | if (tbl) { |
270 | mwifiex_11n_dispatch_pkt(priv, tbl, seq_num); | 314 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num); |
271 | return; | 315 | return; |
272 | } | 316 | } |
273 | /* if !tbl then create one */ | 317 | /* if !tbl then create one */ |
@@ -279,6 +323,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
279 | new_node->tid = tid; | 323 | new_node->tid = tid; |
280 | memcpy(new_node->ta, ta, ETH_ALEN); | 324 | memcpy(new_node->ta, ta, ETH_ALEN); |
281 | new_node->start_win = seq_num; | 325 | new_node->start_win = seq_num; |
326 | new_node->init_win = seq_num; | ||
327 | new_node->flags = 0; | ||
282 | 328 | ||
283 | if (mwifiex_queuing_ra_based(priv)) { | 329 | if (mwifiex_queuing_ra_based(priv)) { |
284 | dev_dbg(priv->adapter->dev, | 330 | dev_dbg(priv->adapter->dev, |
@@ -290,15 +336,20 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
290 | last_seq = node->rx_seq[tid]; | 336 | last_seq = node->rx_seq[tid]; |
291 | } | 337 | } |
292 | } else { | 338 | } else { |
293 | last_seq = priv->rx_seq[tid]; | 339 | node = mwifiex_get_sta_entry(priv, ta); |
340 | if (node) | ||
341 | last_seq = node->rx_seq[tid]; | ||
342 | else | ||
343 | last_seq = priv->rx_seq[tid]; | ||
294 | } | 344 | } |
295 | 345 | ||
296 | if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && | 346 | if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && |
297 | last_seq >= new_node->start_win) | 347 | last_seq >= new_node->start_win) { |
298 | new_node->start_win = last_seq + 1; | 348 | new_node->start_win = last_seq + 1; |
349 | new_node->flags |= RXREOR_INIT_WINDOW_SHIFT; | ||
350 | } | ||
299 | 351 | ||
300 | new_node->win_size = win_size; | 352 | new_node->win_size = win_size; |
301 | new_node->flags = 0; | ||
302 | 353 | ||
303 | new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, | 354 | new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, |
304 | GFP_KERNEL); | 355 | GFP_KERNEL); |
@@ -358,10 +409,28 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, | |||
358 | *cmd_addba_req) | 409 | *cmd_addba_req) |
359 | { | 410 | { |
360 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &cmd->params.add_ba_rsp; | 411 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &cmd->params.add_ba_rsp; |
412 | struct mwifiex_sta_node *sta_ptr; | ||
413 | u32 rx_win_size = priv->add_ba_param.rx_win_size; | ||
361 | u8 tid; | 414 | u8 tid; |
362 | int win_size; | 415 | int win_size; |
363 | uint16_t block_ack_param_set; | 416 | uint16_t block_ack_param_set; |
364 | 417 | ||
418 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && | ||
419 | ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | ||
420 | priv->adapter->is_hw_11ac_capable && | ||
421 | memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) { | ||
422 | sta_ptr = mwifiex_get_sta_entry(priv, | ||
423 | cmd_addba_req->peer_mac_addr); | ||
424 | if (!sta_ptr) { | ||
425 | dev_warn(priv->adapter->dev, | ||
426 | "BA setup with unknown TDLS peer %pM!\n", | ||
427 | cmd_addba_req->peer_mac_addr); | ||
428 | return -1; | ||
429 | } | ||
430 | if (sta_ptr->is_11ac_enabled) | ||
431 | rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE; | ||
432 | } | ||
433 | |||
365 | cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); | 434 | cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); |
366 | cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN); | 435 | cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN); |
367 | 436 | ||
@@ -376,10 +445,12 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, | |||
376 | >> BLOCKACKPARAM_TID_POS; | 445 | >> BLOCKACKPARAM_TID_POS; |
377 | add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); | 446 | add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); |
378 | block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; | 447 | block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; |
379 | /* We donot support AMSDU inside AMPDU, hence reset the bit */ | 448 | |
380 | block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; | 449 | /* If we don't support AMSDU inside AMPDU, reset the bit */ |
381 | block_ack_param_set |= (priv->add_ba_param.rx_win_size << | 450 | if (!priv->add_ba_param.rx_amsdu || |
382 | BLOCKACKPARAM_WINSIZE_POS); | 451 | (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED)) |
452 | block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; | ||
453 | block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS; | ||
383 | add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); | 454 | add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); |
384 | win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) | 455 | win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) |
385 | & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) | 456 | & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) |
@@ -431,33 +502,46 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
431 | struct mwifiex_rx_reorder_tbl *tbl; | 502 | struct mwifiex_rx_reorder_tbl *tbl; |
432 | int start_win, end_win, win_size; | 503 | int start_win, end_win, win_size; |
433 | u16 pkt_index; | 504 | u16 pkt_index; |
505 | bool init_window_shift = false; | ||
434 | 506 | ||
435 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); | 507 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); |
436 | if (!tbl) { | 508 | if (!tbl) { |
437 | if (pkt_type != PKT_TYPE_BAR) { | 509 | if (pkt_type != PKT_TYPE_BAR) |
438 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 510 | mwifiex_11n_dispatch_pkt(priv, payload); |
439 | mwifiex_handle_uap_rx_forward(priv, payload); | ||
440 | else | ||
441 | mwifiex_process_rx_packet(priv, payload); | ||
442 | } | ||
443 | return 0; | 511 | return 0; |
444 | } | 512 | } |
513 | |||
514 | if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) { | ||
515 | mwifiex_11n_dispatch_pkt(priv, payload); | ||
516 | return 0; | ||
517 | } | ||
518 | |||
445 | start_win = tbl->start_win; | 519 | start_win = tbl->start_win; |
446 | win_size = tbl->win_size; | 520 | win_size = tbl->win_size; |
447 | end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); | 521 | end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); |
448 | del_timer(&tbl->timer_context.timer); | 522 | if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) { |
523 | init_window_shift = true; | ||
524 | tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT; | ||
525 | } | ||
449 | mod_timer(&tbl->timer_context.timer, | 526 | mod_timer(&tbl->timer_context.timer, |
450 | jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size)); | 527 | jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size)); |
451 | 528 | ||
452 | /* | ||
453 | * If seq_num is less then starting win then ignore and drop the | ||
454 | * packet | ||
455 | */ | ||
456 | if (tbl->flags & RXREOR_FORCE_NO_DROP) { | 529 | if (tbl->flags & RXREOR_FORCE_NO_DROP) { |
457 | dev_dbg(priv->adapter->dev, | 530 | dev_dbg(priv->adapter->dev, |
458 | "RXREOR_FORCE_NO_DROP when HS is activated\n"); | 531 | "RXREOR_FORCE_NO_DROP when HS is activated\n"); |
459 | tbl->flags &= ~RXREOR_FORCE_NO_DROP; | 532 | tbl->flags &= ~RXREOR_FORCE_NO_DROP; |
533 | } else if (init_window_shift && seq_num < start_win && | ||
534 | seq_num >= tbl->init_win) { | ||
535 | dev_dbg(priv->adapter->dev, | ||
536 | "Sender TID sequence number reset %d->%d for SSN %d\n", | ||
537 | start_win, seq_num, tbl->init_win); | ||
538 | tbl->start_win = start_win = seq_num; | ||
539 | end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); | ||
460 | } else { | 540 | } else { |
541 | /* | ||
542 | * If seq_num is less then starting win then ignore and drop | ||
543 | * the packet | ||
544 | */ | ||
461 | if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { | 545 | if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { |
462 | if (seq_num >= ((start_win + TWOPOW11) & | 546 | if (seq_num >= ((start_win + TWOPOW11) & |
463 | (MAX_TID_VALUE - 1)) && | 547 | (MAX_TID_VALUE - 1)) && |
@@ -485,7 +569,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
485 | start_win = (end_win - win_size) + 1; | 569 | start_win = (end_win - win_size) + 1; |
486 | else | 570 | else |
487 | start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; | 571 | start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; |
488 | mwifiex_11n_dispatch_pkt(priv, tbl, start_win); | 572 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); |
489 | } | 573 | } |
490 | 574 | ||
491 | if (pkt_type != PKT_TYPE_BAR) { | 575 | if (pkt_type != PKT_TYPE_BAR) { |
@@ -576,16 +660,7 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, | |||
576 | * Check if we had rejected the ADDBA, if yes then do not create | 660 | * Check if we had rejected the ADDBA, if yes then do not create |
577 | * the stream | 661 | * the stream |
578 | */ | 662 | */ |
579 | if (le16_to_cpu(add_ba_rsp->status_code) == BA_RESULT_SUCCESS) { | 663 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { |
580 | win_size = (block_ack_param_set & | ||
581 | IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) | ||
582 | >> BLOCKACKPARAM_WINSIZE_POS; | ||
583 | |||
584 | dev_dbg(priv->adapter->dev, | ||
585 | "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n", | ||
586 | add_ba_rsp->peer_mac_addr, tid, | ||
587 | add_ba_rsp->ssn, win_size); | ||
588 | } else { | ||
589 | dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", | 664 | dev_err(priv->adapter->dev, "ADDBA RSP: failed %pM tid=%d)\n", |
590 | add_ba_rsp->peer_mac_addr, tid); | 665 | add_ba_rsp->peer_mac_addr, tid); |
591 | 666 | ||
@@ -593,8 +668,28 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, | |||
593 | add_ba_rsp->peer_mac_addr); | 668 | add_ba_rsp->peer_mac_addr); |
594 | if (tbl) | 669 | if (tbl) |
595 | mwifiex_del_rx_reorder_entry(priv, tbl); | 670 | mwifiex_del_rx_reorder_entry(priv, tbl); |
671 | |||
672 | return 0; | ||
596 | } | 673 | } |
597 | 674 | ||
675 | win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) | ||
676 | >> BLOCKACKPARAM_WINSIZE_POS; | ||
677 | |||
678 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, | ||
679 | add_ba_rsp->peer_mac_addr); | ||
680 | if (tbl) { | ||
681 | if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && | ||
682 | priv->add_ba_param.rx_amsdu && | ||
683 | (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) | ||
684 | tbl->amsdu = true; | ||
685 | else | ||
686 | tbl->amsdu = false; | ||
687 | } | ||
688 | |||
689 | dev_dbg(priv->adapter->dev, | ||
690 | "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n", | ||
691 | add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size); | ||
692 | |||
598 | return 0; | 693 | return 0; |
599 | } | 694 | } |
600 | 695 | ||
@@ -615,7 +710,7 @@ void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, | |||
615 | delba.del_ba_param_set |= cpu_to_le16( | 710 | delba.del_ba_param_set |= cpu_to_le16( |
616 | (u16) event->origninator << DELBA_INITIATOR_POS); | 711 | (u16) event->origninator << DELBA_INITIATOR_POS); |
617 | delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); | 712 | delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); |
618 | mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba); | 713 | mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba, false); |
619 | } | 714 | } |
620 | 715 | ||
621 | /* | 716 | /* |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 4064041ac852..0fc76e4a60f8 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h | |||
@@ -42,7 +42,8 @@ | |||
42 | #define BA_SETUP_PACKET_OFFSET 16 | 42 | #define BA_SETUP_PACKET_OFFSET 16 |
43 | 43 | ||
44 | enum mwifiex_rxreor_flags { | 44 | enum mwifiex_rxreor_flags { |
45 | RXREOR_FORCE_NO_DROP = 1<<0, | 45 | RXREOR_FORCE_NO_DROP = 1<<0, |
46 | RXREOR_INIT_WINDOW_SHIFT = 1<<1, | ||
46 | }; | 47 | }; |
47 | 48 | ||
48 | static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) | 49 | static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) |
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index a42a506fd32b..2aa208ffbe23 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile | |||
@@ -41,6 +41,7 @@ mwifiex-y += uap_txrx.o | |||
41 | mwifiex-y += cfg80211.o | 41 | mwifiex-y += cfg80211.o |
42 | mwifiex-y += ethtool.o | 42 | mwifiex-y += ethtool.o |
43 | mwifiex-y += 11h.o | 43 | mwifiex-y += 11h.o |
44 | mwifiex-y += tdls.o | ||
44 | mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o | 45 | mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o |
45 | obj-$(CONFIG_MWIFIEX) += mwifiex.o | 46 | obj-$(CONFIG_MWIFIEX) += mwifiex.o |
46 | 47 | ||
diff --git a/drivers/net/wireless/mwifiex/README b/drivers/net/wireless/mwifiex/README index 3d64613ebb29..b9242c3dca43 100644 --- a/drivers/net/wireless/mwifiex/README +++ b/drivers/net/wireless/mwifiex/README | |||
@@ -131,7 +131,7 @@ info | |||
131 | hs_configured = <0/1, host sleep not configured/configured> | 131 | hs_configured = <0/1, host sleep not configured/configured> |
132 | hs_activated = <0/1, extended host sleep not activated/activated> | 132 | hs_activated = <0/1, extended host sleep not activated/activated> |
133 | num_tx_timeout = <number of Tx timeout> | 133 | num_tx_timeout = <number of Tx timeout> |
134 | num_cmd_timeout = <number of timeout commands> | 134 | is_cmd_timedout = <0/1 command timeout not occurred/occurred> |
135 | timeout_cmd_id = <command id of the last timeout command> | 135 | timeout_cmd_id = <command id of the last timeout command> |
136 | timeout_cmd_act = <command action of the last timeout command> | 136 | timeout_cmd_act = <command action of the last timeout command> |
137 | last_cmd_id = <command id of the last several commands sent to device> | 137 | last_cmd_id = <command id of the last several commands sent to device> |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 8bfc07cd330e..21ee27ab7b74 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -252,9 +252,9 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy, | |||
252 | 252 | ||
253 | if (mask != priv->mgmt_frame_mask) { | 253 | if (mask != priv->mgmt_frame_mask) { |
254 | priv->mgmt_frame_mask = mask; | 254 | priv->mgmt_frame_mask = mask; |
255 | mwifiex_send_cmd_async(priv, HostCmd_CMD_MGMT_FRAME_REG, | 255 | mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, |
256 | HostCmd_ACT_GEN_SET, 0, | 256 | HostCmd_ACT_GEN_SET, 0, |
257 | &priv->mgmt_frame_mask); | 257 | &priv->mgmt_frame_mask, false); |
258 | wiphy_dbg(wiphy, "info: mgmt frame registered\n"); | 258 | wiphy_dbg(wiphy, "info: mgmt frame registered\n"); |
259 | } | 259 | } |
260 | } | 260 | } |
@@ -515,8 +515,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
515 | 515 | ||
516 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 516 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
517 | 517 | ||
518 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, | 518 | if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, |
519 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 519 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { |
520 | wiphy_err(wiphy, "11D: setting domain info in FW\n"); | 520 | wiphy_err(wiphy, "11D: setting domain info in FW\n"); |
521 | return -1; | 521 | return -1; |
522 | } | 522 | } |
@@ -580,9 +580,9 @@ mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) | |||
580 | frag_thr > MWIFIEX_FRAG_MAX_VALUE) | 580 | frag_thr > MWIFIEX_FRAG_MAX_VALUE) |
581 | frag_thr = MWIFIEX_FRAG_MAX_VALUE; | 581 | frag_thr = MWIFIEX_FRAG_MAX_VALUE; |
582 | 582 | ||
583 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 583 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
584 | HostCmd_ACT_GEN_SET, FRAG_THRESH_I, | 584 | HostCmd_ACT_GEN_SET, FRAG_THRESH_I, |
585 | &frag_thr); | 585 | &frag_thr, true); |
586 | } | 586 | } |
587 | 587 | ||
588 | /* | 588 | /* |
@@ -597,9 +597,9 @@ mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) | |||
597 | if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) | 597 | if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) |
598 | rts_thr = MWIFIEX_RTS_MAX_VALUE; | 598 | rts_thr = MWIFIEX_RTS_MAX_VALUE; |
599 | 599 | ||
600 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 600 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
601 | HostCmd_ACT_GEN_SET, RTS_THRESH_I, | 601 | HostCmd_ACT_GEN_SET, RTS_THRESH_I, |
602 | &rts_thr); | 602 | &rts_thr, true); |
603 | } | 603 | } |
604 | 604 | ||
605 | /* | 605 | /* |
@@ -637,20 +637,19 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
637 | 637 | ||
638 | bss_started = priv->bss_started; | 638 | bss_started = priv->bss_started; |
639 | 639 | ||
640 | ret = mwifiex_send_cmd_sync(priv, | 640 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, |
641 | HostCmd_CMD_UAP_BSS_STOP, | 641 | HostCmd_ACT_GEN_SET, 0, |
642 | HostCmd_ACT_GEN_SET, 0, | 642 | NULL, true); |
643 | NULL); | ||
644 | if (ret) { | 643 | if (ret) { |
645 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | 644 | wiphy_err(wiphy, "Failed to stop the BSS\n"); |
646 | kfree(bss_cfg); | 645 | kfree(bss_cfg); |
647 | return ret; | 646 | return ret; |
648 | } | 647 | } |
649 | 648 | ||
650 | ret = mwifiex_send_cmd_async(priv, | 649 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, |
651 | HostCmd_CMD_UAP_SYS_CONFIG, | 650 | HostCmd_ACT_GEN_SET, |
652 | HostCmd_ACT_GEN_SET, | 651 | UAP_BSS_PARAMS_I, bss_cfg, |
653 | UAP_BSS_PARAMS_I, bss_cfg); | 652 | false); |
654 | 653 | ||
655 | kfree(bss_cfg); | 654 | kfree(bss_cfg); |
656 | 655 | ||
@@ -662,10 +661,9 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
662 | if (!bss_started) | 661 | if (!bss_started) |
663 | break; | 662 | break; |
664 | 663 | ||
665 | ret = mwifiex_send_cmd_async(priv, | 664 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, |
666 | HostCmd_CMD_UAP_BSS_START, | 665 | HostCmd_ACT_GEN_SET, 0, |
667 | HostCmd_ACT_GEN_SET, 0, | 666 | NULL, false); |
668 | NULL); | ||
669 | if (ret) { | 667 | if (ret) { |
670 | wiphy_err(wiphy, "Failed to start BSS\n"); | 668 | wiphy_err(wiphy, "Failed to start BSS\n"); |
671 | return ret; | 669 | return ret; |
@@ -700,8 +698,8 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) | |||
700 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) | 698 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) |
701 | mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA); | 699 | mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA); |
702 | 700 | ||
703 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, | 701 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, |
704 | HostCmd_ACT_GEN_SET, 0, &mode)) | 702 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
705 | return -1; | 703 | return -1; |
706 | 704 | ||
707 | return 0; | 705 | return 0; |
@@ -721,13 +719,13 @@ mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv) | |||
721 | return -1; | 719 | return -1; |
722 | 720 | ||
723 | mode = P2P_MODE_DEVICE; | 721 | mode = P2P_MODE_DEVICE; |
724 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, | 722 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, |
725 | HostCmd_ACT_GEN_SET, 0, &mode)) | 723 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
726 | return -1; | 724 | return -1; |
727 | 725 | ||
728 | mode = P2P_MODE_CLIENT; | 726 | mode = P2P_MODE_CLIENT; |
729 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, | 727 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, |
730 | HostCmd_ACT_GEN_SET, 0, &mode)) | 728 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
731 | return -1; | 729 | return -1; |
732 | 730 | ||
733 | return 0; | 731 | return 0; |
@@ -747,13 +745,13 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) | |||
747 | return -1; | 745 | return -1; |
748 | 746 | ||
749 | mode = P2P_MODE_DEVICE; | 747 | mode = P2P_MODE_DEVICE; |
750 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, | 748 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, |
751 | HostCmd_ACT_GEN_SET, 0, &mode)) | 749 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
752 | return -1; | 750 | return -1; |
753 | 751 | ||
754 | mode = P2P_MODE_GO; | 752 | mode = P2P_MODE_GO; |
755 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, | 753 | if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, |
756 | HostCmd_ACT_GEN_SET, 0, &mode)) | 754 | HostCmd_ACT_GEN_SET, 0, &mode, true)) |
757 | return -1; | 755 | return -1; |
758 | 756 | ||
759 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) | 757 | if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) |
@@ -853,8 +851,8 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
853 | 851 | ||
854 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; | 852 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; |
855 | 853 | ||
856 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, | 854 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, |
857 | HostCmd_ACT_GEN_SET, 0, NULL); | 855 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
858 | 856 | ||
859 | return ret; | 857 | return ret; |
860 | } | 858 | } |
@@ -942,8 +940,8 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
942 | STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; | 940 | STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; |
943 | 941 | ||
944 | /* Get signal information from the firmware */ | 942 | /* Get signal information from the firmware */ |
945 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, | 943 | if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, |
946 | HostCmd_ACT_GEN_GET, 0, NULL)) { | 944 | HostCmd_ACT_GEN_GET, 0, NULL, true)) { |
947 | dev_err(priv->adapter->dev, "failed to get signal information\n"); | 945 | dev_err(priv->adapter->dev, "failed to get signal information\n"); |
948 | return -EFAULT; | 946 | return -EFAULT; |
949 | } | 947 | } |
@@ -954,9 +952,9 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
954 | } | 952 | } |
955 | 953 | ||
956 | /* Get DTIM period information from firmware */ | 954 | /* Get DTIM period information from firmware */ |
957 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 955 | mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
958 | HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, | 956 | HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, |
959 | &priv->dtim_period); | 957 | &priv->dtim_period, true); |
960 | 958 | ||
961 | mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate); | 959 | mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate); |
962 | 960 | ||
@@ -1160,9 +1158,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1160 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1158 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
1161 | u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; | 1159 | u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; |
1162 | enum ieee80211_band band; | 1160 | enum ieee80211_band band; |
1161 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1163 | 1162 | ||
1164 | if (!priv->media_connected) { | 1163 | if (!priv->media_connected) { |
1165 | dev_err(priv->adapter->dev, | 1164 | dev_err(adapter->dev, |
1166 | "Can not set Tx data rate in disconnected state\n"); | 1165 | "Can not set Tx data rate in disconnected state\n"); |
1167 | return -EINVAL; | 1166 | return -EINVAL; |
1168 | } | 1167 | } |
@@ -1183,11 +1182,18 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1183 | 1182 | ||
1184 | /* Fill HT MCS rates */ | 1183 | /* Fill HT MCS rates */ |
1185 | bitmap_rates[2] = mask->control[band].ht_mcs[0]; | 1184 | bitmap_rates[2] = mask->control[band].ht_mcs[0]; |
1186 | if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) | 1185 | if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) |
1187 | bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; | 1186 | bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; |
1188 | 1187 | ||
1189 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, | 1188 | /* Fill VHT MCS rates */ |
1190 | HostCmd_ACT_GEN_SET, 0, bitmap_rates); | 1189 | if (adapter->fw_api_ver == MWIFIEX_FW_V15) { |
1190 | bitmap_rates[10] = mask->control[band].vht_mcs[0]; | ||
1191 | if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) | ||
1192 | bitmap_rates[11] = mask->control[band].vht_mcs[1]; | ||
1193 | } | ||
1194 | |||
1195 | return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, | ||
1196 | HostCmd_ACT_GEN_SET, 0, bitmap_rates, true); | ||
1191 | } | 1197 | } |
1192 | 1198 | ||
1193 | /* | 1199 | /* |
@@ -1216,14 +1222,14 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, | |||
1216 | subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold); | 1222 | subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold); |
1217 | subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; | 1223 | subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; |
1218 | subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; | 1224 | subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; |
1219 | return mwifiex_send_cmd_sync(priv, | 1225 | return mwifiex_send_cmd(priv, |
1220 | HostCmd_CMD_802_11_SUBSCRIBE_EVENT, | 1226 | HostCmd_CMD_802_11_SUBSCRIBE_EVENT, |
1221 | 0, 0, &subsc_evt); | 1227 | 0, 0, &subsc_evt, true); |
1222 | } else { | 1228 | } else { |
1223 | subsc_evt.action = HostCmd_ACT_BITWISE_CLR; | 1229 | subsc_evt.action = HostCmd_ACT_BITWISE_CLR; |
1224 | return mwifiex_send_cmd_sync(priv, | 1230 | return mwifiex_send_cmd(priv, |
1225 | HostCmd_CMD_802_11_SUBSCRIBE_EVENT, | 1231 | HostCmd_CMD_802_11_SUBSCRIBE_EVENT, |
1226 | 0, 0, &subsc_evt); | 1232 | 0, 0, &subsc_evt, true); |
1227 | } | 1233 | } |
1228 | 1234 | ||
1229 | return 0; | 1235 | return 0; |
@@ -1276,10 +1282,9 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1276 | if (!mac || is_broadcast_ether_addr(mac)) { | 1282 | if (!mac || is_broadcast_ether_addr(mac)) { |
1277 | wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__); | 1283 | wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__); |
1278 | list_for_each_entry(sta_node, &priv->sta_list, list) { | 1284 | list_for_each_entry(sta_node, &priv->sta_list, list) { |
1279 | if (mwifiex_send_cmd_sync(priv, | 1285 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, |
1280 | HostCmd_CMD_UAP_STA_DEAUTH, | 1286 | HostCmd_ACT_GEN_SET, 0, |
1281 | HostCmd_ACT_GEN_SET, 0, | 1287 | sta_node->mac_addr, true)) |
1282 | sta_node->mac_addr)) | ||
1283 | return -1; | 1288 | return -1; |
1284 | mwifiex_uap_del_sta_data(priv, sta_node); | 1289 | mwifiex_uap_del_sta_data(priv, sta_node); |
1285 | } | 1290 | } |
@@ -1289,10 +1294,9 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1289 | sta_node = mwifiex_get_sta_entry(priv, mac); | 1294 | sta_node = mwifiex_get_sta_entry(priv, mac); |
1290 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | 1295 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); |
1291 | if (sta_node) { | 1296 | if (sta_node) { |
1292 | if (mwifiex_send_cmd_sync(priv, | 1297 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, |
1293 | HostCmd_CMD_UAP_STA_DEAUTH, | 1298 | HostCmd_ACT_GEN_SET, 0, |
1294 | HostCmd_ACT_GEN_SET, 0, | 1299 | sta_node->mac_addr, true)) |
1295 | sta_node->mac_addr)) | ||
1296 | return -1; | 1300 | return -1; |
1297 | mwifiex_uap_del_sta_data(priv, sta_node); | 1301 | mwifiex_uap_del_sta_data(priv, sta_node); |
1298 | } | 1302 | } |
@@ -1328,13 +1332,40 @@ mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) | |||
1328 | tx_ant = RF_ANTENNA_AUTO; | 1332 | tx_ant = RF_ANTENNA_AUTO; |
1329 | rx_ant = RF_ANTENNA_AUTO; | 1333 | rx_ant = RF_ANTENNA_AUTO; |
1330 | } | 1334 | } |
1335 | } else { | ||
1336 | struct ieee80211_sta_ht_cap *ht_info; | ||
1337 | int rx_mcs_supp; | ||
1338 | enum ieee80211_band band; | ||
1339 | |||
1340 | if ((tx_ant == 0x1 && rx_ant == 0x1)) { | ||
1341 | adapter->user_dev_mcs_support = HT_STREAM_1X1; | ||
1342 | if (adapter->is_hw_11ac_capable) | ||
1343 | adapter->usr_dot_11ac_mcs_support = | ||
1344 | MWIFIEX_11AC_MCS_MAP_1X1; | ||
1345 | } else { | ||
1346 | adapter->user_dev_mcs_support = HT_STREAM_2X2; | ||
1347 | if (adapter->is_hw_11ac_capable) | ||
1348 | adapter->usr_dot_11ac_mcs_support = | ||
1349 | MWIFIEX_11AC_MCS_MAP_2X2; | ||
1350 | } | ||
1351 | |||
1352 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1353 | if (!adapter->wiphy->bands[band]) | ||
1354 | continue; | ||
1355 | |||
1356 | ht_info = &adapter->wiphy->bands[band]->ht_cap; | ||
1357 | rx_mcs_supp = | ||
1358 | GET_RXMCSSUPP(adapter->user_dev_mcs_support); | ||
1359 | memset(&ht_info->mcs, 0, adapter->number_of_antenna); | ||
1360 | memset(&ht_info->mcs, 0xff, rx_mcs_supp); | ||
1361 | } | ||
1331 | } | 1362 | } |
1332 | 1363 | ||
1333 | ant_cfg.tx_ant = tx_ant; | 1364 | ant_cfg.tx_ant = tx_ant; |
1334 | ant_cfg.rx_ant = rx_ant; | 1365 | ant_cfg.rx_ant = rx_ant; |
1335 | 1366 | ||
1336 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_ANTENNA, | 1367 | return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA, |
1337 | HostCmd_ACT_GEN_SET, 0, &ant_cfg); | 1368 | HostCmd_ACT_GEN_SET, 0, &ant_cfg, true); |
1338 | } | 1369 | } |
1339 | 1370 | ||
1340 | /* cfg80211 operation handler for stop ap. | 1371 | /* cfg80211 operation handler for stop ap. |
@@ -1349,8 +1380,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1349 | 1380 | ||
1350 | priv->ap_11n_enabled = 0; | 1381 | priv->ap_11n_enabled = 0; |
1351 | 1382 | ||
1352 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | 1383 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, |
1353 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 1384 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { |
1354 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | 1385 | wiphy_err(wiphy, "Failed to stop the BSS\n"); |
1355 | return -1; | 1386 | return -1; |
1356 | } | 1387 | } |
@@ -1416,9 +1447,6 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1416 | 1447 | ||
1417 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) | 1448 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) |
1418 | config_bands |= BAND_GN; | 1449 | config_bands |= BAND_GN; |
1419 | |||
1420 | if (params->chandef.width > NL80211_CHAN_WIDTH_40) | ||
1421 | config_bands |= BAND_GAC; | ||
1422 | } else { | 1450 | } else { |
1423 | bss_cfg->band_cfg = BAND_CONFIG_A; | 1451 | bss_cfg->band_cfg = BAND_CONFIG_A; |
1424 | config_bands = BAND_A; | 1452 | config_bands = BAND_A; |
@@ -1464,16 +1492,16 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1464 | bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; | 1492 | bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; |
1465 | } | 1493 | } |
1466 | 1494 | ||
1467 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | 1495 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, |
1468 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 1496 | HostCmd_ACT_GEN_SET, 0, NULL, true)) { |
1469 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | 1497 | wiphy_err(wiphy, "Failed to stop the BSS\n"); |
1470 | kfree(bss_cfg); | 1498 | kfree(bss_cfg); |
1471 | return -1; | 1499 | return -1; |
1472 | } | 1500 | } |
1473 | 1501 | ||
1474 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | 1502 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, |
1475 | HostCmd_ACT_GEN_SET, | 1503 | HostCmd_ACT_GEN_SET, |
1476 | UAP_BSS_PARAMS_I, bss_cfg)) { | 1504 | UAP_BSS_PARAMS_I, bss_cfg, false)) { |
1477 | wiphy_err(wiphy, "Failed to set the SSID\n"); | 1505 | wiphy_err(wiphy, "Failed to set the SSID\n"); |
1478 | kfree(bss_cfg); | 1506 | kfree(bss_cfg); |
1479 | return -1; | 1507 | return -1; |
@@ -1481,8 +1509,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1481 | 1509 | ||
1482 | kfree(bss_cfg); | 1510 | kfree(bss_cfg); |
1483 | 1511 | ||
1484 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_BSS_START, | 1512 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, |
1485 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 1513 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { |
1486 | wiphy_err(wiphy, "Failed to start the BSS\n"); | 1514 | wiphy_err(wiphy, "Failed to start the BSS\n"); |
1487 | return -1; | 1515 | return -1; |
1488 | } | 1516 | } |
@@ -1492,9 +1520,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1492 | else | 1520 | else |
1493 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | 1521 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; |
1494 | 1522 | ||
1495 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, | 1523 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
1496 | HostCmd_ACT_GEN_SET, 0, | 1524 | HostCmd_ACT_GEN_SET, 0, |
1497 | &priv->curr_pkt_filter)) | 1525 | &priv->curr_pkt_filter, true)) |
1498 | return -1; | 1526 | return -1; |
1499 | 1527 | ||
1500 | return 0; | 1528 | return 0; |
@@ -1583,8 +1611,9 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
1583 | * the function notifies the CFG802.11 subsystem of the new BSS connection. | 1611 | * the function notifies the CFG802.11 subsystem of the new BSS connection. |
1584 | */ | 1612 | */ |
1585 | static int | 1613 | static int |
1586 | mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | 1614 | mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, |
1587 | u8 *bssid, int mode, struct ieee80211_channel *channel, | 1615 | const u8 *ssid, const u8 *bssid, int mode, |
1616 | struct ieee80211_channel *channel, | ||
1588 | struct cfg80211_connect_params *sme, bool privacy) | 1617 | struct cfg80211_connect_params *sme, bool privacy) |
1589 | { | 1618 | { |
1590 | struct cfg80211_ssid req_ssid; | 1619 | struct cfg80211_ssid req_ssid; |
@@ -1881,7 +1910,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
1881 | params->privacy); | 1910 | params->privacy); |
1882 | done: | 1911 | done: |
1883 | if (!ret) { | 1912 | if (!ret) { |
1884 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); | 1913 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, |
1914 | params->chandef.chan, GFP_KERNEL); | ||
1885 | dev_dbg(priv->adapter->dev, | 1915 | dev_dbg(priv->adapter->dev, |
1886 | "info: joined/created adhoc network with bssid" | 1916 | "info: joined/created adhoc network with bssid" |
1887 | " %pM successfully\n", priv->cfg_bssid); | 1917 | " %pM successfully\n", priv->cfg_bssid); |
@@ -2070,10 +2100,10 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
2070 | else | 2100 | else |
2071 | ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; | 2101 | ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; |
2072 | 2102 | ||
2073 | if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap)) | 2103 | if (adapter->user_dev_mcs_support == HT_STREAM_2X2) |
2074 | ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; | 2104 | ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT; |
2075 | else | 2105 | else |
2076 | ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | 2106 | ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; |
2077 | 2107 | ||
2078 | if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) | 2108 | if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) |
2079 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; | 2109 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; |
@@ -2098,8 +2128,8 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, | |||
2098 | ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; | 2128 | ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; |
2099 | ht_info->cap |= IEEE80211_HT_CAP_SM_PS; | 2129 | ht_info->cap |= IEEE80211_HT_CAP_SM_PS; |
2100 | 2130 | ||
2101 | rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support); | 2131 | rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support); |
2102 | /* Set MCS for 1x1 */ | 2132 | /* Set MCS for 1x1/2x2 */ |
2103 | memset(mcs, 0xff, rx_mcs_supp); | 2133 | memset(mcs, 0xff, rx_mcs_supp); |
2104 | /* Clear all the other values */ | 2134 | /* Clear all the other values */ |
2105 | memset(&mcs[rx_mcs_supp], 0, | 2135 | memset(&mcs[rx_mcs_supp], 0, |
@@ -2460,9 +2490,8 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, | |||
2460 | MWIFIEX_CRITERIA_UNICAST | | 2490 | MWIFIEX_CRITERIA_UNICAST | |
2461 | MWIFIEX_CRITERIA_MULTICAST; | 2491 | MWIFIEX_CRITERIA_MULTICAST; |
2462 | 2492 | ||
2463 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG, | 2493 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, |
2464 | HostCmd_ACT_GEN_SET, 0, | 2494 | HostCmd_ACT_GEN_SET, 0, &mef_cfg, true); |
2465 | &mef_cfg); | ||
2466 | 2495 | ||
2467 | kfree(mef_entry); | 2496 | kfree(mef_entry); |
2468 | return ret; | 2497 | return ret; |
@@ -2574,9 +2603,9 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, | |||
2574 | if (!coalesce) { | 2603 | if (!coalesce) { |
2575 | dev_dbg(adapter->dev, | 2604 | dev_dbg(adapter->dev, |
2576 | "Disable coalesce and reset all previous rules\n"); | 2605 | "Disable coalesce and reset all previous rules\n"); |
2577 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_COALESCE_CFG, | 2606 | return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG, |
2578 | HostCmd_ACT_GEN_SET, 0, | 2607 | HostCmd_ACT_GEN_SET, 0, |
2579 | &coalesce_cfg); | 2608 | &coalesce_cfg, true); |
2580 | } | 2609 | } |
2581 | 2610 | ||
2582 | coalesce_cfg.num_of_rules = coalesce->n_rules; | 2611 | coalesce_cfg.num_of_rules = coalesce->n_rules; |
@@ -2591,8 +2620,172 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, | |||
2591 | } | 2620 | } |
2592 | } | 2621 | } |
2593 | 2622 | ||
2594 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_COALESCE_CFG, | 2623 | return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG, |
2595 | HostCmd_ACT_GEN_SET, 0, &coalesce_cfg); | 2624 | HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true); |
2625 | } | ||
2626 | |||
2627 | /* cfg80211 ops handler for tdls_mgmt. | ||
2628 | * Function prepares TDLS action frame packets and forwards them to FW | ||
2629 | */ | ||
2630 | static int | ||
2631 | mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | ||
2632 | u8 *peer, u8 action_code, u8 dialog_token, | ||
2633 | u16 status_code, u32 peer_capability, | ||
2634 | const u8 *extra_ies, size_t extra_ies_len) | ||
2635 | { | ||
2636 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
2637 | int ret; | ||
2638 | |||
2639 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
2640 | return -ENOTSUPP; | ||
2641 | |||
2642 | /* make sure we are in station mode and connected */ | ||
2643 | if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected)) | ||
2644 | return -ENOTSUPP; | ||
2645 | |||
2646 | switch (action_code) { | ||
2647 | case WLAN_TDLS_SETUP_REQUEST: | ||
2648 | dev_dbg(priv->adapter->dev, | ||
2649 | "Send TDLS Setup Request to %pM status_code=%d\n", peer, | ||
2650 | status_code); | ||
2651 | ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, | ||
2652 | dialog_token, status_code, | ||
2653 | extra_ies, extra_ies_len); | ||
2654 | break; | ||
2655 | case WLAN_TDLS_SETUP_RESPONSE: | ||
2656 | dev_dbg(priv->adapter->dev, | ||
2657 | "Send TDLS Setup Response to %pM status_code=%d\n", | ||
2658 | peer, status_code); | ||
2659 | ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, | ||
2660 | dialog_token, status_code, | ||
2661 | extra_ies, extra_ies_len); | ||
2662 | break; | ||
2663 | case WLAN_TDLS_SETUP_CONFIRM: | ||
2664 | dev_dbg(priv->adapter->dev, | ||
2665 | "Send TDLS Confirm to %pM status_code=%d\n", peer, | ||
2666 | status_code); | ||
2667 | ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, | ||
2668 | dialog_token, status_code, | ||
2669 | extra_ies, extra_ies_len); | ||
2670 | break; | ||
2671 | case WLAN_TDLS_TEARDOWN: | ||
2672 | dev_dbg(priv->adapter->dev, "Send TDLS Tear down to %pM\n", | ||
2673 | peer); | ||
2674 | ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, | ||
2675 | dialog_token, status_code, | ||
2676 | extra_ies, extra_ies_len); | ||
2677 | break; | ||
2678 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
2679 | dev_dbg(priv->adapter->dev, | ||
2680 | "Send TDLS Discovery Request to %pM\n", peer); | ||
2681 | ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, | ||
2682 | dialog_token, status_code, | ||
2683 | extra_ies, extra_ies_len); | ||
2684 | break; | ||
2685 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
2686 | dev_dbg(priv->adapter->dev, | ||
2687 | "Send TDLS Discovery Response to %pM\n", peer); | ||
2688 | ret = mwifiex_send_tdls_action_frame(priv, peer, action_code, | ||
2689 | dialog_token, status_code, | ||
2690 | extra_ies, extra_ies_len); | ||
2691 | break; | ||
2692 | default: | ||
2693 | dev_warn(priv->adapter->dev, | ||
2694 | "Unknown TDLS mgmt/action frame %pM\n", peer); | ||
2695 | ret = -EINVAL; | ||
2696 | break; | ||
2697 | } | ||
2698 | |||
2699 | return ret; | ||
2700 | } | ||
2701 | |||
2702 | static int | ||
2703 | mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | ||
2704 | u8 *peer, enum nl80211_tdls_operation action) | ||
2705 | { | ||
2706 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
2707 | |||
2708 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) || | ||
2709 | !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) | ||
2710 | return -ENOTSUPP; | ||
2711 | |||
2712 | /* make sure we are in station mode and connected */ | ||
2713 | if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected)) | ||
2714 | return -ENOTSUPP; | ||
2715 | |||
2716 | dev_dbg(priv->adapter->dev, | ||
2717 | "TDLS peer=%pM, oper=%d\n", peer, action); | ||
2718 | |||
2719 | switch (action) { | ||
2720 | case NL80211_TDLS_ENABLE_LINK: | ||
2721 | action = MWIFIEX_TDLS_ENABLE_LINK; | ||
2722 | break; | ||
2723 | case NL80211_TDLS_DISABLE_LINK: | ||
2724 | action = MWIFIEX_TDLS_DISABLE_LINK; | ||
2725 | break; | ||
2726 | case NL80211_TDLS_TEARDOWN: | ||
2727 | /* shouldn't happen!*/ | ||
2728 | dev_warn(priv->adapter->dev, | ||
2729 | "tdls_oper: teardown from driver not supported\n"); | ||
2730 | return -EINVAL; | ||
2731 | case NL80211_TDLS_SETUP: | ||
2732 | /* shouldn't happen!*/ | ||
2733 | dev_warn(priv->adapter->dev, | ||
2734 | "tdls_oper: setup from driver not supported\n"); | ||
2735 | return -EINVAL; | ||
2736 | case NL80211_TDLS_DISCOVERY_REQ: | ||
2737 | /* shouldn't happen!*/ | ||
2738 | dev_warn(priv->adapter->dev, | ||
2739 | "tdls_oper: discovery from driver not supported\n"); | ||
2740 | return -EINVAL; | ||
2741 | default: | ||
2742 | dev_err(priv->adapter->dev, | ||
2743 | "tdls_oper: operation not supported\n"); | ||
2744 | return -ENOTSUPP; | ||
2745 | } | ||
2746 | |||
2747 | return mwifiex_tdls_oper(priv, peer, action); | ||
2748 | } | ||
2749 | |||
2750 | static int | ||
2751 | mwifiex_cfg80211_add_station(struct wiphy *wiphy, | ||
2752 | struct net_device *dev, | ||
2753 | u8 *mac, struct station_parameters *params) | ||
2754 | { | ||
2755 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
2756 | |||
2757 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
2758 | return -ENOTSUPP; | ||
2759 | |||
2760 | /* make sure we are in station mode and connected */ | ||
2761 | if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected) | ||
2762 | return -ENOTSUPP; | ||
2763 | |||
2764 | return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK); | ||
2765 | } | ||
2766 | |||
2767 | static int | ||
2768 | mwifiex_cfg80211_change_station(struct wiphy *wiphy, | ||
2769 | struct net_device *dev, | ||
2770 | u8 *mac, struct station_parameters *params) | ||
2771 | { | ||
2772 | int ret; | ||
2773 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
2774 | |||
2775 | /* we support change_station handler only for TDLS peers*/ | ||
2776 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
2777 | return -ENOTSUPP; | ||
2778 | |||
2779 | /* make sure we are in station mode and connected */ | ||
2780 | if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected) | ||
2781 | return -ENOTSUPP; | ||
2782 | |||
2783 | priv->sta_params = params; | ||
2784 | |||
2785 | ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK); | ||
2786 | priv->sta_params = NULL; | ||
2787 | |||
2788 | return ret; | ||
2596 | } | 2789 | } |
2597 | 2790 | ||
2598 | /* station cfg80211 operations */ | 2791 | /* station cfg80211 operations */ |
@@ -2630,6 +2823,10 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2630 | .set_wakeup = mwifiex_cfg80211_set_wakeup, | 2823 | .set_wakeup = mwifiex_cfg80211_set_wakeup, |
2631 | #endif | 2824 | #endif |
2632 | .set_coalesce = mwifiex_cfg80211_set_coalesce, | 2825 | .set_coalesce = mwifiex_cfg80211_set_coalesce, |
2826 | .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt, | ||
2827 | .tdls_oper = mwifiex_cfg80211_tdls_oper, | ||
2828 | .add_station = mwifiex_cfg80211_add_station, | ||
2829 | .change_station = mwifiex_cfg80211_change_station, | ||
2633 | }; | 2830 | }; |
2634 | 2831 | ||
2635 | #ifdef CONFIG_PM | 2832 | #ifdef CONFIG_PM |
@@ -2715,6 +2912,11 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2715 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | | 2912 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | |
2716 | WIPHY_FLAG_AP_UAPSD | | 2913 | WIPHY_FLAG_AP_UAPSD | |
2717 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 2914 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; |
2915 | |||
2916 | if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) | ||
2917 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | ||
2918 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP; | ||
2919 | |||
2718 | wiphy->regulatory_flags |= | 2920 | wiphy->regulatory_flags |= |
2719 | REGULATORY_CUSTOM_REG | | 2921 | REGULATORY_CUSTOM_REG | |
2720 | REGULATORY_STRICT_REG; | 2922 | REGULATORY_STRICT_REG; |
@@ -2736,7 +2938,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2736 | 2938 | ||
2737 | wiphy->features |= NL80211_FEATURE_HT_IBSS | | 2939 | wiphy->features |= NL80211_FEATURE_HT_IBSS | |
2738 | NL80211_FEATURE_INACTIVITY_TIMER | | 2940 | NL80211_FEATURE_INACTIVITY_TIMER | |
2739 | NL80211_FEATURE_LOW_PRIORITY_SCAN; | 2941 | NL80211_FEATURE_LOW_PRIORITY_SCAN | |
2942 | NL80211_FEATURE_NEED_OBSS_SCAN; | ||
2740 | 2943 | ||
2741 | /* Reserve space for mwifiex specific private data for BSS */ | 2944 | /* Reserve space for mwifiex specific private data for BSS */ |
2742 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); | 2945 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); |
@@ -2767,17 +2970,17 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2767 | country_code); | 2970 | country_code); |
2768 | } | 2971 | } |
2769 | 2972 | ||
2770 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 2973 | mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
2771 | HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr); | 2974 | HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true); |
2772 | wiphy->frag_threshold = thr; | 2975 | wiphy->frag_threshold = thr; |
2773 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 2976 | mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
2774 | HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr); | 2977 | HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true); |
2775 | wiphy->rts_threshold = thr; | 2978 | wiphy->rts_threshold = thr; |
2776 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 2979 | mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
2777 | HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry); | 2980 | HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true); |
2778 | wiphy->retry_short = (u8) retry; | 2981 | wiphy->retry_short = (u8) retry; |
2779 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 2982 | mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
2780 | HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry); | 2983 | HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true); |
2781 | wiphy->retry_long = (u8) retry; | 2984 | wiphy->retry_long = (u8) retry; |
2782 | 2985 | ||
2783 | adapter->wiphy = wiphy; | 2986 | adapter->wiphy = wiphy; |
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index 9eefacbc844b..0ddec3d4b059 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c | |||
@@ -71,6 +71,95 @@ u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, | |||
71 | 71 | ||
72 | static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; | 72 | static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; |
73 | 73 | ||
74 | /* For every mcs_rate line, the first 8 bytes are for stream 1x1, | ||
75 | * and all 16 bytes are for stream 2x2. | ||
76 | */ | ||
77 | static const u16 mcs_rate[4][16] = { | ||
78 | /* LGI 40M */ | ||
79 | { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, | ||
80 | 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c }, | ||
81 | |||
82 | /* SGI 40M */ | ||
83 | { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, | ||
84 | 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 }, | ||
85 | |||
86 | /* LGI 20M */ | ||
87 | { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, | ||
88 | 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 }, | ||
89 | |||
90 | /* SGI 20M */ | ||
91 | { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, | ||
92 | 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } | ||
93 | }; | ||
94 | |||
95 | /* AC rates */ | ||
96 | static const u16 ac_mcs_rate_nss1[8][10] = { | ||
97 | /* LG 160M */ | ||
98 | { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, | ||
99 | 0x492, 0x57C, 0x618 }, | ||
100 | |||
101 | /* SG 160M */ | ||
102 | { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, | ||
103 | 0x514, 0x618, 0x6C6 }, | ||
104 | |||
105 | /* LG 80M */ | ||
106 | { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, | ||
107 | 0x249, 0x2BE, 0x30C }, | ||
108 | |||
109 | /* SG 80M */ | ||
110 | { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, | ||
111 | 0x28A, 0x30C, 0x363 }, | ||
112 | |||
113 | /* LG 40M */ | ||
114 | { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, | ||
115 | 0x10E, 0x144, 0x168 }, | ||
116 | |||
117 | /* SG 40M */ | ||
118 | { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, | ||
119 | 0x12C, 0x168, 0x190 }, | ||
120 | |||
121 | /* LG 20M */ | ||
122 | { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 }, | ||
123 | |||
124 | /* SG 20M */ | ||
125 | { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 }, | ||
126 | }; | ||
127 | |||
128 | /* NSS2 note: the value in the table is 2 multiplier of the actual rate */ | ||
129 | static const u16 ac_mcs_rate_nss2[8][10] = { | ||
130 | /* LG 160M */ | ||
131 | { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, | ||
132 | 0x924, 0xAF8, 0xC30 }, | ||
133 | |||
134 | /* SG 160M */ | ||
135 | { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, | ||
136 | 0xA28, 0xC30, 0xD8B }, | ||
137 | |||
138 | /* LG 80M */ | ||
139 | { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, | ||
140 | 0x492, 0x57C, 0x618 }, | ||
141 | |||
142 | /* SG 80M */ | ||
143 | { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, | ||
144 | 0x514, 0x618, 0x6C6 }, | ||
145 | |||
146 | /* LG 40M */ | ||
147 | { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, | ||
148 | 0x21C, 0x288, 0x2D0 }, | ||
149 | |||
150 | /* SG 40M */ | ||
151 | { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, | ||
152 | 0x258, 0x2D0, 0x320 }, | ||
153 | |||
154 | /* LG 20M */ | ||
155 | { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, | ||
156 | 0x138, 0x00 }, | ||
157 | |||
158 | /* SG 20M */ | ||
159 | { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, | ||
160 | 0x15B, 0x00 }, | ||
161 | }; | ||
162 | |||
74 | struct region_code_mapping { | 163 | struct region_code_mapping { |
75 | u8 code; | 164 | u8 code; |
76 | u8 region[IEEE80211_COUNTRY_STRING_LEN]; | 165 | u8 region[IEEE80211_COUNTRY_STRING_LEN]; |
@@ -109,95 +198,6 @@ u8 *mwifiex_11d_code_2_region(u8 code) | |||
109 | u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, | 198 | u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, |
110 | u8 index, u8 ht_info) | 199 | u8 index, u8 ht_info) |
111 | { | 200 | { |
112 | /* | ||
113 | * For every mcs_rate line, the first 8 bytes are for stream 1x1, | ||
114 | * and all 16 bytes are for stream 2x2. | ||
115 | */ | ||
116 | u16 mcs_rate[4][16] = { | ||
117 | /* LGI 40M */ | ||
118 | { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, | ||
119 | 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c }, | ||
120 | |||
121 | /* SGI 40M */ | ||
122 | { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, | ||
123 | 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 }, | ||
124 | |||
125 | /* LGI 20M */ | ||
126 | { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, | ||
127 | 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 }, | ||
128 | |||
129 | /* SGI 20M */ | ||
130 | { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, | ||
131 | 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } | ||
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; | 201 | u32 rate = 0; |
202 | u8 mcs_index = 0; | 202 | u8 mcs_index = 0; |
203 | u8 bw = 0; | 203 | u8 bw = 0; |
@@ -252,28 +252,8 @@ u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, | |||
252 | u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, | 252 | u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, |
253 | u8 index, u8 ht_info) | 253 | u8 index, u8 ht_info) |
254 | { | 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 | }; | ||
275 | u32 mcs_num_supp = | 255 | u32 mcs_num_supp = |
276 | (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8; | 256 | (priv->adapter->user_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8; |
277 | u32 rate; | 257 | u32 rate; |
278 | 258 | ||
279 | if (priv->adapter->is_hw_11ac_capable) | 259 | if (priv->adapter->is_hw_11ac_capable) |
@@ -458,7 +438,6 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) | |||
458 | break; | 438 | break; |
459 | case BAND_G: | 439 | case BAND_G: |
460 | case BAND_G | BAND_GN: | 440 | case BAND_G | BAND_GN: |
461 | case BAND_G | BAND_GN | BAND_GAC: | ||
462 | dev_dbg(adapter->dev, "info: infra band=%d " | 441 | dev_dbg(adapter->dev, "info: infra band=%d " |
463 | "supported_rates_g\n", adapter->config_bands); | 442 | "supported_rates_g\n", adapter->config_bands); |
464 | k = mwifiex_copy_rates(rates, k, supported_rates_g, | 443 | k = mwifiex_copy_rates(rates, k, supported_rates_g, |
@@ -469,10 +448,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) | |||
469 | case BAND_A | BAND_B: | 448 | case BAND_A | BAND_B: |
470 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: | 449 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: |
471 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC: | 450 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC: |
472 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | | ||
473 | BAND_AAC | BAND_GAC: | ||
474 | case BAND_B | BAND_G | BAND_GN: | 451 | case BAND_B | BAND_G | BAND_GN: |
475 | case BAND_B | BAND_G | BAND_GN | BAND_GAC: | ||
476 | dev_dbg(adapter->dev, "info: infra band=%d " | 452 | dev_dbg(adapter->dev, "info: infra band=%d " |
477 | "supported_rates_bg\n", adapter->config_bands); | 453 | "supported_rates_bg\n", adapter->config_bands); |
478 | k = mwifiex_copy_rates(rates, k, supported_rates_bg, | 454 | k = mwifiex_copy_rates(rates, k, supported_rates_bg, |
@@ -496,7 +472,6 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) | |||
496 | sizeof(supported_rates_a)); | 472 | sizeof(supported_rates_a)); |
497 | break; | 473 | break; |
498 | case BAND_GN: | 474 | case BAND_GN: |
499 | case BAND_GN | BAND_GAC: | ||
500 | dev_dbg(adapter->dev, "info: infra band=%d " | 475 | dev_dbg(adapter->dev, "info: infra band=%d " |
501 | "supported_rates_n\n", adapter->config_bands); | 476 | "supported_rates_n\n", adapter->config_bands); |
502 | k = mwifiex_copy_rates(rates, k, supported_rates_n, | 477 | 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 1ddc8b2e3722..1062c918a7bf 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -37,13 +37,12 @@ | |||
37 | static void | 37 | static void |
38 | mwifiex_init_cmd_node(struct mwifiex_private *priv, | 38 | mwifiex_init_cmd_node(struct mwifiex_private *priv, |
39 | struct cmd_ctrl_node *cmd_node, | 39 | struct cmd_ctrl_node *cmd_node, |
40 | u32 cmd_oid, void *data_buf) | 40 | u32 cmd_oid, void *data_buf, bool sync) |
41 | { | 41 | { |
42 | cmd_node->priv = priv; | 42 | cmd_node->priv = priv; |
43 | cmd_node->cmd_oid = cmd_oid; | 43 | cmd_node->cmd_oid = cmd_oid; |
44 | if (priv->adapter->cmd_wait_q_required) { | 44 | if (sync) { |
45 | cmd_node->wait_q_enabled = priv->adapter->cmd_wait_q_required; | 45 | cmd_node->wait_q_enabled = true; |
46 | priv->adapter->cmd_wait_q_required = false; | ||
47 | cmd_node->cmd_wait_q_woken = false; | 46 | cmd_node->cmd_wait_q_woken = false; |
48 | cmd_node->condition = &cmd_node->cmd_wait_q_woken; | 47 | cmd_node->condition = &cmd_node->cmd_wait_q_woken; |
49 | } | 48 | } |
@@ -166,8 +165,10 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
166 | dev_err(adapter->dev, | 165 | dev_err(adapter->dev, |
167 | "DNLD_CMD: FW in reset state, ignore cmd %#x\n", | 166 | "DNLD_CMD: FW in reset state, ignore cmd %#x\n", |
168 | cmd_code); | 167 | cmd_code); |
169 | mwifiex_complete_cmd(adapter, cmd_node); | 168 | if (cmd_node->wait_q_enabled) |
169 | mwifiex_complete_cmd(adapter, cmd_node); | ||
170 | mwifiex_recycle_cmd_node(adapter, cmd_node); | 170 | mwifiex_recycle_cmd_node(adapter, cmd_node); |
171 | queue_work(adapter->workqueue, &adapter->main_work); | ||
171 | return -1; | 172 | return -1; |
172 | } | 173 | } |
173 | 174 | ||
@@ -276,11 +277,11 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | |||
276 | 277 | ||
277 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 278 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
278 | 279 | ||
280 | adapter->seq_num++; | ||
279 | sleep_cfm_buf->seq_num = | 281 | sleep_cfm_buf->seq_num = |
280 | cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO | 282 | cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO |
281 | (adapter->seq_num, priv->bss_num, | 283 | (adapter->seq_num, priv->bss_num, |
282 | priv->bss_type))); | 284 | priv->bss_type))); |
283 | adapter->seq_num++; | ||
284 | 285 | ||
285 | if (adapter->iface_type == MWIFIEX_USB) { | 286 | if (adapter->iface_type == MWIFIEX_USB) { |
286 | sleep_cfm_tmp = | 287 | sleep_cfm_tmp = |
@@ -480,28 +481,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
480 | } | 481 | } |
481 | 482 | ||
482 | /* | 483 | /* |
483 | * This function is used to send synchronous command to the firmware. | 484 | * This function prepares a command and send it to the firmware. |
484 | * | ||
485 | * it allocates a wait queue for the command and wait for the command | ||
486 | * response. | ||
487 | */ | ||
488 | int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, | ||
489 | u16 cmd_action, u32 cmd_oid, void *data_buf) | ||
490 | { | ||
491 | int ret = 0; | ||
492 | struct mwifiex_adapter *adapter = priv->adapter; | ||
493 | |||
494 | adapter->cmd_wait_q_required = true; | ||
495 | |||
496 | ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, | ||
497 | data_buf); | ||
498 | |||
499 | return ret; | ||
500 | } | ||
501 | |||
502 | |||
503 | /* | ||
504 | * This function prepares a command and asynchronously send it to the firmware. | ||
505 | * | 485 | * |
506 | * Preparation includes - | 486 | * Preparation includes - |
507 | * - Sanity tests to make sure the card is still present or the FW | 487 | * - Sanity tests to make sure the card is still present or the FW |
@@ -511,8 +491,8 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, | |||
511 | * - Fill up the non-default parameters and buffer pointers | 491 | * - Fill up the non-default parameters and buffer pointers |
512 | * - Add the command to pending queue | 492 | * - Add the command to pending queue |
513 | */ | 493 | */ |
514 | int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | 494 | int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, |
515 | u16 cmd_action, u32 cmd_oid, void *data_buf) | 495 | u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync) |
516 | { | 496 | { |
517 | int ret; | 497 | int ret; |
518 | struct mwifiex_adapter *adapter = priv->adapter; | 498 | struct mwifiex_adapter *adapter = priv->adapter; |
@@ -529,11 +509,21 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
529 | return -1; | 509 | return -1; |
530 | } | 510 | } |
531 | 511 | ||
512 | if (adapter->hs_enabling && cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) { | ||
513 | dev_err(adapter->dev, "PREP_CMD: host entering sleep state\n"); | ||
514 | return -1; | ||
515 | } | ||
516 | |||
532 | if (adapter->surprise_removed) { | 517 | if (adapter->surprise_removed) { |
533 | dev_err(adapter->dev, "PREP_CMD: card is removed\n"); | 518 | dev_err(adapter->dev, "PREP_CMD: card is removed\n"); |
534 | return -1; | 519 | return -1; |
535 | } | 520 | } |
536 | 521 | ||
522 | if (adapter->is_cmd_timedout) { | ||
523 | dev_err(adapter->dev, "PREP_CMD: FW is in bad state\n"); | ||
524 | return -1; | ||
525 | } | ||
526 | |||
537 | if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { | 527 | if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { |
538 | if (cmd_no != HostCmd_CMD_FUNC_INIT) { | 528 | if (cmd_no != HostCmd_CMD_FUNC_INIT) { |
539 | dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); | 529 | dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); |
@@ -550,7 +540,7 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
550 | } | 540 | } |
551 | 541 | ||
552 | /* Initialize the command node */ | 542 | /* Initialize the command node */ |
553 | mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf); | 543 | mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf, sync); |
554 | 544 | ||
555 | if (!cmd_node->cmd_skb) { | 545 | if (!cmd_node->cmd_skb) { |
556 | dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); | 546 | dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); |
@@ -595,7 +585,8 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
595 | } | 585 | } |
596 | 586 | ||
597 | /* Send command */ | 587 | /* Send command */ |
598 | if (cmd_no == HostCmd_CMD_802_11_SCAN) { | 588 | if (cmd_no == HostCmd_CMD_802_11_SCAN || |
589 | cmd_no == HostCmd_CMD_802_11_SCAN_EXT) { | ||
599 | mwifiex_queue_scan_cmd(priv, cmd_node); | 590 | mwifiex_queue_scan_cmd(priv, cmd_node); |
600 | } else { | 591 | } else { |
601 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | 592 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); |
@@ -785,7 +776,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
785 | unsigned long flags; | 776 | unsigned long flags; |
786 | 777 | ||
787 | /* Now we got response from FW, cancel the command timer */ | 778 | /* Now we got response from FW, cancel the command timer */ |
788 | del_timer(&adapter->cmd_timer); | 779 | del_timer_sync(&adapter->cmd_timer); |
789 | 780 | ||
790 | if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { | 781 | if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { |
791 | resp = (struct host_cmd_ds_command *) adapter->upld_buf; | 782 | resp = (struct host_cmd_ds_command *) adapter->upld_buf; |
@@ -794,7 +785,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
794 | return -1; | 785 | return -1; |
795 | } | 786 | } |
796 | 787 | ||
797 | adapter->num_cmd_timeout = 0; | 788 | adapter->is_cmd_timedout = 0; |
798 | 789 | ||
799 | resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; | 790 | resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; |
800 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { | 791 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { |
@@ -905,8 +896,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
905 | struct cmd_ctrl_node *cmd_node; | 896 | struct cmd_ctrl_node *cmd_node; |
906 | struct timeval tstamp; | 897 | struct timeval tstamp; |
907 | 898 | ||
908 | adapter->num_cmd_timeout++; | 899 | adapter->is_cmd_timedout = 1; |
909 | adapter->dbg.num_cmd_timeout++; | ||
910 | if (!adapter->curr_cmd) { | 900 | if (!adapter->curr_cmd) { |
911 | dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); | 901 | dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); |
912 | return; | 902 | return; |
@@ -929,8 +919,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
929 | dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", | 919 | dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", |
930 | adapter->dbg.num_cmd_host_to_card_failure); | 920 | adapter->dbg.num_cmd_host_to_card_failure); |
931 | 921 | ||
932 | dev_err(adapter->dev, "num_cmd_timeout = %d\n", | 922 | dev_err(adapter->dev, "is_cmd_timedout = %d\n", |
933 | adapter->dbg.num_cmd_timeout); | 923 | adapter->is_cmd_timedout); |
934 | dev_err(adapter->dev, "num_tx_timeout = %d\n", | 924 | dev_err(adapter->dev, "num_tx_timeout = %d\n", |
935 | adapter->dbg.num_tx_timeout); | 925 | adapter->dbg.num_tx_timeout); |
936 | 926 | ||
@@ -987,13 +977,14 @@ void | |||
987 | mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | 977 | mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) |
988 | { | 978 | { |
989 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; | 979 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; |
990 | unsigned long flags; | 980 | unsigned long flags, cmd_flags; |
981 | struct mwifiex_private *priv; | ||
982 | int i; | ||
991 | 983 | ||
984 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); | ||
992 | /* Cancel current cmd */ | 985 | /* Cancel current cmd */ |
993 | if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { | 986 | if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { |
994 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
995 | adapter->curr_cmd->wait_q_enabled = false; | 987 | adapter->curr_cmd->wait_q_enabled = false; |
996 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | ||
997 | adapter->cmd_wait_q.status = -1; | 988 | adapter->cmd_wait_q.status = -1; |
998 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); | 989 | mwifiex_complete_cmd(adapter, adapter->curr_cmd); |
999 | } | 990 | } |
@@ -1013,6 +1004,7 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | |||
1013 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); | 1004 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); |
1014 | } | 1005 | } |
1015 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); | 1006 | spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); |
1007 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | ||
1016 | 1008 | ||
1017 | /* Cancel all pending scan command */ | 1009 | /* Cancel all pending scan command */ |
1018 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | 1010 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); |
@@ -1027,9 +1019,21 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | |||
1027 | } | 1019 | } |
1028 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | 1020 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); |
1029 | 1021 | ||
1030 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 1022 | if (adapter->scan_processing) { |
1031 | adapter->scan_processing = false; | 1023 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); |
1032 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 1024 | adapter->scan_processing = false; |
1025 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | ||
1026 | for (i = 0; i < adapter->priv_num; i++) { | ||
1027 | priv = adapter->priv[i]; | ||
1028 | if (!priv) | ||
1029 | continue; | ||
1030 | if (priv->scan_request) { | ||
1031 | dev_dbg(adapter->dev, "info: aborting scan\n"); | ||
1032 | cfg80211_scan_done(priv->scan_request, 1); | ||
1033 | priv->scan_request = NULL; | ||
1034 | } | ||
1035 | } | ||
1036 | } | ||
1033 | } | 1037 | } |
1034 | 1038 | ||
1035 | /* | 1039 | /* |
@@ -1048,7 +1052,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
1048 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | 1052 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; |
1049 | unsigned long cmd_flags; | 1053 | unsigned long cmd_flags; |
1050 | unsigned long scan_pending_q_flags; | 1054 | unsigned long scan_pending_q_flags; |
1051 | bool cancel_scan_cmd = false; | 1055 | struct mwifiex_private *priv; |
1056 | int i; | ||
1052 | 1057 | ||
1053 | if ((adapter->curr_cmd) && | 1058 | if ((adapter->curr_cmd) && |
1054 | (adapter->curr_cmd->wait_q_enabled)) { | 1059 | (adapter->curr_cmd->wait_q_enabled)) { |
@@ -1074,15 +1079,24 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
1074 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 1079 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); |
1075 | spin_lock_irqsave(&adapter->scan_pending_q_lock, | 1080 | spin_lock_irqsave(&adapter->scan_pending_q_lock, |
1076 | scan_pending_q_flags); | 1081 | scan_pending_q_flags); |
1077 | cancel_scan_cmd = true; | ||
1078 | } | 1082 | } |
1079 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1083 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1080 | scan_pending_q_flags); | 1084 | scan_pending_q_flags); |
1081 | 1085 | ||
1082 | if (cancel_scan_cmd) { | 1086 | if (adapter->scan_processing) { |
1083 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); | 1087 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); |
1084 | adapter->scan_processing = false; | 1088 | adapter->scan_processing = false; |
1085 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | 1089 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); |
1090 | for (i = 0; i < adapter->priv_num; i++) { | ||
1091 | priv = adapter->priv[i]; | ||
1092 | if (!priv) | ||
1093 | continue; | ||
1094 | if (priv->scan_request) { | ||
1095 | dev_dbg(adapter->dev, "info: aborting scan\n"); | ||
1096 | cfg80211_scan_done(priv->scan_request, 1); | ||
1097 | priv->scan_request = NULL; | ||
1098 | } | ||
1099 | } | ||
1086 | } | 1100 | } |
1087 | adapter->cmd_wait_q.status = -1; | 1101 | adapter->cmd_wait_q.status = -1; |
1088 | } | 1102 | } |
@@ -1454,7 +1468,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1454 | { | 1468 | { |
1455 | struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; | 1469 | struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; |
1456 | struct mwifiex_adapter *adapter = priv->adapter; | 1470 | struct mwifiex_adapter *adapter = priv->adapter; |
1457 | int i; | 1471 | struct mwifiex_ie_types_header *tlv; |
1472 | struct hw_spec_fw_api_rev *api_rev; | ||
1473 | u16 resp_size, api_id; | ||
1474 | int i, left_len, parsed_len = 0; | ||
1458 | 1475 | ||
1459 | adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); | 1476 | adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); |
1460 | 1477 | ||
@@ -1490,6 +1507,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1490 | } | 1507 | } |
1491 | 1508 | ||
1492 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); | 1509 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); |
1510 | adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff; | ||
1493 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); | 1511 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); |
1494 | 1512 | ||
1495 | if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { | 1513 | if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { |
@@ -1498,8 +1516,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1498 | /* Copy 11AC cap */ | 1516 | /* Copy 11AC cap */ |
1499 | adapter->hw_dot_11ac_dev_cap = | 1517 | adapter->hw_dot_11ac_dev_cap = |
1500 | le32_to_cpu(hw_spec->dot_11ac_dev_cap); | 1518 | le32_to_cpu(hw_spec->dot_11ac_dev_cap); |
1501 | adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap; | 1519 | adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap |
1502 | adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap; | 1520 | & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; |
1521 | adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap | ||
1522 | & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; | ||
1503 | 1523 | ||
1504 | /* Copy 11AC mcs */ | 1524 | /* Copy 11AC mcs */ |
1505 | adapter->hw_dot_11ac_mcs_support = | 1525 | adapter->hw_dot_11ac_mcs_support = |
@@ -1510,6 +1530,46 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1510 | adapter->is_hw_11ac_capable = false; | 1530 | adapter->is_hw_11ac_capable = false; |
1511 | } | 1531 | } |
1512 | 1532 | ||
1533 | resp_size = le16_to_cpu(resp->size) - S_DS_GEN; | ||
1534 | if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) { | ||
1535 | /* we have variable HW SPEC information */ | ||
1536 | left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec); | ||
1537 | while (left_len > sizeof(struct mwifiex_ie_types_header)) { | ||
1538 | tlv = (void *)&hw_spec->tlvs + parsed_len; | ||
1539 | switch (le16_to_cpu(tlv->type)) { | ||
1540 | case TLV_TYPE_FW_API_REV: | ||
1541 | api_rev = (struct hw_spec_fw_api_rev *)tlv; | ||
1542 | api_id = le16_to_cpu(api_rev->api_id); | ||
1543 | switch (api_id) { | ||
1544 | case KEY_API_VER_ID: | ||
1545 | adapter->fw_key_api_major_ver = | ||
1546 | api_rev->major_ver; | ||
1547 | adapter->fw_key_api_minor_ver = | ||
1548 | api_rev->minor_ver; | ||
1549 | dev_dbg(adapter->dev, | ||
1550 | "fw_key_api v%d.%d\n", | ||
1551 | adapter->fw_key_api_major_ver, | ||
1552 | adapter->fw_key_api_minor_ver); | ||
1553 | break; | ||
1554 | default: | ||
1555 | dev_warn(adapter->dev, | ||
1556 | "Unknown FW api_id: %d\n", | ||
1557 | api_id); | ||
1558 | break; | ||
1559 | } | ||
1560 | break; | ||
1561 | default: | ||
1562 | dev_warn(adapter->dev, | ||
1563 | "Unknown GET_HW_SPEC TLV type: %#x\n", | ||
1564 | le16_to_cpu(tlv->type)); | ||
1565 | break; | ||
1566 | } | ||
1567 | parsed_len += le16_to_cpu(tlv->len) + | ||
1568 | sizeof(struct mwifiex_ie_types_header); | ||
1569 | left_len -= parsed_len; | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1513 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", | 1573 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", |
1514 | adapter->fw_release_number); | 1574 | adapter->fw_release_number); |
1515 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", | 1575 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", |
@@ -1538,6 +1598,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1538 | 1598 | ||
1539 | adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); | 1599 | adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); |
1540 | adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; | 1600 | adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; |
1601 | adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support; | ||
1541 | 1602 | ||
1542 | if (adapter->if_ops.update_mp_end_port) | 1603 | if (adapter->if_ops.update_mp_end_port) |
1543 | adapter->if_ops.update_mp_end_port(adapter, | 1604 | adapter->if_ops.update_mp_end_port(adapter, |
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index a5f9875cfd6e..b8a49aad12fd 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c | |||
@@ -85,8 +85,8 @@ static struct mwifiex_debug_data items[] = { | |||
85 | item_addr(hs_activated), 1}, | 85 | item_addr(hs_activated), 1}, |
86 | {"num_tx_timeout", item_size(num_tx_timeout), | 86 | {"num_tx_timeout", item_size(num_tx_timeout), |
87 | item_addr(num_tx_timeout), 1}, | 87 | item_addr(num_tx_timeout), 1}, |
88 | {"num_cmd_timeout", item_size(num_cmd_timeout), | 88 | {"is_cmd_timedout", item_size(is_cmd_timedout), |
89 | item_addr(num_cmd_timeout), 1}, | 89 | item_addr(is_cmd_timedout), 1}, |
90 | {"timeout_cmd_id", item_size(timeout_cmd_id), | 90 | {"timeout_cmd_id", item_size(timeout_cmd_id), |
91 | item_addr(timeout_cmd_id), 1}, | 91 | item_addr(timeout_cmd_id), 1}, |
92 | {"timeout_cmd_act", item_size(timeout_cmd_act), | 92 | {"timeout_cmd_act", item_size(timeout_cmd_act), |
@@ -493,7 +493,7 @@ mwifiex_regrdwr_write(struct file *file, | |||
493 | { | 493 | { |
494 | unsigned long addr = get_zeroed_page(GFP_KERNEL); | 494 | unsigned long addr = get_zeroed_page(GFP_KERNEL); |
495 | char *buf = (char *) addr; | 495 | char *buf = (char *) addr; |
496 | size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); | 496 | size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1); |
497 | int ret; | 497 | int ret; |
498 | u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; | 498 | u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; |
499 | 499 | ||
@@ -594,7 +594,7 @@ mwifiex_rdeeprom_write(struct file *file, | |||
594 | { | 594 | { |
595 | unsigned long addr = get_zeroed_page(GFP_KERNEL); | 595 | unsigned long addr = get_zeroed_page(GFP_KERNEL); |
596 | char *buf = (char *) addr; | 596 | char *buf = (char *) addr; |
597 | size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); | 597 | size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1); |
598 | int ret = 0; | 598 | int ret = 0; |
599 | int offset = -1, bytes = -1; | 599 | int offset = -1, bytes = -1; |
600 | 600 | ||
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 3a21bd03d6db..e7b3e16e5d34 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -75,10 +75,16 @@ | |||
75 | 75 | ||
76 | #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) | 76 | #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) |
77 | #define MWIFIEX_BUF_FLAG_BRIDGED_PKT BIT(1) | 77 | #define MWIFIEX_BUF_FLAG_BRIDGED_PKT BIT(1) |
78 | #define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) | ||
78 | 79 | ||
79 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 | 80 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 |
80 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 | 81 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 |
81 | 82 | ||
83 | #define MWIFIEX_TDLS_DISABLE_LINK 0x00 | ||
84 | #define MWIFIEX_TDLS_ENABLE_LINK 0x01 | ||
85 | #define MWIFIEX_TDLS_CREATE_LINK 0x02 | ||
86 | #define MWIFIEX_TDLS_CONFIG_LINK 0x03 | ||
87 | |||
82 | enum mwifiex_bss_type { | 88 | enum mwifiex_bss_type { |
83 | MWIFIEX_BSS_TYPE_STA = 0, | 89 | MWIFIEX_BSS_TYPE_STA = 0, |
84 | MWIFIEX_BSS_TYPE_UAP = 1, | 90 | MWIFIEX_BSS_TYPE_UAP = 1, |
@@ -92,6 +98,23 @@ enum mwifiex_bss_role { | |||
92 | MWIFIEX_BSS_ROLE_ANY = 0xff, | 98 | MWIFIEX_BSS_ROLE_ANY = 0xff, |
93 | }; | 99 | }; |
94 | 100 | ||
101 | enum mwifiex_tdls_status { | ||
102 | TDLS_NOT_SETUP = 0, | ||
103 | TDLS_SETUP_INPROGRESS, | ||
104 | TDLS_SETUP_COMPLETE, | ||
105 | TDLS_SETUP_FAILURE, | ||
106 | TDLS_LINK_TEARDOWN, | ||
107 | }; | ||
108 | |||
109 | enum mwifiex_tdls_error_code { | ||
110 | TDLS_ERR_NO_ERROR = 0, | ||
111 | TDLS_ERR_INTERNAL_ERROR, | ||
112 | TDLS_ERR_MAX_LINKS_EST, | ||
113 | TDLS_ERR_LINK_EXISTS, | ||
114 | TDLS_ERR_LINK_NONEXISTENT, | ||
115 | TDLS_ERR_PEER_STA_UNREACHABLE = 25, | ||
116 | }; | ||
117 | |||
95 | #define BSS_ROLE_BIT_MASK BIT(0) | 118 | #define BSS_ROLE_BIT_MASK BIT(0) |
96 | 119 | ||
97 | #define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) | 120 | #define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 5fa932d5f905..b485dc1ae5eb 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -50,21 +50,23 @@ struct tx_packet_hdr { | |||
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 | BAND_AN | BAND_AAC) |
54 | 54 | ||
55 | #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)) | 56 | BIT(13)) |
57 | #define IS_SUPPORT_MULTI_BANDS(adapter) \ | 57 | #define IS_SUPPORT_MULTI_BANDS(adapter) \ |
58 | (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) | 58 | (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) |
59 | 59 | ||
60 | /* shift bit 12 and bit 13 in fw_cap_info from the firmware to bit 13 and 14 | 60 | /* bit 13: 11ac BAND_AAC |
61 | * for 11ac so that bit 11 is for GN, bit 12 for AN, bit 13 for GAC, and bit | 61 | * bit 12: reserved for lab testing, will be reused for BAND_AN |
62 | * bit 14 for AAC, in order to be compatible with the band capability | 62 | * bit 11: 11n BAND_GN |
63 | * defined in the driver after right shift of 8 bits. | 63 | * bit 10: 11a BAND_A |
64 | * bit 9: 11g BAND_G | ||
65 | * bit 8: 11b BAND_B | ||
66 | * Map these bits to band capability by right shifting 8 bits. | ||
64 | */ | 67 | */ |
65 | #define GET_FW_DEFAULT_BANDS(adapter) \ | 68 | #define GET_FW_DEFAULT_BANDS(adapter) \ |
66 | (((((adapter->fw_cap_info & 0x3000) << 1) | \ | 69 | (((adapter->fw_cap_info & 0x2f00) >> 8) & \ |
67 | (adapter->fw_cap_info & ~0xF000)) >> 8) & \ | ||
68 | ALL_802_11_BANDS) | 70 | ALL_802_11_BANDS) |
69 | 71 | ||
70 | #define HostCmd_WEP_KEY_INDEX_MASK 0x3fff | 72 | #define HostCmd_WEP_KEY_INDEX_MASK 0x3fff |
@@ -77,12 +79,21 @@ enum KEY_TYPE_ID { | |||
77 | KEY_TYPE_ID_WAPI, | 79 | KEY_TYPE_ID_WAPI, |
78 | KEY_TYPE_ID_AES_CMAC, | 80 | KEY_TYPE_ID_AES_CMAC, |
79 | }; | 81 | }; |
82 | |||
83 | #define WPA_PN_SIZE 8 | ||
84 | #define KEY_PARAMS_FIXED_LEN 10 | ||
85 | #define KEY_INDEX_MASK 0xf | ||
86 | #define FW_KEY_API_VER_MAJOR_V2 2 | ||
87 | |||
80 | #define KEY_MCAST BIT(0) | 88 | #define KEY_MCAST BIT(0) |
81 | #define KEY_UNICAST BIT(1) | 89 | #define KEY_UNICAST BIT(1) |
82 | #define KEY_ENABLED BIT(2) | 90 | #define KEY_ENABLED BIT(2) |
91 | #define KEY_DEFAULT BIT(3) | ||
92 | #define KEY_TX_KEY BIT(4) | ||
93 | #define KEY_RX_KEY BIT(5) | ||
83 | #define KEY_IGTK BIT(10) | 94 | #define KEY_IGTK BIT(10) |
84 | 95 | ||
85 | #define WAPI_KEY_LEN 50 | 96 | #define WAPI_KEY_LEN (WLAN_KEY_LEN_SMS4 + PN_LEN + 2) |
86 | 97 | ||
87 | #define MAX_POLL_TRIES 100 | 98 | #define MAX_POLL_TRIES 100 |
88 | #define MAX_FIRMWARE_POLL_TRIES 100 | 99 | #define MAX_FIRMWARE_POLL_TRIES 100 |
@@ -130,6 +141,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
130 | #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) | 141 | #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) |
131 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) | 142 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) |
132 | #define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) | 143 | #define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) |
144 | #define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35) | ||
133 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) | 145 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) |
134 | #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) | 146 | #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) |
135 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) | 147 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) |
@@ -144,6 +156,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
144 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) | 156 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) |
145 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) | 157 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) |
146 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) | 158 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) |
159 | #define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86) | ||
160 | #define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87) | ||
147 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) | 161 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) |
148 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) | 162 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) |
149 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) | 163 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) |
@@ -154,6 +168,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
154 | #define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) | 168 | #define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) |
155 | #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) | 169 | #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) |
156 | #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) | 170 | #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) |
171 | #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) | ||
172 | #define TLV_TYPE_FW_API_REV (PROPRIETARY_TLV_BASE_ID + 199) | ||
157 | 173 | ||
158 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 | 174 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 |
159 | 175 | ||
@@ -176,13 +192,21 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
176 | #define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 | 192 | #define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 |
177 | 193 | ||
178 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) | 194 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) |
195 | #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) | ||
179 | 196 | ||
180 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ | 197 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ |
181 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ | 198 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ |
182 | IEEE80211_HT_CAP_SM_PS) | 199 | IEEE80211_HT_CAP_SM_PS) |
183 | 200 | ||
201 | #define MWIFIEX_DEF_11N_TX_BF_CAP 0x09E1E008 | ||
202 | |||
184 | #define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR | 203 | #define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR |
185 | 204 | ||
205 | #define GET_RXSTBC(x) (x & IEEE80211_HT_CAP_RX_STBC) | ||
206 | #define MWIFIEX_RX_STBC1 0x0100 | ||
207 | #define MWIFIEX_RX_STBC12 0x0200 | ||
208 | #define MWIFIEX_RX_STBC123 0x0300 | ||
209 | |||
186 | /* dev_cap bitmap | 210 | /* dev_cap bitmap |
187 | * BIT | 211 | * BIT |
188 | * 0-16 reserved | 212 | * 0-16 reserved |
@@ -204,6 +228,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
204 | #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) | 228 | #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) |
205 | #define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) | 229 | #define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) |
206 | #define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) | 230 | #define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) |
231 | #define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30)) | ||
207 | 232 | ||
208 | /* httxcfg bitmap | 233 | /* httxcfg bitmap |
209 | * 0 reserved | 234 | * 0 reserved |
@@ -216,8 +241,21 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
216 | */ | 241 | */ |
217 | #define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6)) | 242 | #define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6)) |
218 | 243 | ||
244 | /* 11AC Tx and Rx MCS map for 1x1 mode: | ||
245 | * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 | ||
246 | * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 7 streams | ||
247 | */ | ||
248 | #define MWIFIEX_11AC_MCS_MAP_1X1 0xfffefffe | ||
249 | |||
250 | /* 11AC Tx and Rx MCS map for 2x2 mode: | ||
251 | * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 and 2 | ||
252 | * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 6 streams | ||
253 | */ | ||
254 | #define MWIFIEX_11AC_MCS_MAP_2X2 0xfffafffa | ||
255 | |||
219 | #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) | 256 | #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) |
220 | #define SETHT_MCS32(x) (x[4] |= 1) | 257 | #define SETHT_MCS32(x) (x[4] |= 1) |
258 | #define HT_STREAM_1X1 0x11 | ||
221 | #define HT_STREAM_2X2 0x22 | 259 | #define HT_STREAM_2X2 0x22 |
222 | 260 | ||
223 | #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) | 261 | #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) |
@@ -226,17 +264,24 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
226 | 264 | ||
227 | /* HW_SPEC fw_cap_info */ | 265 | /* HW_SPEC fw_cap_info */ |
228 | 266 | ||
229 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(12)|BIT(13))) | 267 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & BIT(13)) |
230 | 268 | ||
231 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) | 269 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) |
232 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) | 270 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) |
233 | #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ | 271 | #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ |
234 | (2 * (nss - 1))) | 272 | (2 * (nss - 1))) |
235 | #define NO_NSS_SUPPORT 0x3 | ||
236 | |||
237 | #define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) | 273 | #define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) |
238 | #define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) | 274 | #define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) |
239 | 275 | ||
276 | /* Clear SU Beanformer, MU beanformer, MU beanformee and | ||
277 | * sounding dimensions bits | ||
278 | */ | ||
279 | #define MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK \ | ||
280 | (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | \ | ||
281 | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE | \ | ||
282 | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | \ | ||
283 | IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK) | ||
284 | |||
240 | #define MOD_CLASS_HR_DSSS 0x03 | 285 | #define MOD_CLASS_HR_DSSS 0x03 |
241 | #define MOD_CLASS_OFDM 0x07 | 286 | #define MOD_CLASS_OFDM 0x07 |
242 | #define MOD_CLASS_HT 0x08 | 287 | #define MOD_CLASS_HT 0x08 |
@@ -295,10 +340,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
295 | #define HostCmd_CMD_CAU_REG_ACCESS 0x00ed | 340 | #define HostCmd_CMD_CAU_REG_ACCESS 0x00ed |
296 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 | 341 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 |
297 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa | 342 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa |
343 | #define HostCmd_CMD_802_11_SCAN_EXT 0x0107 | ||
298 | #define HostCmd_CMD_COALESCE_CFG 0x010a | 344 | #define HostCmd_CMD_COALESCE_CFG 0x010a |
299 | #define HostCmd_CMD_MGMT_FRAME_REG 0x010c | 345 | #define HostCmd_CMD_MGMT_FRAME_REG 0x010c |
300 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d | 346 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d |
301 | #define HostCmd_CMD_11AC_CFG 0x0112 | 347 | #define HostCmd_CMD_11AC_CFG 0x0112 |
348 | #define HostCmd_CMD_TDLS_OPER 0x0122 | ||
302 | 349 | ||
303 | #define PROTOCOL_NO_SECURITY 0x01 | 350 | #define PROTOCOL_NO_SECURITY 0x01 |
304 | #define PROTOCOL_STATIC_WEP 0x02 | 351 | #define PROTOCOL_STATIC_WEP 0x02 |
@@ -440,6 +487,7 @@ enum P2P_MODES { | |||
440 | #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c | 487 | #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c |
441 | #define EVENT_HOSTWAKE_STAIE 0x0000004d | 488 | #define EVENT_HOSTWAKE_STAIE 0x0000004d |
442 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 | 489 | #define EVENT_CHANNEL_SWITCH_ANN 0x00000050 |
490 | #define EVENT_EXT_SCAN_REPORT 0x00000058 | ||
443 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f | 491 | #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f |
444 | 492 | ||
445 | #define EVENT_ID_MASK 0xffff | 493 | #define EVENT_ID_MASK 0xffff |
@@ -468,6 +516,12 @@ enum P2P_MODES { | |||
468 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | 516 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) |
469 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | 517 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) |
470 | 518 | ||
519 | #define ACT_TDLS_DELETE 0x00 | ||
520 | #define ACT_TDLS_CREATE 0x01 | ||
521 | #define ACT_TDLS_CONFIG 0x02 | ||
522 | |||
523 | #define MWIFIEX_FW_V15 15 | ||
524 | |||
471 | struct mwifiex_ie_types_header { | 525 | struct mwifiex_ie_types_header { |
472 | __le16 type; | 526 | __le16 type; |
473 | __le16 len; | 527 | __le16 len; |
@@ -480,6 +534,7 @@ struct mwifiex_ie_types_data { | |||
480 | 534 | ||
481 | #define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 | 535 | #define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 |
482 | #define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 | 536 | #define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 |
537 | #define MWIFIEX_TXPD_FLAGS_TDLS_PACKET 0x10 | ||
483 | 538 | ||
484 | struct txpd { | 539 | struct txpd { |
485 | u8 bss_type; | 540 | u8 bss_type; |
@@ -676,6 +731,56 @@ struct mwifiex_cmac_param { | |||
676 | u8 key[WLAN_KEY_LEN_AES_CMAC]; | 731 | u8 key[WLAN_KEY_LEN_AES_CMAC]; |
677 | } __packed; | 732 | } __packed; |
678 | 733 | ||
734 | struct mwifiex_wep_param { | ||
735 | __le16 key_len; | ||
736 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
737 | } __packed; | ||
738 | |||
739 | struct mwifiex_tkip_param { | ||
740 | u8 pn[WPA_PN_SIZE]; | ||
741 | __le16 key_len; | ||
742 | u8 key[WLAN_KEY_LEN_TKIP]; | ||
743 | } __packed; | ||
744 | |||
745 | struct mwifiex_aes_param { | ||
746 | u8 pn[WPA_PN_SIZE]; | ||
747 | __le16 key_len; | ||
748 | u8 key[WLAN_KEY_LEN_CCMP]; | ||
749 | } __packed; | ||
750 | |||
751 | struct mwifiex_wapi_param { | ||
752 | u8 pn[PN_LEN]; | ||
753 | __le16 key_len; | ||
754 | u8 key[WLAN_KEY_LEN_SMS4]; | ||
755 | } __packed; | ||
756 | |||
757 | struct mwifiex_cmac_aes_param { | ||
758 | u8 ipn[IGTK_PN_LEN]; | ||
759 | __le16 key_len; | ||
760 | u8 key[WLAN_KEY_LEN_AES_CMAC]; | ||
761 | } __packed; | ||
762 | |||
763 | struct mwifiex_ie_type_key_param_set_v2 { | ||
764 | __le16 type; | ||
765 | __le16 len; | ||
766 | u8 mac_addr[ETH_ALEN]; | ||
767 | u8 key_idx; | ||
768 | u8 key_type; | ||
769 | __le16 key_info; | ||
770 | union { | ||
771 | struct mwifiex_wep_param wep; | ||
772 | struct mwifiex_tkip_param tkip; | ||
773 | struct mwifiex_aes_param aes; | ||
774 | struct mwifiex_wapi_param wapi; | ||
775 | struct mwifiex_cmac_aes_param cmac_aes; | ||
776 | } key_params; | ||
777 | } __packed; | ||
778 | |||
779 | struct host_cmd_ds_802_11_key_material_v2 { | ||
780 | __le16 action; | ||
781 | struct mwifiex_ie_type_key_param_set_v2 key_param_set; | ||
782 | } __packed; | ||
783 | |||
679 | struct host_cmd_ds_802_11_key_material { | 784 | struct host_cmd_ds_802_11_key_material { |
680 | __le16 action; | 785 | __le16 action; |
681 | struct mwifiex_ie_type_key_param_set key_param_set; | 786 | struct mwifiex_ie_type_key_param_set key_param_set; |
@@ -727,6 +832,17 @@ struct host_cmd_ds_802_11_ps_mode_enh { | |||
727 | } params; | 832 | } params; |
728 | } __packed; | 833 | } __packed; |
729 | 834 | ||
835 | enum FW_API_VER_ID { | ||
836 | KEY_API_VER_ID = 1, | ||
837 | }; | ||
838 | |||
839 | struct hw_spec_fw_api_rev { | ||
840 | struct mwifiex_ie_types_header header; | ||
841 | __le16 api_id; | ||
842 | u8 major_ver; | ||
843 | u8 minor_ver; | ||
844 | } __packed; | ||
845 | |||
730 | struct host_cmd_ds_get_hw_spec { | 846 | struct host_cmd_ds_get_hw_spec { |
731 | __le16 hw_if_version; | 847 | __le16 hw_if_version; |
732 | __le16 version; | 848 | __le16 version; |
@@ -748,6 +864,7 @@ struct host_cmd_ds_get_hw_spec { | |||
748 | __le32 reserved_6; | 864 | __le32 reserved_6; |
749 | __le32 dot_11ac_dev_cap; | 865 | __le32 dot_11ac_dev_cap; |
750 | __le32 dot_11ac_mcs_support; | 866 | __le32 dot_11ac_mcs_support; |
867 | u8 tlvs[0]; | ||
751 | } __packed; | 868 | } __packed; |
752 | 869 | ||
753 | struct host_cmd_ds_802_11_rssi_info { | 870 | struct host_cmd_ds_802_11_rssi_info { |
@@ -993,6 +1110,7 @@ struct mwifiex_rate_scope { | |||
993 | __le16 hr_dsss_rate_bitmap; | 1110 | __le16 hr_dsss_rate_bitmap; |
994 | __le16 ofdm_rate_bitmap; | 1111 | __le16 ofdm_rate_bitmap; |
995 | __le16 ht_mcs_rate_bitmap[8]; | 1112 | __le16 ht_mcs_rate_bitmap[8]; |
1113 | __le16 vht_mcs_rate_bitmap[8]; | ||
996 | } __packed; | 1114 | } __packed; |
997 | 1115 | ||
998 | struct mwifiex_rate_drop_pattern { | 1116 | struct mwifiex_rate_drop_pattern { |
@@ -1047,14 +1165,28 @@ struct host_cmd_ds_rf_ant_siso { | |||
1047 | __le16 ant_mode; | 1165 | __le16 ant_mode; |
1048 | }; | 1166 | }; |
1049 | 1167 | ||
1050 | struct mwifiex_bcn_param { | 1168 | struct host_cmd_ds_tdls_oper { |
1051 | u8 bssid[ETH_ALEN]; | 1169 | __le16 tdls_action; |
1052 | u8 rssi; | 1170 | __le16 reason; |
1171 | u8 peer_mac[ETH_ALEN]; | ||
1172 | } __packed; | ||
1173 | |||
1174 | struct mwifiex_fixed_bcn_param { | ||
1053 | __le64 timestamp; | 1175 | __le64 timestamp; |
1054 | __le16 beacon_period; | 1176 | __le16 beacon_period; |
1055 | __le16 cap_info_bitmap; | 1177 | __le16 cap_info_bitmap; |
1056 | } __packed; | 1178 | } __packed; |
1057 | 1179 | ||
1180 | struct mwifiex_event_scan_result { | ||
1181 | __le16 event_id; | ||
1182 | u8 bss_index; | ||
1183 | u8 bss_type; | ||
1184 | u8 more_event; | ||
1185 | u8 reserved[3]; | ||
1186 | __le16 buf_size; | ||
1187 | u8 num_of_set; | ||
1188 | } __packed; | ||
1189 | |||
1058 | #define MWIFIEX_USER_SCAN_CHAN_MAX 50 | 1190 | #define MWIFIEX_USER_SCAN_CHAN_MAX 50 |
1059 | 1191 | ||
1060 | #define MWIFIEX_MAX_SSID_LIST_LENGTH 10 | 1192 | #define MWIFIEX_MAX_SSID_LIST_LENGTH 10 |
@@ -1124,6 +1256,28 @@ struct host_cmd_ds_802_11_scan_rsp { | |||
1124 | u8 bss_desc_and_tlv_buffer[1]; | 1256 | u8 bss_desc_and_tlv_buffer[1]; |
1125 | } __packed; | 1257 | } __packed; |
1126 | 1258 | ||
1259 | struct host_cmd_ds_802_11_scan_ext { | ||
1260 | u32 reserved; | ||
1261 | u8 tlv_buffer[1]; | ||
1262 | } __packed; | ||
1263 | |||
1264 | struct mwifiex_ie_types_bss_scan_rsp { | ||
1265 | struct mwifiex_ie_types_header header; | ||
1266 | u8 bssid[ETH_ALEN]; | ||
1267 | u8 frame_body[1]; | ||
1268 | } __packed; | ||
1269 | |||
1270 | struct mwifiex_ie_types_bss_scan_info { | ||
1271 | struct mwifiex_ie_types_header header; | ||
1272 | __le16 rssi; | ||
1273 | __le16 anpi; | ||
1274 | u8 cca_busy_fraction; | ||
1275 | u8 radio_type; | ||
1276 | u8 channel; | ||
1277 | u8 reserved; | ||
1278 | __le64 tsf; | ||
1279 | } __packed; | ||
1280 | |||
1127 | struct host_cmd_ds_802_11_bg_scan_query { | 1281 | struct host_cmd_ds_802_11_bg_scan_query { |
1128 | u8 flush; | 1282 | u8 flush; |
1129 | } __packed; | 1283 | } __packed; |
@@ -1296,6 +1450,11 @@ struct mwifiex_ie_types_vhtcap { | |||
1296 | struct ieee80211_vht_cap vht_cap; | 1450 | struct ieee80211_vht_cap vht_cap; |
1297 | } __packed; | 1451 | } __packed; |
1298 | 1452 | ||
1453 | struct mwifiex_ie_types_aid { | ||
1454 | struct mwifiex_ie_types_header header; | ||
1455 | __le16 aid; | ||
1456 | } __packed; | ||
1457 | |||
1299 | struct mwifiex_ie_types_oper_mode_ntf { | 1458 | struct mwifiex_ie_types_oper_mode_ntf { |
1300 | struct mwifiex_ie_types_header header; | 1459 | struct mwifiex_ie_types_header header; |
1301 | u8 oper_mode; | 1460 | u8 oper_mode; |
@@ -1331,6 +1490,11 @@ struct mwifiex_ie_types_extcap { | |||
1331 | u8 ext_capab[0]; | 1490 | u8 ext_capab[0]; |
1332 | } __packed; | 1491 | } __packed; |
1333 | 1492 | ||
1493 | struct mwifiex_ie_types_qos_info { | ||
1494 | struct mwifiex_ie_types_header header; | ||
1495 | u8 qos_info; | ||
1496 | } __packed; | ||
1497 | |||
1334 | struct host_cmd_ds_mac_reg_access { | 1498 | struct host_cmd_ds_mac_reg_access { |
1335 | __le16 action; | 1499 | __le16 action; |
1336 | __le16 offset; | 1500 | __le16 offset; |
@@ -1441,6 +1605,11 @@ struct host_cmd_tlv_rates { | |||
1441 | u8 rates[0]; | 1605 | u8 rates[0]; |
1442 | } __packed; | 1606 | } __packed; |
1443 | 1607 | ||
1608 | struct mwifiex_ie_types_bssid_list { | ||
1609 | struct mwifiex_ie_types_header header; | ||
1610 | u8 bssid[ETH_ALEN]; | ||
1611 | } __packed; | ||
1612 | |||
1444 | struct host_cmd_tlv_bcast_ssid { | 1613 | struct host_cmd_tlv_bcast_ssid { |
1445 | struct mwifiex_ie_types_header header; | 1614 | struct mwifiex_ie_types_header header; |
1446 | u8 bcast_ctl; | 1615 | u8 bcast_ctl; |
@@ -1634,6 +1803,7 @@ struct host_cmd_ds_command { | |||
1634 | struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; | 1803 | struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; |
1635 | struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; | 1804 | struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; |
1636 | struct host_cmd_ds_802_11_scan scan; | 1805 | struct host_cmd_ds_802_11_scan scan; |
1806 | struct host_cmd_ds_802_11_scan_ext ext_scan; | ||
1637 | struct host_cmd_ds_802_11_scan_rsp scan_resp; | 1807 | struct host_cmd_ds_802_11_scan_rsp scan_resp; |
1638 | struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; | 1808 | struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; |
1639 | struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; | 1809 | struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; |
@@ -1653,6 +1823,7 @@ struct host_cmd_ds_command { | |||
1653 | struct host_cmd_ds_11n_cfg htcfg; | 1823 | struct host_cmd_ds_11n_cfg htcfg; |
1654 | struct host_cmd_ds_wmm_get_status get_wmm_status; | 1824 | struct host_cmd_ds_wmm_get_status get_wmm_status; |
1655 | struct host_cmd_ds_802_11_key_material key_material; | 1825 | struct host_cmd_ds_802_11_key_material key_material; |
1826 | struct host_cmd_ds_802_11_key_material_v2 key_material_v2; | ||
1656 | struct host_cmd_ds_version_ext verext; | 1827 | struct host_cmd_ds_version_ext verext; |
1657 | struct host_cmd_ds_mgmt_frame_reg reg_mask; | 1828 | struct host_cmd_ds_mgmt_frame_reg reg_mask; |
1658 | struct host_cmd_ds_remain_on_chan roc_cfg; | 1829 | struct host_cmd_ds_remain_on_chan roc_cfg; |
@@ -1671,6 +1842,7 @@ struct host_cmd_ds_command { | |||
1671 | struct host_cmd_ds_sta_deauth sta_deauth; | 1842 | struct host_cmd_ds_sta_deauth sta_deauth; |
1672 | struct host_cmd_11ac_vht_cfg vht_cfg; | 1843 | struct host_cmd_11ac_vht_cfg vht_cfg; |
1673 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; | 1844 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; |
1845 | struct host_cmd_ds_tdls_oper tdls_oper; | ||
1674 | } params; | 1846 | } params; |
1675 | } __packed; | 1847 | } __packed; |
1676 | 1848 | ||
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index 81ac001ee741..3bf3d58bbc02 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c | |||
@@ -138,9 +138,9 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv, | |||
138 | } | 138 | } |
139 | 139 | ||
140 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) | 140 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) |
141 | return mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | 141 | return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, |
142 | HostCmd_ACT_GEN_SET, | 142 | HostCmd_ACT_GEN_SET, |
143 | UAP_CUSTOM_IE_I, ie_list); | 143 | UAP_CUSTOM_IE_I, ie_list, false); |
144 | 144 | ||
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 1d0a817f2bf0..4ecd0b208ac6 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -137,6 +137,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv) | |||
137 | priv->csa_expire_time = 0; | 137 | priv->csa_expire_time = 0; |
138 | priv->del_list_idx = 0; | 138 | priv->del_list_idx = 0; |
139 | priv->hs2_enabled = false; | 139 | priv->hs2_enabled = false; |
140 | memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); | ||
140 | 141 | ||
141 | return mwifiex_add_bss_prio_tbl(priv); | 142 | return mwifiex_add_bss_prio_tbl(priv); |
142 | } | 143 | } |
@@ -233,7 +234,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
233 | 234 | ||
234 | adapter->pm_wakeup_fw_try = false; | 235 | adapter->pm_wakeup_fw_try = false; |
235 | 236 | ||
236 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | ||
237 | adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | 237 | adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; |
238 | 238 | ||
239 | adapter->is_hs_configured = false; | 239 | adapter->is_hs_configured = false; |
@@ -281,6 +281,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
281 | adapter->arp_filter_size = 0; | 281 | adapter->arp_filter_size = 0; |
282 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; | 282 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; |
283 | adapter->empty_tx_q_cnt = 0; | 283 | adapter->empty_tx_q_cnt = 0; |
284 | adapter->ext_scan = true; | ||
285 | adapter->fw_key_api_major_ver = 0; | ||
286 | adapter->fw_key_api_minor_ver = 0; | ||
284 | } | 287 | } |
285 | 288 | ||
286 | /* | 289 | /* |
@@ -450,6 +453,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
450 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); | 453 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); |
451 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); | 454 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); |
452 | INIT_LIST_HEAD(&priv->sta_list); | 455 | INIT_LIST_HEAD(&priv->sta_list); |
456 | skb_queue_head_init(&priv->tdls_txq); | ||
453 | 457 | ||
454 | spin_lock_init(&priv->tx_ba_stream_tbl_lock); | 458 | spin_lock_init(&priv->tx_ba_stream_tbl_lock); |
455 | spin_lock_init(&priv->rx_reorder_tbl_lock); | 459 | spin_lock_init(&priv->rx_reorder_tbl_lock); |
@@ -615,7 +619,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
615 | /* cancel current command */ | 619 | /* cancel current command */ |
616 | if (adapter->curr_cmd) { | 620 | if (adapter->curr_cmd) { |
617 | dev_warn(adapter->dev, "curr_cmd is still in processing\n"); | 621 | dev_warn(adapter->dev, "curr_cmd is still in processing\n"); |
618 | del_timer(&adapter->cmd_timer); | 622 | del_timer_sync(&adapter->cmd_timer); |
619 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); | 623 | mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); |
620 | adapter->curr_cmd = NULL; | 624 | adapter->curr_cmd = NULL; |
621 | } | 625 | } |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 00a95f4c6a6c..ee494db54060 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -60,8 +60,7 @@ 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, | 63 | BAND_AAC = 32, |
64 | BAND_AAC = 64, | ||
65 | }; | 64 | }; |
66 | 65 | ||
67 | #define MWIFIEX_WPA_PASSHPHRASE_LEN 64 | 66 | #define MWIFIEX_WPA_PASSHPHRASE_LEN 64 |
@@ -86,6 +85,10 @@ struct wep_key { | |||
86 | #define BAND_CONFIG_A 0x01 | 85 | #define BAND_CONFIG_A 0x01 |
87 | #define MWIFIEX_SUPPORTED_RATES 14 | 86 | #define MWIFIEX_SUPPORTED_RATES 14 |
88 | #define MWIFIEX_SUPPORTED_RATES_EXT 32 | 87 | #define MWIFIEX_SUPPORTED_RATES_EXT 32 |
88 | #define MWIFIEX_TDLS_SUPPORTED_RATES 8 | ||
89 | #define MWIFIEX_TDLS_DEF_QOS_CAPAB 0xf | ||
90 | #define MWIFIEX_PRIO_BK 2 | ||
91 | #define MWIFIEX_PRIO_VI 5 | ||
89 | 92 | ||
90 | struct mwifiex_uap_bss_param { | 93 | struct mwifiex_uap_bss_param { |
91 | u8 channel; | 94 | u8 channel; |
@@ -174,6 +177,7 @@ struct mwifiex_ds_rx_reorder_tbl { | |||
174 | struct mwifiex_ds_tx_ba_stream_tbl { | 177 | struct mwifiex_ds_tx_ba_stream_tbl { |
175 | u16 tid; | 178 | u16 tid; |
176 | u8 ra[ETH_ALEN]; | 179 | u8 ra[ETH_ALEN]; |
180 | u8 amsdu; | ||
177 | }; | 181 | }; |
178 | 182 | ||
179 | #define DBG_CMD_NUM 5 | 183 | #define DBG_CMD_NUM 5 |
@@ -206,7 +210,7 @@ struct mwifiex_debug_info { | |||
206 | u32 num_cmd_assoc_success; | 210 | u32 num_cmd_assoc_success; |
207 | u32 num_cmd_assoc_failure; | 211 | u32 num_cmd_assoc_failure; |
208 | u32 num_tx_timeout; | 212 | u32 num_tx_timeout; |
209 | u32 num_cmd_timeout; | 213 | u8 is_cmd_timedout; |
210 | u16 timeout_cmd_id; | 214 | u16 timeout_cmd_id; |
211 | u16 timeout_cmd_act; | 215 | u16 timeout_cmd_act; |
212 | u16 last_cmd_id[DBG_CMD_NUM]; | 216 | u16 last_cmd_id[DBG_CMD_NUM]; |
@@ -233,7 +237,10 @@ struct mwifiex_ds_encrypt_key { | |||
233 | u8 mac_addr[ETH_ALEN]; | 237 | u8 mac_addr[ETH_ALEN]; |
234 | u32 is_wapi_key; | 238 | u32 is_wapi_key; |
235 | u8 pn[PN_LEN]; /* packet number */ | 239 | u8 pn[PN_LEN]; /* packet number */ |
240 | u8 pn_len; | ||
236 | u8 is_igtk_key; | 241 | u8 is_igtk_key; |
242 | u8 is_current_wep_key; | ||
243 | u8 is_rx_seq_valid; | ||
237 | }; | 244 | }; |
238 | 245 | ||
239 | struct mwifiex_power_cfg { | 246 | struct mwifiex_power_cfg { |
@@ -432,4 +439,16 @@ struct mwifiex_ds_coalesce_cfg { | |||
432 | struct mwifiex_coalesce_rule rule[MWIFIEX_COALESCE_MAX_RULES]; | 439 | struct mwifiex_coalesce_rule rule[MWIFIEX_COALESCE_MAX_RULES]; |
433 | }; | 440 | }; |
434 | 441 | ||
442 | struct mwifiex_ds_tdls_oper { | ||
443 | u16 tdls_action; | ||
444 | u8 peer_mac[ETH_ALEN]; | ||
445 | u16 capability; | ||
446 | u8 qos_info; | ||
447 | u8 *ext_capab; | ||
448 | u8 ext_capab_len; | ||
449 | u8 *supp_rates; | ||
450 | u8 supp_rates_len; | ||
451 | u8 *ht_capab; | ||
452 | }; | ||
453 | |||
435 | #endif /* !_MWIFIEX_IOCTL_H_ */ | 454 | #endif /* !_MWIFIEX_IOCTL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 4e4686e6ac09..89dc62a467f4 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -515,8 +515,7 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, | |||
515 | 515 | ||
516 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | 516 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && |
517 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | 517 | !bss_desc->disable_11n && !bss_desc->disable_11ac && |
518 | (priv->adapter->config_bands & BAND_GAC || | 518 | priv->adapter->config_bands & BAND_AAC) |
519 | priv->adapter->config_bands & BAND_AAC)) | ||
520 | mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos); | 519 | mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos); |
521 | 520 | ||
522 | /* Append vendor specific IE TLV */ | 521 | /* Append vendor specific IE TLV */ |
@@ -902,9 +901,9 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, | |||
902 | mwifiex_get_active_data_rates(priv, adhoc_start->data_rate); | 901 | mwifiex_get_active_data_rates(priv, adhoc_start->data_rate); |
903 | if ((adapter->adhoc_start_band & BAND_G) && | 902 | if ((adapter->adhoc_start_band & BAND_G) && |
904 | (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { | 903 | (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { |
905 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, | 904 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
906 | HostCmd_ACT_GEN_SET, 0, | 905 | HostCmd_ACT_GEN_SET, 0, |
907 | &priv->curr_pkt_filter)) { | 906 | &priv->curr_pkt_filter, false)) { |
908 | dev_err(adapter->dev, | 907 | dev_err(adapter->dev, |
909 | "ADHOC_S_CMD: G Protection config failed\n"); | 908 | "ADHOC_S_CMD: G Protection config failed\n"); |
910 | return -1; | 909 | return -1; |
@@ -983,7 +982,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, | |||
983 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); | 982 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); |
984 | radio_type = mwifiex_band_to_radio_type( | 983 | radio_type = mwifiex_band_to_radio_type( |
985 | priv->adapter->config_bands); | 984 | priv->adapter->config_bands); |
986 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); | 985 | mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); |
987 | 986 | ||
988 | if (adapter->sec_chan_offset == | 987 | if (adapter->sec_chan_offset == |
989 | IEEE80211_HT_PARAM_CHA_SEC_NONE) { | 988 | IEEE80211_HT_PARAM_CHA_SEC_NONE) { |
@@ -1074,9 +1073,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, | |||
1074 | priv-> | 1073 | priv-> |
1075 | curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; | 1074 | curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; |
1076 | 1075 | ||
1077 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, | 1076 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
1078 | HostCmd_ACT_GEN_SET, 0, | 1077 | HostCmd_ACT_GEN_SET, 0, |
1079 | &curr_pkt_filter)) { | 1078 | &curr_pkt_filter, false)) { |
1080 | dev_err(priv->adapter->dev, | 1079 | dev_err(priv->adapter->dev, |
1081 | "ADHOC_J_CMD: G Protection config failed\n"); | 1080 | "ADHOC_J_CMD: G Protection config failed\n"); |
1082 | return -1; | 1081 | return -1; |
@@ -1300,8 +1299,7 @@ int mwifiex_associate(struct mwifiex_private *priv, | |||
1300 | 1299 | ||
1301 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | 1300 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && |
1302 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | 1301 | !bss_desc->disable_11n && !bss_desc->disable_11ac && |
1303 | (priv->adapter->config_bands & BAND_GAC || | 1302 | priv->adapter->config_bands & BAND_AAC) |
1304 | priv->adapter->config_bands & BAND_AAC)) | ||
1305 | mwifiex_set_11ac_ba_params(priv); | 1303 | mwifiex_set_11ac_ba_params(priv); |
1306 | else | 1304 | else |
1307 | mwifiex_set_ba_params(priv); | 1305 | mwifiex_set_ba_params(priv); |
@@ -1314,8 +1312,8 @@ int mwifiex_associate(struct mwifiex_private *priv, | |||
1314 | retrieval */ | 1312 | retrieval */ |
1315 | priv->assoc_rsp_size = 0; | 1313 | priv->assoc_rsp_size = 0; |
1316 | 1314 | ||
1317 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_ASSOCIATE, | 1315 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, |
1318 | HostCmd_ACT_GEN_SET, 0, bss_desc); | 1316 | HostCmd_ACT_GEN_SET, 0, bss_desc, true); |
1319 | } | 1317 | } |
1320 | 1318 | ||
1321 | /* | 1319 | /* |
@@ -1335,14 +1333,13 @@ mwifiex_adhoc_start(struct mwifiex_private *priv, | |||
1335 | priv->curr_bss_params.band); | 1333 | priv->curr_bss_params.band); |
1336 | 1334 | ||
1337 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | 1335 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && |
1338 | (priv->adapter->config_bands & BAND_GAC || | 1336 | priv->adapter->config_bands & BAND_AAC) |
1339 | priv->adapter->config_bands & BAND_AAC)) | ||
1340 | mwifiex_set_11ac_ba_params(priv); | 1337 | mwifiex_set_11ac_ba_params(priv); |
1341 | else | 1338 | else |
1342 | mwifiex_set_ba_params(priv); | 1339 | mwifiex_set_ba_params(priv); |
1343 | 1340 | ||
1344 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_START, | 1341 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, |
1345 | HostCmd_ACT_GEN_SET, 0, adhoc_ssid); | 1342 | HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true); |
1346 | } | 1343 | } |
1347 | 1344 | ||
1348 | /* | 1345 | /* |
@@ -1376,8 +1373,7 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, | |||
1376 | 1373 | ||
1377 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | 1374 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && |
1378 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | 1375 | !bss_desc->disable_11n && !bss_desc->disable_11ac && |
1379 | (priv->adapter->config_bands & BAND_GAC || | 1376 | priv->adapter->config_bands & BAND_AAC) |
1380 | priv->adapter->config_bands & BAND_AAC)) | ||
1381 | mwifiex_set_11ac_ba_params(priv); | 1377 | mwifiex_set_11ac_ba_params(priv); |
1382 | else | 1378 | else |
1383 | mwifiex_set_ba_params(priv); | 1379 | mwifiex_set_ba_params(priv); |
@@ -1387,8 +1383,8 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, | |||
1387 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", | 1383 | dev_dbg(priv->adapter->dev, "info: curr_bss_params.band = %c\n", |
1388 | priv->curr_bss_params.band); | 1384 | priv->curr_bss_params.band); |
1389 | 1385 | ||
1390 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, | 1386 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, |
1391 | HostCmd_ACT_GEN_SET, 0, bss_desc); | 1387 | HostCmd_ACT_GEN_SET, 0, bss_desc, true); |
1392 | } | 1388 | } |
1393 | 1389 | ||
1394 | /* | 1390 | /* |
@@ -1407,8 +1403,8 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) | |||
1407 | else | 1403 | else |
1408 | memcpy(mac_address, mac, ETH_ALEN); | 1404 | memcpy(mac_address, mac, ETH_ALEN); |
1409 | 1405 | ||
1410 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, | 1406 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, |
1411 | HostCmd_ACT_GEN_SET, 0, mac_address); | 1407 | HostCmd_ACT_GEN_SET, 0, mac_address, true); |
1412 | 1408 | ||
1413 | return ret; | 1409 | return ret; |
1414 | } | 1410 | } |
@@ -1436,19 +1432,31 @@ int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) | |||
1436 | GFP_KERNEL); | 1432 | GFP_KERNEL); |
1437 | break; | 1433 | break; |
1438 | case NL80211_IFTYPE_ADHOC: | 1434 | case NL80211_IFTYPE_ADHOC: |
1439 | return mwifiex_send_cmd_sync(priv, | 1435 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP, |
1440 | HostCmd_CMD_802_11_AD_HOC_STOP, | 1436 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
1441 | HostCmd_ACT_GEN_SET, 0, NULL); | ||
1442 | case NL80211_IFTYPE_AP: | 1437 | case NL80211_IFTYPE_AP: |
1443 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | 1438 | return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, |
1444 | HostCmd_ACT_GEN_SET, 0, NULL); | 1439 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
1445 | default: | 1440 | default: |
1446 | break; | 1441 | break; |
1447 | } | 1442 | } |
1448 | 1443 | ||
1449 | return ret; | 1444 | return ret; |
1450 | } | 1445 | } |
1451 | EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); | 1446 | |
1447 | /* This function deauthenticates/disconnects from all BSS. */ | ||
1448 | void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter) | ||
1449 | { | ||
1450 | struct mwifiex_private *priv; | ||
1451 | int i; | ||
1452 | |||
1453 | for (i = 0; i < adapter->priv_num; i++) { | ||
1454 | priv = adapter->priv[i]; | ||
1455 | if (priv) | ||
1456 | mwifiex_deauthenticate(priv, NULL); | ||
1457 | } | ||
1458 | } | ||
1459 | EXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all); | ||
1452 | 1460 | ||
1453 | /* | 1461 | /* |
1454 | * This function converts band to radio type used in channel TLV. | 1462 | * This function converts band to radio type used in channel TLV. |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 9d3d2758ec35..77db0886c6e2 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -38,7 +38,8 @@ static void scan_delay_timer_fn(unsigned long data) | |||
38 | if (adapter->surprise_removed) | 38 | if (adapter->surprise_removed) |
39 | return; | 39 | return; |
40 | 40 | ||
41 | if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) { | 41 | if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT || |
42 | !adapter->scan_processing) { | ||
42 | /* | 43 | /* |
43 | * Abort scan operation by cancelling all pending scan | 44 | * Abort scan operation by cancelling all pending scan |
44 | * commands | 45 | * commands |
@@ -194,7 +195,7 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) | |||
194 | if (adapter->if_ops.cleanup_if) | 195 | if (adapter->if_ops.cleanup_if) |
195 | adapter->if_ops.cleanup_if(adapter); | 196 | adapter->if_ops.cleanup_if(adapter); |
196 | 197 | ||
197 | del_timer(&adapter->cmd_timer); | 198 | del_timer_sync(&adapter->cmd_timer); |
198 | 199 | ||
199 | /* Free private structures */ | 200 | /* Free private structures */ |
200 | for (i = 0; i < adapter->priv_num; i++) { | 201 | for (i = 0; i < adapter->priv_num; i++) { |
@@ -678,8 +679,8 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr) | |||
678 | memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); | 679 | memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); |
679 | 680 | ||
680 | /* Send request to firmware */ | 681 | /* Send request to firmware */ |
681 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS, | 682 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS, |
682 | HostCmd_ACT_GEN_SET, 0, NULL); | 683 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
683 | 684 | ||
684 | if (!ret) | 685 | if (!ret) |
685 | memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); | 686 | memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); |
@@ -871,7 +872,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
871 | adapter->is_suspended = false; | 872 | adapter->is_suspended = false; |
872 | adapter->hs_activated = false; | 873 | adapter->hs_activated = false; |
873 | init_waitqueue_head(&adapter->hs_activate_wait_q); | 874 | init_waitqueue_head(&adapter->hs_activate_wait_q); |
874 | adapter->cmd_wait_q_required = false; | ||
875 | init_waitqueue_head(&adapter->cmd_wait_q.wait); | 875 | init_waitqueue_head(&adapter->cmd_wait_q.wait); |
876 | adapter->cmd_wait_q.status = 0; | 876 | adapter->cmd_wait_q.status = 0; |
877 | adapter->scan_wait_q_woken = false; | 877 | adapter->scan_wait_q_woken = false; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index d8ad554ce39f..d53e1e8c9467 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -59,7 +59,7 @@ enum { | |||
59 | 59 | ||
60 | #define MWIFIEX_UPLD_SIZE (2312) | 60 | #define MWIFIEX_UPLD_SIZE (2312) |
61 | 61 | ||
62 | #define MAX_EVENT_SIZE 1024 | 62 | #define MAX_EVENT_SIZE 2048 |
63 | 63 | ||
64 | #define ARP_FILTER_MAX_BUF_SIZE 68 | 64 | #define ARP_FILTER_MAX_BUF_SIZE 68 |
65 | 65 | ||
@@ -116,7 +116,7 @@ enum { | |||
116 | #define MWIFIEX_TYPE_DATA 0 | 116 | #define MWIFIEX_TYPE_DATA 0 |
117 | #define MWIFIEX_TYPE_EVENT 3 | 117 | #define MWIFIEX_TYPE_EVENT 3 |
118 | 118 | ||
119 | #define MAX_BITMAP_RATES_SIZE 10 | 119 | #define MAX_BITMAP_RATES_SIZE 18 |
120 | 120 | ||
121 | #define MAX_CHANNEL_BAND_BG 14 | 121 | #define MAX_CHANNEL_BAND_BG 14 |
122 | #define MAX_CHANNEL_BAND_A 165 | 122 | #define MAX_CHANNEL_BAND_A 165 |
@@ -145,7 +145,6 @@ struct mwifiex_dbg { | |||
145 | u32 num_cmd_assoc_success; | 145 | u32 num_cmd_assoc_success; |
146 | u32 num_cmd_assoc_failure; | 146 | u32 num_cmd_assoc_failure; |
147 | u32 num_tx_timeout; | 147 | u32 num_tx_timeout; |
148 | u32 num_cmd_timeout; | ||
149 | u16 timeout_cmd_id; | 148 | u16 timeout_cmd_id; |
150 | u16 timeout_cmd_act; | 149 | u16 timeout_cmd_act; |
151 | u16 last_cmd_id[DBG_CMD_NUM]; | 150 | u16 last_cmd_id[DBG_CMD_NUM]; |
@@ -193,6 +192,8 @@ struct mwifiex_add_ba_param { | |||
193 | u32 tx_win_size; | 192 | u32 tx_win_size; |
194 | u32 rx_win_size; | 193 | u32 rx_win_size; |
195 | u32 timeout; | 194 | u32 timeout; |
195 | u8 tx_amsdu; | ||
196 | u8 rx_amsdu; | ||
196 | }; | 197 | }; |
197 | 198 | ||
198 | struct mwifiex_tx_aggr { | 199 | struct mwifiex_tx_aggr { |
@@ -210,6 +211,7 @@ struct mwifiex_ra_list_tbl { | |||
210 | u16 ba_pkt_count; | 211 | u16 ba_pkt_count; |
211 | u8 ba_packet_thr; | 212 | u8 ba_packet_thr; |
212 | u16 total_pkt_count; | 213 | u16 total_pkt_count; |
214 | bool tdls_link; | ||
213 | }; | 215 | }; |
214 | 216 | ||
215 | struct mwifiex_tid_tbl { | 217 | struct mwifiex_tid_tbl { |
@@ -262,6 +264,31 @@ struct ieee_types_generic { | |||
262 | u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)]; | 264 | u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)]; |
263 | } __packed; | 265 | } __packed; |
264 | 266 | ||
267 | struct ieee_types_bss_co_2040 { | ||
268 | struct ieee_types_header ieee_hdr; | ||
269 | u8 bss_2040co; | ||
270 | } __packed; | ||
271 | |||
272 | struct ieee_types_extcap { | ||
273 | struct ieee_types_header ieee_hdr; | ||
274 | u8 ext_capab[8]; | ||
275 | } __packed; | ||
276 | |||
277 | struct ieee_types_vht_cap { | ||
278 | struct ieee_types_header ieee_hdr; | ||
279 | struct ieee80211_vht_cap vhtcap; | ||
280 | } __packed; | ||
281 | |||
282 | struct ieee_types_vht_oper { | ||
283 | struct ieee_types_header ieee_hdr; | ||
284 | struct ieee80211_vht_operation vhtoper; | ||
285 | } __packed; | ||
286 | |||
287 | struct ieee_types_aid { | ||
288 | struct ieee_types_header ieee_hdr; | ||
289 | u16 aid; | ||
290 | } __packed; | ||
291 | |||
265 | struct mwifiex_bssdescriptor { | 292 | struct mwifiex_bssdescriptor { |
266 | u8 mac_address[ETH_ALEN]; | 293 | u8 mac_address[ETH_ALEN]; |
267 | struct cfg80211_ssid ssid; | 294 | struct cfg80211_ssid ssid; |
@@ -443,6 +470,7 @@ struct mwifiex_private { | |||
443 | u8 wpa_ie_len; | 470 | u8 wpa_ie_len; |
444 | u8 wpa_is_gtk_set; | 471 | u8 wpa_is_gtk_set; |
445 | struct host_cmd_ds_802_11_key_material aes_key; | 472 | struct host_cmd_ds_802_11_key_material aes_key; |
473 | struct host_cmd_ds_802_11_key_material_v2 aes_key_v2; | ||
446 | u8 wapi_ie[256]; | 474 | u8 wapi_ie[256]; |
447 | u8 wapi_ie_len; | 475 | u8 wapi_ie_len; |
448 | u8 *wps_ie; | 476 | u8 *wps_ie; |
@@ -461,6 +489,7 @@ struct mwifiex_private { | |||
461 | struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID]; | 489 | struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID]; |
462 | struct mwifiex_add_ba_param add_ba_param; | 490 | struct mwifiex_add_ba_param add_ba_param; |
463 | u16 rx_seq[MAX_NUM_TID]; | 491 | u16 rx_seq[MAX_NUM_TID]; |
492 | u8 tos_to_tid_inv[MAX_NUM_TID]; | ||
464 | struct list_head rx_reorder_tbl_ptr; | 493 | struct list_head rx_reorder_tbl_ptr; |
465 | /* spin lock for rx_reorder_tbl_ptr queue */ | 494 | /* spin lock for rx_reorder_tbl_ptr queue */ |
466 | spinlock_t rx_reorder_tbl_lock; | 495 | spinlock_t rx_reorder_tbl_lock; |
@@ -518,6 +547,8 @@ struct mwifiex_private { | |||
518 | unsigned long csa_expire_time; | 547 | unsigned long csa_expire_time; |
519 | u8 del_list_idx; | 548 | u8 del_list_idx; |
520 | bool hs2_enabled; | 549 | bool hs2_enabled; |
550 | struct station_parameters *sta_params; | ||
551 | struct sk_buff_head tdls_txq; | ||
521 | }; | 552 | }; |
522 | 553 | ||
523 | enum mwifiex_ba_status { | 554 | enum mwifiex_ba_status { |
@@ -531,6 +562,7 @@ struct mwifiex_tx_ba_stream_tbl { | |||
531 | int tid; | 562 | int tid; |
532 | u8 ra[ETH_ALEN]; | 563 | u8 ra[ETH_ALEN]; |
533 | enum mwifiex_ba_status ba_status; | 564 | enum mwifiex_ba_status ba_status; |
565 | u8 amsdu; | ||
534 | }; | 566 | }; |
535 | 567 | ||
536 | struct mwifiex_rx_reorder_tbl; | 568 | struct mwifiex_rx_reorder_tbl; |
@@ -545,10 +577,12 @@ struct mwifiex_rx_reorder_tbl { | |||
545 | struct list_head list; | 577 | struct list_head list; |
546 | int tid; | 578 | int tid; |
547 | u8 ta[ETH_ALEN]; | 579 | u8 ta[ETH_ALEN]; |
580 | int init_win; | ||
548 | int start_win; | 581 | int start_win; |
549 | int win_size; | 582 | int win_size; |
550 | void **rx_reorder_ptr; | 583 | void **rx_reorder_ptr; |
551 | struct reorder_tmr_cnxt timer_context; | 584 | struct reorder_tmr_cnxt timer_context; |
585 | u8 amsdu; | ||
552 | u8 flags; | 586 | u8 flags; |
553 | }; | 587 | }; |
554 | 588 | ||
@@ -583,17 +617,35 @@ struct mwifiex_bss_priv { | |||
583 | u64 fw_tsf; | 617 | u64 fw_tsf; |
584 | }; | 618 | }; |
585 | 619 | ||
586 | /* This is AP specific structure which stores information | 620 | struct mwifiex_tdls_capab { |
587 | * about associated STA | 621 | __le16 capab; |
622 | u8 rates[32]; | ||
623 | u8 rates_len; | ||
624 | u8 qos_info; | ||
625 | u8 coex_2040; | ||
626 | u16 aid; | ||
627 | struct ieee80211_ht_cap ht_capb; | ||
628 | struct ieee80211_ht_operation ht_oper; | ||
629 | struct ieee_types_extcap extcap; | ||
630 | struct ieee_types_generic rsn_ie; | ||
631 | struct ieee80211_vht_cap vhtcap; | ||
632 | struct ieee80211_vht_operation vhtoper; | ||
633 | }; | ||
634 | |||
635 | /* This is AP/TDLS specific structure which stores information | ||
636 | * about associated/peer STA | ||
588 | */ | 637 | */ |
589 | struct mwifiex_sta_node { | 638 | struct mwifiex_sta_node { |
590 | struct list_head list; | 639 | struct list_head list; |
591 | u8 mac_addr[ETH_ALEN]; | 640 | u8 mac_addr[ETH_ALEN]; |
592 | u8 is_wmm_enabled; | 641 | u8 is_wmm_enabled; |
593 | u8 is_11n_enabled; | 642 | u8 is_11n_enabled; |
643 | u8 is_11ac_enabled; | ||
594 | u8 ampdu_sta[MAX_NUM_TID]; | 644 | u8 ampdu_sta[MAX_NUM_TID]; |
595 | u16 rx_seq[MAX_NUM_TID]; | 645 | u16 rx_seq[MAX_NUM_TID]; |
596 | u16 max_amsdu; | 646 | u16 max_amsdu; |
647 | u8 tdls_status; | ||
648 | struct mwifiex_tdls_capab tdls_cap; | ||
597 | }; | 649 | }; |
598 | 650 | ||
599 | struct mwifiex_if_ops { | 651 | struct mwifiex_if_ops { |
@@ -671,7 +723,7 @@ struct mwifiex_adapter { | |||
671 | struct cmd_ctrl_node *curr_cmd; | 723 | struct cmd_ctrl_node *curr_cmd; |
672 | /* spin lock for command */ | 724 | /* spin lock for command */ |
673 | spinlock_t mwifiex_cmd_lock; | 725 | spinlock_t mwifiex_cmd_lock; |
674 | u32 num_cmd_timeout; | 726 | u8 is_cmd_timedout; |
675 | u16 last_init_cmd; | 727 | u16 last_init_cmd; |
676 | struct timer_list cmd_timer; | 728 | struct timer_list cmd_timer; |
677 | struct list_head cmd_free_q; | 729 | struct list_head cmd_free_q; |
@@ -722,15 +774,16 @@ struct mwifiex_adapter { | |||
722 | u16 hs_activate_wait_q_woken; | 774 | u16 hs_activate_wait_q_woken; |
723 | wait_queue_head_t hs_activate_wait_q; | 775 | wait_queue_head_t hs_activate_wait_q; |
724 | bool is_suspended; | 776 | bool is_suspended; |
777 | bool hs_enabling; | ||
725 | u8 event_body[MAX_EVENT_SIZE]; | 778 | u8 event_body[MAX_EVENT_SIZE]; |
726 | u32 hw_dot_11n_dev_cap; | 779 | u32 hw_dot_11n_dev_cap; |
727 | u8 hw_dev_mcs_support; | 780 | u8 hw_dev_mcs_support; |
781 | u8 user_dev_mcs_support; | ||
728 | u8 adhoc_11n_enabled; | 782 | u8 adhoc_11n_enabled; |
729 | u8 sec_chan_offset; | 783 | u8 sec_chan_offset; |
730 | struct mwifiex_dbg dbg; | 784 | struct mwifiex_dbg dbg; |
731 | u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; | 785 | u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; |
732 | u32 arp_filter_size; | 786 | u32 arp_filter_size; |
733 | u16 cmd_wait_q_required; | ||
734 | struct mwifiex_wait_queue cmd_wait_q; | 787 | struct mwifiex_wait_queue cmd_wait_q; |
735 | u8 scan_wait_q_woken; | 788 | u8 scan_wait_q_woken; |
736 | spinlock_t queue_lock; /* lock for tx queues */ | 789 | spinlock_t queue_lock; /* lock for tx queues */ |
@@ -753,6 +806,9 @@ struct mwifiex_adapter { | |||
753 | atomic_t is_tx_received; | 806 | atomic_t is_tx_received; |
754 | atomic_t pending_bridged_pkts; | 807 | atomic_t pending_bridged_pkts; |
755 | struct semaphore *card_sem; | 808 | struct semaphore *card_sem; |
809 | bool ext_scan; | ||
810 | u8 fw_api_ver; | ||
811 | u8 fw_key_api_major_ver, fw_key_api_minor_ver; | ||
756 | }; | 812 | }; |
757 | 813 | ||
758 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 814 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
@@ -788,11 +844,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter); | |||
788 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, | 844 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, |
789 | struct cmd_ctrl_node *cmd_node); | 845 | struct cmd_ctrl_node *cmd_node); |
790 | 846 | ||
791 | int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | 847 | int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, |
792 | u16 cmd_action, u32 cmd_oid, void *data_buf); | 848 | u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync); |
793 | |||
794 | int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, | ||
795 | u16 cmd_action, u32 cmd_oid, void *data_buf); | ||
796 | 849 | ||
797 | void mwifiex_cmd_timeout_func(unsigned long function_context); | 850 | void mwifiex_cmd_timeout_func(unsigned long function_context); |
798 | 851 | ||
@@ -880,6 +933,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, | |||
880 | void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason); | 933 | void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason); |
881 | u8 mwifiex_band_to_radio_type(u8 band); | 934 | u8 mwifiex_band_to_radio_type(u8 band); |
882 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); | 935 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); |
936 | void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter); | ||
883 | int mwifiex_adhoc_start(struct mwifiex_private *priv, | 937 | int mwifiex_adhoc_start(struct mwifiex_private *priv, |
884 | struct cfg80211_ssid *adhoc_ssid); | 938 | struct cfg80211_ssid *adhoc_ssid); |
885 | int mwifiex_adhoc_join(struct mwifiex_private *priv, | 939 | int mwifiex_adhoc_join(struct mwifiex_private *priv, |
@@ -938,6 +992,12 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv, | |||
938 | struct cfg80211_ap_settings *params); | 992 | struct cfg80211_ap_settings *params); |
939 | void mwifiex_set_ba_params(struct mwifiex_private *priv); | 993 | void mwifiex_set_ba_params(struct mwifiex_private *priv); |
940 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); | 994 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); |
995 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | ||
996 | struct host_cmd_ds_command *cmd, | ||
997 | void *data_buf); | ||
998 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv); | ||
999 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, | ||
1000 | void *buf); | ||
941 | 1001 | ||
942 | /* | 1002 | /* |
943 | * This function checks if the queuing is RA based or not. | 1003 | * This function checks if the queuing is RA based or not. |
@@ -1078,7 +1138,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, | |||
1078 | const u8 *key, int key_len, u8 key_index, | 1138 | const u8 *key, int key_len, u8 key_index, |
1079 | const u8 *mac_addr, int disable); | 1139 | const u8 *mac_addr, int disable); |
1080 | 1140 | ||
1081 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); | 1141 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len); |
1082 | 1142 | ||
1083 | int mwifiex_get_ver_ext(struct mwifiex_private *priv); | 1143 | int mwifiex_get_ver_ext(struct mwifiex_private *priv); |
1084 | 1144 | ||
@@ -1159,6 +1219,32 @@ void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv); | |||
1159 | 1219 | ||
1160 | extern const struct ethtool_ops mwifiex_ethtool_ops; | 1220 | extern const struct ethtool_ops mwifiex_ethtool_ops; |
1161 | 1221 | ||
1222 | void mwifiex_del_all_sta_list(struct mwifiex_private *priv); | ||
1223 | void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac); | ||
1224 | void | ||
1225 | mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, | ||
1226 | int ies_len, struct mwifiex_sta_node *node); | ||
1227 | struct mwifiex_sta_node * | ||
1228 | mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac); | ||
1229 | struct mwifiex_sta_node * | ||
1230 | mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); | ||
1231 | int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer, | ||
1232 | u8 action_code, u8 dialog_token, | ||
1233 | u16 status_code, const u8 *extra_ies, | ||
1234 | size_t extra_ies_len); | ||
1235 | int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, | ||
1236 | u8 *peer, u8 action_code, u8 dialog_token, | ||
1237 | u16 status_code, const u8 *extra_ies, | ||
1238 | size_t extra_ies_len); | ||
1239 | void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | ||
1240 | u8 *buf, int len); | ||
1241 | int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action); | ||
1242 | int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac); | ||
1243 | void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv); | ||
1244 | bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv); | ||
1245 | u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, | ||
1246 | u32 pri_chan, u8 chan_bw); | ||
1247 | |||
1162 | #ifdef CONFIG_DEBUG_FS | 1248 | #ifdef CONFIG_DEBUG_FS |
1163 | void mwifiex_debugfs_init(void); | 1249 | void mwifiex_debugfs_init(void); |
1164 | void mwifiex_debugfs_remove(void); | 1250 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 7fe7b53fb17a..a7e8b96b2d90 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -39,20 +39,31 @@ static struct semaphore add_remove_card_sem; | |||
39 | 39 | ||
40 | static int | 40 | static int |
41 | mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, | 41 | mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, |
42 | int size, int flags) | 42 | size_t size, int flags) |
43 | { | 43 | { |
44 | struct pcie_service_card *card = adapter->card; | 44 | struct pcie_service_card *card = adapter->card; |
45 | dma_addr_t buf_pa; | 45 | struct mwifiex_dma_mapping mapping; |
46 | 46 | ||
47 | buf_pa = pci_map_single(card->dev, skb->data, size, flags); | 47 | mapping.addr = pci_map_single(card->dev, skb->data, size, flags); |
48 | if (pci_dma_mapping_error(card->dev, buf_pa)) { | 48 | if (pci_dma_mapping_error(card->dev, mapping.addr)) { |
49 | dev_err(adapter->dev, "failed to map pci memory!\n"); | 49 | dev_err(adapter->dev, "failed to map pci memory!\n"); |
50 | return -1; | 50 | return -1; |
51 | } | 51 | } |
52 | memcpy(skb->cb, &buf_pa, sizeof(dma_addr_t)); | 52 | mapping.len = size; |
53 | memcpy(skb->cb, &mapping, sizeof(mapping)); | ||
53 | return 0; | 54 | return 0; |
54 | } | 55 | } |
55 | 56 | ||
57 | static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter, | ||
58 | struct sk_buff *skb, int flags) | ||
59 | { | ||
60 | struct pcie_service_card *card = adapter->card; | ||
61 | struct mwifiex_dma_mapping mapping; | ||
62 | |||
63 | MWIFIEX_SKB_PACB(skb, &mapping); | ||
64 | pci_unmap_single(card->dev, mapping.addr, mapping.len, flags); | ||
65 | } | ||
66 | |||
56 | /* | 67 | /* |
57 | * This function reads sleep cookie and checks if FW is ready | 68 | * This function reads sleep cookie and checks if FW is ready |
58 | */ | 69 | */ |
@@ -109,6 +120,7 @@ static int mwifiex_pcie_suspend(struct device *dev) | |||
109 | 120 | ||
110 | /* Indicate device suspended */ | 121 | /* Indicate device suspended */ |
111 | adapter->is_suspended = true; | 122 | adapter->is_suspended = true; |
123 | adapter->hs_enabling = false; | ||
112 | 124 | ||
113 | return 0; | 125 | return 0; |
114 | } | 126 | } |
@@ -179,6 +191,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, | |||
179 | card->pcie.firmware = data->firmware; | 191 | card->pcie.firmware = data->firmware; |
180 | card->pcie.reg = data->reg; | 192 | card->pcie.reg = data->reg; |
181 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; | 193 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; |
194 | card->pcie.tx_buf_size = data->tx_buf_size; | ||
182 | } | 195 | } |
183 | 196 | ||
184 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, | 197 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, |
@@ -199,7 +212,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
199 | struct pcie_service_card *card; | 212 | struct pcie_service_card *card; |
200 | struct mwifiex_adapter *adapter; | 213 | struct mwifiex_adapter *adapter; |
201 | struct mwifiex_private *priv; | 214 | struct mwifiex_private *priv; |
202 | int i; | ||
203 | 215 | ||
204 | card = pci_get_drvdata(pdev); | 216 | card = pci_get_drvdata(pdev); |
205 | if (!card) | 217 | if (!card) |
@@ -218,11 +230,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
218 | mwifiex_pcie_resume(&pdev->dev); | 230 | mwifiex_pcie_resume(&pdev->dev); |
219 | #endif | 231 | #endif |
220 | 232 | ||
221 | for (i = 0; i < adapter->priv_num; i++) | 233 | mwifiex_deauthenticate_all(adapter); |
222 | if ((GET_BSS_ROLE(adapter->priv[i]) == | ||
223 | MWIFIEX_BSS_ROLE_STA) && | ||
224 | adapter->priv[i]->media_connected) | ||
225 | mwifiex_deauthenticate(adapter->priv[i], NULL); | ||
226 | 234 | ||
227 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 235 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
228 | 236 | ||
@@ -320,6 +328,30 @@ static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) | |||
320 | return; | 328 | return; |
321 | } | 329 | } |
322 | 330 | ||
331 | static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, | ||
332 | u32 max_delay_loop_cnt) | ||
333 | { | ||
334 | struct pcie_service_card *card = adapter->card; | ||
335 | u8 *buffer; | ||
336 | u32 sleep_cookie, count; | ||
337 | |||
338 | for (count = 0; count < max_delay_loop_cnt; count++) { | ||
339 | buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN; | ||
340 | sleep_cookie = *(u32 *)buffer; | ||
341 | |||
342 | if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) { | ||
343 | dev_dbg(adapter->dev, | ||
344 | "sleep cookie found at count %d\n", count); | ||
345 | break; | ||
346 | } | ||
347 | usleep_range(20, 30); | ||
348 | } | ||
349 | |||
350 | if (count >= max_delay_loop_cnt) | ||
351 | dev_dbg(adapter->dev, | ||
352 | "max count reached while accessing sleep cookie\n"); | ||
353 | } | ||
354 | |||
323 | /* This function wakes up the card by reading fw_status register. */ | 355 | /* This function wakes up the card by reading fw_status register. */ |
324 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | 356 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) |
325 | { | 357 | { |
@@ -456,7 +488,7 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) | |||
456 | PCI_DMA_FROMDEVICE)) | 488 | PCI_DMA_FROMDEVICE)) |
457 | return -1; | 489 | return -1; |
458 | 490 | ||
459 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 491 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
460 | 492 | ||
461 | dev_dbg(adapter->dev, | 493 | dev_dbg(adapter->dev, |
462 | "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", | 494 | "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", |
@@ -513,7 +545,7 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) | |||
513 | PCI_DMA_FROMDEVICE)) | 545 | PCI_DMA_FROMDEVICE)) |
514 | return -1; | 546 | return -1; |
515 | 547 | ||
516 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 548 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
517 | 549 | ||
518 | dev_dbg(adapter->dev, | 550 | dev_dbg(adapter->dev, |
519 | "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", | 551 | "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", |
@@ -549,8 +581,8 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter) | |||
549 | desc2 = card->txbd_ring[i]; | 581 | desc2 = card->txbd_ring[i]; |
550 | if (card->tx_buf_list[i]) { | 582 | if (card->tx_buf_list[i]) { |
551 | skb = card->tx_buf_list[i]; | 583 | skb = card->tx_buf_list[i]; |
552 | pci_unmap_single(card->dev, desc2->paddr, | 584 | mwifiex_unmap_pci_memory(adapter, skb, |
553 | skb->len, PCI_DMA_TODEVICE); | 585 | PCI_DMA_TODEVICE); |
554 | dev_kfree_skb_any(skb); | 586 | dev_kfree_skb_any(skb); |
555 | } | 587 | } |
556 | memset(desc2, 0, sizeof(*desc2)); | 588 | memset(desc2, 0, sizeof(*desc2)); |
@@ -558,8 +590,8 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter) | |||
558 | desc = card->txbd_ring[i]; | 590 | desc = card->txbd_ring[i]; |
559 | if (card->tx_buf_list[i]) { | 591 | if (card->tx_buf_list[i]) { |
560 | skb = card->tx_buf_list[i]; | 592 | skb = card->tx_buf_list[i]; |
561 | pci_unmap_single(card->dev, desc->paddr, | 593 | mwifiex_unmap_pci_memory(adapter, skb, |
562 | skb->len, PCI_DMA_TODEVICE); | 594 | PCI_DMA_TODEVICE); |
563 | dev_kfree_skb_any(skb); | 595 | dev_kfree_skb_any(skb); |
564 | } | 596 | } |
565 | memset(desc, 0, sizeof(*desc)); | 597 | memset(desc, 0, sizeof(*desc)); |
@@ -587,8 +619,8 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter) | |||
587 | desc2 = card->rxbd_ring[i]; | 619 | desc2 = card->rxbd_ring[i]; |
588 | if (card->rx_buf_list[i]) { | 620 | if (card->rx_buf_list[i]) { |
589 | skb = card->rx_buf_list[i]; | 621 | skb = card->rx_buf_list[i]; |
590 | pci_unmap_single(card->dev, desc2->paddr, | 622 | mwifiex_unmap_pci_memory(adapter, skb, |
591 | skb->len, PCI_DMA_FROMDEVICE); | 623 | PCI_DMA_FROMDEVICE); |
592 | dev_kfree_skb_any(skb); | 624 | dev_kfree_skb_any(skb); |
593 | } | 625 | } |
594 | memset(desc2, 0, sizeof(*desc2)); | 626 | memset(desc2, 0, sizeof(*desc2)); |
@@ -596,8 +628,8 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter) | |||
596 | desc = card->rxbd_ring[i]; | 628 | desc = card->rxbd_ring[i]; |
597 | if (card->rx_buf_list[i]) { | 629 | if (card->rx_buf_list[i]) { |
598 | skb = card->rx_buf_list[i]; | 630 | skb = card->rx_buf_list[i]; |
599 | pci_unmap_single(card->dev, desc->paddr, | 631 | mwifiex_unmap_pci_memory(adapter, skb, |
600 | skb->len, PCI_DMA_FROMDEVICE); | 632 | PCI_DMA_FROMDEVICE); |
601 | dev_kfree_skb_any(skb); | 633 | dev_kfree_skb_any(skb); |
602 | } | 634 | } |
603 | memset(desc, 0, sizeof(*desc)); | 635 | memset(desc, 0, sizeof(*desc)); |
@@ -622,8 +654,8 @@ static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter) | |||
622 | desc = card->evtbd_ring[i]; | 654 | desc = card->evtbd_ring[i]; |
623 | if (card->evt_buf_list[i]) { | 655 | if (card->evt_buf_list[i]) { |
624 | skb = card->evt_buf_list[i]; | 656 | skb = card->evt_buf_list[i]; |
625 | pci_unmap_single(card->dev, desc->paddr, MAX_EVENT_SIZE, | 657 | mwifiex_unmap_pci_memory(adapter, skb, |
626 | PCI_DMA_FROMDEVICE); | 658 | PCI_DMA_FROMDEVICE); |
627 | dev_kfree_skb_any(skb); | 659 | dev_kfree_skb_any(skb); |
628 | } | 660 | } |
629 | card->evt_buf_list[i] = NULL; | 661 | card->evt_buf_list[i] = NULL; |
@@ -861,7 +893,6 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter) | |||
861 | static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) | 893 | static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) |
862 | { | 894 | { |
863 | struct pcie_service_card *card; | 895 | struct pcie_service_card *card; |
864 | dma_addr_t buf_pa; | ||
865 | 896 | ||
866 | if (!adapter) | 897 | if (!adapter) |
867 | return 0; | 898 | return 0; |
@@ -869,16 +900,14 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) | |||
869 | card = adapter->card; | 900 | card = adapter->card; |
870 | 901 | ||
871 | if (card && card->cmdrsp_buf) { | 902 | if (card && card->cmdrsp_buf) { |
872 | MWIFIEX_SKB_PACB(card->cmdrsp_buf, &buf_pa); | 903 | mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf, |
873 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 904 | PCI_DMA_FROMDEVICE); |
874 | PCI_DMA_FROMDEVICE); | ||
875 | dev_kfree_skb_any(card->cmdrsp_buf); | 905 | dev_kfree_skb_any(card->cmdrsp_buf); |
876 | } | 906 | } |
877 | 907 | ||
878 | if (card && card->cmd_buf) { | 908 | if (card && card->cmd_buf) { |
879 | MWIFIEX_SKB_PACB(card->cmd_buf, &buf_pa); | 909 | mwifiex_unmap_pci_memory(adapter, card->cmd_buf, |
880 | pci_unmap_single(card->dev, buf_pa, card->cmd_buf->len, | 910 | PCI_DMA_TODEVICE); |
881 | PCI_DMA_TODEVICE); | ||
882 | } | 911 | } |
883 | return 0; | 912 | return 0; |
884 | } | 913 | } |
@@ -956,7 +985,6 @@ static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter) | |||
956 | static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) | 985 | static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) |
957 | { | 986 | { |
958 | struct sk_buff *skb; | 987 | struct sk_buff *skb; |
959 | dma_addr_t buf_pa; | ||
960 | u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0; | 988 | u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0; |
961 | struct mwifiex_pcie_buf_desc *desc; | 989 | struct mwifiex_pcie_buf_desc *desc; |
962 | struct mwifiex_pfu_buf_desc *desc2; | 990 | struct mwifiex_pfu_buf_desc *desc2; |
@@ -986,13 +1014,13 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) | |||
986 | reg->tx_start_ptr; | 1014 | reg->tx_start_ptr; |
987 | 1015 | ||
988 | skb = card->tx_buf_list[wrdoneidx]; | 1016 | skb = card->tx_buf_list[wrdoneidx]; |
1017 | |||
989 | if (skb) { | 1018 | if (skb) { |
990 | dev_dbg(adapter->dev, | 1019 | dev_dbg(adapter->dev, |
991 | "SEND COMP: Detach skb %p at txbd_rdidx=%d\n", | 1020 | "SEND COMP: Detach skb %p at txbd_rdidx=%d\n", |
992 | skb, wrdoneidx); | 1021 | skb, wrdoneidx); |
993 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1022 | mwifiex_unmap_pci_memory(adapter, skb, |
994 | pci_unmap_single(card->dev, buf_pa, skb->len, | 1023 | PCI_DMA_TODEVICE); |
995 | PCI_DMA_TODEVICE); | ||
996 | 1024 | ||
997 | unmap_count++; | 1025 | unmap_count++; |
998 | 1026 | ||
@@ -1006,7 +1034,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) | |||
1006 | card->tx_buf_list[wrdoneidx] = NULL; | 1034 | card->tx_buf_list[wrdoneidx] = NULL; |
1007 | 1035 | ||
1008 | if (reg->pfu_enabled) { | 1036 | if (reg->pfu_enabled) { |
1009 | desc2 = (void *)card->txbd_ring[wrdoneidx]; | 1037 | desc2 = card->txbd_ring[wrdoneidx]; |
1010 | memset(desc2, 0, sizeof(*desc2)); | 1038 | memset(desc2, 0, sizeof(*desc2)); |
1011 | } else { | 1039 | } else { |
1012 | desc = card->txbd_ring[wrdoneidx]; | 1040 | desc = card->txbd_ring[wrdoneidx]; |
@@ -1082,16 +1110,16 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | |||
1082 | tmp = (__le16 *)&payload[2]; | 1110 | tmp = (__le16 *)&payload[2]; |
1083 | *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); | 1111 | *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); |
1084 | 1112 | ||
1085 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , | 1113 | if (mwifiex_map_pci_memory(adapter, skb, skb->len, |
1086 | PCI_DMA_TODEVICE)) | 1114 | PCI_DMA_TODEVICE)) |
1087 | return -1; | 1115 | return -1; |
1088 | 1116 | ||
1089 | wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr; | 1117 | wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr; |
1090 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1118 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
1091 | card->tx_buf_list[wrindx] = skb; | 1119 | card->tx_buf_list[wrindx] = skb; |
1092 | 1120 | ||
1093 | if (reg->pfu_enabled) { | 1121 | if (reg->pfu_enabled) { |
1094 | desc2 = (void *)card->txbd_ring[wrindx]; | 1122 | desc2 = card->txbd_ring[wrindx]; |
1095 | desc2->paddr = buf_pa; | 1123 | desc2->paddr = buf_pa; |
1096 | desc2->len = (u16)skb->len; | 1124 | desc2->len = (u16)skb->len; |
1097 | desc2->frag_len = (u16)skb->len; | 1125 | desc2->frag_len = (u16)skb->len; |
@@ -1162,8 +1190,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | |||
1162 | 1190 | ||
1163 | return -EINPROGRESS; | 1191 | return -EINPROGRESS; |
1164 | done_unmap: | 1192 | done_unmap: |
1165 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1193 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1166 | pci_unmap_single(card->dev, buf_pa, skb->len, PCI_DMA_TODEVICE); | ||
1167 | card->tx_buf_list[wrindx] = NULL; | 1194 | card->tx_buf_list[wrindx] = NULL; |
1168 | if (reg->pfu_enabled) | 1195 | if (reg->pfu_enabled) |
1169 | memset(desc2, 0, sizeof(*desc2)); | 1196 | memset(desc2, 0, sizeof(*desc2)); |
@@ -1217,9 +1244,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
1217 | if (!skb_data) | 1244 | if (!skb_data) |
1218 | return -ENOMEM; | 1245 | return -ENOMEM; |
1219 | 1246 | ||
1220 | MWIFIEX_SKB_PACB(skb_data, &buf_pa); | 1247 | mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE); |
1221 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_RX_DATA_BUF_SIZE, | ||
1222 | PCI_DMA_FROMDEVICE); | ||
1223 | card->rx_buf_list[rd_index] = NULL; | 1248 | card->rx_buf_list[rd_index] = NULL; |
1224 | 1249 | ||
1225 | /* Get data length from interface header - | 1250 | /* Get data length from interface header - |
@@ -1246,7 +1271,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
1246 | PCI_DMA_FROMDEVICE)) | 1271 | PCI_DMA_FROMDEVICE)) |
1247 | return -1; | 1272 | return -1; |
1248 | 1273 | ||
1249 | MWIFIEX_SKB_PACB(skb_tmp, &buf_pa); | 1274 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp); |
1250 | 1275 | ||
1251 | dev_dbg(adapter->dev, | 1276 | dev_dbg(adapter->dev, |
1252 | "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n", | 1277 | "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n", |
@@ -1254,7 +1279,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
1254 | card->rx_buf_list[rd_index] = skb_tmp; | 1279 | card->rx_buf_list[rd_index] = skb_tmp; |
1255 | 1280 | ||
1256 | if (reg->pfu_enabled) { | 1281 | if (reg->pfu_enabled) { |
1257 | desc2 = (void *)card->rxbd_ring[rd_index]; | 1282 | desc2 = card->rxbd_ring[rd_index]; |
1258 | desc2->paddr = buf_pa; | 1283 | desc2->paddr = buf_pa; |
1259 | desc2->len = skb_tmp->len; | 1284 | desc2->len = skb_tmp->len; |
1260 | desc2->frag_len = skb_tmp->len; | 1285 | desc2->frag_len = skb_tmp->len; |
@@ -1322,7 +1347,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1322 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE)) | 1347 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE)) |
1323 | return -1; | 1348 | return -1; |
1324 | 1349 | ||
1325 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1350 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
1326 | 1351 | ||
1327 | /* Write the lower 32bits of the physical address to low command | 1352 | /* Write the lower 32bits of the physical address to low command |
1328 | * address scratch register | 1353 | * address scratch register |
@@ -1331,8 +1356,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1331 | dev_err(adapter->dev, | 1356 | dev_err(adapter->dev, |
1332 | "%s: failed to write download command to boot code.\n", | 1357 | "%s: failed to write download command to boot code.\n", |
1333 | __func__); | 1358 | __func__); |
1334 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1359 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1335 | PCI_DMA_TODEVICE); | ||
1336 | return -1; | 1360 | return -1; |
1337 | } | 1361 | } |
1338 | 1362 | ||
@@ -1344,8 +1368,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1344 | dev_err(adapter->dev, | 1368 | dev_err(adapter->dev, |
1345 | "%s: failed to write download command to boot code.\n", | 1369 | "%s: failed to write download command to boot code.\n", |
1346 | __func__); | 1370 | __func__); |
1347 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1371 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1348 | PCI_DMA_TODEVICE); | ||
1349 | return -1; | 1372 | return -1; |
1350 | } | 1373 | } |
1351 | 1374 | ||
@@ -1354,8 +1377,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1354 | dev_err(adapter->dev, | 1377 | dev_err(adapter->dev, |
1355 | "%s: failed to write command len to cmd_size scratch reg\n", | 1378 | "%s: failed to write command len to cmd_size scratch reg\n", |
1356 | __func__); | 1379 | __func__); |
1357 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1380 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1358 | PCI_DMA_TODEVICE); | ||
1359 | return -1; | 1381 | return -1; |
1360 | } | 1382 | } |
1361 | 1383 | ||
@@ -1364,8 +1386,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1364 | CPU_INTR_DOOR_BELL)) { | 1386 | CPU_INTR_DOOR_BELL)) { |
1365 | dev_err(adapter->dev, | 1387 | dev_err(adapter->dev, |
1366 | "%s: failed to assert door-bell intr\n", __func__); | 1388 | "%s: failed to assert door-bell intr\n", __func__); |
1367 | pci_unmap_single(card->dev, buf_pa, | 1389 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1368 | MWIFIEX_UPLD_SIZE, PCI_DMA_TODEVICE); | ||
1369 | return -1; | 1390 | return -1; |
1370 | } | 1391 | } |
1371 | 1392 | ||
@@ -1439,7 +1460,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1439 | */ | 1460 | */ |
1440 | 1461 | ||
1441 | if (card->cmdrsp_buf) { | 1462 | if (card->cmdrsp_buf) { |
1442 | MWIFIEX_SKB_PACB(card->cmdrsp_buf, &cmdrsp_buf_pa); | 1463 | cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf); |
1443 | /* Write the lower 32bits of the cmdrsp buffer physical | 1464 | /* Write the lower 32bits of the cmdrsp buffer physical |
1444 | address */ | 1465 | address */ |
1445 | if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, | 1466 | if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, |
@@ -1460,7 +1481,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1460 | } | 1481 | } |
1461 | } | 1482 | } |
1462 | 1483 | ||
1463 | MWIFIEX_SKB_PACB(card->cmd_buf, &cmd_buf_pa); | 1484 | cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf); |
1464 | /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */ | 1485 | /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */ |
1465 | if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, | 1486 | if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, |
1466 | (u32)cmd_buf_pa)) { | 1487 | (u32)cmd_buf_pa)) { |
@@ -1514,13 +1535,17 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1514 | int count = 0; | 1535 | int count = 0; |
1515 | u16 rx_len; | 1536 | u16 rx_len; |
1516 | __le16 pkt_len; | 1537 | __le16 pkt_len; |
1517 | dma_addr_t buf_pa; | ||
1518 | 1538 | ||
1519 | dev_dbg(adapter->dev, "info: Rx CMD Response\n"); | 1539 | dev_dbg(adapter->dev, "info: Rx CMD Response\n"); |
1520 | 1540 | ||
1521 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1541 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE); |
1522 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1542 | |
1523 | PCI_DMA_FROMDEVICE); | 1543 | /* Unmap the command as a response has been received. */ |
1544 | if (card->cmd_buf) { | ||
1545 | mwifiex_unmap_pci_memory(adapter, card->cmd_buf, | ||
1546 | PCI_DMA_TODEVICE); | ||
1547 | card->cmd_buf = NULL; | ||
1548 | } | ||
1524 | 1549 | ||
1525 | pkt_len = *((__le16 *)skb->data); | 1550 | pkt_len = *((__le16 *)skb->data); |
1526 | rx_len = le16_to_cpu(pkt_len); | 1551 | rx_len = le16_to_cpu(pkt_len); |
@@ -1539,6 +1564,8 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1539 | "Write register failed\n"); | 1564 | "Write register failed\n"); |
1540 | return -1; | 1565 | return -1; |
1541 | } | 1566 | } |
1567 | mwifiex_delay_for_sleep_cookie(adapter, | ||
1568 | MWIFIEX_MAX_DELAY_COUNT); | ||
1542 | while (reg->sleep_cookie && (count++ < 10) && | 1569 | while (reg->sleep_cookie && (count++ < 10) && |
1543 | mwifiex_pcie_ok_to_access_hw(adapter)) | 1570 | mwifiex_pcie_ok_to_access_hw(adapter)) |
1544 | usleep_range(50, 60); | 1571 | usleep_range(50, 60); |
@@ -1552,8 +1579,6 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1552 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, | 1579 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, |
1553 | PCI_DMA_FROMDEVICE)) | 1580 | PCI_DMA_FROMDEVICE)) |
1554 | return -1; | 1581 | return -1; |
1555 | |||
1556 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1557 | } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { | 1582 | } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { |
1558 | adapter->curr_cmd->resp_skb = skb; | 1583 | adapter->curr_cmd->resp_skb = skb; |
1559 | adapter->cmd_resp_received = true; | 1584 | adapter->cmd_resp_received = true; |
@@ -1588,8 +1613,6 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, | |||
1588 | struct sk_buff *skb) | 1613 | struct sk_buff *skb) |
1589 | { | 1614 | { |
1590 | struct pcie_service_card *card = adapter->card; | 1615 | struct pcie_service_card *card = adapter->card; |
1591 | dma_addr_t buf_pa; | ||
1592 | struct sk_buff *skb_tmp; | ||
1593 | 1616 | ||
1594 | if (skb) { | 1617 | if (skb) { |
1595 | card->cmdrsp_buf = skb; | 1618 | card->cmdrsp_buf = skb; |
@@ -1599,14 +1622,6 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, | |||
1599 | return -1; | 1622 | return -1; |
1600 | } | 1623 | } |
1601 | 1624 | ||
1602 | skb_tmp = card->cmd_buf; | ||
1603 | if (skb_tmp) { | ||
1604 | MWIFIEX_SKB_PACB(skb_tmp, &buf_pa); | ||
1605 | pci_unmap_single(card->dev, buf_pa, skb_tmp->len, | ||
1606 | PCI_DMA_FROMDEVICE); | ||
1607 | card->cmd_buf = NULL; | ||
1608 | } | ||
1609 | |||
1610 | return 0; | 1625 | return 0; |
1611 | } | 1626 | } |
1612 | 1627 | ||
@@ -1619,7 +1634,6 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) | |||
1619 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | 1634 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; |
1620 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | 1635 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; |
1621 | u32 wrptr, event; | 1636 | u32 wrptr, event; |
1622 | dma_addr_t buf_pa; | ||
1623 | struct mwifiex_evt_buf_desc *desc; | 1637 | struct mwifiex_evt_buf_desc *desc; |
1624 | 1638 | ||
1625 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | 1639 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) |
@@ -1655,9 +1669,7 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) | |||
1655 | 1669 | ||
1656 | dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr); | 1670 | dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr); |
1657 | skb_cmd = card->evt_buf_list[rdptr]; | 1671 | skb_cmd = card->evt_buf_list[rdptr]; |
1658 | MWIFIEX_SKB_PACB(skb_cmd, &buf_pa); | 1672 | mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE); |
1659 | pci_unmap_single(card->dev, buf_pa, MAX_EVENT_SIZE, | ||
1660 | PCI_DMA_FROMDEVICE); | ||
1661 | 1673 | ||
1662 | /* Take the pointer and set it to event pointer in adapter | 1674 | /* Take the pointer and set it to event pointer in adapter |
1663 | and will return back after event handling callback */ | 1675 | and will return back after event handling callback */ |
@@ -1703,7 +1715,6 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1703 | int ret = 0; | 1715 | int ret = 0; |
1704 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | 1716 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; |
1705 | u32 wrptr; | 1717 | u32 wrptr; |
1706 | dma_addr_t buf_pa; | ||
1707 | struct mwifiex_evt_buf_desc *desc; | 1718 | struct mwifiex_evt_buf_desc *desc; |
1708 | 1719 | ||
1709 | if (!skb) | 1720 | if (!skb) |
@@ -1728,11 +1739,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1728 | MAX_EVENT_SIZE, | 1739 | MAX_EVENT_SIZE, |
1729 | PCI_DMA_FROMDEVICE)) | 1740 | PCI_DMA_FROMDEVICE)) |
1730 | return -1; | 1741 | return -1; |
1731 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1732 | card->evt_buf_list[rdptr] = skb; | 1742 | card->evt_buf_list[rdptr] = skb; |
1733 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1734 | desc = card->evtbd_ring[rdptr]; | 1743 | desc = card->evtbd_ring[rdptr]; |
1735 | desc->paddr = buf_pa; | 1744 | desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb); |
1736 | desc->len = (u16)skb->len; | 1745 | desc->len = (u16)skb->len; |
1737 | desc->flags = 0; | 1746 | desc->flags = 0; |
1738 | skb = NULL; | 1747 | skb = NULL; |
@@ -1782,7 +1791,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1782 | struct sk_buff *skb; | 1791 | struct sk_buff *skb; |
1783 | u32 txlen, tx_blocks = 0, tries, len; | 1792 | u32 txlen, tx_blocks = 0, tries, len; |
1784 | u32 block_retry_cnt = 0; | 1793 | u32 block_retry_cnt = 0; |
1785 | dma_addr_t buf_pa; | ||
1786 | struct pcie_service_card *card = adapter->card; | 1794 | struct pcie_service_card *card = adapter->card; |
1787 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | 1795 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; |
1788 | 1796 | ||
@@ -1880,8 +1888,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1880 | goto done; | 1888 | goto done; |
1881 | } | 1889 | } |
1882 | 1890 | ||
1883 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1884 | |||
1885 | /* Wait for the command done interrupt */ | 1891 | /* Wait for the command done interrupt */ |
1886 | do { | 1892 | do { |
1887 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, | 1893 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, |
@@ -1889,16 +1895,15 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1889 | dev_err(adapter->dev, "%s: Failed to read " | 1895 | dev_err(adapter->dev, "%s: Failed to read " |
1890 | "interrupt status during fw dnld.\n", | 1896 | "interrupt status during fw dnld.\n", |
1891 | __func__); | 1897 | __func__); |
1892 | pci_unmap_single(card->dev, buf_pa, skb->len, | 1898 | mwifiex_unmap_pci_memory(adapter, skb, |
1893 | PCI_DMA_TODEVICE); | 1899 | PCI_DMA_TODEVICE); |
1894 | ret = -1; | 1900 | ret = -1; |
1895 | goto done; | 1901 | goto done; |
1896 | } | 1902 | } |
1897 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == | 1903 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == |
1898 | CPU_INTR_DOOR_BELL); | 1904 | CPU_INTR_DOOR_BELL); |
1899 | 1905 | ||
1900 | pci_unmap_single(card->dev, buf_pa, skb->len, | 1906 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1901 | PCI_DMA_TODEVICE); | ||
1902 | 1907 | ||
1903 | offset += txlen; | 1908 | offset += txlen; |
1904 | } while (true); | 1909 | } while (true); |
@@ -2338,6 +2343,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
2338 | } | 2343 | } |
2339 | 2344 | ||
2340 | adapter->dev = &pdev->dev; | 2345 | adapter->dev = &pdev->dev; |
2346 | adapter->tx_buf_size = card->pcie.tx_buf_size; | ||
2341 | strcpy(adapter->fw_name, card->pcie.firmware); | 2347 | strcpy(adapter->fw_name, card->pcie.firmware); |
2342 | 2348 | ||
2343 | return 0; | 2349 | return 0; |
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h index d322ab8604ea..e8ec561f8a64 100644 --- a/drivers/net/wireless/mwifiex/pcie.h +++ b/drivers/net/wireless/mwifiex/pcie.h | |||
@@ -97,6 +97,8 @@ | |||
97 | #define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256 | 97 | #define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256 |
98 | /* FW awake cookie after FW ready */ | 98 | /* FW awake cookie after FW ready */ |
99 | #define FW_AWAKE_COOKIE (0xAA55AA55) | 99 | #define FW_AWAKE_COOKIE (0xAA55AA55) |
100 | #define MWIFIEX_DEF_SLEEP_COOKIE 0xBEEFBEEF | ||
101 | #define MWIFIEX_MAX_DELAY_COUNT 5 | ||
100 | 102 | ||
101 | struct mwifiex_pcie_card_reg { | 103 | struct mwifiex_pcie_card_reg { |
102 | u16 cmd_addr_lo; | 104 | u16 cmd_addr_lo; |
@@ -195,18 +197,21 @@ struct mwifiex_pcie_device { | |||
195 | const char *firmware; | 197 | const char *firmware; |
196 | const struct mwifiex_pcie_card_reg *reg; | 198 | const struct mwifiex_pcie_card_reg *reg; |
197 | u16 blksz_fw_dl; | 199 | u16 blksz_fw_dl; |
200 | u16 tx_buf_size; | ||
198 | }; | 201 | }; |
199 | 202 | ||
200 | static const struct mwifiex_pcie_device mwifiex_pcie8766 = { | 203 | static const struct mwifiex_pcie_device mwifiex_pcie8766 = { |
201 | .firmware = PCIE8766_DEFAULT_FW_NAME, | 204 | .firmware = PCIE8766_DEFAULT_FW_NAME, |
202 | .reg = &mwifiex_reg_8766, | 205 | .reg = &mwifiex_reg_8766, |
203 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, | 206 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, |
207 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | ||
204 | }; | 208 | }; |
205 | 209 | ||
206 | static const struct mwifiex_pcie_device mwifiex_pcie8897 = { | 210 | static const struct mwifiex_pcie_device mwifiex_pcie8897 = { |
207 | .firmware = PCIE8897_DEFAULT_FW_NAME, | 211 | .firmware = PCIE8897_DEFAULT_FW_NAME, |
208 | .reg = &mwifiex_reg_8897, | 212 | .reg = &mwifiex_reg_8897, |
209 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, | 213 | .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, |
214 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, | ||
210 | }; | 215 | }; |
211 | 216 | ||
212 | struct mwifiex_evt_buf_desc { | 217 | struct mwifiex_evt_buf_desc { |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 668547c2de84..7b3af3d29ded 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -591,11 +591,13 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, | |||
591 | *chan_tlv_out, | 591 | *chan_tlv_out, |
592 | struct mwifiex_chan_scan_param_set *scan_chan_list) | 592 | struct mwifiex_chan_scan_param_set *scan_chan_list) |
593 | { | 593 | { |
594 | struct mwifiex_adapter *adapter = priv->adapter; | ||
594 | int ret = 0; | 595 | int ret = 0; |
595 | struct mwifiex_chan_scan_param_set *tmp_chan_list; | 596 | struct mwifiex_chan_scan_param_set *tmp_chan_list; |
596 | struct mwifiex_chan_scan_param_set *start_chan; | 597 | struct mwifiex_chan_scan_param_set *start_chan; |
597 | 598 | struct cmd_ctrl_node *cmd_node, *tmp_node; | |
598 | u32 tlv_idx, rates_size; | 599 | unsigned long flags; |
600 | u32 tlv_idx, rates_size, cmd_no; | ||
599 | u32 total_scan_time; | 601 | u32 total_scan_time; |
600 | u32 done_early; | 602 | u32 done_early; |
601 | u8 radio_type; | 603 | u8 radio_type; |
@@ -733,9 +735,13 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, | |||
733 | 735 | ||
734 | /* Send the scan command to the firmware with the specified | 736 | /* Send the scan command to the firmware with the specified |
735 | cfg */ | 737 | cfg */ |
736 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN, | 738 | if (priv->adapter->ext_scan) |
737 | HostCmd_ACT_GEN_SET, 0, | 739 | cmd_no = HostCmd_CMD_802_11_SCAN_EXT; |
738 | scan_cfg_out); | 740 | else |
741 | cmd_no = HostCmd_CMD_802_11_SCAN; | ||
742 | |||
743 | ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET, | ||
744 | 0, scan_cfg_out, false); | ||
739 | 745 | ||
740 | /* rate IE is updated per scan command but same starting | 746 | /* rate IE is updated per scan command but same starting |
741 | * pointer is used each time so that rate IE from earlier | 747 | * pointer is used each time so that rate IE from earlier |
@@ -744,8 +750,19 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, | |||
744 | scan_cfg_out->tlv_buf_len -= | 750 | scan_cfg_out->tlv_buf_len -= |
745 | sizeof(struct mwifiex_ie_types_header) + rates_size; | 751 | sizeof(struct mwifiex_ie_types_header) + rates_size; |
746 | 752 | ||
747 | if (ret) | 753 | if (ret) { |
754 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
755 | list_for_each_entry_safe(cmd_node, tmp_node, | ||
756 | &adapter->scan_pending_q, | ||
757 | list) { | ||
758 | list_del(&cmd_node->list); | ||
759 | cmd_node->wait_q_enabled = false; | ||
760 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||
761 | } | ||
762 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
763 | flags); | ||
748 | break; | 764 | break; |
765 | } | ||
749 | } | 766 | } |
750 | 767 | ||
751 | if (ret) | 768 | if (ret) |
@@ -786,6 +803,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
786 | struct mwifiex_adapter *adapter = priv->adapter; | 803 | struct mwifiex_adapter *adapter = priv->adapter; |
787 | struct mwifiex_ie_types_num_probes *num_probes_tlv; | 804 | struct mwifiex_ie_types_num_probes *num_probes_tlv; |
788 | struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; | 805 | struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; |
806 | struct mwifiex_ie_types_bssid_list *bssid_tlv; | ||
789 | u8 *tlv_pos; | 807 | u8 *tlv_pos; |
790 | u32 num_probes; | 808 | u32 num_probes; |
791 | u32 ssid_len; | 809 | u32 ssid_len; |
@@ -848,6 +866,17 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
848 | user_scan_in->specific_bssid, | 866 | user_scan_in->specific_bssid, |
849 | sizeof(scan_cfg_out->specific_bssid)); | 867 | sizeof(scan_cfg_out->specific_bssid)); |
850 | 868 | ||
869 | if (adapter->ext_scan && | ||
870 | !is_zero_ether_addr(scan_cfg_out->specific_bssid)) { | ||
871 | bssid_tlv = | ||
872 | (struct mwifiex_ie_types_bssid_list *)tlv_pos; | ||
873 | bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID); | ||
874 | bssid_tlv->header.len = cpu_to_le16(ETH_ALEN); | ||
875 | memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid, | ||
876 | ETH_ALEN); | ||
877 | tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list); | ||
878 | } | ||
879 | |||
851 | for (i = 0; i < user_scan_in->num_ssids; i++) { | 880 | for (i = 0; i < user_scan_in->num_ssids; i++) { |
852 | ssid_len = user_scan_in->ssid_list[i].ssid_len; | 881 | ssid_len = user_scan_in->ssid_list[i].ssid_len; |
853 | 882 | ||
@@ -941,7 +970,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
941 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); | 970 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); |
942 | radio_type = | 971 | radio_type = |
943 | mwifiex_band_to_radio_type(priv->adapter->config_bands); | 972 | mwifiex_band_to_radio_type(priv->adapter->config_bands); |
944 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); | 973 | mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); |
945 | tlv_pos += sizeof(struct mwifiex_ie_types_htcap); | 974 | tlv_pos += sizeof(struct mwifiex_ie_types_htcap); |
946 | } | 975 | } |
947 | 976 | ||
@@ -1576,6 +1605,228 @@ done: | |||
1576 | return 0; | 1605 | return 0; |
1577 | } | 1606 | } |
1578 | 1607 | ||
1608 | static int | ||
1609 | mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, | ||
1610 | u32 *bytes_left, u64 fw_tsf, u8 *radio_type, | ||
1611 | bool ext_scan, s32 rssi_val) | ||
1612 | { | ||
1613 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1614 | struct mwifiex_chan_freq_power *cfp; | ||
1615 | struct cfg80211_bss *bss; | ||
1616 | u8 bssid[ETH_ALEN]; | ||
1617 | s32 rssi; | ||
1618 | const u8 *ie_buf; | ||
1619 | size_t ie_len; | ||
1620 | u16 channel = 0; | ||
1621 | u16 beacon_size = 0; | ||
1622 | u32 curr_bcn_bytes; | ||
1623 | u32 freq; | ||
1624 | u16 beacon_period; | ||
1625 | u16 cap_info_bitmap; | ||
1626 | u8 *current_ptr; | ||
1627 | u64 timestamp; | ||
1628 | struct mwifiex_fixed_bcn_param *bcn_param; | ||
1629 | struct mwifiex_bss_priv *bss_priv; | ||
1630 | |||
1631 | if (*bytes_left >= sizeof(beacon_size)) { | ||
1632 | /* Extract & convert beacon size from command buffer */ | ||
1633 | memcpy(&beacon_size, *bss_info, sizeof(beacon_size)); | ||
1634 | *bytes_left -= sizeof(beacon_size); | ||
1635 | *bss_info += sizeof(beacon_size); | ||
1636 | } | ||
1637 | |||
1638 | if (!beacon_size || beacon_size > *bytes_left) { | ||
1639 | *bss_info += *bytes_left; | ||
1640 | *bytes_left = 0; | ||
1641 | return -EFAULT; | ||
1642 | } | ||
1643 | |||
1644 | /* Initialize the current working beacon pointer for this BSS | ||
1645 | * iteration | ||
1646 | */ | ||
1647 | current_ptr = *bss_info; | ||
1648 | |||
1649 | /* Advance the return beacon pointer past the current beacon */ | ||
1650 | *bss_info += beacon_size; | ||
1651 | *bytes_left -= beacon_size; | ||
1652 | |||
1653 | curr_bcn_bytes = beacon_size; | ||
1654 | |||
1655 | /* First 5 fields are bssid, RSSI(for legacy scan only), | ||
1656 | * time stamp, beacon interval, and capability information | ||
1657 | */ | ||
1658 | if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) + | ||
1659 | sizeof(struct mwifiex_fixed_bcn_param)) { | ||
1660 | dev_err(adapter->dev, "InterpretIE: not enough bytes left\n"); | ||
1661 | return -EFAULT; | ||
1662 | } | ||
1663 | |||
1664 | memcpy(bssid, current_ptr, ETH_ALEN); | ||
1665 | current_ptr += ETH_ALEN; | ||
1666 | curr_bcn_bytes -= ETH_ALEN; | ||
1667 | |||
1668 | if (!ext_scan) { | ||
1669 | rssi = (s32) *current_ptr; | ||
1670 | rssi = (-rssi) * 100; /* Convert dBm to mBm */ | ||
1671 | current_ptr += sizeof(u8); | ||
1672 | curr_bcn_bytes -= sizeof(u8); | ||
1673 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); | ||
1674 | } else { | ||
1675 | rssi = rssi_val; | ||
1676 | } | ||
1677 | |||
1678 | bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr; | ||
1679 | current_ptr += sizeof(*bcn_param); | ||
1680 | curr_bcn_bytes -= sizeof(*bcn_param); | ||
1681 | |||
1682 | timestamp = le64_to_cpu(bcn_param->timestamp); | ||
1683 | beacon_period = le16_to_cpu(bcn_param->beacon_period); | ||
1684 | |||
1685 | cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); | ||
1686 | dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", | ||
1687 | cap_info_bitmap); | ||
1688 | |||
1689 | /* Rest of the current buffer are IE's */ | ||
1690 | ie_buf = current_ptr; | ||
1691 | ie_len = curr_bcn_bytes; | ||
1692 | dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n", | ||
1693 | curr_bcn_bytes); | ||
1694 | |||
1695 | while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) { | ||
1696 | u8 element_id, element_len; | ||
1697 | |||
1698 | element_id = *current_ptr; | ||
1699 | element_len = *(current_ptr + 1); | ||
1700 | if (curr_bcn_bytes < element_len + | ||
1701 | sizeof(struct ieee_types_header)) { | ||
1702 | dev_err(adapter->dev, | ||
1703 | "%s: bytes left < IE length\n", __func__); | ||
1704 | return -EFAULT; | ||
1705 | } | ||
1706 | if (element_id == WLAN_EID_DS_PARAMS) { | ||
1707 | channel = *(current_ptr + | ||
1708 | sizeof(struct ieee_types_header)); | ||
1709 | break; | ||
1710 | } | ||
1711 | |||
1712 | current_ptr += element_len + sizeof(struct ieee_types_header); | ||
1713 | curr_bcn_bytes -= element_len + | ||
1714 | sizeof(struct ieee_types_header); | ||
1715 | } | ||
1716 | |||
1717 | if (channel) { | ||
1718 | struct ieee80211_channel *chan; | ||
1719 | u8 band; | ||
1720 | |||
1721 | /* Skip entry if on csa closed channel */ | ||
1722 | if (channel == priv->csa_chan) { | ||
1723 | dev_dbg(adapter->dev, | ||
1724 | "Dropping entry on csa closed channel\n"); | ||
1725 | return 0; | ||
1726 | } | ||
1727 | |||
1728 | band = BAND_G; | ||
1729 | if (radio_type) | ||
1730 | band = mwifiex_radio_type_to_band(*radio_type & | ||
1731 | (BIT(0) | BIT(1))); | ||
1732 | |||
1733 | cfp = mwifiex_get_cfp(priv, band, channel, 0); | ||
1734 | |||
1735 | freq = cfp ? cfp->freq : 0; | ||
1736 | |||
1737 | chan = ieee80211_get_channel(priv->wdev->wiphy, freq); | ||
1738 | |||
1739 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
1740 | bss = cfg80211_inform_bss(priv->wdev->wiphy, | ||
1741 | chan, bssid, timestamp, | ||
1742 | cap_info_bitmap, beacon_period, | ||
1743 | ie_buf, ie_len, rssi, GFP_KERNEL); | ||
1744 | bss_priv = (struct mwifiex_bss_priv *)bss->priv; | ||
1745 | bss_priv->band = band; | ||
1746 | bss_priv->fw_tsf = fw_tsf; | ||
1747 | if (priv->media_connected && | ||
1748 | !memcmp(bssid, priv->curr_bss_params.bss_descriptor | ||
1749 | .mac_address, ETH_ALEN)) | ||
1750 | mwifiex_update_curr_bss_params(priv, bss); | ||
1751 | cfg80211_put_bss(priv->wdev->wiphy, bss); | ||
1752 | } | ||
1753 | } else { | ||
1754 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | ||
1755 | } | ||
1756 | |||
1757 | return 0; | ||
1758 | } | ||
1759 | |||
1760 | static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) | ||
1761 | { | ||
1762 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1763 | struct cmd_ctrl_node *cmd_node; | ||
1764 | unsigned long flags; | ||
1765 | |||
1766 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
1767 | if (list_empty(&adapter->scan_pending_q)) { | ||
1768 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | ||
1769 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
1770 | adapter->scan_processing = false; | ||
1771 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | ||
1772 | |||
1773 | /* Need to indicate IOCTL complete */ | ||
1774 | if (adapter->curr_cmd->wait_q_enabled) { | ||
1775 | adapter->cmd_wait_q.status = 0; | ||
1776 | if (!priv->scan_request) { | ||
1777 | dev_dbg(adapter->dev, | ||
1778 | "complete internal scan\n"); | ||
1779 | mwifiex_complete_cmd(adapter, | ||
1780 | adapter->curr_cmd); | ||
1781 | } | ||
1782 | } | ||
1783 | if (priv->report_scan_result) | ||
1784 | priv->report_scan_result = false; | ||
1785 | |||
1786 | if (priv->scan_request) { | ||
1787 | dev_dbg(adapter->dev, "info: notifying scan done\n"); | ||
1788 | cfg80211_scan_done(priv->scan_request, 0); | ||
1789 | priv->scan_request = NULL; | ||
1790 | } else { | ||
1791 | priv->scan_aborting = false; | ||
1792 | dev_dbg(adapter->dev, "info: scan already aborted\n"); | ||
1793 | } | ||
1794 | } else { | ||
1795 | if ((priv->scan_aborting && !priv->scan_request) || | ||
1796 | priv->scan_block) { | ||
1797 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1798 | flags); | ||
1799 | adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; | ||
1800 | mod_timer(&priv->scan_delay_timer, jiffies); | ||
1801 | dev_dbg(priv->adapter->dev, | ||
1802 | "info: %s: triggerring scan abort\n", __func__); | ||
1803 | } else if (!mwifiex_wmm_lists_empty(adapter) && | ||
1804 | (priv->scan_request && (priv->scan_request->flags & | ||
1805 | NL80211_SCAN_FLAG_LOW_PRIORITY))) { | ||
1806 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1807 | flags); | ||
1808 | adapter->scan_delay_cnt = 1; | ||
1809 | mod_timer(&priv->scan_delay_timer, jiffies + | ||
1810 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); | ||
1811 | dev_dbg(priv->adapter->dev, | ||
1812 | "info: %s: deferring scan\n", __func__); | ||
1813 | } else { | ||
1814 | /* Get scan command from scan_pending_q and put to | ||
1815 | * cmd_pending_q | ||
1816 | */ | ||
1817 | cmd_node = list_first_entry(&adapter->scan_pending_q, | ||
1818 | struct cmd_ctrl_node, list); | ||
1819 | list_del(&cmd_node->list); | ||
1820 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1821 | flags); | ||
1822 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | ||
1823 | true); | ||
1824 | } | ||
1825 | } | ||
1826 | |||
1827 | return; | ||
1828 | } | ||
1829 | |||
1579 | /* | 1830 | /* |
1580 | * This function handles the command response of scan. | 1831 | * This function handles the command response of scan. |
1581 | * | 1832 | * |
@@ -1600,7 +1851,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1600 | { | 1851 | { |
1601 | int ret = 0; | 1852 | int ret = 0; |
1602 | struct mwifiex_adapter *adapter = priv->adapter; | 1853 | struct mwifiex_adapter *adapter = priv->adapter; |
1603 | struct cmd_ctrl_node *cmd_node; | ||
1604 | struct host_cmd_ds_802_11_scan_rsp *scan_rsp; | 1854 | struct host_cmd_ds_802_11_scan_rsp *scan_rsp; |
1605 | struct mwifiex_ie_types_data *tlv_data; | 1855 | struct mwifiex_ie_types_data *tlv_data; |
1606 | struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; | 1856 | struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; |
@@ -1609,12 +1859,11 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1609 | u32 bytes_left; | 1859 | u32 bytes_left; |
1610 | u32 idx; | 1860 | u32 idx; |
1611 | u32 tlv_buf_size; | 1861 | u32 tlv_buf_size; |
1612 | struct mwifiex_chan_freq_power *cfp; | ||
1613 | struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; | 1862 | struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; |
1614 | struct chan_band_param_set *chan_band; | 1863 | struct chan_band_param_set *chan_band; |
1615 | u8 is_bgscan_resp; | 1864 | u8 is_bgscan_resp; |
1616 | unsigned long flags; | 1865 | __le64 fw_tsf = 0; |
1617 | struct cfg80211_bss *bss; | 1866 | u8 *radio_type; |
1618 | 1867 | ||
1619 | is_bgscan_resp = (le16_to_cpu(resp->command) | 1868 | is_bgscan_resp = (le16_to_cpu(resp->command) |
1620 | == HostCmd_CMD_802_11_BG_SCAN_QUERY); | 1869 | == HostCmd_CMD_802_11_BG_SCAN_QUERY); |
@@ -1676,220 +1925,194 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1676 | &chan_band_tlv); | 1925 | &chan_band_tlv); |
1677 | 1926 | ||
1678 | for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { | 1927 | for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { |
1679 | u8 bssid[ETH_ALEN]; | 1928 | /* |
1680 | s32 rssi; | 1929 | * If the TSF TLV was appended to the scan results, save this |
1681 | const u8 *ie_buf; | 1930 | * entry's TSF value in the fw_tsf field. It is the firmware's |
1682 | size_t ie_len; | 1931 | * TSF value at the time the beacon or probe response was |
1683 | u16 channel = 0; | 1932 | * received. |
1684 | __le64 fw_tsf = 0; | 1933 | */ |
1685 | u16 beacon_size = 0; | 1934 | if (tsf_tlv) |
1686 | u32 curr_bcn_bytes; | 1935 | memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], |
1687 | u32 freq; | 1936 | sizeof(fw_tsf)); |
1688 | u16 beacon_period; | ||
1689 | u16 cap_info_bitmap; | ||
1690 | u8 *current_ptr; | ||
1691 | u64 timestamp; | ||
1692 | struct mwifiex_bcn_param *bcn_param; | ||
1693 | struct mwifiex_bss_priv *bss_priv; | ||
1694 | |||
1695 | if (bytes_left >= sizeof(beacon_size)) { | ||
1696 | /* Extract & convert beacon size from command buffer */ | ||
1697 | memcpy(&beacon_size, bss_info, sizeof(beacon_size)); | ||
1698 | bytes_left -= sizeof(beacon_size); | ||
1699 | bss_info += sizeof(beacon_size); | ||
1700 | } | ||
1701 | 1937 | ||
1702 | if (!beacon_size || beacon_size > bytes_left) { | 1938 | if (chan_band_tlv) { |
1703 | bss_info += bytes_left; | 1939 | chan_band = &chan_band_tlv->chan_band_param[idx]; |
1704 | bytes_left = 0; | 1940 | radio_type = &chan_band->radio_type; |
1705 | ret = -1; | 1941 | } else { |
1706 | goto check_next_scan; | 1942 | radio_type = NULL; |
1707 | } | 1943 | } |
1708 | 1944 | ||
1709 | /* Initialize the current working beacon pointer for this BSS | 1945 | ret = mwifiex_parse_single_response_buf(priv, &bss_info, |
1710 | * iteration */ | 1946 | &bytes_left, |
1711 | current_ptr = bss_info; | 1947 | le64_to_cpu(fw_tsf), |
1948 | radio_type, false, 0); | ||
1949 | if (ret) | ||
1950 | goto check_next_scan; | ||
1951 | } | ||
1712 | 1952 | ||
1713 | /* Advance the return beacon pointer past the current beacon */ | 1953 | check_next_scan: |
1714 | bss_info += beacon_size; | 1954 | mwifiex_check_next_scan_command(priv); |
1715 | bytes_left -= beacon_size; | 1955 | return ret; |
1956 | } | ||
1716 | 1957 | ||
1717 | curr_bcn_bytes = beacon_size; | 1958 | /* |
1959 | * This function prepares an extended scan command to be sent to the firmware | ||
1960 | * | ||
1961 | * This uses the scan command configuration sent to the command processing | ||
1962 | * module in command preparation stage to configure a extended scan command | ||
1963 | * structure to send to firmware. | ||
1964 | */ | ||
1965 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | ||
1966 | struct host_cmd_ds_command *cmd, | ||
1967 | void *data_buf) | ||
1968 | { | ||
1969 | struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan; | ||
1970 | struct mwifiex_scan_cmd_config *scan_cfg = data_buf; | ||
1718 | 1971 | ||
1719 | /* | 1972 | memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); |
1720 | * First 5 fields are bssid, RSSI, time stamp, beacon interval, | ||
1721 | * and capability information | ||
1722 | */ | ||
1723 | if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) { | ||
1724 | dev_err(adapter->dev, | ||
1725 | "InterpretIE: not enough bytes left\n"); | ||
1726 | continue; | ||
1727 | } | ||
1728 | bcn_param = (struct mwifiex_bcn_param *)current_ptr; | ||
1729 | current_ptr += sizeof(*bcn_param); | ||
1730 | curr_bcn_bytes -= sizeof(*bcn_param); | ||
1731 | 1973 | ||
1732 | memcpy(bssid, bcn_param->bssid, ETH_ALEN); | 1974 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT); |
1733 | 1975 | ||
1734 | rssi = (s32) bcn_param->rssi; | 1976 | /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ |
1735 | rssi = (-rssi) * 100; /* Convert dBm to mBm */ | 1977 | cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved) |
1736 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); | 1978 | + scan_cfg->tlv_buf_len + S_DS_GEN)); |
1737 | 1979 | ||
1738 | timestamp = le64_to_cpu(bcn_param->timestamp); | 1980 | return 0; |
1739 | beacon_period = le16_to_cpu(bcn_param->beacon_period); | 1981 | } |
1740 | 1982 | ||
1741 | cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); | 1983 | /* This function handles the command response of extended scan */ |
1742 | dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", | 1984 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv) |
1743 | cap_info_bitmap); | 1985 | { |
1986 | dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n"); | ||
1987 | return 0; | ||
1988 | } | ||
1744 | 1989 | ||
1745 | /* Rest of the current buffer are IE's */ | 1990 | /* This function This function handles the event extended scan report. It |
1746 | ie_buf = current_ptr; | 1991 | * parses extended scan results and informs to cfg80211 stack. |
1747 | ie_len = curr_bcn_bytes; | 1992 | */ |
1748 | dev_dbg(adapter->dev, | 1993 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, |
1749 | "info: InterpretIE: IELength for this AP = %d\n", | 1994 | void *buf) |
1750 | curr_bcn_bytes); | 1995 | { |
1996 | int ret = 0; | ||
1997 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1998 | u8 *bss_info; | ||
1999 | u32 bytes_left, bytes_left_for_tlv, idx; | ||
2000 | u16 type, len; | ||
2001 | struct mwifiex_ie_types_data *tlv; | ||
2002 | struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv; | ||
2003 | struct mwifiex_ie_types_bss_scan_info *scan_info_tlv; | ||
2004 | u8 *radio_type; | ||
2005 | u64 fw_tsf = 0; | ||
2006 | s32 rssi = 0; | ||
2007 | struct mwifiex_event_scan_result *event_scan = buf; | ||
2008 | u8 num_of_set = event_scan->num_of_set; | ||
2009 | u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result); | ||
2010 | u16 scan_resp_size = le16_to_cpu(event_scan->buf_size); | ||
2011 | |||
2012 | if (num_of_set > MWIFIEX_MAX_AP) { | ||
2013 | dev_err(adapter->dev, | ||
2014 | "EXT_SCAN: Invalid number of AP returned (%d)!!\n", | ||
2015 | num_of_set); | ||
2016 | ret = -1; | ||
2017 | goto check_next_scan; | ||
2018 | } | ||
1751 | 2019 | ||
1752 | while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) { | 2020 | bytes_left = scan_resp_size; |
1753 | u8 element_id, element_len; | 2021 | dev_dbg(adapter->dev, |
2022 | "EXT_SCAN: size %d, returned %d APs...", | ||
2023 | scan_resp_size, num_of_set); | ||
1754 | 2024 | ||
1755 | element_id = *current_ptr; | 2025 | tlv = (struct mwifiex_ie_types_data *)scan_resp; |
1756 | element_len = *(current_ptr + 1); | ||
1757 | if (curr_bcn_bytes < element_len + | ||
1758 | sizeof(struct ieee_types_header)) { | ||
1759 | dev_err(priv->adapter->dev, | ||
1760 | "%s: bytes left < IE length\n", | ||
1761 | __func__); | ||
1762 | goto check_next_scan; | ||
1763 | } | ||
1764 | if (element_id == WLAN_EID_DS_PARAMS) { | ||
1765 | channel = *(current_ptr + sizeof(struct ieee_types_header)); | ||
1766 | break; | ||
1767 | } | ||
1768 | 2026 | ||
1769 | current_ptr += element_len + | 2027 | for (idx = 0; idx < num_of_set && bytes_left; idx++) { |
1770 | sizeof(struct ieee_types_header); | 2028 | type = le16_to_cpu(tlv->header.type); |
1771 | curr_bcn_bytes -= element_len + | 2029 | len = le16_to_cpu(tlv->header.len); |
1772 | sizeof(struct ieee_types_header); | 2030 | if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) { |
2031 | dev_err(adapter->dev, "EXT_SCAN: Error bytes left < TLV length\n"); | ||
2032 | break; | ||
1773 | } | 2033 | } |
2034 | scan_rsp_tlv = NULL; | ||
2035 | scan_info_tlv = NULL; | ||
2036 | bytes_left_for_tlv = bytes_left; | ||
1774 | 2037 | ||
1775 | /* | 2038 | /* BSS response TLV with beacon or probe response buffer |
1776 | * If the TSF TLV was appended to the scan results, save this | 2039 | * at the initial position of each descriptor |
1777 | * entry's TSF value in the fw_tsf field. It is the firmware's | ||
1778 | * TSF value at the time the beacon or probe response was | ||
1779 | * received. | ||
1780 | */ | 2040 | */ |
1781 | if (tsf_tlv) | 2041 | if (type != TLV_TYPE_BSS_SCAN_RSP) |
1782 | memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], | 2042 | break; |
1783 | sizeof(fw_tsf)); | ||
1784 | |||
1785 | if (channel) { | ||
1786 | struct ieee80211_channel *chan; | ||
1787 | u8 band; | ||
1788 | 2043 | ||
1789 | /* Skip entry if on csa closed channel */ | 2044 | bss_info = (u8 *)tlv; |
1790 | if (channel == priv->csa_chan) { | 2045 | scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv; |
1791 | dev_dbg(adapter->dev, | 2046 | tlv = (struct mwifiex_ie_types_data *)(tlv->data + len); |
1792 | "Dropping entry on csa closed channel\n"); | 2047 | bytes_left_for_tlv -= |
2048 | (len + sizeof(struct mwifiex_ie_types_header)); | ||
2049 | |||
2050 | while (bytes_left_for_tlv >= | ||
2051 | sizeof(struct mwifiex_ie_types_header) && | ||
2052 | le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) { | ||
2053 | type = le16_to_cpu(tlv->header.type); | ||
2054 | len = le16_to_cpu(tlv->header.len); | ||
2055 | if (bytes_left_for_tlv < | ||
2056 | sizeof(struct mwifiex_ie_types_header) + len) { | ||
2057 | dev_err(adapter->dev, | ||
2058 | "EXT_SCAN: Error in processing TLV, bytes left < TLV length\n"); | ||
2059 | scan_rsp_tlv = NULL; | ||
2060 | bytes_left_for_tlv = 0; | ||
1793 | continue; | 2061 | continue; |
1794 | } | 2062 | } |
1795 | 2063 | switch (type) { | |
1796 | band = BAND_G; | 2064 | case TLV_TYPE_BSS_SCAN_INFO: |
1797 | if (chan_band_tlv) { | 2065 | scan_info_tlv = |
1798 | chan_band = | 2066 | (struct mwifiex_ie_types_bss_scan_info *)tlv; |
1799 | &chan_band_tlv->chan_band_param[idx]; | 2067 | if (len != |
1800 | band = mwifiex_radio_type_to_band( | 2068 | sizeof(struct mwifiex_ie_types_bss_scan_info) - |
1801 | chan_band->radio_type | 2069 | sizeof(struct mwifiex_ie_types_header)) { |
1802 | & (BIT(0) | BIT(1))); | 2070 | bytes_left_for_tlv = 0; |
1803 | } | 2071 | continue; |
1804 | 2072 | } | |
1805 | cfp = mwifiex_get_cfp(priv, band, channel, 0); | 2073 | break; |
1806 | 2074 | default: | |
1807 | freq = cfp ? cfp->freq : 0; | 2075 | break; |
1808 | |||
1809 | chan = ieee80211_get_channel(priv->wdev->wiphy, freq); | ||
1810 | |||
1811 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
1812 | bss = cfg80211_inform_bss(priv->wdev->wiphy, | ||
1813 | chan, bssid, timestamp, | ||
1814 | cap_info_bitmap, beacon_period, | ||
1815 | ie_buf, ie_len, rssi, GFP_KERNEL); | ||
1816 | bss_priv = (struct mwifiex_bss_priv *)bss->priv; | ||
1817 | bss_priv->band = band; | ||
1818 | bss_priv->fw_tsf = le64_to_cpu(fw_tsf); | ||
1819 | if (priv->media_connected && | ||
1820 | !memcmp(bssid, | ||
1821 | priv->curr_bss_params.bss_descriptor | ||
1822 | .mac_address, ETH_ALEN)) | ||
1823 | mwifiex_update_curr_bss_params(priv, | ||
1824 | bss); | ||
1825 | cfg80211_put_bss(priv->wdev->wiphy, bss); | ||
1826 | } | 2076 | } |
1827 | } else { | 2077 | tlv = (struct mwifiex_ie_types_data *)(tlv->data + len); |
1828 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | 2078 | bytes_left -= |
2079 | (len + sizeof(struct mwifiex_ie_types_header)); | ||
2080 | bytes_left_for_tlv -= | ||
2081 | (len + sizeof(struct mwifiex_ie_types_header)); | ||
1829 | } | 2082 | } |
1830 | } | ||
1831 | 2083 | ||
1832 | check_next_scan: | 2084 | if (!scan_rsp_tlv) |
1833 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | 2085 | break; |
1834 | if (list_empty(&adapter->scan_pending_q)) { | ||
1835 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | ||
1836 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
1837 | adapter->scan_processing = false; | ||
1838 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | ||
1839 | 2086 | ||
1840 | /* Need to indicate IOCTL complete */ | 2087 | /* Advance pointer to the beacon buffer length and |
1841 | if (adapter->curr_cmd->wait_q_enabled) { | 2088 | * update the bytes count so that the function |
1842 | adapter->cmd_wait_q.status = 0; | 2089 | * wlan_interpret_bss_desc_with_ie() can handle the |
1843 | if (!priv->scan_request) { | 2090 | * scan buffer withut any change |
1844 | dev_dbg(adapter->dev, | 2091 | */ |
1845 | "complete internal scan\n"); | 2092 | bss_info += sizeof(u16); |
1846 | mwifiex_complete_cmd(adapter, | 2093 | bytes_left -= sizeof(u16); |
1847 | adapter->curr_cmd); | ||
1848 | } | ||
1849 | } | ||
1850 | if (priv->report_scan_result) | ||
1851 | priv->report_scan_result = false; | ||
1852 | 2094 | ||
1853 | if (priv->scan_request) { | 2095 | if (scan_info_tlv) { |
1854 | dev_dbg(adapter->dev, "info: notifying scan done\n"); | 2096 | rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi)); |
1855 | cfg80211_scan_done(priv->scan_request, 0); | 2097 | rssi *= 100; /* Convert dBm to mBm */ |
1856 | priv->scan_request = NULL; | 2098 | dev_dbg(adapter->dev, |
1857 | } else { | 2099 | "info: InterpretIE: RSSI=%d\n", rssi); |
1858 | priv->scan_aborting = false; | 2100 | fw_tsf = le64_to_cpu(scan_info_tlv->tsf); |
1859 | dev_dbg(adapter->dev, "info: scan already aborted\n"); | 2101 | radio_type = &scan_info_tlv->radio_type; |
1860 | } | ||
1861 | } else { | ||
1862 | if ((priv->scan_aborting && !priv->scan_request) || | ||
1863 | priv->scan_block) { | ||
1864 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1865 | flags); | ||
1866 | adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; | ||
1867 | mod_timer(&priv->scan_delay_timer, jiffies); | ||
1868 | dev_dbg(priv->adapter->dev, | ||
1869 | "info: %s: triggerring scan abort\n", __func__); | ||
1870 | } else if (!mwifiex_wmm_lists_empty(adapter) && | ||
1871 | (priv->scan_request && (priv->scan_request->flags & | ||
1872 | NL80211_SCAN_FLAG_LOW_PRIORITY))) { | ||
1873 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1874 | flags); | ||
1875 | adapter->scan_delay_cnt = 1; | ||
1876 | mod_timer(&priv->scan_delay_timer, jiffies + | ||
1877 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); | ||
1878 | dev_dbg(priv->adapter->dev, | ||
1879 | "info: %s: deferring scan\n", __func__); | ||
1880 | } else { | 2102 | } else { |
1881 | /* Get scan command from scan_pending_q and put to | 2103 | radio_type = NULL; |
1882 | cmd_pending_q */ | ||
1883 | cmd_node = list_first_entry(&adapter->scan_pending_q, | ||
1884 | struct cmd_ctrl_node, list); | ||
1885 | list_del(&cmd_node->list); | ||
1886 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1887 | flags); | ||
1888 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | ||
1889 | true); | ||
1890 | } | 2104 | } |
2105 | ret = mwifiex_parse_single_response_buf(priv, &bss_info, | ||
2106 | &bytes_left, fw_tsf, | ||
2107 | radio_type, true, rssi); | ||
2108 | if (ret) | ||
2109 | goto check_next_scan; | ||
1891 | } | 2110 | } |
1892 | 2111 | ||
2112 | check_next_scan: | ||
2113 | if (!event_scan->more_event) | ||
2114 | mwifiex_check_next_scan_command(priv); | ||
2115 | |||
1893 | return ret; | 2116 | return ret; |
1894 | } | 2117 | } |
1895 | 2118 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index b44a31523461..d206f04d4994 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -84,6 +84,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | |||
84 | card->mp_agg_pkt_limit = data->mp_agg_pkt_limit; | 84 | card->mp_agg_pkt_limit = data->mp_agg_pkt_limit; |
85 | card->supports_sdio_new_mode = data->supports_sdio_new_mode; | 85 | card->supports_sdio_new_mode = data->supports_sdio_new_mode; |
86 | card->has_control_mask = data->has_control_mask; | 86 | card->has_control_mask = data->has_control_mask; |
87 | card->tx_buf_size = data->tx_buf_size; | ||
87 | } | 88 | } |
88 | 89 | ||
89 | sdio_claim_host(func); | 90 | sdio_claim_host(func); |
@@ -165,7 +166,6 @@ mwifiex_sdio_remove(struct sdio_func *func) | |||
165 | struct sdio_mmc_card *card; | 166 | struct sdio_mmc_card *card; |
166 | struct mwifiex_adapter *adapter; | 167 | struct mwifiex_adapter *adapter; |
167 | struct mwifiex_private *priv; | 168 | struct mwifiex_private *priv; |
168 | int i; | ||
169 | 169 | ||
170 | pr_debug("info: SDIO func num=%d\n", func->num); | 170 | pr_debug("info: SDIO func num=%d\n", func->num); |
171 | 171 | ||
@@ -184,11 +184,7 @@ mwifiex_sdio_remove(struct sdio_func *func) | |||
184 | if (adapter->is_suspended) | 184 | if (adapter->is_suspended) |
185 | mwifiex_sdio_resume(adapter->dev); | 185 | mwifiex_sdio_resume(adapter->dev); |
186 | 186 | ||
187 | for (i = 0; i < adapter->priv_num; i++) | 187 | mwifiex_deauthenticate_all(adapter); |
188 | if ((GET_BSS_ROLE(adapter->priv[i]) == | ||
189 | MWIFIEX_BSS_ROLE_STA) && | ||
190 | adapter->priv[i]->media_connected) | ||
191 | mwifiex_deauthenticate(adapter->priv[i], NULL); | ||
192 | 188 | ||
193 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 189 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
194 | mwifiex_disable_auto_ds(priv); | 190 | mwifiex_disable_auto_ds(priv); |
@@ -241,6 +237,7 @@ static int mwifiex_sdio_suspend(struct device *dev) | |||
241 | /* Enable the Host Sleep */ | 237 | /* Enable the Host Sleep */ |
242 | if (!mwifiex_enable_hs(adapter)) { | 238 | if (!mwifiex_enable_hs(adapter)) { |
243 | dev_err(adapter->dev, "cmd: failed to suspend\n"); | 239 | dev_err(adapter->dev, "cmd: failed to suspend\n"); |
240 | adapter->hs_enabling = false; | ||
244 | return -EFAULT; | 241 | return -EFAULT; |
245 | } | 242 | } |
246 | 243 | ||
@@ -249,6 +246,7 @@ static int mwifiex_sdio_suspend(struct device *dev) | |||
249 | 246 | ||
250 | /* Indicate device suspended */ | 247 | /* Indicate device suspended */ |
251 | adapter->is_suspended = true; | 248 | adapter->is_suspended = true; |
249 | adapter->hs_enabling = false; | ||
252 | 250 | ||
253 | return ret; | 251 | return ret; |
254 | } | 252 | } |
@@ -1760,6 +1758,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
1760 | 1758 | ||
1761 | /* save adapter pointer in card */ | 1759 | /* save adapter pointer in card */ |
1762 | card->adapter = adapter; | 1760 | card->adapter = adapter; |
1761 | adapter->tx_buf_size = card->tx_buf_size; | ||
1763 | 1762 | ||
1764 | sdio_claim_host(func); | 1763 | sdio_claim_host(func); |
1765 | 1764 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 532ae0ac4dfb..c71201b2e2a3 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
@@ -233,6 +233,7 @@ struct sdio_mmc_card { | |||
233 | u8 mp_agg_pkt_limit; | 233 | u8 mp_agg_pkt_limit; |
234 | bool supports_sdio_new_mode; | 234 | bool supports_sdio_new_mode; |
235 | bool has_control_mask; | 235 | bool has_control_mask; |
236 | u16 tx_buf_size; | ||
236 | 237 | ||
237 | u32 mp_rd_bitmap; | 238 | u32 mp_rd_bitmap; |
238 | u32 mp_wr_bitmap; | 239 | u32 mp_wr_bitmap; |
@@ -256,6 +257,7 @@ struct mwifiex_sdio_device { | |||
256 | u8 mp_agg_pkt_limit; | 257 | u8 mp_agg_pkt_limit; |
257 | bool supports_sdio_new_mode; | 258 | bool supports_sdio_new_mode; |
258 | bool has_control_mask; | 259 | bool has_control_mask; |
260 | u16 tx_buf_size; | ||
259 | }; | 261 | }; |
260 | 262 | ||
261 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { | 263 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { |
@@ -312,6 +314,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { | |||
312 | .mp_agg_pkt_limit = 8, | 314 | .mp_agg_pkt_limit = 8, |
313 | .supports_sdio_new_mode = false, | 315 | .supports_sdio_new_mode = false, |
314 | .has_control_mask = true, | 316 | .has_control_mask = true, |
317 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | ||
315 | }; | 318 | }; |
316 | 319 | ||
317 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | 320 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { |
@@ -321,6 +324,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | |||
321 | .mp_agg_pkt_limit = 8, | 324 | .mp_agg_pkt_limit = 8, |
322 | .supports_sdio_new_mode = false, | 325 | .supports_sdio_new_mode = false, |
323 | .has_control_mask = true, | 326 | .has_control_mask = true, |
327 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | ||
324 | }; | 328 | }; |
325 | 329 | ||
326 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | 330 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { |
@@ -330,6 +334,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | |||
330 | .mp_agg_pkt_limit = 8, | 334 | .mp_agg_pkt_limit = 8, |
331 | .supports_sdio_new_mode = false, | 335 | .supports_sdio_new_mode = false, |
332 | .has_control_mask = true, | 336 | .has_control_mask = true, |
337 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, | ||
333 | }; | 338 | }; |
334 | 339 | ||
335 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | 340 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { |
@@ -339,6 +344,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | |||
339 | .mp_agg_pkt_limit = 16, | 344 | .mp_agg_pkt_limit = 16, |
340 | .supports_sdio_new_mode = true, | 345 | .supports_sdio_new_mode = true, |
341 | .has_control_mask = false, | 346 | .has_control_mask = false, |
347 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, | ||
342 | }; | 348 | }; |
343 | 349 | ||
344 | /* | 350 | /* |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 9208a8816b80..e3cac1495cc7 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -185,6 +185,13 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, | |||
185 | i++) | 185 | i++) |
186 | rate_scope->ht_mcs_rate_bitmap[i] = | 186 | rate_scope->ht_mcs_rate_bitmap[i] = |
187 | cpu_to_le16(pbitmap_rates[2 + i]); | 187 | cpu_to_le16(pbitmap_rates[2 + i]); |
188 | if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { | ||
189 | for (i = 0; | ||
190 | i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); | ||
191 | i++) | ||
192 | rate_scope->vht_mcs_rate_bitmap[i] = | ||
193 | cpu_to_le16(pbitmap_rates[10 + i]); | ||
194 | } | ||
188 | } else { | 195 | } else { |
189 | rate_scope->hr_dsss_rate_bitmap = | 196 | rate_scope->hr_dsss_rate_bitmap = |
190 | cpu_to_le16(priv->bitmap_rates[0]); | 197 | cpu_to_le16(priv->bitmap_rates[0]); |
@@ -195,6 +202,13 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, | |||
195 | i++) | 202 | i++) |
196 | rate_scope->ht_mcs_rate_bitmap[i] = | 203 | rate_scope->ht_mcs_rate_bitmap[i] = |
197 | cpu_to_le16(priv->bitmap_rates[2 + i]); | 204 | cpu_to_le16(priv->bitmap_rates[2 + i]); |
205 | if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { | ||
206 | for (i = 0; | ||
207 | i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); | ||
208 | i++) | ||
209 | rate_scope->vht_mcs_rate_bitmap[i] = | ||
210 | cpu_to_le16(priv->bitmap_rates[10 + i]); | ||
211 | } | ||
198 | } | 212 | } |
199 | 213 | ||
200 | rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + | 214 | rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + |
@@ -532,8 +546,228 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, | |||
532 | return 0; | 546 | return 0; |
533 | } | 547 | } |
534 | 548 | ||
549 | /* This function populates key material v2 command | ||
550 | * to set network key for AES & CMAC AES. | ||
551 | */ | ||
552 | static int mwifiex_set_aes_key_v2(struct mwifiex_private *priv, | ||
553 | struct host_cmd_ds_command *cmd, | ||
554 | struct mwifiex_ds_encrypt_key *enc_key, | ||
555 | struct host_cmd_ds_802_11_key_material_v2 *km) | ||
556 | { | ||
557 | struct mwifiex_adapter *adapter = priv->adapter; | ||
558 | u16 size, len = KEY_PARAMS_FIXED_LEN; | ||
559 | |||
560 | if (enc_key->is_igtk_key) { | ||
561 | dev_dbg(adapter->dev, "%s: Set CMAC AES Key\n", __func__); | ||
562 | if (enc_key->is_rx_seq_valid) | ||
563 | memcpy(km->key_param_set.key_params.cmac_aes.ipn, | ||
564 | enc_key->pn, enc_key->pn_len); | ||
565 | km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST); | ||
566 | km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK); | ||
567 | km->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC; | ||
568 | km->key_param_set.key_params.cmac_aes.key_len = | ||
569 | cpu_to_le16(enc_key->key_len); | ||
570 | memcpy(km->key_param_set.key_params.cmac_aes.key, | ||
571 | enc_key->key_material, enc_key->key_len); | ||
572 | len += sizeof(struct mwifiex_cmac_aes_param); | ||
573 | } else { | ||
574 | dev_dbg(adapter->dev, "%s: Set AES Key\n", __func__); | ||
575 | if (enc_key->is_rx_seq_valid) | ||
576 | memcpy(km->key_param_set.key_params.aes.pn, | ||
577 | enc_key->pn, enc_key->pn_len); | ||
578 | km->key_param_set.key_type = KEY_TYPE_ID_AES; | ||
579 | km->key_param_set.key_params.aes.key_len = | ||
580 | cpu_to_le16(enc_key->key_len); | ||
581 | memcpy(km->key_param_set.key_params.aes.key, | ||
582 | enc_key->key_material, enc_key->key_len); | ||
583 | len += sizeof(struct mwifiex_aes_param); | ||
584 | } | ||
585 | |||
586 | km->key_param_set.len = cpu_to_le16(len); | ||
587 | size = len + sizeof(struct mwifiex_ie_types_header) + | ||
588 | sizeof(km->action) + S_DS_GEN; | ||
589 | cmd->size = cpu_to_le16(size); | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | /* This function prepares command to set/get/reset network key(s). | ||
595 | * This function prepares key material command for V2 format. | ||
596 | * Preparation includes - | ||
597 | * - Setting command ID, action and proper size | ||
598 | * - Setting WEP keys, WAPI keys or WPA keys along with required | ||
599 | * encryption (TKIP, AES) (as required) | ||
600 | * - Ensuring correct endian-ness | ||
601 | */ | ||
602 | static int | ||
603 | mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv, | ||
604 | struct host_cmd_ds_command *cmd, | ||
605 | u16 cmd_action, u32 cmd_oid, | ||
606 | struct mwifiex_ds_encrypt_key *enc_key) | ||
607 | { | ||
608 | struct mwifiex_adapter *adapter = priv->adapter; | ||
609 | u8 *mac = enc_key->mac_addr; | ||
610 | u16 key_info, len = KEY_PARAMS_FIXED_LEN; | ||
611 | struct host_cmd_ds_802_11_key_material_v2 *km = | ||
612 | &cmd->params.key_material_v2; | ||
613 | |||
614 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); | ||
615 | km->action = cpu_to_le16(cmd_action); | ||
616 | |||
617 | if (cmd_action == HostCmd_ACT_GEN_GET) { | ||
618 | dev_dbg(adapter->dev, "%s: Get key\n", __func__); | ||
619 | km->key_param_set.key_idx = | ||
620 | enc_key->key_index & KEY_INDEX_MASK; | ||
621 | km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); | ||
622 | km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); | ||
623 | memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); | ||
624 | |||
625 | if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) | ||
626 | key_info = KEY_UNICAST; | ||
627 | else | ||
628 | key_info = KEY_MCAST; | ||
629 | |||
630 | if (enc_key->is_igtk_key) | ||
631 | key_info |= KEY_IGTK; | ||
632 | |||
633 | km->key_param_set.key_info = cpu_to_le16(key_info); | ||
634 | |||
635 | cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + | ||
636 | S_DS_GEN + KEY_PARAMS_FIXED_LEN + | ||
637 | sizeof(km->action)); | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | memset(&km->key_param_set, 0, | ||
642 | sizeof(struct mwifiex_ie_type_key_param_set_v2)); | ||
643 | |||
644 | if (enc_key->key_disable) { | ||
645 | dev_dbg(adapter->dev, "%s: Remove key\n", __func__); | ||
646 | km->action = cpu_to_le16(HostCmd_ACT_GEN_REMOVE); | ||
647 | km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); | ||
648 | km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); | ||
649 | km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; | ||
650 | key_info = KEY_MCAST | KEY_UNICAST; | ||
651 | km->key_param_set.key_info = cpu_to_le16(key_info); | ||
652 | memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); | ||
653 | cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + | ||
654 | S_DS_GEN + KEY_PARAMS_FIXED_LEN + | ||
655 | sizeof(km->action)); | ||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | km->action = cpu_to_le16(HostCmd_ACT_GEN_SET); | ||
660 | km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; | ||
661 | km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); | ||
662 | key_info = KEY_ENABLED; | ||
663 | memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); | ||
664 | |||
665 | if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) { | ||
666 | dev_dbg(adapter->dev, "%s: Set WEP Key\n", __func__); | ||
667 | len += sizeof(struct mwifiex_wep_param); | ||
668 | km->key_param_set.len = cpu_to_le16(len); | ||
669 | km->key_param_set.key_type = KEY_TYPE_ID_WEP; | ||
670 | |||
671 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | ||
672 | key_info |= KEY_MCAST | KEY_UNICAST; | ||
673 | } else { | ||
674 | if (enc_key->is_current_wep_key) { | ||
675 | key_info |= KEY_MCAST | KEY_UNICAST; | ||
676 | if (km->key_param_set.key_idx == | ||
677 | (priv->wep_key_curr_index & KEY_INDEX_MASK)) | ||
678 | key_info |= KEY_DEFAULT; | ||
679 | } else { | ||
680 | if (mac) { | ||
681 | if (is_broadcast_ether_addr(mac)) | ||
682 | key_info |= KEY_MCAST; | ||
683 | else | ||
684 | key_info |= KEY_UNICAST | | ||
685 | KEY_DEFAULT; | ||
686 | } else { | ||
687 | key_info |= KEY_MCAST; | ||
688 | } | ||
689 | } | ||
690 | } | ||
691 | km->key_param_set.key_info = cpu_to_le16(key_info); | ||
692 | |||
693 | km->key_param_set.key_params.wep.key_len = | ||
694 | cpu_to_le16(enc_key->key_len); | ||
695 | memcpy(km->key_param_set.key_params.wep.key, | ||
696 | enc_key->key_material, enc_key->key_len); | ||
697 | |||
698 | cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + | ||
699 | len + sizeof(km->action) + S_DS_GEN); | ||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | if (is_broadcast_ether_addr(mac)) | ||
704 | key_info |= KEY_MCAST | KEY_RX_KEY; | ||
705 | else | ||
706 | key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY; | ||
707 | |||
708 | if (enc_key->is_wapi_key) { | ||
709 | dev_dbg(adapter->dev, "%s: Set WAPI Key\n", __func__); | ||
710 | km->key_param_set.key_type = KEY_TYPE_ID_WAPI; | ||
711 | memcpy(km->key_param_set.key_params.wapi.pn, enc_key->pn, | ||
712 | PN_LEN); | ||
713 | km->key_param_set.key_params.wapi.key_len = | ||
714 | cpu_to_le16(enc_key->key_len); | ||
715 | memcpy(km->key_param_set.key_params.wapi.key, | ||
716 | enc_key->key_material, enc_key->key_len); | ||
717 | if (is_broadcast_ether_addr(mac)) | ||
718 | priv->sec_info.wapi_key_on = true; | ||
719 | |||
720 | if (!priv->sec_info.wapi_key_on) | ||
721 | key_info |= KEY_DEFAULT; | ||
722 | km->key_param_set.key_info = cpu_to_le16(key_info); | ||
723 | |||
724 | len += sizeof(struct mwifiex_wapi_param); | ||
725 | km->key_param_set.len = cpu_to_le16(len); | ||
726 | cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + | ||
727 | len + sizeof(km->action) + S_DS_GEN); | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { | ||
732 | key_info |= KEY_DEFAULT; | ||
733 | /* Enable unicast bit for WPA-NONE/ADHOC_AES */ | ||
734 | if (!priv->sec_info.wpa2_enabled && | ||
735 | !is_broadcast_ether_addr(mac)) | ||
736 | key_info |= KEY_UNICAST; | ||
737 | } else { | ||
738 | /* Enable default key for WPA/WPA2 */ | ||
739 | if (!priv->wpa_is_gtk_set) | ||
740 | key_info |= KEY_DEFAULT; | ||
741 | } | ||
742 | |||
743 | km->key_param_set.key_info = cpu_to_le16(key_info); | ||
744 | |||
745 | if (enc_key->key_len == WLAN_KEY_LEN_CCMP) | ||
746 | return mwifiex_set_aes_key_v2(priv, cmd, enc_key, km); | ||
747 | |||
748 | if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { | ||
749 | dev_dbg(adapter->dev, "%s: Set TKIP Key\n", __func__); | ||
750 | if (enc_key->is_rx_seq_valid) | ||
751 | memcpy(km->key_param_set.key_params.tkip.pn, | ||
752 | enc_key->pn, enc_key->pn_len); | ||
753 | km->key_param_set.key_type = KEY_TYPE_ID_TKIP; | ||
754 | km->key_param_set.key_params.tkip.key_len = | ||
755 | cpu_to_le16(enc_key->key_len); | ||
756 | memcpy(km->key_param_set.key_params.tkip.key, | ||
757 | enc_key->key_material, enc_key->key_len); | ||
758 | |||
759 | len += sizeof(struct mwifiex_tkip_param); | ||
760 | km->key_param_set.len = cpu_to_le16(len); | ||
761 | cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + | ||
762 | len + sizeof(km->action) + S_DS_GEN); | ||
763 | } | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
535 | /* | 768 | /* |
536 | * This function prepares command to set/get/reset network key(s). | 769 | * This function prepares command to set/get/reset network key(s). |
770 | * This function prepares key material command for V1 format. | ||
537 | * | 771 | * |
538 | * Preparation includes - | 772 | * Preparation includes - |
539 | * - Setting command ID, action and proper size | 773 | * - Setting command ID, action and proper size |
@@ -542,10 +776,10 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, | |||
542 | * - Ensuring correct endian-ness | 776 | * - Ensuring correct endian-ness |
543 | */ | 777 | */ |
544 | static int | 778 | static int |
545 | mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, | 779 | mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv, |
546 | struct host_cmd_ds_command *cmd, | 780 | struct host_cmd_ds_command *cmd, |
547 | u16 cmd_action, u32 cmd_oid, | 781 | u16 cmd_action, u32 cmd_oid, |
548 | struct mwifiex_ds_encrypt_key *enc_key) | 782 | struct mwifiex_ds_encrypt_key *enc_key) |
549 | { | 783 | { |
550 | struct host_cmd_ds_802_11_key_material *key_material = | 784 | struct host_cmd_ds_802_11_key_material *key_material = |
551 | &cmd->params.key_material; | 785 | &cmd->params.key_material; |
@@ -724,6 +958,24 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, | |||
724 | return ret; | 958 | return ret; |
725 | } | 959 | } |
726 | 960 | ||
961 | /* Wrapper function for setting network key depending upon FW KEY API version */ | ||
962 | static int | ||
963 | mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, | ||
964 | struct host_cmd_ds_command *cmd, | ||
965 | u16 cmd_action, u32 cmd_oid, | ||
966 | struct mwifiex_ds_encrypt_key *enc_key) | ||
967 | { | ||
968 | if (priv->adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2) | ||
969 | return mwifiex_cmd_802_11_key_material_v2(priv, cmd, | ||
970 | cmd_action, cmd_oid, | ||
971 | enc_key); | ||
972 | |||
973 | else | ||
974 | return mwifiex_cmd_802_11_key_material_v1(priv, cmd, | ||
975 | cmd_action, cmd_oid, | ||
976 | enc_key); | ||
977 | } | ||
978 | |||
727 | /* | 979 | /* |
728 | * This function prepares command to set/get 11d domain information. | 980 | * This function prepares command to set/get 11d domain information. |
729 | * | 981 | * |
@@ -1173,9 +1425,9 @@ int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, | |||
1173 | /* property header is 6 bytes, data must fit in cmd buffer */ | 1425 | /* property header is 6 bytes, data must fit in cmd buffer */ |
1174 | if (prop && prop->value && prop->length > 6 && | 1426 | if (prop && prop->value && prop->length > 6 && |
1175 | prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) { | 1427 | prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) { |
1176 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, | 1428 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA, |
1177 | HostCmd_ACT_GEN_SET, 0, | 1429 | HostCmd_ACT_GEN_SET, 0, |
1178 | prop); | 1430 | prop, true); |
1179 | if (ret) | 1431 | if (ret) |
1180 | return ret; | 1432 | return ret; |
1181 | } | 1433 | } |
@@ -1280,6 +1532,127 @@ mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv, | |||
1280 | return 0; | 1532 | return 0; |
1281 | } | 1533 | } |
1282 | 1534 | ||
1535 | static int | ||
1536 | mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | ||
1537 | struct host_cmd_ds_command *cmd, | ||
1538 | void *data_buf) | ||
1539 | { | ||
1540 | struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper; | ||
1541 | struct mwifiex_ds_tdls_oper *oper = data_buf; | ||
1542 | struct mwifiex_sta_node *sta_ptr; | ||
1543 | struct host_cmd_tlv_rates *tlv_rates; | ||
1544 | struct mwifiex_ie_types_htcap *ht_capab; | ||
1545 | struct mwifiex_ie_types_qos_info *wmm_qos_info; | ||
1546 | struct mwifiex_ie_types_extcap *extcap; | ||
1547 | struct mwifiex_ie_types_vhtcap *vht_capab; | ||
1548 | struct mwifiex_ie_types_aid *aid; | ||
1549 | u8 *pos, qos_info; | ||
1550 | u16 config_len = 0; | ||
1551 | struct station_parameters *params = priv->sta_params; | ||
1552 | |||
1553 | cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER); | ||
1554 | cmd->size = cpu_to_le16(S_DS_GEN); | ||
1555 | le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_tdls_oper)); | ||
1556 | |||
1557 | tdls_oper->reason = 0; | ||
1558 | memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN); | ||
1559 | sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac); | ||
1560 | |||
1561 | pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper); | ||
1562 | |||
1563 | switch (oper->tdls_action) { | ||
1564 | case MWIFIEX_TDLS_DISABLE_LINK: | ||
1565 | tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE); | ||
1566 | break; | ||
1567 | case MWIFIEX_TDLS_CREATE_LINK: | ||
1568 | tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE); | ||
1569 | break; | ||
1570 | case MWIFIEX_TDLS_CONFIG_LINK: | ||
1571 | tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG); | ||
1572 | |||
1573 | if (!params) { | ||
1574 | dev_err(priv->adapter->dev, | ||
1575 | "TDLS config params not available for %pM\n", | ||
1576 | oper->peer_mac); | ||
1577 | return -ENODATA; | ||
1578 | } | ||
1579 | |||
1580 | *(__le16 *)pos = cpu_to_le16(params->capability); | ||
1581 | config_len += sizeof(params->capability); | ||
1582 | |||
1583 | qos_info = params->uapsd_queues | (params->max_sp << 5); | ||
1584 | wmm_qos_info = (struct mwifiex_ie_types_qos_info *)(pos + | ||
1585 | config_len); | ||
1586 | wmm_qos_info->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA); | ||
1587 | wmm_qos_info->header.len = cpu_to_le16(sizeof(qos_info)); | ||
1588 | wmm_qos_info->qos_info = qos_info; | ||
1589 | config_len += sizeof(struct mwifiex_ie_types_qos_info); | ||
1590 | |||
1591 | if (params->ht_capa) { | ||
1592 | ht_capab = (struct mwifiex_ie_types_htcap *)(pos + | ||
1593 | config_len); | ||
1594 | ht_capab->header.type = | ||
1595 | cpu_to_le16(WLAN_EID_HT_CAPABILITY); | ||
1596 | ht_capab->header.len = | ||
1597 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); | ||
1598 | memcpy(&ht_capab->ht_cap, params->ht_capa, | ||
1599 | sizeof(struct ieee80211_ht_cap)); | ||
1600 | config_len += sizeof(struct mwifiex_ie_types_htcap); | ||
1601 | } | ||
1602 | |||
1603 | if (params->supported_rates && params->supported_rates_len) { | ||
1604 | tlv_rates = (struct host_cmd_tlv_rates *)(pos + | ||
1605 | config_len); | ||
1606 | tlv_rates->header.type = | ||
1607 | cpu_to_le16(WLAN_EID_SUPP_RATES); | ||
1608 | tlv_rates->header.len = | ||
1609 | cpu_to_le16(params->supported_rates_len); | ||
1610 | memcpy(tlv_rates->rates, params->supported_rates, | ||
1611 | params->supported_rates_len); | ||
1612 | config_len += sizeof(struct host_cmd_tlv_rates) + | ||
1613 | params->supported_rates_len; | ||
1614 | } | ||
1615 | |||
1616 | if (params->ext_capab && params->ext_capab_len) { | ||
1617 | extcap = (struct mwifiex_ie_types_extcap *)(pos + | ||
1618 | config_len); | ||
1619 | extcap->header.type = | ||
1620 | cpu_to_le16(WLAN_EID_EXT_CAPABILITY); | ||
1621 | extcap->header.len = cpu_to_le16(params->ext_capab_len); | ||
1622 | memcpy(extcap->ext_capab, params->ext_capab, | ||
1623 | params->ext_capab_len); | ||
1624 | config_len += sizeof(struct mwifiex_ie_types_extcap) + | ||
1625 | params->ext_capab_len; | ||
1626 | } | ||
1627 | if (params->vht_capa) { | ||
1628 | vht_capab = (struct mwifiex_ie_types_vhtcap *)(pos + | ||
1629 | config_len); | ||
1630 | vht_capab->header.type = | ||
1631 | cpu_to_le16(WLAN_EID_VHT_CAPABILITY); | ||
1632 | vht_capab->header.len = | ||
1633 | cpu_to_le16(sizeof(struct ieee80211_vht_cap)); | ||
1634 | memcpy(&vht_capab->vht_cap, params->vht_capa, | ||
1635 | sizeof(struct ieee80211_vht_cap)); | ||
1636 | config_len += sizeof(struct mwifiex_ie_types_vhtcap); | ||
1637 | } | ||
1638 | if (params->aid) { | ||
1639 | aid = (struct mwifiex_ie_types_aid *)(pos + config_len); | ||
1640 | aid->header.type = cpu_to_le16(WLAN_EID_AID); | ||
1641 | aid->header.len = cpu_to_le16(sizeof(params->aid)); | ||
1642 | aid->aid = cpu_to_le16(params->aid); | ||
1643 | config_len += sizeof(struct mwifiex_ie_types_aid); | ||
1644 | } | ||
1645 | |||
1646 | break; | ||
1647 | default: | ||
1648 | dev_err(priv->adapter->dev, "Unknown TDLS operation\n"); | ||
1649 | return -ENOTSUPP; | ||
1650 | } | ||
1651 | |||
1652 | le16_add_cpu(&cmd->size, config_len); | ||
1653 | |||
1654 | return 0; | ||
1655 | } | ||
1283 | /* | 1656 | /* |
1284 | * This function prepares the commands before sending them to the firmware. | 1657 | * This function prepares the commands before sending them to the firmware. |
1285 | * | 1658 | * |
@@ -1472,6 +1845,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1472 | ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, | 1845 | ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, |
1473 | data_buf); | 1846 | data_buf); |
1474 | break; | 1847 | break; |
1848 | case HostCmd_CMD_802_11_SCAN_EXT: | ||
1849 | ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf); | ||
1850 | break; | ||
1475 | case HostCmd_CMD_MAC_REG_ACCESS: | 1851 | case HostCmd_CMD_MAC_REG_ACCESS: |
1476 | case HostCmd_CMD_BBP_REG_ACCESS: | 1852 | case HostCmd_CMD_BBP_REG_ACCESS: |
1477 | case HostCmd_CMD_RF_REG_ACCESS: | 1853 | case HostCmd_CMD_RF_REG_ACCESS: |
@@ -1507,6 +1883,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1507 | ret = mwifiex_cmd_coalesce_cfg(priv, cmd_ptr, cmd_action, | 1883 | ret = mwifiex_cmd_coalesce_cfg(priv, cmd_ptr, cmd_action, |
1508 | data_buf); | 1884 | data_buf); |
1509 | break; | 1885 | break; |
1886 | case HostCmd_CMD_TDLS_OPER: | ||
1887 | ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); | ||
1888 | break; | ||
1510 | default: | 1889 | default: |
1511 | dev_err(priv->adapter->dev, | 1890 | dev_err(priv->adapter->dev, |
1512 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1891 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
@@ -1547,15 +1926,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1547 | 1926 | ||
1548 | if (first_sta) { | 1927 | if (first_sta) { |
1549 | if (priv->adapter->iface_type == MWIFIEX_PCIE) { | 1928 | if (priv->adapter->iface_type == MWIFIEX_PCIE) { |
1550 | ret = mwifiex_send_cmd_sync(priv, | 1929 | ret = mwifiex_send_cmd(priv, |
1551 | HostCmd_CMD_PCIE_DESC_DETAILS, | 1930 | HostCmd_CMD_PCIE_DESC_DETAILS, |
1552 | HostCmd_ACT_GEN_SET, 0, NULL); | 1931 | HostCmd_ACT_GEN_SET, 0, NULL, |
1932 | true); | ||
1553 | if (ret) | 1933 | if (ret) |
1554 | return -1; | 1934 | return -1; |
1555 | } | 1935 | } |
1556 | 1936 | ||
1557 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_FUNC_INIT, | 1937 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_FUNC_INIT, |
1558 | HostCmd_ACT_GEN_SET, 0, NULL); | 1938 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
1559 | if (ret) | 1939 | if (ret) |
1560 | return -1; | 1940 | return -1; |
1561 | 1941 | ||
@@ -1573,55 +1953,57 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1573 | } | 1953 | } |
1574 | 1954 | ||
1575 | if (adapter->cal_data) { | 1955 | if (adapter->cal_data) { |
1576 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, | 1956 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA, |
1577 | HostCmd_ACT_GEN_SET, 0, NULL); | 1957 | HostCmd_ACT_GEN_SET, 0, NULL, |
1958 | true); | ||
1578 | if (ret) | 1959 | if (ret) |
1579 | return -1; | 1960 | return -1; |
1580 | } | 1961 | } |
1581 | 1962 | ||
1582 | /* Read MAC address from HW */ | 1963 | /* Read MAC address from HW */ |
1583 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_GET_HW_SPEC, | 1964 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC, |
1584 | HostCmd_ACT_GEN_GET, 0, NULL); | 1965 | HostCmd_ACT_GEN_GET, 0, NULL, true); |
1585 | if (ret) | 1966 | if (ret) |
1586 | return -1; | 1967 | return -1; |
1587 | 1968 | ||
1588 | /* Reconfigure tx buf size */ | 1969 | /* Reconfigure tx buf size */ |
1589 | ret = mwifiex_send_cmd_sync(priv, | 1970 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, |
1590 | HostCmd_CMD_RECONFIGURE_TX_BUFF, | 1971 | HostCmd_ACT_GEN_SET, 0, |
1591 | HostCmd_ACT_GEN_SET, 0, | 1972 | &priv->adapter->tx_buf_size, true); |
1592 | &priv->adapter->tx_buf_size); | ||
1593 | if (ret) | 1973 | if (ret) |
1594 | return -1; | 1974 | return -1; |
1595 | 1975 | ||
1596 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { | 1976 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { |
1597 | /* Enable IEEE PS by default */ | 1977 | /* Enable IEEE PS by default */ |
1598 | priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; | 1978 | priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; |
1599 | ret = mwifiex_send_cmd_sync( | 1979 | ret = mwifiex_send_cmd(priv, |
1600 | priv, HostCmd_CMD_802_11_PS_MODE_ENH, | 1980 | HostCmd_CMD_802_11_PS_MODE_ENH, |
1601 | EN_AUTO_PS, BITMAP_STA_PS, NULL); | 1981 | EN_AUTO_PS, BITMAP_STA_PS, NULL, |
1982 | true); | ||
1602 | if (ret) | 1983 | if (ret) |
1603 | return -1; | 1984 | return -1; |
1604 | } | 1985 | } |
1605 | } | 1986 | } |
1606 | 1987 | ||
1607 | /* get tx rate */ | 1988 | /* get tx rate */ |
1608 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, | 1989 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, |
1609 | HostCmd_ACT_GEN_GET, 0, NULL); | 1990 | HostCmd_ACT_GEN_GET, 0, NULL, true); |
1610 | if (ret) | 1991 | if (ret) |
1611 | return -1; | 1992 | return -1; |
1612 | priv->data_rate = 0; | 1993 | priv->data_rate = 0; |
1613 | 1994 | ||
1614 | /* get tx power */ | 1995 | /* get tx power */ |
1615 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_TX_PWR, | 1996 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_RF_TX_PWR, |
1616 | HostCmd_ACT_GEN_GET, 0, NULL); | 1997 | HostCmd_ACT_GEN_GET, 0, NULL, true); |
1617 | if (ret) | 1998 | if (ret) |
1618 | return -1; | 1999 | return -1; |
1619 | 2000 | ||
1620 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { | 2001 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { |
1621 | /* set ibss coalescing_status */ | 2002 | /* set ibss coalescing_status */ |
1622 | ret = mwifiex_send_cmd_sync( | 2003 | ret = mwifiex_send_cmd( |
1623 | priv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, | 2004 | priv, |
1624 | HostCmd_ACT_GEN_SET, 0, &enable); | 2005 | HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, |
2006 | HostCmd_ACT_GEN_SET, 0, &enable, true); | ||
1625 | if (ret) | 2007 | if (ret) |
1626 | return -1; | 2008 | return -1; |
1627 | } | 2009 | } |
@@ -1629,16 +2011,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1629 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); | 2011 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); |
1630 | amsdu_aggr_ctrl.enable = true; | 2012 | amsdu_aggr_ctrl.enable = true; |
1631 | /* Send request to firmware */ | 2013 | /* Send request to firmware */ |
1632 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, | 2014 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, |
1633 | HostCmd_ACT_GEN_SET, 0, | 2015 | HostCmd_ACT_GEN_SET, 0, |
1634 | &amsdu_aggr_ctrl); | 2016 | &amsdu_aggr_ctrl, true); |
1635 | if (ret) | 2017 | if (ret) |
1636 | return -1; | 2018 | return -1; |
1637 | /* MAC Control must be the last command in init_fw */ | 2019 | /* MAC Control must be the last command in init_fw */ |
1638 | /* set MAC Control */ | 2020 | /* set MAC Control */ |
1639 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, | 2021 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
1640 | HostCmd_ACT_GEN_SET, 0, | 2022 | HostCmd_ACT_GEN_SET, 0, |
1641 | &priv->curr_pkt_filter); | 2023 | &priv->curr_pkt_filter, true); |
1642 | if (ret) | 2024 | if (ret) |
1643 | return -1; | 2025 | return -1; |
1644 | 2026 | ||
@@ -1647,10 +2029,9 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1647 | /* Enable auto deep sleep */ | 2029 | /* Enable auto deep sleep */ |
1648 | auto_ds.auto_ds = DEEP_SLEEP_ON; | 2030 | auto_ds.auto_ds = DEEP_SLEEP_ON; |
1649 | auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; | 2031 | auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; |
1650 | ret = mwifiex_send_cmd_sync(priv, | 2032 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
1651 | HostCmd_CMD_802_11_PS_MODE_ENH, | 2033 | EN_AUTO_PS, BITMAP_AUTO_DS, |
1652 | EN_AUTO_PS, BITMAP_AUTO_DS, | 2034 | &auto_ds, true); |
1653 | &auto_ds); | ||
1654 | if (ret) | 2035 | if (ret) |
1655 | return -1; | 2036 | return -1; |
1656 | } | 2037 | } |
@@ -1658,9 +2039,9 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1658 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { | 2039 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { |
1659 | /* Send cmd to FW to enable/disable 11D function */ | 2040 | /* Send cmd to FW to enable/disable 11D function */ |
1660 | state_11d = ENABLE_11D; | 2041 | state_11d = ENABLE_11D; |
1661 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | 2042 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, |
1662 | HostCmd_ACT_GEN_SET, DOT11D_I, | 2043 | HostCmd_ACT_GEN_SET, DOT11D_I, |
1663 | &state_11d); | 2044 | &state_11d, true); |
1664 | if (ret) | 2045 | if (ret) |
1665 | dev_err(priv->adapter->dev, | 2046 | dev_err(priv->adapter->dev, |
1666 | "11D: failed to enable 11D\n"); | 2047 | "11D: failed to enable 11D\n"); |
@@ -1673,8 +2054,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1673 | * (Short GI, Channel BW, Green field support etc.) for transmit | 2054 | * (Short GI, Channel BW, Green field support etc.) for transmit |
1674 | */ | 2055 | */ |
1675 | tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG; | 2056 | tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG; |
1676 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_11N_CFG, | 2057 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG, |
1677 | HostCmd_ACT_GEN_SET, 0, &tx_cfg); | 2058 | HostCmd_ACT_GEN_SET, 0, &tx_cfg, true); |
1678 | 2059 | ||
1679 | ret = -EINPROGRESS; | 2060 | ret = -EINPROGRESS; |
1680 | 2061 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 24523e4015cb..bfebb0144df5 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -69,6 +69,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | |||
69 | 69 | ||
70 | break; | 70 | break; |
71 | case HostCmd_CMD_802_11_SCAN: | 71 | case HostCmd_CMD_802_11_SCAN: |
72 | case HostCmd_CMD_802_11_SCAN_EXT: | ||
72 | /* Cancel all pending scan command */ | 73 | /* Cancel all pending scan command */ |
73 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | 74 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); |
74 | list_for_each_entry_safe(cmd_node, tmp_node, | 75 | list_for_each_entry_safe(cmd_node, tmp_node, |
@@ -157,8 +158,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, | |||
157 | 158 | ||
158 | priv->subsc_evt_rssi_state = EVENT_HANDLED; | 159 | priv->subsc_evt_rssi_state = EVENT_HANDLED; |
159 | 160 | ||
160 | mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, | 161 | mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, |
161 | 0, 0, subsc_evt); | 162 | 0, 0, subsc_evt, false); |
162 | 163 | ||
163 | return 0; | 164 | return 0; |
164 | } | 165 | } |
@@ -303,6 +304,15 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, | |||
303 | priv->bitmap_rates[2 + i] = | 304 | priv->bitmap_rates[2 + i] = |
304 | le16_to_cpu(rate_scope-> | 305 | le16_to_cpu(rate_scope-> |
305 | ht_mcs_rate_bitmap[i]); | 306 | ht_mcs_rate_bitmap[i]); |
307 | |||
308 | if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { | ||
309 | for (i = 0; i < ARRAY_SIZE(rate_scope-> | ||
310 | vht_mcs_rate_bitmap); | ||
311 | i++) | ||
312 | priv->bitmap_rates[10 + i] = | ||
313 | le16_to_cpu(rate_scope-> | ||
314 | vht_mcs_rate_bitmap[i]); | ||
315 | } | ||
306 | break; | 316 | break; |
307 | /* Add RATE_DROP tlv here */ | 317 | /* Add RATE_DROP tlv here */ |
308 | } | 318 | } |
@@ -316,9 +326,8 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, | |||
316 | if (priv->is_data_rate_auto) | 326 | if (priv->is_data_rate_auto) |
317 | priv->data_rate = 0; | 327 | priv->data_rate = 0; |
318 | else | 328 | else |
319 | return mwifiex_send_cmd_async(priv, | 329 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, |
320 | HostCmd_CMD_802_11_TX_RATE_QUERY, | 330 | HostCmd_ACT_GEN_GET, 0, NULL, false); |
321 | HostCmd_ACT_GEN_GET, 0, NULL); | ||
322 | 331 | ||
323 | return 0; | 332 | return 0; |
324 | } | 333 | } |
@@ -561,13 +570,13 @@ static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv, | |||
561 | } | 570 | } |
562 | 571 | ||
563 | /* | 572 | /* |
564 | * This function handles the command response of set/get key material. | 573 | * This function handles the command response of set/get v1 key material. |
565 | * | 574 | * |
566 | * Handling includes updating the driver parameters to reflect the | 575 | * Handling includes updating the driver parameters to reflect the |
567 | * changes. | 576 | * changes. |
568 | */ | 577 | */ |
569 | static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, | 578 | static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv, |
570 | struct host_cmd_ds_command *resp) | 579 | struct host_cmd_ds_command *resp) |
571 | { | 580 | { |
572 | struct host_cmd_ds_802_11_key_material *key = | 581 | struct host_cmd_ds_802_11_key_material *key = |
573 | &resp->params.key_material; | 582 | &resp->params.key_material; |
@@ -590,6 +599,51 @@ static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, | |||
590 | } | 599 | } |
591 | 600 | ||
592 | /* | 601 | /* |
602 | * This function handles the command response of set/get v2 key material. | ||
603 | * | ||
604 | * Handling includes updating the driver parameters to reflect the | ||
605 | * changes. | ||
606 | */ | ||
607 | static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv, | ||
608 | struct host_cmd_ds_command *resp) | ||
609 | { | ||
610 | struct host_cmd_ds_802_11_key_material_v2 *key_v2; | ||
611 | __le16 len; | ||
612 | |||
613 | key_v2 = &resp->params.key_material_v2; | ||
614 | if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) { | ||
615 | if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) { | ||
616 | dev_dbg(priv->adapter->dev, "info: key: GTK is set\n"); | ||
617 | priv->wpa_is_gtk_set = true; | ||
618 | priv->scan_block = false; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES) | ||
623 | return 0; | ||
624 | |||
625 | memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0, | ||
626 | WLAN_KEY_LEN_CCMP); | ||
627 | priv->aes_key_v2.key_param_set.key_params.aes.key_len = | ||
628 | key_v2->key_param_set.key_params.aes.key_len; | ||
629 | len = priv->aes_key_v2.key_param_set.key_params.aes.key_len; | ||
630 | memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key, | ||
631 | key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len)); | ||
632 | |||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | /* Wrapper function for processing response of key material command */ | ||
637 | static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, | ||
638 | struct host_cmd_ds_command *resp) | ||
639 | { | ||
640 | if (priv->adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2) | ||
641 | return mwifiex_ret_802_11_key_material_v2(priv, resp); | ||
642 | else | ||
643 | return mwifiex_ret_802_11_key_material_v1(priv, resp); | ||
644 | } | ||
645 | |||
646 | /* | ||
593 | * This function handles the command response of get 11d domain information. | 647 | * This function handles the command response of get 11d domain information. |
594 | */ | 648 | */ |
595 | static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, | 649 | static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, |
@@ -800,7 +854,60 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, | |||
800 | 854 | ||
801 | return 0; | 855 | return 0; |
802 | } | 856 | } |
857 | static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv, | ||
858 | struct host_cmd_ds_command *resp) | ||
859 | { | ||
860 | struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper; | ||
861 | u16 reason = le16_to_cpu(cmd_tdls_oper->reason); | ||
862 | u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action); | ||
863 | struct mwifiex_sta_node *node = | ||
864 | mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac); | ||
803 | 865 | ||
866 | switch (action) { | ||
867 | case ACT_TDLS_DELETE: | ||
868 | if (reason) | ||
869 | dev_err(priv->adapter->dev, | ||
870 | "TDLS link delete for %pM failed: reason %d\n", | ||
871 | cmd_tdls_oper->peer_mac, reason); | ||
872 | else | ||
873 | dev_dbg(priv->adapter->dev, | ||
874 | "TDLS link config for %pM successful\n", | ||
875 | cmd_tdls_oper->peer_mac); | ||
876 | break; | ||
877 | case ACT_TDLS_CREATE: | ||
878 | if (reason) { | ||
879 | dev_err(priv->adapter->dev, | ||
880 | "TDLS link creation for %pM failed: reason %d", | ||
881 | cmd_tdls_oper->peer_mac, reason); | ||
882 | if (node && reason != TDLS_ERR_LINK_EXISTS) | ||
883 | node->tdls_status = TDLS_SETUP_FAILURE; | ||
884 | } else { | ||
885 | dev_dbg(priv->adapter->dev, | ||
886 | "TDLS link creation for %pM successful", | ||
887 | cmd_tdls_oper->peer_mac); | ||
888 | } | ||
889 | break; | ||
890 | case ACT_TDLS_CONFIG: | ||
891 | if (reason) { | ||
892 | dev_err(priv->adapter->dev, | ||
893 | "TDLS link config for %pM failed, reason %d\n", | ||
894 | cmd_tdls_oper->peer_mac, reason); | ||
895 | if (node) | ||
896 | node->tdls_status = TDLS_SETUP_FAILURE; | ||
897 | } else { | ||
898 | dev_dbg(priv->adapter->dev, | ||
899 | "TDLS link config for %pM successful\n", | ||
900 | cmd_tdls_oper->peer_mac); | ||
901 | } | ||
902 | break; | ||
903 | default: | ||
904 | dev_err(priv->adapter->dev, | ||
905 | "Unknown TDLS command action respnse %d", action); | ||
906 | return -1; | ||
907 | } | ||
908 | |||
909 | return 0; | ||
910 | } | ||
804 | /* | 911 | /* |
805 | * This function handles the command response for subscribe event command. | 912 | * This function handles the command response for subscribe event command. |
806 | */ | 913 | */ |
@@ -871,6 +978,10 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
871 | ret = mwifiex_ret_802_11_scan(priv, resp); | 978 | ret = mwifiex_ret_802_11_scan(priv, resp); |
872 | adapter->curr_cmd->wait_q_enabled = false; | 979 | adapter->curr_cmd->wait_q_enabled = false; |
873 | break; | 980 | break; |
981 | case HostCmd_CMD_802_11_SCAN_EXT: | ||
982 | ret = mwifiex_ret_802_11_scan_ext(priv); | ||
983 | adapter->curr_cmd->wait_q_enabled = false; | ||
984 | break; | ||
874 | case HostCmd_CMD_802_11_BG_SCAN_QUERY: | 985 | case HostCmd_CMD_802_11_BG_SCAN_QUERY: |
875 | ret = mwifiex_ret_802_11_scan(priv, resp); | 986 | ret = mwifiex_ret_802_11_scan(priv, resp); |
876 | dev_dbg(adapter->dev, | 987 | dev_dbg(adapter->dev, |
@@ -999,6 +1110,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
999 | break; | 1110 | break; |
1000 | case HostCmd_CMD_COALESCE_CFG: | 1111 | case HostCmd_CMD_COALESCE_CFG: |
1001 | break; | 1112 | break; |
1113 | case HostCmd_CMD_TDLS_OPER: | ||
1114 | ret = mwifiex_ret_tdls_oper(priv, resp); | ||
1115 | break; | ||
1002 | default: | 1116 | default: |
1003 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 1117 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
1004 | resp->command); | 1118 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 8c351f71f72f..368450cc56c7 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -54,6 +54,10 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) | |||
54 | 54 | ||
55 | priv->scan_block = false; | 55 | priv->scan_block = false; |
56 | 56 | ||
57 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && | ||
58 | ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) | ||
59 | mwifiex_disable_all_tdls_links(priv); | ||
60 | |||
57 | /* Free Tx and Rx packets, report disconnect to upper layer */ | 61 | /* Free Tx and Rx packets, report disconnect to upper layer */ |
58 | mwifiex_clean_txrx(priv); | 62 | mwifiex_clean_txrx(priv); |
59 | 63 | ||
@@ -112,7 +116,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) | |||
112 | adapter->tx_lock_flag = false; | 116 | adapter->tx_lock_flag = false; |
113 | adapter->pps_uapsd_mode = false; | 117 | adapter->pps_uapsd_mode = false; |
114 | 118 | ||
115 | if (adapter->num_cmd_timeout && adapter->curr_cmd) | 119 | if (adapter->is_cmd_timedout && adapter->curr_cmd) |
116 | return; | 120 | return; |
117 | priv->media_connected = false; | 121 | priv->media_connected = false; |
118 | dev_dbg(adapter->dev, | 122 | dev_dbg(adapter->dev, |
@@ -289,9 +293,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
289 | 293 | ||
290 | case EVENT_HS_ACT_REQ: | 294 | case EVENT_HS_ACT_REQ: |
291 | dev_dbg(adapter->dev, "event: HS_ACT_REQ\n"); | 295 | dev_dbg(adapter->dev, "event: HS_ACT_REQ\n"); |
292 | ret = mwifiex_send_cmd_async(priv, | 296 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, |
293 | HostCmd_CMD_802_11_HS_CFG_ENH, | 297 | 0, 0, NULL, false); |
294 | 0, 0, NULL); | ||
295 | break; | 298 | break; |
296 | 299 | ||
297 | case EVENT_MIC_ERR_UNICAST: | 300 | case EVENT_MIC_ERR_UNICAST: |
@@ -322,27 +325,34 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
322 | 325 | ||
323 | case EVENT_BG_SCAN_REPORT: | 326 | case EVENT_BG_SCAN_REPORT: |
324 | dev_dbg(adapter->dev, "event: BGS_REPORT\n"); | 327 | dev_dbg(adapter->dev, "event: BGS_REPORT\n"); |
325 | ret = mwifiex_send_cmd_async(priv, | 328 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY, |
326 | HostCmd_CMD_802_11_BG_SCAN_QUERY, | 329 | HostCmd_ACT_GEN_GET, 0, NULL, false); |
327 | HostCmd_ACT_GEN_GET, 0, NULL); | ||
328 | break; | 330 | break; |
329 | 331 | ||
330 | case EVENT_PORT_RELEASE: | 332 | case EVENT_PORT_RELEASE: |
331 | dev_dbg(adapter->dev, "event: PORT RELEASE\n"); | 333 | dev_dbg(adapter->dev, "event: PORT RELEASE\n"); |
332 | break; | 334 | break; |
333 | 335 | ||
336 | case EVENT_EXT_SCAN_REPORT: | ||
337 | dev_dbg(adapter->dev, "event: EXT_SCAN Report\n"); | ||
338 | if (adapter->ext_scan) | ||
339 | ret = mwifiex_handle_event_ext_scan_report(priv, | ||
340 | adapter->event_skb->data); | ||
341 | |||
342 | break; | ||
343 | |||
334 | case EVENT_WMM_STATUS_CHANGE: | 344 | case EVENT_WMM_STATUS_CHANGE: |
335 | dev_dbg(adapter->dev, "event: WMM status changed\n"); | 345 | dev_dbg(adapter->dev, "event: WMM status changed\n"); |
336 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS, | 346 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, |
337 | 0, 0, NULL); | 347 | 0, 0, NULL, false); |
338 | break; | 348 | break; |
339 | 349 | ||
340 | case EVENT_RSSI_LOW: | 350 | case EVENT_RSSI_LOW: |
341 | cfg80211_cqm_rssi_notify(priv->netdev, | 351 | cfg80211_cqm_rssi_notify(priv->netdev, |
342 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | 352 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, |
343 | GFP_KERNEL); | 353 | GFP_KERNEL); |
344 | mwifiex_send_cmd_async(priv, HostCmd_CMD_RSSI_INFO, | 354 | mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, |
345 | HostCmd_ACT_GEN_GET, 0, NULL); | 355 | HostCmd_ACT_GEN_GET, 0, NULL, false); |
346 | priv->subsc_evt_rssi_state = RSSI_LOW_RECVD; | 356 | priv->subsc_evt_rssi_state = RSSI_LOW_RECVD; |
347 | dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n"); | 357 | dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n"); |
348 | break; | 358 | break; |
@@ -356,8 +366,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
356 | cfg80211_cqm_rssi_notify(priv->netdev, | 366 | cfg80211_cqm_rssi_notify(priv->netdev, |
357 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | 367 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, |
358 | GFP_KERNEL); | 368 | GFP_KERNEL); |
359 | mwifiex_send_cmd_async(priv, HostCmd_CMD_RSSI_INFO, | 369 | mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, |
360 | HostCmd_ACT_GEN_GET, 0, NULL); | 370 | HostCmd_ACT_GEN_GET, 0, NULL, false); |
361 | priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD; | 371 | priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD; |
362 | dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n"); | 372 | dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n"); |
363 | break; | 373 | break; |
@@ -384,15 +394,15 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
384 | break; | 394 | break; |
385 | case EVENT_IBSS_COALESCED: | 395 | case EVENT_IBSS_COALESCED: |
386 | dev_dbg(adapter->dev, "event: IBSS_COALESCED\n"); | 396 | dev_dbg(adapter->dev, "event: IBSS_COALESCED\n"); |
387 | ret = mwifiex_send_cmd_async(priv, | 397 | ret = mwifiex_send_cmd(priv, |
388 | HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, | 398 | HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, |
389 | HostCmd_ACT_GEN_GET, 0, NULL); | 399 | HostCmd_ACT_GEN_GET, 0, NULL, false); |
390 | break; | 400 | break; |
391 | case EVENT_ADDBA: | 401 | case EVENT_ADDBA: |
392 | dev_dbg(adapter->dev, "event: ADDBA Request\n"); | 402 | dev_dbg(adapter->dev, "event: ADDBA Request\n"); |
393 | mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP, | 403 | mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, |
394 | HostCmd_ACT_GEN_SET, 0, | 404 | HostCmd_ACT_GEN_SET, 0, |
395 | adapter->event_body); | 405 | adapter->event_body, false); |
396 | break; | 406 | break; |
397 | case EVENT_DELBA: | 407 | case EVENT_DELBA: |
398 | dev_dbg(adapter->dev, "event: DELBA Request\n"); | 408 | dev_dbg(adapter->dev, "event: DELBA Request\n"); |
@@ -443,10 +453,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
443 | priv->csa_expire_time = | 453 | priv->csa_expire_time = |
444 | jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME); | 454 | jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME); |
445 | priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel; | 455 | priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel; |
446 | ret = mwifiex_send_cmd_async(priv, | 456 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, |
447 | HostCmd_CMD_802_11_DEAUTHENTICATE, | ||
448 | HostCmd_ACT_GEN_SET, 0, | 457 | HostCmd_ACT_GEN_SET, 0, |
449 | priv->curr_bss_params.bss_descriptor.mac_address); | 458 | priv->curr_bss_params.bss_descriptor.mac_address, |
459 | false); | ||
450 | break; | 460 | break; |
451 | 461 | ||
452 | default: | 462 | default: |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index c5cb2ed19ec2..894270611f2c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -64,6 +64,7 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, | |||
64 | *(cmd_queued->condition)); | 64 | *(cmd_queued->condition)); |
65 | if (status) { | 65 | if (status) { |
66 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); | 66 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); |
67 | mwifiex_cancel_all_pending_cmd(adapter); | ||
67 | return status; | 68 | return status; |
68 | } | 69 | } |
69 | 70 | ||
@@ -108,19 +109,19 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
108 | "info: Set multicast list=%d\n", | 109 | "info: Set multicast list=%d\n", |
109 | mcast_list->num_multicast_addr); | 110 | mcast_list->num_multicast_addr); |
110 | /* Send multicast addresses to firmware */ | 111 | /* Send multicast addresses to firmware */ |
111 | ret = mwifiex_send_cmd_async(priv, | 112 | ret = mwifiex_send_cmd(priv, |
112 | HostCmd_CMD_MAC_MULTICAST_ADR, | 113 | HostCmd_CMD_MAC_MULTICAST_ADR, |
113 | HostCmd_ACT_GEN_SET, 0, | 114 | HostCmd_ACT_GEN_SET, 0, |
114 | mcast_list); | 115 | mcast_list, false); |
115 | } | 116 | } |
116 | } | 117 | } |
117 | dev_dbg(priv->adapter->dev, | 118 | dev_dbg(priv->adapter->dev, |
118 | "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", | 119 | "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", |
119 | old_pkt_filter, priv->curr_pkt_filter); | 120 | old_pkt_filter, priv->curr_pkt_filter); |
120 | if (old_pkt_filter != priv->curr_pkt_filter) { | 121 | if (old_pkt_filter != priv->curr_pkt_filter) { |
121 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, | 122 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
122 | HostCmd_ACT_GEN_SET, | 123 | HostCmd_ACT_GEN_SET, |
123 | 0, &priv->curr_pkt_filter); | 124 | 0, &priv->curr_pkt_filter, false); |
124 | } | 125 | } |
125 | 126 | ||
126 | return ret; | 127 | return ret; |
@@ -237,8 +238,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
237 | 238 | ||
238 | rcu_read_unlock(); | 239 | rcu_read_unlock(); |
239 | 240 | ||
240 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, | 241 | if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, |
241 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 242 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { |
242 | wiphy_err(priv->adapter->wiphy, | 243 | wiphy_err(priv->adapter->wiphy, |
243 | "11D: setting domain info in FW\n"); | 244 | "11D: setting domain info in FW\n"); |
244 | return -1; | 245 | return -1; |
@@ -290,7 +291,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
290 | 291 | ||
291 | if (mwifiex_band_to_radio_type(bss_desc->bss_band) == | 292 | if (mwifiex_band_to_radio_type(bss_desc->bss_band) == |
292 | HostCmd_SCAN_RADIO_TYPE_BG) | 293 | HostCmd_SCAN_RADIO_TYPE_BG) |
293 | config_bands = BAND_B | BAND_G | BAND_GN | BAND_GAC; | 294 | config_bands = BAND_B | BAND_G | BAND_GN; |
294 | else | 295 | else |
295 | config_bands = BAND_A | BAND_AN | BAND_AAC; | 296 | config_bands = BAND_A | BAND_AN | BAND_AAC; |
296 | 297 | ||
@@ -429,16 +430,13 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
429 | status = -1; | 430 | status = -1; |
430 | break; | 431 | break; |
431 | } | 432 | } |
432 | if (cmd_type == MWIFIEX_SYNC_CMD) | 433 | |
433 | status = mwifiex_send_cmd_sync(priv, | 434 | status = mwifiex_send_cmd(priv, |
434 | HostCmd_CMD_802_11_HS_CFG_ENH, | 435 | HostCmd_CMD_802_11_HS_CFG_ENH, |
435 | HostCmd_ACT_GEN_SET, 0, | 436 | HostCmd_ACT_GEN_SET, 0, |
436 | &adapter->hs_cfg); | 437 | &adapter->hs_cfg, |
437 | else | 438 | cmd_type == MWIFIEX_SYNC_CMD); |
438 | status = mwifiex_send_cmd_async(priv, | 439 | |
439 | HostCmd_CMD_802_11_HS_CFG_ENH, | ||
440 | HostCmd_ACT_GEN_SET, 0, | ||
441 | &adapter->hs_cfg); | ||
442 | if (hs_cfg->conditions == HS_CFG_CANCEL) | 440 | if (hs_cfg->conditions == HS_CFG_CANCEL) |
443 | /* Restore previous condition */ | 441 | /* Restore previous condition */ |
444 | adapter->hs_cfg.conditions = | 442 | adapter->hs_cfg.conditions = |
@@ -511,6 +509,9 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) | |||
511 | memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); | 509 | memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); |
512 | hscfg.is_invoke_hostcmd = true; | 510 | hscfg.is_invoke_hostcmd = true; |
513 | 511 | ||
512 | adapter->hs_enabling = true; | ||
513 | mwifiex_cancel_all_pending_cmd(adapter); | ||
514 | |||
514 | if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, | 515 | if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, |
515 | MWIFIEX_BSS_ROLE_STA), | 516 | MWIFIEX_BSS_ROLE_STA), |
516 | HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, | 517 | HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, |
@@ -519,8 +520,9 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) | |||
519 | return false; | 520 | return false; |
520 | } | 521 | } |
521 | 522 | ||
522 | if (wait_event_interruptible(adapter->hs_activate_wait_q, | 523 | if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q, |
523 | adapter->hs_activate_wait_q_woken)) { | 524 | adapter->hs_activate_wait_q_woken, |
525 | (10 * HZ)) <= 0) { | ||
524 | dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); | 526 | dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); |
525 | return false; | 527 | return false; |
526 | } | 528 | } |
@@ -586,8 +588,8 @@ int mwifiex_disable_auto_ds(struct mwifiex_private *priv) | |||
586 | 588 | ||
587 | auto_ds.auto_ds = DEEP_SLEEP_OFF; | 589 | auto_ds.auto_ds = DEEP_SLEEP_OFF; |
588 | 590 | ||
589 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, | 591 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
590 | DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds); | 592 | DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, true); |
591 | } | 593 | } |
592 | EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds); | 594 | EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds); |
593 | 595 | ||
@@ -601,8 +603,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate) | |||
601 | { | 603 | { |
602 | int ret; | 604 | int ret; |
603 | 605 | ||
604 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, | 606 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, |
605 | HostCmd_ACT_GEN_GET, 0, NULL); | 607 | HostCmd_ACT_GEN_GET, 0, NULL, true); |
606 | 608 | ||
607 | if (!ret) { | 609 | if (!ret) { |
608 | if (priv->is_data_rate_auto) | 610 | if (priv->is_data_rate_auto) |
@@ -698,8 +700,8 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, | |||
698 | pg->power_max = (s8) dbm; | 700 | pg->power_max = (s8) dbm; |
699 | pg->ht_bandwidth = HT_BW_40; | 701 | pg->ht_bandwidth = HT_BW_40; |
700 | } | 702 | } |
701 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG, | 703 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_TXPWR_CFG, |
702 | HostCmd_ACT_GEN_SET, 0, buf); | 704 | HostCmd_ACT_GEN_SET, 0, buf, true); |
703 | 705 | ||
704 | kfree(buf); | 706 | kfree(buf); |
705 | return ret; | 707 | return ret; |
@@ -722,12 +724,11 @@ int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) | |||
722 | else | 724 | else |
723 | adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; | 725 | adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; |
724 | sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; | 726 | sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; |
725 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, | 727 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
726 | sub_cmd, BITMAP_STA_PS, NULL); | 728 | sub_cmd, BITMAP_STA_PS, NULL, true); |
727 | if ((!ret) && (sub_cmd == DIS_AUTO_PS)) | 729 | if ((!ret) && (sub_cmd == DIS_AUTO_PS)) |
728 | ret = mwifiex_send_cmd_async(priv, | 730 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
729 | HostCmd_CMD_802_11_PS_MODE_ENH, | 731 | GET_PS, 0, NULL, false); |
730 | GET_PS, 0, NULL); | ||
731 | 732 | ||
732 | return ret; | 733 | return ret; |
733 | } | 734 | } |
@@ -851,9 +852,9 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, | |||
851 | struct mwifiex_ds_encrypt_key *encrypt_key) | 852 | struct mwifiex_ds_encrypt_key *encrypt_key) |
852 | { | 853 | { |
853 | 854 | ||
854 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, | 855 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
855 | HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, | 856 | HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, |
856 | encrypt_key); | 857 | encrypt_key, true); |
857 | } | 858 | } |
858 | 859 | ||
859 | /* | 860 | /* |
@@ -865,6 +866,7 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, | |||
865 | static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, | 866 | static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, |
866 | struct mwifiex_ds_encrypt_key *encrypt_key) | 867 | struct mwifiex_ds_encrypt_key *encrypt_key) |
867 | { | 868 | { |
869 | struct mwifiex_adapter *adapter = priv->adapter; | ||
868 | int ret; | 870 | int ret; |
869 | struct mwifiex_wep_key *wep_key; | 871 | struct mwifiex_wep_key *wep_key; |
870 | int index; | 872 | int index; |
@@ -879,10 +881,17 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, | |||
879 | /* Copy the required key as the current key */ | 881 | /* Copy the required key as the current key */ |
880 | wep_key = &priv->wep_key[index]; | 882 | wep_key = &priv->wep_key[index]; |
881 | if (!wep_key->key_length) { | 883 | if (!wep_key->key_length) { |
882 | dev_err(priv->adapter->dev, | 884 | dev_err(adapter->dev, |
883 | "key not set, so cannot enable it\n"); | 885 | "key not set, so cannot enable it\n"); |
884 | return -1; | 886 | return -1; |
885 | } | 887 | } |
888 | |||
889 | if (adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2) { | ||
890 | memcpy(encrypt_key->key_material, | ||
891 | wep_key->key_material, wep_key->key_length); | ||
892 | encrypt_key->key_len = wep_key->key_length; | ||
893 | } | ||
894 | |||
886 | priv->wep_key_curr_index = (u16) index; | 895 | priv->wep_key_curr_index = (u16) index; |
887 | priv->sec_info.wep_enabled = 1; | 896 | priv->sec_info.wep_enabled = 1; |
888 | } else { | 897 | } else { |
@@ -897,21 +906,32 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, | |||
897 | priv->sec_info.wep_enabled = 1; | 906 | priv->sec_info.wep_enabled = 1; |
898 | } | 907 | } |
899 | if (wep_key->key_length) { | 908 | if (wep_key->key_length) { |
909 | void *enc_key; | ||
910 | |||
911 | if (encrypt_key->key_disable) | ||
912 | memset(&priv->wep_key[index], 0, | ||
913 | sizeof(struct mwifiex_wep_key)); | ||
914 | |||
915 | if (adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2) | ||
916 | enc_key = encrypt_key; | ||
917 | else | ||
918 | enc_key = NULL; | ||
919 | |||
900 | /* Send request to firmware */ | 920 | /* Send request to firmware */ |
901 | ret = mwifiex_send_cmd_async(priv, | 921 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
902 | HostCmd_CMD_802_11_KEY_MATERIAL, | 922 | HostCmd_ACT_GEN_SET, 0, enc_key, false); |
903 | HostCmd_ACT_GEN_SET, 0, NULL); | ||
904 | if (ret) | 923 | if (ret) |
905 | return ret; | 924 | return ret; |
906 | } | 925 | } |
926 | |||
907 | if (priv->sec_info.wep_enabled) | 927 | if (priv->sec_info.wep_enabled) |
908 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; | 928 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; |
909 | else | 929 | else |
910 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | 930 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; |
911 | 931 | ||
912 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, | 932 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
913 | HostCmd_ACT_GEN_SET, 0, | 933 | HostCmd_ACT_GEN_SET, 0, |
914 | &priv->curr_pkt_filter); | 934 | &priv->curr_pkt_filter, true); |
915 | 935 | ||
916 | return ret; | 936 | return ret; |
917 | } | 937 | } |
@@ -946,10 +966,9 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, | |||
946 | */ | 966 | */ |
947 | /* Send the key as PTK to firmware */ | 967 | /* Send the key as PTK to firmware */ |
948 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; | 968 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; |
949 | ret = mwifiex_send_cmd_async(priv, | 969 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
950 | HostCmd_CMD_802_11_KEY_MATERIAL, | 970 | HostCmd_ACT_GEN_SET, |
951 | HostCmd_ACT_GEN_SET, | 971 | KEY_INFO_ENABLED, encrypt_key, false); |
952 | KEY_INFO_ENABLED, encrypt_key); | ||
953 | if (ret) | 972 | if (ret) |
954 | return ret; | 973 | return ret; |
955 | 974 | ||
@@ -973,15 +992,13 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, | |||
973 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; | 992 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; |
974 | 993 | ||
975 | if (remove_key) | 994 | if (remove_key) |
976 | ret = mwifiex_send_cmd_sync(priv, | 995 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
977 | HostCmd_CMD_802_11_KEY_MATERIAL, | 996 | HostCmd_ACT_GEN_SET, |
978 | HostCmd_ACT_GEN_SET, | 997 | !KEY_INFO_ENABLED, encrypt_key, true); |
979 | !KEY_INFO_ENABLED, encrypt_key); | ||
980 | else | 998 | else |
981 | ret = mwifiex_send_cmd_sync(priv, | 999 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
982 | HostCmd_CMD_802_11_KEY_MATERIAL, | 1000 | HostCmd_ACT_GEN_SET, |
983 | HostCmd_ACT_GEN_SET, | 1001 | KEY_INFO_ENABLED, encrypt_key, true); |
984 | KEY_INFO_ENABLED, encrypt_key); | ||
985 | 1002 | ||
986 | return ret; | 1003 | return ret; |
987 | } | 1004 | } |
@@ -1044,19 +1061,27 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, | |||
1044 | 1061 | ||
1045 | memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); | 1062 | memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); |
1046 | encrypt_key.key_len = key_len; | 1063 | encrypt_key.key_len = key_len; |
1064 | encrypt_key.key_index = key_index; | ||
1047 | 1065 | ||
1048 | if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC) | 1066 | if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
1049 | encrypt_key.is_igtk_key = true; | 1067 | encrypt_key.is_igtk_key = true; |
1050 | 1068 | ||
1051 | if (!disable) { | 1069 | if (!disable) { |
1052 | encrypt_key.key_index = key_index; | ||
1053 | if (key_len) | 1070 | if (key_len) |
1054 | memcpy(encrypt_key.key_material, key, key_len); | 1071 | memcpy(encrypt_key.key_material, key, key_len); |
1072 | else | ||
1073 | encrypt_key.is_current_wep_key = true; | ||
1074 | |||
1055 | if (mac_addr) | 1075 | if (mac_addr) |
1056 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | 1076 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); |
1057 | if (kp && kp->seq && kp->seq_len) | 1077 | if (kp && kp->seq && kp->seq_len) { |
1058 | memcpy(encrypt_key.pn, kp->seq, kp->seq_len); | 1078 | memcpy(encrypt_key.pn, kp->seq, kp->seq_len); |
1079 | encrypt_key.pn_len = kp->seq_len; | ||
1080 | encrypt_key.is_rx_seq_valid = true; | ||
1081 | } | ||
1059 | } else { | 1082 | } else { |
1083 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) | ||
1084 | return 0; | ||
1060 | encrypt_key.key_disable = true; | 1085 | encrypt_key.key_disable = true; |
1061 | if (mac_addr) | 1086 | if (mac_addr) |
1062 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | 1087 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); |
@@ -1077,8 +1102,8 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv) | |||
1077 | struct mwifiex_ver_ext ver_ext; | 1102 | struct mwifiex_ver_ext ver_ext; |
1078 | 1103 | ||
1079 | memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); | 1104 | memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); |
1080 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, | 1105 | if (mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT, |
1081 | HostCmd_ACT_GEN_GET, 0, &ver_ext)) | 1106 | HostCmd_ACT_GEN_GET, 0, &ver_ext, true)) |
1082 | return -1; | 1107 | return -1; |
1083 | 1108 | ||
1084 | return 0; | 1109 | return 0; |
@@ -1103,8 +1128,8 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, | |||
1103 | ieee80211_frequency_to_channel(chan->center_freq); | 1128 | ieee80211_frequency_to_channel(chan->center_freq); |
1104 | roc_cfg.duration = cpu_to_le32(duration); | 1129 | roc_cfg.duration = cpu_to_le32(duration); |
1105 | } | 1130 | } |
1106 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_REMAIN_ON_CHAN, | 1131 | if (mwifiex_send_cmd(priv, HostCmd_CMD_REMAIN_ON_CHAN, |
1107 | action, 0, &roc_cfg)) { | 1132 | action, 0, &roc_cfg, true)) { |
1108 | dev_err(priv->adapter->dev, "failed to remain on channel\n"); | 1133 | dev_err(priv->adapter->dev, "failed to remain on channel\n"); |
1109 | return -1; | 1134 | return -1; |
1110 | } | 1135 | } |
@@ -1136,8 +1161,8 @@ mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role) | |||
1136 | break; | 1161 | break; |
1137 | } | 1162 | } |
1138 | 1163 | ||
1139 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, | 1164 | mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, |
1140 | HostCmd_ACT_GEN_SET, 0, NULL); | 1165 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
1141 | 1166 | ||
1142 | return mwifiex_sta_init_cmd(priv, false); | 1167 | return mwifiex_sta_init_cmd(priv, false); |
1143 | } | 1168 | } |
@@ -1152,8 +1177,8 @@ int | |||
1152 | mwifiex_get_stats_info(struct mwifiex_private *priv, | 1177 | mwifiex_get_stats_info(struct mwifiex_private *priv, |
1153 | struct mwifiex_ds_get_stats *log) | 1178 | struct mwifiex_ds_get_stats *log) |
1154 | { | 1179 | { |
1155 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, | 1180 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_GET_LOG, |
1156 | HostCmd_ACT_GEN_GET, 0, log); | 1181 | HostCmd_ACT_GEN_GET, 0, log, true); |
1157 | } | 1182 | } |
1158 | 1183 | ||
1159 | /* | 1184 | /* |
@@ -1195,8 +1220,7 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, | |||
1195 | return -1; | 1220 | return -1; |
1196 | } | 1221 | } |
1197 | 1222 | ||
1198 | return mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); | 1223 | return mwifiex_send_cmd(priv, cmd_no, action, 0, reg_rw, true); |
1199 | |||
1200 | } | 1224 | } |
1201 | 1225 | ||
1202 | /* | 1226 | /* |
@@ -1261,8 +1285,8 @@ mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, | |||
1261 | rd_eeprom.byte_count = cpu_to_le16((u16) bytes); | 1285 | rd_eeprom.byte_count = cpu_to_le16((u16) bytes); |
1262 | 1286 | ||
1263 | /* Send request to firmware */ | 1287 | /* Send request to firmware */ |
1264 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, | 1288 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, |
1265 | HostCmd_ACT_GEN_GET, 0, &rd_eeprom); | 1289 | HostCmd_ACT_GEN_GET, 0, &rd_eeprom, true); |
1266 | 1290 | ||
1267 | if (!ret) | 1291 | if (!ret) |
1268 | memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); | 1292 | memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); |
@@ -1391,7 +1415,7 @@ static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, | |||
1391 | * with requisite parameters and calls the IOCTL handler. | 1415 | * with requisite parameters and calls the IOCTL handler. |
1392 | */ | 1416 | */ |
1393 | int | 1417 | int |
1394 | mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) | 1418 | mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len) |
1395 | { | 1419 | { |
1396 | struct mwifiex_ds_misc_gen_ie gen_ie; | 1420 | struct mwifiex_ds_misc_gen_ie gen_ie; |
1397 | 1421 | ||
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 4651d676df38..ed26387eccf5 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c | |||
@@ -88,11 +88,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, | |||
88 | struct rxpd *local_rx_pd; | 88 | struct rxpd *local_rx_pd; |
89 | int hdr_chop; | 89 | int hdr_chop; |
90 | struct ethhdr *eth; | 90 | struct ethhdr *eth; |
91 | u16 rx_pkt_off, rx_pkt_len; | ||
92 | u8 *offset; | ||
91 | 93 | ||
92 | local_rx_pd = (struct rxpd *) (skb->data); | 94 | local_rx_pd = (struct rxpd *) (skb->data); |
93 | 95 | ||
94 | rx_pkt_hdr = (void *)local_rx_pd + | 96 | rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset); |
95 | le16_to_cpu(local_rx_pd->rx_pkt_offset); | 97 | rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); |
98 | rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; | ||
96 | 99 | ||
97 | if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, | 100 | if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, |
98 | sizeof(bridge_tunnel_header))) || | 101 | sizeof(bridge_tunnel_header))) || |
@@ -142,6 +145,12 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, | |||
142 | return 0; | 145 | return 0; |
143 | } | 146 | } |
144 | 147 | ||
148 | if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | ||
149 | ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) { | ||
150 | offset = (u8 *)local_rx_pd + rx_pkt_off; | ||
151 | mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len); | ||
152 | } | ||
153 | |||
145 | priv->rxpd_rate = local_rx_pd->rx_rate; | 154 | priv->rxpd_rate = local_rx_pd->rx_rate; |
146 | 155 | ||
147 | priv->rxpd_htinfo = local_rx_pd->ht_info; | 156 | priv->rxpd_htinfo = local_rx_pd->ht_info; |
@@ -192,26 +201,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, | |||
192 | return ret; | 201 | return ret; |
193 | } | 202 | } |
194 | 203 | ||
195 | if (rx_pkt_type == PKT_TYPE_AMSDU) { | 204 | if (rx_pkt_type == PKT_TYPE_MGMT) { |
196 | struct sk_buff_head list; | ||
197 | struct sk_buff *rx_skb; | ||
198 | |||
199 | __skb_queue_head_init(&list); | ||
200 | |||
201 | skb_pull(skb, rx_pkt_offset); | ||
202 | skb_trim(skb, rx_pkt_length); | ||
203 | |||
204 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | ||
205 | priv->wdev->iftype, 0, false); | ||
206 | |||
207 | while (!skb_queue_empty(&list)) { | ||
208 | rx_skb = __skb_dequeue(&list); | ||
209 | ret = mwifiex_recv_packet(priv, rx_skb); | ||
210 | if (ret == -1) | ||
211 | dev_err(adapter->dev, "Rx of A-MSDU failed"); | ||
212 | } | ||
213 | return 0; | ||
214 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { | ||
215 | ret = mwifiex_process_mgmt_packet(priv, skb); | 205 | ret = mwifiex_process_mgmt_packet(priv, skb); |
216 | if (ret) | 206 | if (ret) |
217 | dev_err(adapter->dev, "Rx of mgmt packet failed"); | 207 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 354d64c9606f..1236a5de7bca 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c | |||
@@ -95,6 +95,9 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) | ||
99 | local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; | ||
100 | |||
98 | /* Offset of actual data */ | 101 | /* Offset of actual data */ |
99 | pkt_offset = sizeof(struct txpd) + pad; | 102 | pkt_offset = sizeof(struct txpd) + pad; |
100 | if (pkt_type == PKT_TYPE_MGMT) { | 103 | if (pkt_type == PKT_TYPE_MGMT) { |
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c new file mode 100644 index 000000000000..97662a1ba58c --- /dev/null +++ b/drivers/net/wireless/mwifiex/tdls.c | |||
@@ -0,0 +1,1044 @@ | |||
1 | /* Marvell Wireless LAN device driver: TDLS handling | ||
2 | * | ||
3 | * Copyright (C) 2014, Marvell International Ltd. | ||
4 | * | ||
5 | * This software file (the "File") is distributed by Marvell International | ||
6 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
7 | * (the "License"). You may use, redistribute and/or modify this File in | ||
8 | * accordance with the terms and conditions of the License, a copy of which | ||
9 | * is available on the worldwide web at | ||
10 | * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
11 | * | ||
12 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
13 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
14 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
15 | * this warranty disclaimer. | ||
16 | */ | ||
17 | |||
18 | #include "main.h" | ||
19 | #include "wmm.h" | ||
20 | #include "11n.h" | ||
21 | #include "11n_rxreorder.h" | ||
22 | #include "11ac.h" | ||
23 | |||
24 | #define TDLS_REQ_FIX_LEN 6 | ||
25 | #define TDLS_RESP_FIX_LEN 8 | ||
26 | #define TDLS_CONFIRM_FIX_LEN 6 | ||
27 | |||
28 | static void | ||
29 | mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status) | ||
30 | { | ||
31 | struct mwifiex_ra_list_tbl *ra_list; | ||
32 | struct list_head *tid_list; | ||
33 | struct sk_buff *skb, *tmp; | ||
34 | struct mwifiex_txinfo *tx_info; | ||
35 | unsigned long flags; | ||
36 | u32 tid; | ||
37 | u8 tid_down; | ||
38 | |||
39 | dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac); | ||
40 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); | ||
41 | |||
42 | skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) { | ||
43 | if (!ether_addr_equal(mac, skb->data)) | ||
44 | continue; | ||
45 | |||
46 | __skb_unlink(skb, &priv->tdls_txq); | ||
47 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
48 | tid = skb->priority; | ||
49 | tid_down = mwifiex_wmm_downgrade_tid(priv, tid); | ||
50 | |||
51 | if (status == TDLS_SETUP_COMPLETE) { | ||
52 | ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac); | ||
53 | ra_list->tdls_link = true; | ||
54 | tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; | ||
55 | } else { | ||
56 | tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list; | ||
57 | if (!list_empty(tid_list)) | ||
58 | ra_list = list_first_entry(tid_list, | ||
59 | struct mwifiex_ra_list_tbl, list); | ||
60 | else | ||
61 | ra_list = NULL; | ||
62 | tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT; | ||
63 | } | ||
64 | |||
65 | if (!ra_list) { | ||
66 | mwifiex_write_data_complete(priv->adapter, skb, 0, -1); | ||
67 | continue; | ||
68 | } | ||
69 | |||
70 | skb_queue_tail(&ra_list->skb_head, skb); | ||
71 | |||
72 | ra_list->ba_pkt_count++; | ||
73 | ra_list->total_pkt_count++; | ||
74 | |||
75 | if (atomic_read(&priv->wmm.highest_queued_prio) < | ||
76 | tos_to_tid_inv[tid_down]) | ||
77 | atomic_set(&priv->wmm.highest_queued_prio, | ||
78 | tos_to_tid_inv[tid_down]); | ||
79 | |||
80 | atomic_inc(&priv->wmm.tx_pkts_queued); | ||
81 | } | ||
82 | |||
83 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac) | ||
88 | { | ||
89 | struct mwifiex_ra_list_tbl *ra_list; | ||
90 | struct list_head *ra_list_head; | ||
91 | struct sk_buff *skb, *tmp; | ||
92 | unsigned long flags; | ||
93 | int i; | ||
94 | |||
95 | dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac); | ||
96 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); | ||
97 | |||
98 | for (i = 0; i < MAX_NUM_TID; i++) { | ||
99 | if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) { | ||
100 | ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list; | ||
101 | list_for_each_entry(ra_list, ra_list_head, list) { | ||
102 | skb_queue_walk_safe(&ra_list->skb_head, skb, | ||
103 | tmp) { | ||
104 | if (!ether_addr_equal(mac, skb->data)) | ||
105 | continue; | ||
106 | __skb_unlink(skb, &ra_list->skb_head); | ||
107 | atomic_dec(&priv->wmm.tx_pkts_queued); | ||
108 | ra_list->total_pkt_count--; | ||
109 | skb_queue_tail(&priv->tdls_txq, skb); | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | /* This function appends rate TLV to scan config command. */ | ||
120 | static int | ||
121 | mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv, | ||
122 | struct sk_buff *skb) | ||
123 | { | ||
124 | u8 rates[MWIFIEX_SUPPORTED_RATES], *pos; | ||
125 | u16 rates_size, supp_rates_size, ext_rates_size; | ||
126 | |||
127 | memset(rates, 0, sizeof(rates)); | ||
128 | rates_size = mwifiex_get_supported_rates(priv, rates); | ||
129 | |||
130 | supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES); | ||
131 | |||
132 | if (skb_tailroom(skb) < rates_size + 4) { | ||
133 | dev_err(priv->adapter->dev, | ||
134 | "Insuffient space while adding rates\n"); | ||
135 | return -ENOMEM; | ||
136 | } | ||
137 | |||
138 | pos = skb_put(skb, supp_rates_size + 2); | ||
139 | *pos++ = WLAN_EID_SUPP_RATES; | ||
140 | *pos++ = supp_rates_size; | ||
141 | memcpy(pos, rates, supp_rates_size); | ||
142 | |||
143 | if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) { | ||
144 | ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES; | ||
145 | pos = skb_put(skb, ext_rates_size + 2); | ||
146 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
147 | *pos++ = ext_rates_size; | ||
148 | memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES, | ||
149 | ext_rates_size); | ||
150 | } | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static void mwifiex_tdls_add_aid(struct mwifiex_private *priv, | ||
156 | struct sk_buff *skb) | ||
157 | { | ||
158 | struct ieee_types_assoc_rsp *assoc_rsp; | ||
159 | u8 *pos; | ||
160 | |||
161 | assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf; | ||
162 | pos = (void *)skb_put(skb, 4); | ||
163 | *pos++ = WLAN_EID_AID; | ||
164 | *pos++ = 2; | ||
165 | *pos++ = le16_to_cpu(assoc_rsp->a_id); | ||
166 | |||
167 | return; | ||
168 | } | ||
169 | |||
170 | static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv, | ||
171 | struct sk_buff *skb) | ||
172 | { | ||
173 | struct ieee80211_vht_cap vht_cap; | ||
174 | u8 *pos; | ||
175 | |||
176 | pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); | ||
177 | *pos++ = WLAN_EID_VHT_CAPABILITY; | ||
178 | *pos++ = sizeof(struct ieee80211_vht_cap); | ||
179 | |||
180 | memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap)); | ||
181 | |||
182 | mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band); | ||
183 | memcpy(pos, &vht_cap, sizeof(vht_cap)); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, | ||
189 | u8 *mac, struct sk_buff *skb) | ||
190 | { | ||
191 | struct mwifiex_bssdescriptor *bss_desc; | ||
192 | struct ieee80211_vht_operation *vht_oper; | ||
193 | struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL; | ||
194 | struct mwifiex_sta_node *sta_ptr; | ||
195 | struct mwifiex_adapter *adapter = priv->adapter; | ||
196 | u8 supp_chwd_set, peer_supp_chwd_set; | ||
197 | u8 *pos, ap_supp_chwd_set, chan_bw; | ||
198 | u16 mcs_map_user, mcs_map_resp, mcs_map_result; | ||
199 | u16 mcs_user, mcs_resp, nss; | ||
200 | u32 usr_vht_cap_info; | ||
201 | |||
202 | bss_desc = &priv->curr_bss_params.bss_descriptor; | ||
203 | |||
204 | sta_ptr = mwifiex_get_sta_entry(priv, mac); | ||
205 | if (unlikely(!sta_ptr)) { | ||
206 | dev_warn(adapter->dev, "TDLS peer station not found in list\n"); | ||
207 | return -1; | ||
208 | } | ||
209 | |||
210 | if (!mwifiex_is_bss_in_11ac_mode(priv)) { | ||
211 | if (sta_ptr->tdls_cap.extcap.ext_capab[7] & | ||
212 | WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) { | ||
213 | dev_dbg(adapter->dev, | ||
214 | "TDLS peer doesn't support wider bandwitdh\n"); | ||
215 | return 0; | ||
216 | } | ||
217 | } else { | ||
218 | ap_vht_cap = bss_desc->bcn_vht_cap; | ||
219 | } | ||
220 | |||
221 | pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2); | ||
222 | *pos++ = WLAN_EID_VHT_OPERATION; | ||
223 | *pos++ = sizeof(struct ieee80211_vht_operation); | ||
224 | vht_oper = (struct ieee80211_vht_operation *)pos; | ||
225 | |||
226 | if (bss_desc->bss_band & BAND_A) | ||
227 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; | ||
228 | else | ||
229 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; | ||
230 | |||
231 | /* find the minmum bandwith between AP/TDLS peers */ | ||
232 | vht_cap = &sta_ptr->tdls_cap.vhtcap; | ||
233 | supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info); | ||
234 | peer_supp_chwd_set = | ||
235 | GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info)); | ||
236 | supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set); | ||
237 | |||
238 | /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */ | ||
239 | |||
240 | if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] & | ||
241 | WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) { | ||
242 | ap_supp_chwd_set = | ||
243 | GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info)); | ||
244 | supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set); | ||
245 | } | ||
246 | |||
247 | switch (supp_chwd_set) { | ||
248 | case IEEE80211_VHT_CHANWIDTH_80MHZ: | ||
249 | vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; | ||
250 | break; | ||
251 | case IEEE80211_VHT_CHANWIDTH_160MHZ: | ||
252 | vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ; | ||
253 | break; | ||
254 | case IEEE80211_VHT_CHANWIDTH_80P80MHZ: | ||
255 | vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ; | ||
256 | break; | ||
257 | default: | ||
258 | vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; | ||
259 | break; | ||
260 | } | ||
261 | |||
262 | mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support); | ||
263 | mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map); | ||
264 | mcs_map_result = 0; | ||
265 | |||
266 | for (nss = 1; nss <= 8; nss++) { | ||
267 | mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); | ||
268 | mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); | ||
269 | |||
270 | if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) || | ||
271 | (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED)) | ||
272 | SET_VHTNSSMCS(mcs_map_result, nss, | ||
273 | IEEE80211_VHT_MCS_NOT_SUPPORTED); | ||
274 | else | ||
275 | SET_VHTNSSMCS(mcs_map_result, nss, | ||
276 | min_t(u16, mcs_user, mcs_resp)); | ||
277 | } | ||
278 | |||
279 | vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result); | ||
280 | |||
281 | switch (vht_oper->chan_width) { | ||
282 | case IEEE80211_VHT_CHANWIDTH_80MHZ: | ||
283 | chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ; | ||
284 | break; | ||
285 | case IEEE80211_VHT_CHANWIDTH_160MHZ: | ||
286 | chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ; | ||
287 | break; | ||
288 | case IEEE80211_VHT_CHANWIDTH_80P80MHZ: | ||
289 | chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ; | ||
290 | break; | ||
291 | default: | ||
292 | chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT; | ||
293 | break; | ||
294 | } | ||
295 | vht_oper->center_freq_seg1_idx = | ||
296 | mwifiex_get_center_freq_index(priv, BAND_AAC, | ||
297 | bss_desc->channel, | ||
298 | chan_bw); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv, | ||
304 | struct sk_buff *skb) | ||
305 | { | ||
306 | struct ieee_types_extcap *extcap; | ||
307 | |||
308 | extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap)); | ||
309 | extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY; | ||
310 | extcap->ieee_hdr.len = 8; | ||
311 | memset(extcap->ext_capab, 0, 8); | ||
312 | extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED; | ||
313 | |||
314 | if (priv->adapter->is_hw_11ac_capable) | ||
315 | extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED; | ||
316 | } | ||
317 | |||
318 | static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb) | ||
319 | { | ||
320 | u8 *pos = (void *)skb_put(skb, 3); | ||
321 | |||
322 | *pos++ = WLAN_EID_QOS_CAPA; | ||
323 | *pos++ = 1; | ||
324 | *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB; | ||
325 | } | ||
326 | |||
327 | static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | ||
328 | u8 *peer, u8 action_code, u8 dialog_token, | ||
329 | u16 status_code, struct sk_buff *skb) | ||
330 | { | ||
331 | struct ieee80211_tdls_data *tf; | ||
332 | int ret; | ||
333 | u16 capab; | ||
334 | struct ieee80211_ht_cap *ht_cap; | ||
335 | u8 radio, *pos; | ||
336 | |||
337 | capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap; | ||
338 | |||
339 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | ||
340 | memcpy(tf->da, peer, ETH_ALEN); | ||
341 | memcpy(tf->sa, priv->curr_addr, ETH_ALEN); | ||
342 | tf->ether_type = cpu_to_be16(ETH_P_TDLS); | ||
343 | tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; | ||
344 | |||
345 | switch (action_code) { | ||
346 | case WLAN_TDLS_SETUP_REQUEST: | ||
347 | tf->category = WLAN_CATEGORY_TDLS; | ||
348 | tf->action_code = WLAN_TDLS_SETUP_REQUEST; | ||
349 | skb_put(skb, sizeof(tf->u.setup_req)); | ||
350 | tf->u.setup_req.dialog_token = dialog_token; | ||
351 | tf->u.setup_req.capability = cpu_to_le16(capab); | ||
352 | ret = mwifiex_tdls_append_rates_ie(priv, skb); | ||
353 | if (ret) { | ||
354 | dev_kfree_skb_any(skb); | ||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
359 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
360 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
361 | ht_cap = (void *)pos; | ||
362 | radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | ||
363 | ret = mwifiex_fill_cap_info(priv, radio, ht_cap); | ||
364 | if (ret) { | ||
365 | dev_kfree_skb_any(skb); | ||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | if (priv->adapter->is_hw_11ac_capable) { | ||
370 | ret = mwifiex_tdls_add_vht_capab(priv, skb); | ||
371 | if (ret) { | ||
372 | dev_kfree_skb_any(skb); | ||
373 | return ret; | ||
374 | } | ||
375 | mwifiex_tdls_add_aid(priv, skb); | ||
376 | } | ||
377 | |||
378 | mwifiex_tdls_add_ext_capab(priv, skb); | ||
379 | mwifiex_tdls_add_qos_capab(skb); | ||
380 | break; | ||
381 | |||
382 | case WLAN_TDLS_SETUP_RESPONSE: | ||
383 | tf->category = WLAN_CATEGORY_TDLS; | ||
384 | tf->action_code = WLAN_TDLS_SETUP_RESPONSE; | ||
385 | skb_put(skb, sizeof(tf->u.setup_resp)); | ||
386 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); | ||
387 | tf->u.setup_resp.dialog_token = dialog_token; | ||
388 | tf->u.setup_resp.capability = cpu_to_le16(capab); | ||
389 | ret = mwifiex_tdls_append_rates_ie(priv, skb); | ||
390 | if (ret) { | ||
391 | dev_kfree_skb_any(skb); | ||
392 | return ret; | ||
393 | } | ||
394 | |||
395 | pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
396 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
397 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
398 | ht_cap = (void *)pos; | ||
399 | radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | ||
400 | ret = mwifiex_fill_cap_info(priv, radio, ht_cap); | ||
401 | if (ret) { | ||
402 | dev_kfree_skb_any(skb); | ||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | if (priv->adapter->is_hw_11ac_capable) { | ||
407 | ret = mwifiex_tdls_add_vht_capab(priv, skb); | ||
408 | if (ret) { | ||
409 | dev_kfree_skb_any(skb); | ||
410 | return ret; | ||
411 | } | ||
412 | mwifiex_tdls_add_aid(priv, skb); | ||
413 | } | ||
414 | |||
415 | mwifiex_tdls_add_ext_capab(priv, skb); | ||
416 | mwifiex_tdls_add_qos_capab(skb); | ||
417 | break; | ||
418 | |||
419 | case WLAN_TDLS_SETUP_CONFIRM: | ||
420 | tf->category = WLAN_CATEGORY_TDLS; | ||
421 | tf->action_code = WLAN_TDLS_SETUP_CONFIRM; | ||
422 | skb_put(skb, sizeof(tf->u.setup_cfm)); | ||
423 | tf->u.setup_cfm.status_code = cpu_to_le16(status_code); | ||
424 | tf->u.setup_cfm.dialog_token = dialog_token; | ||
425 | if (priv->adapter->is_hw_11ac_capable) { | ||
426 | ret = mwifiex_tdls_add_vht_oper(priv, peer, skb); | ||
427 | if (ret) { | ||
428 | dev_kfree_skb_any(skb); | ||
429 | return ret; | ||
430 | } | ||
431 | } | ||
432 | break; | ||
433 | |||
434 | case WLAN_TDLS_TEARDOWN: | ||
435 | tf->category = WLAN_CATEGORY_TDLS; | ||
436 | tf->action_code = WLAN_TDLS_TEARDOWN; | ||
437 | skb_put(skb, sizeof(tf->u.teardown)); | ||
438 | tf->u.teardown.reason_code = cpu_to_le16(status_code); | ||
439 | break; | ||
440 | |||
441 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
442 | tf->category = WLAN_CATEGORY_TDLS; | ||
443 | tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; | ||
444 | skb_put(skb, sizeof(tf->u.discover_req)); | ||
445 | tf->u.discover_req.dialog_token = dialog_token; | ||
446 | break; | ||
447 | default: | ||
448 | dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n"); | ||
449 | return -EINVAL; | ||
450 | } | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static void | ||
456 | mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid) | ||
457 | { | ||
458 | struct ieee80211_tdls_lnkie *lnkid; | ||
459 | |||
460 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); | ||
461 | lnkid->ie_type = WLAN_EID_LINK_ID; | ||
462 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - | ||
463 | sizeof(struct ieee_types_header); | ||
464 | |||
465 | memcpy(lnkid->bssid, bssid, ETH_ALEN); | ||
466 | memcpy(lnkid->init_sta, src_addr, ETH_ALEN); | ||
467 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); | ||
468 | } | ||
469 | |||
470 | int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, | ||
471 | u8 *peer, u8 action_code, u8 dialog_token, | ||
472 | u16 status_code, const u8 *extra_ies, | ||
473 | size_t extra_ies_len) | ||
474 | { | ||
475 | struct sk_buff *skb; | ||
476 | struct mwifiex_txinfo *tx_info; | ||
477 | struct timeval tv; | ||
478 | int ret; | ||
479 | u16 skb_len; | ||
480 | |||
481 | skb_len = MWIFIEX_MIN_DATA_HEADER_LEN + | ||
482 | max(sizeof(struct ieee80211_mgmt), | ||
483 | sizeof(struct ieee80211_tdls_data)) + | ||
484 | MWIFIEX_MGMT_FRAME_HEADER_SIZE + | ||
485 | MWIFIEX_SUPPORTED_RATES + | ||
486 | 3 + /* Qos Info */ | ||
487 | sizeof(struct ieee_types_extcap) + | ||
488 | sizeof(struct ieee80211_ht_cap) + | ||
489 | sizeof(struct ieee_types_bss_co_2040) + | ||
490 | sizeof(struct ieee80211_ht_operation) + | ||
491 | sizeof(struct ieee80211_tdls_lnkie) + | ||
492 | extra_ies_len; | ||
493 | |||
494 | if (priv->adapter->is_hw_11ac_capable) | ||
495 | skb_len += sizeof(struct ieee_types_vht_cap) + | ||
496 | sizeof(struct ieee_types_vht_oper) + | ||
497 | sizeof(struct ieee_types_aid); | ||
498 | |||
499 | skb = dev_alloc_skb(skb_len); | ||
500 | if (!skb) { | ||
501 | dev_err(priv->adapter->dev, | ||
502 | "allocate skb failed for management frame\n"); | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN); | ||
506 | |||
507 | switch (action_code) { | ||
508 | case WLAN_TDLS_SETUP_REQUEST: | ||
509 | case WLAN_TDLS_SETUP_CONFIRM: | ||
510 | case WLAN_TDLS_TEARDOWN: | ||
511 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
512 | ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code, | ||
513 | dialog_token, status_code, | ||
514 | skb); | ||
515 | if (ret) { | ||
516 | dev_kfree_skb_any(skb); | ||
517 | return ret; | ||
518 | } | ||
519 | if (extra_ies_len) | ||
520 | memcpy(skb_put(skb, extra_ies_len), extra_ies, | ||
521 | extra_ies_len); | ||
522 | mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer, | ||
523 | priv->cfg_bssid); | ||
524 | break; | ||
525 | case WLAN_TDLS_SETUP_RESPONSE: | ||
526 | ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code, | ||
527 | dialog_token, status_code, | ||
528 | skb); | ||
529 | if (ret) { | ||
530 | dev_kfree_skb_any(skb); | ||
531 | return ret; | ||
532 | } | ||
533 | if (extra_ies_len) | ||
534 | memcpy(skb_put(skb, extra_ies_len), extra_ies, | ||
535 | extra_ies_len); | ||
536 | mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr, | ||
537 | priv->cfg_bssid); | ||
538 | break; | ||
539 | } | ||
540 | |||
541 | switch (action_code) { | ||
542 | case WLAN_TDLS_SETUP_REQUEST: | ||
543 | case WLAN_TDLS_SETUP_RESPONSE: | ||
544 | skb->priority = MWIFIEX_PRIO_BK; | ||
545 | break; | ||
546 | default: | ||
547 | skb->priority = MWIFIEX_PRIO_VI; | ||
548 | break; | ||
549 | } | ||
550 | |||
551 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
552 | tx_info->bss_num = priv->bss_num; | ||
553 | tx_info->bss_type = priv->bss_type; | ||
554 | |||
555 | do_gettimeofday(&tv); | ||
556 | skb->tstamp = timeval_to_ktime(tv); | ||
557 | mwifiex_queue_tx_pkt(priv, skb); | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static int | ||
563 | mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer, | ||
564 | u8 action_code, u8 dialog_token, | ||
565 | u16 status_code, struct sk_buff *skb) | ||
566 | { | ||
567 | struct ieee80211_mgmt *mgmt; | ||
568 | u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
569 | int ret; | ||
570 | u16 capab; | ||
571 | struct ieee80211_ht_cap *ht_cap; | ||
572 | u8 radio, *pos; | ||
573 | |||
574 | capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap; | ||
575 | |||
576 | mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u)); | ||
577 | |||
578 | memset(mgmt, 0, 24); | ||
579 | memcpy(mgmt->da, peer, ETH_ALEN); | ||
580 | memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN); | ||
581 | memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN); | ||
582 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
583 | IEEE80211_STYPE_ACTION); | ||
584 | |||
585 | /* add address 4 */ | ||
586 | pos = skb_put(skb, ETH_ALEN); | ||
587 | |||
588 | switch (action_code) { | ||
589 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
590 | skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1); | ||
591 | mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; | ||
592 | mgmt->u.action.u.tdls_discover_resp.action_code = | ||
593 | WLAN_PUB_ACTION_TDLS_DISCOVER_RES; | ||
594 | mgmt->u.action.u.tdls_discover_resp.dialog_token = | ||
595 | dialog_token; | ||
596 | mgmt->u.action.u.tdls_discover_resp.capability = | ||
597 | cpu_to_le16(capab); | ||
598 | /* move back for addr4 */ | ||
599 | memmove(pos + ETH_ALEN, &mgmt->u.action.category, | ||
600 | sizeof(mgmt->u.action.u.tdls_discover_resp)); | ||
601 | /* init address 4 */ | ||
602 | memcpy(pos, bc_addr, ETH_ALEN); | ||
603 | |||
604 | ret = mwifiex_tdls_append_rates_ie(priv, skb); | ||
605 | if (ret) { | ||
606 | dev_kfree_skb_any(skb); | ||
607 | return ret; | ||
608 | } | ||
609 | |||
610 | pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
611 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
612 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
613 | ht_cap = (void *)pos; | ||
614 | radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band); | ||
615 | ret = mwifiex_fill_cap_info(priv, radio, ht_cap); | ||
616 | if (ret) { | ||
617 | dev_kfree_skb_any(skb); | ||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | if (priv->adapter->is_hw_11ac_capable) { | ||
622 | ret = mwifiex_tdls_add_vht_capab(priv, skb); | ||
623 | if (ret) { | ||
624 | dev_kfree_skb_any(skb); | ||
625 | return ret; | ||
626 | } | ||
627 | mwifiex_tdls_add_aid(priv, skb); | ||
628 | } | ||
629 | |||
630 | mwifiex_tdls_add_ext_capab(priv, skb); | ||
631 | mwifiex_tdls_add_qos_capab(skb); | ||
632 | break; | ||
633 | default: | ||
634 | dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n"); | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, | ||
642 | u8 *peer, u8 action_code, u8 dialog_token, | ||
643 | u16 status_code, const u8 *extra_ies, | ||
644 | size_t extra_ies_len) | ||
645 | { | ||
646 | struct sk_buff *skb; | ||
647 | struct mwifiex_txinfo *tx_info; | ||
648 | struct timeval tv; | ||
649 | u8 *pos; | ||
650 | u32 pkt_type, tx_control; | ||
651 | u16 pkt_len, skb_len; | ||
652 | |||
653 | skb_len = MWIFIEX_MIN_DATA_HEADER_LEN + | ||
654 | max(sizeof(struct ieee80211_mgmt), | ||
655 | sizeof(struct ieee80211_tdls_data)) + | ||
656 | MWIFIEX_MGMT_FRAME_HEADER_SIZE + | ||
657 | MWIFIEX_SUPPORTED_RATES + | ||
658 | sizeof(struct ieee_types_extcap) + | ||
659 | sizeof(struct ieee80211_ht_cap) + | ||
660 | sizeof(struct ieee_types_bss_co_2040) + | ||
661 | sizeof(struct ieee80211_ht_operation) + | ||
662 | sizeof(struct ieee80211_tdls_lnkie) + | ||
663 | extra_ies_len + | ||
664 | 3 + /* Qos Info */ | ||
665 | ETH_ALEN; /* Address4 */ | ||
666 | |||
667 | if (priv->adapter->is_hw_11ac_capable) | ||
668 | skb_len += sizeof(struct ieee_types_vht_cap) + | ||
669 | sizeof(struct ieee_types_vht_oper) + | ||
670 | sizeof(struct ieee_types_aid); | ||
671 | |||
672 | skb = dev_alloc_skb(skb_len); | ||
673 | if (!skb) { | ||
674 | dev_err(priv->adapter->dev, | ||
675 | "allocate skb failed for management frame\n"); | ||
676 | return -ENOMEM; | ||
677 | } | ||
678 | |||
679 | skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN); | ||
680 | |||
681 | pkt_type = PKT_TYPE_MGMT; | ||
682 | tx_control = 0; | ||
683 | pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len)); | ||
684 | memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len)); | ||
685 | memcpy(pos, &pkt_type, sizeof(pkt_type)); | ||
686 | memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control)); | ||
687 | |||
688 | if (mwifiex_construct_tdls_action_frame(priv, peer, action_code, | ||
689 | dialog_token, status_code, | ||
690 | skb)) { | ||
691 | dev_kfree_skb_any(skb); | ||
692 | return -EINVAL; | ||
693 | } | ||
694 | |||
695 | if (extra_ies_len) | ||
696 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); | ||
697 | |||
698 | /* the TDLS link IE is always added last we are the responder */ | ||
699 | |||
700 | mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr, | ||
701 | priv->cfg_bssid); | ||
702 | |||
703 | skb->priority = MWIFIEX_PRIO_VI; | ||
704 | |||
705 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
706 | tx_info->bss_num = priv->bss_num; | ||
707 | tx_info->bss_type = priv->bss_type; | ||
708 | tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; | ||
709 | |||
710 | pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len); | ||
711 | memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len, | ||
712 | sizeof(pkt_len)); | ||
713 | do_gettimeofday(&tv); | ||
714 | skb->tstamp = timeval_to_ktime(tv); | ||
715 | mwifiex_queue_tx_pkt(priv, skb); | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | /* This function process tdls action frame from peer. | ||
721 | * Peer capabilities are stored into station node structure. | ||
722 | */ | ||
723 | void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | ||
724 | u8 *buf, int len) | ||
725 | { | ||
726 | struct mwifiex_sta_node *sta_ptr; | ||
727 | u8 *peer, *pos, *end; | ||
728 | u8 i, action, basic; | ||
729 | int ie_len = 0; | ||
730 | |||
731 | if (len < (sizeof(struct ethhdr) + 3)) | ||
732 | return; | ||
733 | if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE) | ||
734 | return; | ||
735 | if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS) | ||
736 | return; | ||
737 | |||
738 | peer = buf + ETH_ALEN; | ||
739 | action = *(buf + sizeof(struct ethhdr) + 2); | ||
740 | |||
741 | /* just handle TDLS setup request/response/confirm */ | ||
742 | if (action > WLAN_TDLS_SETUP_CONFIRM) | ||
743 | return; | ||
744 | |||
745 | dev_dbg(priv->adapter->dev, | ||
746 | "rx:tdls action: peer=%pM, action=%d\n", peer, action); | ||
747 | |||
748 | sta_ptr = mwifiex_add_sta_entry(priv, peer); | ||
749 | if (!sta_ptr) | ||
750 | return; | ||
751 | |||
752 | switch (action) { | ||
753 | case WLAN_TDLS_SETUP_REQUEST: | ||
754 | if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN)) | ||
755 | return; | ||
756 | |||
757 | pos = buf + sizeof(struct ethhdr) + 4; | ||
758 | /* payload 1+ category 1 + action 1 + dialog 1 */ | ||
759 | sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos); | ||
760 | ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; | ||
761 | pos += 2; | ||
762 | break; | ||
763 | |||
764 | case WLAN_TDLS_SETUP_RESPONSE: | ||
765 | if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN)) | ||
766 | return; | ||
767 | /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/ | ||
768 | pos = buf + sizeof(struct ethhdr) + 6; | ||
769 | sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos); | ||
770 | ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; | ||
771 | pos += 2; | ||
772 | break; | ||
773 | |||
774 | case WLAN_TDLS_SETUP_CONFIRM: | ||
775 | if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN)) | ||
776 | return; | ||
777 | pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN; | ||
778 | ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; | ||
779 | break; | ||
780 | default: | ||
781 | dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n"); | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) { | ||
786 | if (pos + 2 + pos[1] > end) | ||
787 | break; | ||
788 | |||
789 | switch (*pos) { | ||
790 | case WLAN_EID_SUPP_RATES: | ||
791 | sta_ptr->tdls_cap.rates_len = pos[1]; | ||
792 | for (i = 0; i < pos[1]; i++) | ||
793 | sta_ptr->tdls_cap.rates[i] = pos[i + 2]; | ||
794 | break; | ||
795 | |||
796 | case WLAN_EID_EXT_SUPP_RATES: | ||
797 | basic = sta_ptr->tdls_cap.rates_len; | ||
798 | for (i = 0; i < pos[1]; i++) | ||
799 | sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2]; | ||
800 | sta_ptr->tdls_cap.rates_len += pos[1]; | ||
801 | break; | ||
802 | case WLAN_EID_HT_CAPABILITY: | ||
803 | memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos, | ||
804 | sizeof(struct ieee80211_ht_cap)); | ||
805 | sta_ptr->is_11n_enabled = 1; | ||
806 | break; | ||
807 | case WLAN_EID_HT_OPERATION: | ||
808 | memcpy(&sta_ptr->tdls_cap.ht_oper, pos, | ||
809 | sizeof(struct ieee80211_ht_operation)); | ||
810 | break; | ||
811 | case WLAN_EID_BSS_COEX_2040: | ||
812 | sta_ptr->tdls_cap.coex_2040 = pos[2]; | ||
813 | break; | ||
814 | case WLAN_EID_EXT_CAPABILITY: | ||
815 | memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos, | ||
816 | sizeof(struct ieee_types_header) + | ||
817 | min_t(u8, pos[1], 8)); | ||
818 | break; | ||
819 | case WLAN_EID_RSN: | ||
820 | memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos, | ||
821 | sizeof(struct ieee_types_header) + pos[1]); | ||
822 | break; | ||
823 | case WLAN_EID_QOS_CAPA: | ||
824 | sta_ptr->tdls_cap.qos_info = pos[2]; | ||
825 | break; | ||
826 | case WLAN_EID_VHT_OPERATION: | ||
827 | if (priv->adapter->is_hw_11ac_capable) | ||
828 | memcpy(&sta_ptr->tdls_cap.vhtoper, pos, | ||
829 | sizeof(struct ieee80211_vht_operation)); | ||
830 | break; | ||
831 | case WLAN_EID_VHT_CAPABILITY: | ||
832 | if (priv->adapter->is_hw_11ac_capable) { | ||
833 | memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos, | ||
834 | sizeof(struct ieee80211_vht_cap)); | ||
835 | sta_ptr->is_11ac_enabled = 1; | ||
836 | } | ||
837 | break; | ||
838 | case WLAN_EID_AID: | ||
839 | if (priv->adapter->is_hw_11ac_capable) | ||
840 | sta_ptr->tdls_cap.aid = | ||
841 | le16_to_cpu(*(__le16 *)(pos + 2)); | ||
842 | default: | ||
843 | break; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | return; | ||
848 | } | ||
849 | |||
850 | static int | ||
851 | mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer) | ||
852 | { | ||
853 | struct mwifiex_sta_node *sta_ptr; | ||
854 | struct mwifiex_ds_tdls_oper tdls_oper; | ||
855 | |||
856 | memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); | ||
857 | sta_ptr = mwifiex_get_sta_entry(priv, peer); | ||
858 | |||
859 | if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) { | ||
860 | dev_err(priv->adapter->dev, | ||
861 | "link absent for peer %pM; cannot config\n", peer); | ||
862 | return -EINVAL; | ||
863 | } | ||
864 | |||
865 | memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); | ||
866 | tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK; | ||
867 | return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, | ||
868 | HostCmd_ACT_GEN_SET, 0, &tdls_oper, true); | ||
869 | } | ||
870 | |||
871 | static int | ||
872 | mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer) | ||
873 | { | ||
874 | struct mwifiex_sta_node *sta_ptr; | ||
875 | struct mwifiex_ds_tdls_oper tdls_oper; | ||
876 | |||
877 | memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); | ||
878 | sta_ptr = mwifiex_get_sta_entry(priv, peer); | ||
879 | |||
880 | if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) { | ||
881 | dev_dbg(priv->adapter->dev, | ||
882 | "Setup already in progress for peer %pM\n", peer); | ||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | sta_ptr = mwifiex_add_sta_entry(priv, peer); | ||
887 | if (!sta_ptr) | ||
888 | return -ENOMEM; | ||
889 | |||
890 | sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS; | ||
891 | mwifiex_hold_tdls_packets(priv, peer); | ||
892 | memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); | ||
893 | tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK; | ||
894 | return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, | ||
895 | HostCmd_ACT_GEN_SET, 0, &tdls_oper, true); | ||
896 | } | ||
897 | |||
898 | static int | ||
899 | mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer) | ||
900 | { | ||
901 | struct mwifiex_sta_node *sta_ptr; | ||
902 | struct mwifiex_ds_tdls_oper tdls_oper; | ||
903 | unsigned long flags; | ||
904 | |||
905 | memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); | ||
906 | sta_ptr = mwifiex_get_sta_entry(priv, peer); | ||
907 | |||
908 | if (sta_ptr) { | ||
909 | if (sta_ptr->is_11n_enabled) { | ||
910 | mwifiex_11n_cleanup_reorder_tbl(priv); | ||
911 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, | ||
912 | flags); | ||
913 | mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); | ||
914 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
915 | flags); | ||
916 | } | ||
917 | mwifiex_del_sta_entry(priv, peer); | ||
918 | } | ||
919 | |||
920 | mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); | ||
921 | memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); | ||
922 | tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK; | ||
923 | return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, | ||
924 | HostCmd_ACT_GEN_SET, 0, &tdls_oper, true); | ||
925 | } | ||
926 | |||
927 | static int | ||
928 | mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer) | ||
929 | { | ||
930 | struct mwifiex_sta_node *sta_ptr; | ||
931 | struct ieee80211_mcs_info mcs; | ||
932 | unsigned long flags; | ||
933 | int i; | ||
934 | |||
935 | sta_ptr = mwifiex_get_sta_entry(priv, peer); | ||
936 | |||
937 | if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) { | ||
938 | dev_dbg(priv->adapter->dev, | ||
939 | "tdls: enable link %pM success\n", peer); | ||
940 | |||
941 | sta_ptr->tdls_status = TDLS_SETUP_COMPLETE; | ||
942 | |||
943 | mcs = sta_ptr->tdls_cap.ht_capb.mcs; | ||
944 | if (mcs.rx_mask[0] != 0xff) | ||
945 | sta_ptr->is_11n_enabled = true; | ||
946 | if (sta_ptr->is_11n_enabled) { | ||
947 | if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) & | ||
948 | IEEE80211_HT_CAP_MAX_AMSDU) | ||
949 | sta_ptr->max_amsdu = | ||
950 | MWIFIEX_TX_DATA_BUF_SIZE_8K; | ||
951 | else | ||
952 | sta_ptr->max_amsdu = | ||
953 | MWIFIEX_TX_DATA_BUF_SIZE_4K; | ||
954 | |||
955 | for (i = 0; i < MAX_NUM_TID; i++) | ||
956 | sta_ptr->ampdu_sta[i] = | ||
957 | priv->aggr_prio_tbl[i].ampdu_user; | ||
958 | } else { | ||
959 | for (i = 0; i < MAX_NUM_TID; i++) | ||
960 | sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; | ||
961 | } | ||
962 | |||
963 | memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); | ||
964 | mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE); | ||
965 | } else { | ||
966 | dev_dbg(priv->adapter->dev, | ||
967 | "tdls: enable link %pM failed\n", peer); | ||
968 | if (sta_ptr) { | ||
969 | mwifiex_11n_cleanup_reorder_tbl(priv); | ||
970 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, | ||
971 | flags); | ||
972 | mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); | ||
973 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
974 | flags); | ||
975 | mwifiex_del_sta_entry(priv, peer); | ||
976 | } | ||
977 | mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); | ||
978 | |||
979 | return -1; | ||
980 | } | ||
981 | |||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action) | ||
986 | { | ||
987 | switch (action) { | ||
988 | case MWIFIEX_TDLS_ENABLE_LINK: | ||
989 | return mwifiex_tdls_process_enable_link(priv, peer); | ||
990 | case MWIFIEX_TDLS_DISABLE_LINK: | ||
991 | return mwifiex_tdls_process_disable_link(priv, peer); | ||
992 | case MWIFIEX_TDLS_CREATE_LINK: | ||
993 | return mwifiex_tdls_process_create_link(priv, peer); | ||
994 | case MWIFIEX_TDLS_CONFIG_LINK: | ||
995 | return mwifiex_tdls_process_config_link(priv, peer); | ||
996 | } | ||
997 | return 0; | ||
998 | } | ||
999 | |||
1000 | int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac) | ||
1001 | { | ||
1002 | struct mwifiex_sta_node *sta_ptr; | ||
1003 | |||
1004 | sta_ptr = mwifiex_get_sta_entry(priv, mac); | ||
1005 | if (sta_ptr) | ||
1006 | return sta_ptr->tdls_status; | ||
1007 | |||
1008 | return TDLS_NOT_SETUP; | ||
1009 | } | ||
1010 | |||
1011 | void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv) | ||
1012 | { | ||
1013 | struct mwifiex_sta_node *sta_ptr; | ||
1014 | struct mwifiex_ds_tdls_oper tdls_oper; | ||
1015 | unsigned long flags; | ||
1016 | |||
1017 | if (list_empty(&priv->sta_list)) | ||
1018 | return; | ||
1019 | |||
1020 | list_for_each_entry(sta_ptr, &priv->sta_list, list) { | ||
1021 | memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); | ||
1022 | |||
1023 | if (sta_ptr->is_11n_enabled) { | ||
1024 | mwifiex_11n_cleanup_reorder_tbl(priv); | ||
1025 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, | ||
1026 | flags); | ||
1027 | mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); | ||
1028 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
1029 | flags); | ||
1030 | } | ||
1031 | |||
1032 | mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr, | ||
1033 | TDLS_LINK_TEARDOWN); | ||
1034 | memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN); | ||
1035 | tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK; | ||
1036 | if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, | ||
1037 | HostCmd_ACT_GEN_SET, 0, &tdls_oper, false)) | ||
1038 | dev_warn(priv->adapter->dev, | ||
1039 | "Disable link failed for TDLS peer %pM", | ||
1040 | sta_ptr->mac_addr); | ||
1041 | } | ||
1042 | |||
1043 | mwifiex_del_all_sta_list(priv); | ||
1044 | } | ||
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 64424c81b44f..9be6544bdded 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -159,6 +159,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
159 | struct cfg80211_ap_settings *params) | 159 | struct cfg80211_ap_settings *params) |
160 | { | 160 | { |
161 | const u8 *ht_ie; | 161 | const u8 *ht_ie; |
162 | u16 cap_info; | ||
162 | 163 | ||
163 | if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) | 164 | if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) |
164 | return; | 165 | return; |
@@ -168,6 +169,25 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
168 | if (ht_ie) { | 169 | if (ht_ie) { |
169 | memcpy(&bss_cfg->ht_cap, ht_ie + 2, | 170 | memcpy(&bss_cfg->ht_cap, ht_ie + 2, |
170 | sizeof(struct ieee80211_ht_cap)); | 171 | sizeof(struct ieee80211_ht_cap)); |
172 | cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info); | ||
173 | memset(&bss_cfg->ht_cap.mcs, 0, | ||
174 | priv->adapter->number_of_antenna); | ||
175 | switch (GET_RXSTBC(cap_info)) { | ||
176 | case MWIFIEX_RX_STBC1: | ||
177 | /* HT_CAP 1X1 mode */ | ||
178 | memset(&bss_cfg->ht_cap.mcs, 0xff, 1); | ||
179 | break; | ||
180 | case MWIFIEX_RX_STBC12: /* fall through */ | ||
181 | case MWIFIEX_RX_STBC123: | ||
182 | /* HT_CAP 2X2 mode */ | ||
183 | memset(&bss_cfg->ht_cap.mcs, 0xff, 2); | ||
184 | break; | ||
185 | default: | ||
186 | dev_warn(priv->adapter->dev, | ||
187 | "Unsupported RX-STBC, default to 2x2\n"); | ||
188 | memset(&bss_cfg->ht_cap.mcs, 0xff, 2); | ||
189 | break; | ||
190 | } | ||
171 | priv->ap_11n_enabled = 1; | 191 | priv->ap_11n_enabled = 1; |
172 | } else { | 192 | } else { |
173 | memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); | 193 | memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); |
@@ -226,8 +246,8 @@ void mwifiex_set_vht_width(struct mwifiex_private *priv, | |||
226 | if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80) | 246 | if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80) |
227 | vht_cfg.misc_config |= VHT_BW_80_160_80P80; | 247 | vht_cfg.misc_config |= VHT_BW_80_160_80P80; |
228 | 248 | ||
229 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_11AC_CFG, | 249 | mwifiex_send_cmd(priv, HostCmd_CMD_11AC_CFG, |
230 | HostCmd_ACT_GEN_SET, 0, &vht_cfg); | 250 | HostCmd_ACT_GEN_SET, 0, &vht_cfg, true); |
231 | 251 | ||
232 | return; | 252 | return; |
233 | } | 253 | } |
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 718066577c6c..92e77a398ecf 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c | |||
@@ -21,126 +21,8 @@ | |||
21 | #include "main.h" | 21 | #include "main.h" |
22 | #include "11n.h" | 22 | #include "11n.h" |
23 | 23 | ||
24 | /* | ||
25 | * This function will return the pointer to station entry in station list | ||
26 | * table which matches specified mac address. | ||
27 | * This function should be called after acquiring RA list spinlock. | ||
28 | * NULL is returned if station entry is not found in associated STA list. | ||
29 | */ | ||
30 | struct mwifiex_sta_node * | ||
31 | mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac) | ||
32 | { | ||
33 | struct mwifiex_sta_node *node; | ||
34 | |||
35 | if (!mac) | ||
36 | return NULL; | ||
37 | |||
38 | list_for_each_entry(node, &priv->sta_list, list) { | ||
39 | if (!memcmp(node->mac_addr, mac, ETH_ALEN)) | ||
40 | return node; | ||
41 | } | ||
42 | |||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * This function will add a sta_node entry to associated station list | ||
48 | * table with the given mac address. | ||
49 | * If entry exist already, existing entry is returned. | ||
50 | * If received mac address is NULL, NULL is returned. | ||
51 | */ | ||
52 | static struct mwifiex_sta_node * | ||
53 | mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac) | ||
54 | { | ||
55 | struct mwifiex_sta_node *node; | ||
56 | unsigned long flags; | ||
57 | |||
58 | if (!mac) | ||
59 | return NULL; | ||
60 | |||
61 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | ||
62 | node = mwifiex_get_sta_entry(priv, mac); | ||
63 | if (node) | ||
64 | goto done; | ||
65 | |||
66 | node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_ATOMIC); | ||
67 | if (!node) | ||
68 | goto done; | ||
69 | |||
70 | memcpy(node->mac_addr, mac, ETH_ALEN); | ||
71 | list_add_tail(&node->list, &priv->sta_list); | ||
72 | |||
73 | done: | ||
74 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
75 | return node; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * This function will search for HT IE in association request IEs | ||
80 | * and set station HT parameters accordingly. | ||
81 | */ | ||
82 | static void | ||
83 | mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, | ||
84 | int ies_len, struct mwifiex_sta_node *node) | ||
85 | { | ||
86 | const struct ieee80211_ht_cap *ht_cap; | ||
87 | |||
88 | if (!ies) | ||
89 | return; | ||
90 | 24 | ||
91 | ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len); | ||
92 | if (ht_cap) { | ||
93 | node->is_11n_enabled = 1; | ||
94 | node->max_amsdu = le16_to_cpu(ht_cap->cap_info) & | ||
95 | IEEE80211_HT_CAP_MAX_AMSDU ? | ||
96 | MWIFIEX_TX_DATA_BUF_SIZE_8K : | ||
97 | MWIFIEX_TX_DATA_BUF_SIZE_4K; | ||
98 | } else { | ||
99 | node->is_11n_enabled = 0; | ||
100 | } | ||
101 | 25 | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * This function will delete a station entry from station list | ||
107 | */ | ||
108 | static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac) | ||
109 | { | ||
110 | struct mwifiex_sta_node *node; | ||
111 | unsigned long flags; | ||
112 | |||
113 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | ||
114 | |||
115 | node = mwifiex_get_sta_entry(priv, mac); | ||
116 | if (node) { | ||
117 | list_del(&node->list); | ||
118 | kfree(node); | ||
119 | } | ||
120 | |||
121 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * This function will delete all stations from associated station list. | ||
127 | */ | ||
128 | static void mwifiex_del_all_sta_list(struct mwifiex_private *priv) | ||
129 | { | ||
130 | struct mwifiex_sta_node *node, *tmp; | ||
131 | unsigned long flags; | ||
132 | |||
133 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | ||
134 | |||
135 | list_for_each_entry_safe(node, tmp, &priv->sta_list, list) { | ||
136 | list_del(&node->list); | ||
137 | kfree(node); | ||
138 | } | ||
139 | |||
140 | INIT_LIST_HEAD(&priv->sta_list); | ||
141 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
142 | return; | ||
143 | } | ||
144 | 26 | ||
145 | /* | 27 | /* |
146 | * This function handles AP interface specific events generated by firmware. | 28 | * This function handles AP interface specific events generated by firmware. |
@@ -268,9 +150,9 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
268 | case EVENT_ADDBA: | 150 | case EVENT_ADDBA: |
269 | dev_dbg(adapter->dev, "event: ADDBA Request\n"); | 151 | dev_dbg(adapter->dev, "event: ADDBA Request\n"); |
270 | if (priv->media_connected) | 152 | if (priv->media_connected) |
271 | mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP, | 153 | mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, |
272 | HostCmd_ACT_GEN_SET, 0, | 154 | HostCmd_ACT_GEN_SET, 0, |
273 | adapter->event_body); | 155 | adapter->event_body, false); |
274 | break; | 156 | break; |
275 | case EVENT_DELBA: | 157 | case EVENT_DELBA: |
276 | dev_dbg(adapter->dev, "event: DELBA Request\n"); | 158 | dev_dbg(adapter->dev, "event: DELBA Request\n"); |
@@ -284,6 +166,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
284 | mwifiex_11n_ba_stream_timeout(priv, ba_timeout); | 166 | mwifiex_11n_ba_stream_timeout(priv, ba_timeout); |
285 | } | 167 | } |
286 | break; | 168 | break; |
169 | case EVENT_EXT_SCAN_REPORT: | ||
170 | dev_dbg(adapter->dev, "event: EXT_SCAN Report\n"); | ||
171 | if (adapter->ext_scan) | ||
172 | return mwifiex_handle_event_ext_scan_report(priv, | ||
173 | adapter->event_skb->data); | ||
174 | break; | ||
287 | default: | 175 | default: |
288 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 176 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
289 | eventcause); | 177 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 3c74eb254927..9a56bc61cb1d 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c | |||
@@ -284,27 +284,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, | |||
284 | return 0; | 284 | return 0; |
285 | } | 285 | } |
286 | 286 | ||
287 | if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) { | 287 | if (rx_pkt_type == PKT_TYPE_MGMT) { |
288 | struct sk_buff_head list; | ||
289 | struct sk_buff *rx_skb; | ||
290 | |||
291 | __skb_queue_head_init(&list); | ||
292 | skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); | ||
293 | skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length)); | ||
294 | |||
295 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | ||
296 | priv->wdev->iftype, 0, false); | ||
297 | |||
298 | while (!skb_queue_empty(&list)) { | ||
299 | rx_skb = __skb_dequeue(&list); | ||
300 | ret = mwifiex_recv_packet(priv, rx_skb); | ||
301 | if (ret) | ||
302 | dev_err(adapter->dev, | ||
303 | "AP:Rx A-MSDU failed"); | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { | ||
308 | ret = mwifiex_process_mgmt_packet(priv, skb); | 288 | ret = mwifiex_process_mgmt_packet(priv, skb); |
309 | if (ret) | 289 | if (ret) |
310 | dev_err(adapter->dev, "Rx of mgmt packet failed"); | 290 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 208748804a55..edbe4aff00d8 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -459,6 +459,7 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message) | |||
459 | * 'suspended' state and a 'disconnect' one. | 459 | * 'suspended' state and a 'disconnect' one. |
460 | */ | 460 | */ |
461 | adapter->is_suspended = true; | 461 | adapter->is_suspended = true; |
462 | adapter->hs_enabling = false; | ||
462 | 463 | ||
463 | if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb) | 464 | if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb) |
464 | usb_kill_urb(card->rx_cmd.urb); | 465 | usb_kill_urb(card->rx_cmd.urb); |
@@ -766,11 +767,13 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
766 | switch (le16_to_cpu(card->udev->descriptor.idProduct)) { | 767 | switch (le16_to_cpu(card->udev->descriptor.idProduct)) { |
767 | case USB8897_PID_1: | 768 | case USB8897_PID_1: |
768 | case USB8897_PID_2: | 769 | case USB8897_PID_2: |
770 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; | ||
769 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); | 771 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); |
770 | break; | 772 | break; |
771 | case USB8797_PID_1: | 773 | case USB8797_PID_1: |
772 | case USB8797_PID_2: | 774 | case USB8797_PID_2: |
773 | default: | 775 | default: |
776 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | ||
774 | strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME); | 777 | strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME); |
775 | break; | 778 | break; |
776 | } | 779 | } |
@@ -1024,7 +1027,6 @@ static void mwifiex_usb_cleanup_module(void) | |||
1024 | 1027 | ||
1025 | if (usb_card && usb_card->adapter) { | 1028 | if (usb_card && usb_card->adapter) { |
1026 | struct mwifiex_adapter *adapter = usb_card->adapter; | 1029 | struct mwifiex_adapter *adapter = usb_card->adapter; |
1027 | int i; | ||
1028 | 1030 | ||
1029 | /* In case driver is removed when asynchronous FW downloading is | 1031 | /* In case driver is removed when asynchronous FW downloading is |
1030 | * in progress | 1032 | * in progress |
@@ -1035,11 +1037,8 @@ static void mwifiex_usb_cleanup_module(void) | |||
1035 | if (adapter->is_suspended) | 1037 | if (adapter->is_suspended) |
1036 | mwifiex_usb_resume(usb_card->intf); | 1038 | mwifiex_usb_resume(usb_card->intf); |
1037 | #endif | 1039 | #endif |
1038 | for (i = 0; i < adapter->priv_num; i++) | 1040 | |
1039 | if ((GET_BSS_ROLE(adapter->priv[i]) == | 1041 | mwifiex_deauthenticate_all(adapter); |
1040 | MWIFIEX_BSS_ROLE_STA) && | ||
1041 | adapter->priv[i]->media_connected) | ||
1042 | mwifiex_deauthenticate(adapter->priv[i], NULL); | ||
1043 | 1042 | ||
1044 | mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, | 1043 | mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, |
1045 | MWIFIEX_BSS_ROLE_ANY), | 1044 | MWIFIEX_BSS_ROLE_ANY), |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 9b82e225880c..c3824e37f3f2 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -72,7 +72,7 @@ int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, | |||
72 | return -1; | 72 | return -1; |
73 | } | 73 | } |
74 | 74 | ||
75 | return mwifiex_send_cmd_sync(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL); | 75 | return mwifiex_send_cmd(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL, true); |
76 | } | 76 | } |
77 | EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw); | 77 | EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw); |
78 | 78 | ||
@@ -104,6 +104,7 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, | |||
104 | info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try; | 104 | info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try; |
105 | info->is_hs_configured = adapter->is_hs_configured; | 105 | info->is_hs_configured = adapter->is_hs_configured; |
106 | info->hs_activated = adapter->hs_activated; | 106 | info->hs_activated = adapter->hs_activated; |
107 | info->is_cmd_timedout = adapter->is_cmd_timedout; | ||
107 | info->num_cmd_host_to_card_failure | 108 | info->num_cmd_host_to_card_failure |
108 | = adapter->dbg.num_cmd_host_to_card_failure; | 109 | = adapter->dbg.num_cmd_host_to_card_failure; |
109 | info->num_cmd_sleep_cfm_host_to_card_failure | 110 | info->num_cmd_sleep_cfm_host_to_card_failure |
@@ -119,7 +120,6 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, | |||
119 | info->num_cmd_assoc_failure = | 120 | info->num_cmd_assoc_failure = |
120 | adapter->dbg.num_cmd_assoc_failure; | 121 | adapter->dbg.num_cmd_assoc_failure; |
121 | info->num_tx_timeout = adapter->dbg.num_tx_timeout; | 122 | info->num_tx_timeout = adapter->dbg.num_tx_timeout; |
122 | info->num_cmd_timeout = adapter->dbg.num_cmd_timeout; | ||
123 | info->timeout_cmd_id = adapter->dbg.timeout_cmd_id; | 123 | info->timeout_cmd_id = adapter->dbg.timeout_cmd_id; |
124 | info->timeout_cmd_act = adapter->dbg.timeout_cmd_act; | 124 | info->timeout_cmd_act = adapter->dbg.timeout_cmd_act; |
125 | memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id, | 125 | memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id, |
@@ -252,3 +252,117 @@ int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, | |||
252 | 252 | ||
253 | return 0; | 253 | return 0; |
254 | } | 254 | } |
255 | |||
256 | /* This function will return the pointer to station entry in station list | ||
257 | * table which matches specified mac address. | ||
258 | * This function should be called after acquiring RA list spinlock. | ||
259 | * NULL is returned if station entry is not found in associated STA list. | ||
260 | */ | ||
261 | struct mwifiex_sta_node * | ||
262 | mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac) | ||
263 | { | ||
264 | struct mwifiex_sta_node *node; | ||
265 | |||
266 | if (!mac) | ||
267 | return NULL; | ||
268 | |||
269 | list_for_each_entry(node, &priv->sta_list, list) { | ||
270 | if (!memcmp(node->mac_addr, mac, ETH_ALEN)) | ||
271 | return node; | ||
272 | } | ||
273 | |||
274 | return NULL; | ||
275 | } | ||
276 | |||
277 | /* This function will add a sta_node entry to associated station list | ||
278 | * table with the given mac address. | ||
279 | * If entry exist already, existing entry is returned. | ||
280 | * If received mac address is NULL, NULL is returned. | ||
281 | */ | ||
282 | struct mwifiex_sta_node * | ||
283 | mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac) | ||
284 | { | ||
285 | struct mwifiex_sta_node *node; | ||
286 | unsigned long flags; | ||
287 | |||
288 | if (!mac) | ||
289 | return NULL; | ||
290 | |||
291 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | ||
292 | node = mwifiex_get_sta_entry(priv, mac); | ||
293 | if (node) | ||
294 | goto done; | ||
295 | |||
296 | node = kzalloc(sizeof(*node), GFP_ATOMIC); | ||
297 | if (!node) | ||
298 | goto done; | ||
299 | |||
300 | memcpy(node->mac_addr, mac, ETH_ALEN); | ||
301 | list_add_tail(&node->list, &priv->sta_list); | ||
302 | |||
303 | done: | ||
304 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
305 | return node; | ||
306 | } | ||
307 | |||
308 | /* This function will search for HT IE in association request IEs | ||
309 | * and set station HT parameters accordingly. | ||
310 | */ | ||
311 | void | ||
312 | mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, | ||
313 | int ies_len, struct mwifiex_sta_node *node) | ||
314 | { | ||
315 | const struct ieee80211_ht_cap *ht_cap; | ||
316 | |||
317 | if (!ies) | ||
318 | return; | ||
319 | |||
320 | ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len); | ||
321 | if (ht_cap) { | ||
322 | node->is_11n_enabled = 1; | ||
323 | node->max_amsdu = le16_to_cpu(ht_cap->cap_info) & | ||
324 | IEEE80211_HT_CAP_MAX_AMSDU ? | ||
325 | MWIFIEX_TX_DATA_BUF_SIZE_8K : | ||
326 | MWIFIEX_TX_DATA_BUF_SIZE_4K; | ||
327 | } else { | ||
328 | node->is_11n_enabled = 0; | ||
329 | } | ||
330 | |||
331 | return; | ||
332 | } | ||
333 | |||
334 | /* This function will delete a station entry from station list */ | ||
335 | void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac) | ||
336 | { | ||
337 | struct mwifiex_sta_node *node; | ||
338 | unsigned long flags; | ||
339 | |||
340 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | ||
341 | |||
342 | node = mwifiex_get_sta_entry(priv, mac); | ||
343 | if (node) { | ||
344 | list_del(&node->list); | ||
345 | kfree(node); | ||
346 | } | ||
347 | |||
348 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
349 | return; | ||
350 | } | ||
351 | |||
352 | /* This function will delete all stations from associated station list. */ | ||
353 | void mwifiex_del_all_sta_list(struct mwifiex_private *priv) | ||
354 | { | ||
355 | struct mwifiex_sta_node *node, *tmp; | ||
356 | unsigned long flags; | ||
357 | |||
358 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | ||
359 | |||
360 | list_for_each_entry_safe(node, tmp, &priv->sta_list, list) { | ||
361 | list_del(&node->list); | ||
362 | kfree(node); | ||
363 | } | ||
364 | |||
365 | INIT_LIST_HEAD(&priv->sta_list); | ||
366 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | ||
367 | return; | ||
368 | } | ||
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h index cb2d0582bd36..ddae57021397 100644 --- a/drivers/net/wireless/mwifiex/util.h +++ b/drivers/net/wireless/mwifiex/util.h | |||
@@ -30,8 +30,24 @@ static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) | |||
30 | return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t)); | 30 | return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t)); |
31 | } | 31 | } |
32 | 32 | ||
33 | static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb, dma_addr_t *buf_pa) | 33 | struct mwifiex_dma_mapping { |
34 | dma_addr_t addr; | ||
35 | size_t len; | ||
36 | }; | ||
37 | |||
38 | static inline void MWIFIEX_SKB_PACB(struct sk_buff *skb, | ||
39 | struct mwifiex_dma_mapping *mapping) | ||
34 | { | 40 | { |
35 | memcpy(buf_pa, skb->cb, sizeof(dma_addr_t)); | 41 | memcpy(mapping, skb->cb, sizeof(*mapping)); |
36 | } | 42 | } |
43 | |||
44 | static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb) | ||
45 | { | ||
46 | struct mwifiex_dma_mapping mapping; | ||
47 | |||
48 | MWIFIEX_SKB_PACB(skb, &mapping); | ||
49 | |||
50 | return mapping.addr; | ||
51 | } | ||
52 | |||
37 | #endif /* !_MWIFIEX_UTIL_H_ */ | 53 | #endif /* !_MWIFIEX_UTIL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 981cf6e7c73b..0a7cc742aed7 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -37,8 +37,8 @@ | |||
37 | /* Offset for TOS field in the IP header */ | 37 | /* Offset for TOS field in the IP header */ |
38 | #define IPTOS_OFFSET 5 | 38 | #define IPTOS_OFFSET 5 |
39 | 39 | ||
40 | static bool enable_tx_amsdu; | 40 | static bool disable_tx_amsdu; |
41 | module_param(enable_tx_amsdu, bool, 0644); | 41 | module_param(disable_tx_amsdu, bool, 0644); |
42 | 42 | ||
43 | /* WMM information IE */ | 43 | /* WMM information IE */ |
44 | static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, | 44 | static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, |
@@ -64,21 +64,6 @@ static u8 tos_to_tid[] = { | |||
64 | 0x07 /* 1 1 1 AC_VO */ | 64 | 0x07 /* 1 1 1 AC_VO */ |
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* | ||
68 | * This table inverses the tos_to_tid operation to get a priority | ||
69 | * which is in sequential order, and can be compared. | ||
70 | * Use this to compare the priority of two different TIDs. | ||
71 | */ | ||
72 | static u8 tos_to_tid_inv[] = { | ||
73 | 0x02, /* from tos_to_tid[2] = 0 */ | ||
74 | 0x00, /* from tos_to_tid[0] = 1 */ | ||
75 | 0x01, /* from tos_to_tid[1] = 2 */ | ||
76 | 0x03, | ||
77 | 0x04, | ||
78 | 0x05, | ||
79 | 0x06, | ||
80 | 0x07}; | ||
81 | |||
82 | static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; | 67 | static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; |
83 | 68 | ||
84 | /* | 69 | /* |
@@ -175,8 +160,15 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra) | |||
175 | break; | 160 | break; |
176 | 161 | ||
177 | ra_list->is_11n_enabled = 0; | 162 | ra_list->is_11n_enabled = 0; |
163 | ra_list->tdls_link = false; | ||
178 | if (!mwifiex_queuing_ra_based(priv)) { | 164 | if (!mwifiex_queuing_ra_based(priv)) { |
179 | ra_list->is_11n_enabled = IS_11N_ENABLED(priv); | 165 | if (mwifiex_get_tdls_link_status(priv, ra) == |
166 | TDLS_SETUP_COMPLETE) { | ||
167 | ra_list->is_11n_enabled = | ||
168 | mwifiex_tdls_peer_11n_enabled(priv, ra); | ||
169 | } else { | ||
170 | ra_list->is_11n_enabled = IS_11N_ENABLED(priv); | ||
171 | } | ||
180 | } else { | 172 | } else { |
181 | ra_list->is_11n_enabled = | 173 | ra_list->is_11n_enabled = |
182 | mwifiex_is_sta_11n_enabled(priv, node); | 174 | mwifiex_is_sta_11n_enabled(priv, node); |
@@ -213,8 +205,9 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) | |||
213 | * This function map ACs to TIDs. | 205 | * This function map ACs to TIDs. |
214 | */ | 206 | */ |
215 | static void | 207 | static void |
216 | mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) | 208 | mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv) |
217 | { | 209 | { |
210 | struct mwifiex_wmm_desc *wmm = &priv->wmm; | ||
218 | u8 *queue_priority = wmm->queue_priority; | 211 | u8 *queue_priority = wmm->queue_priority; |
219 | int i; | 212 | int i; |
220 | 213 | ||
@@ -224,7 +217,7 @@ mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm) | |||
224 | } | 217 | } |
225 | 218 | ||
226 | for (i = 0; i < MAX_NUM_TID; ++i) | 219 | for (i = 0; i < MAX_NUM_TID; ++i) |
227 | tos_to_tid_inv[tos_to_tid[i]] = (u8)i; | 220 | priv->tos_to_tid_inv[tos_to_tid[i]] = (u8)i; |
228 | 221 | ||
229 | atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); | 222 | atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); |
230 | } | 223 | } |
@@ -285,7 +278,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, | |||
285 | } | 278 | } |
286 | } | 279 | } |
287 | 280 | ||
288 | mwifiex_wmm_queue_priorities_tid(&priv->wmm); | 281 | mwifiex_wmm_queue_priorities_tid(priv); |
289 | } | 282 | } |
290 | 283 | ||
291 | /* | 284 | /* |
@@ -388,8 +381,7 @@ mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) | |||
388 | * AP is disabled (due to call admission control (ACM bit). Mapping | 381 | * AP is disabled (due to call admission control (ACM bit). Mapping |
389 | * of TID to AC is taken care of internally. | 382 | * of TID to AC is taken care of internally. |
390 | */ | 383 | */ |
391 | static u8 | 384 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) |
392 | mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) | ||
393 | { | 385 | { |
394 | enum mwifiex_wmm_ac_e ac, ac_down; | 386 | enum mwifiex_wmm_ac_e ac, ac_down; |
395 | u8 new_tid; | 387 | u8 new_tid; |
@@ -421,9 +413,17 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) | |||
421 | continue; | 413 | continue; |
422 | 414 | ||
423 | for (i = 0; i < MAX_NUM_TID; ++i) { | 415 | for (i = 0; i < MAX_NUM_TID; ++i) { |
424 | priv->aggr_prio_tbl[i].amsdu = tos_to_tid_inv[i]; | 416 | if (!disable_tx_amsdu && |
425 | priv->aggr_prio_tbl[i].ampdu_ap = tos_to_tid_inv[i]; | 417 | adapter->tx_buf_size > MWIFIEX_TX_DATA_BUF_SIZE_2K) |
426 | priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; | 418 | priv->aggr_prio_tbl[i].amsdu = |
419 | priv->tos_to_tid_inv[i]; | ||
420 | else | ||
421 | priv->aggr_prio_tbl[i].amsdu = | ||
422 | BA_STREAM_NOT_ALLOWED; | ||
423 | priv->aggr_prio_tbl[i].ampdu_ap = | ||
424 | priv->tos_to_tid_inv[i]; | ||
425 | priv->aggr_prio_tbl[i].ampdu_user = | ||
426 | priv->tos_to_tid_inv[i]; | ||
427 | } | 427 | } |
428 | 428 | ||
429 | priv->aggr_prio_tbl[6].amsdu | 429 | priv->aggr_prio_tbl[6].amsdu |
@@ -546,6 +546,7 @@ void | |||
546 | mwifiex_clean_txrx(struct mwifiex_private *priv) | 546 | mwifiex_clean_txrx(struct mwifiex_private *priv) |
547 | { | 547 | { |
548 | unsigned long flags; | 548 | unsigned long flags; |
549 | struct sk_buff *skb, *tmp; | ||
549 | 550 | ||
550 | mwifiex_11n_cleanup_reorder_tbl(priv); | 551 | mwifiex_11n_cleanup_reorder_tbl(priv); |
551 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); | 552 | spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); |
@@ -563,6 +564,9 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) | |||
563 | !priv->adapter->surprise_removed) | 564 | !priv->adapter->surprise_removed) |
564 | priv->adapter->if_ops.clean_pcie_ring(priv->adapter); | 565 | priv->adapter->if_ops.clean_pcie_ring(priv->adapter); |
565 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); | 566 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); |
567 | |||
568 | skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) | ||
569 | mwifiex_write_data_complete(priv->adapter, skb, 0, -1); | ||
566 | } | 570 | } |
567 | 571 | ||
568 | /* | 572 | /* |
@@ -591,7 +595,7 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, | |||
591 | * If no such node is found, a new node is added first and then | 595 | * If no such node is found, a new node is added first and then |
592 | * retrieved. | 596 | * retrieved. |
593 | */ | 597 | */ |
594 | static struct mwifiex_ra_list_tbl * | 598 | struct mwifiex_ra_list_tbl * |
595 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) | 599 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr) |
596 | { | 600 | { |
597 | struct mwifiex_ra_list_tbl *ra_list; | 601 | struct mwifiex_ra_list_tbl *ra_list; |
@@ -641,6 +645,21 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
641 | struct mwifiex_ra_list_tbl *ra_list; | 645 | struct mwifiex_ra_list_tbl *ra_list; |
642 | u8 ra[ETH_ALEN], tid_down; | 646 | u8 ra[ETH_ALEN], tid_down; |
643 | unsigned long flags; | 647 | unsigned long flags; |
648 | struct list_head list_head; | ||
649 | int tdls_status = TDLS_NOT_SETUP; | ||
650 | struct ethhdr *eth_hdr = (struct ethhdr *)skb->data; | ||
651 | struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); | ||
652 | |||
653 | memcpy(ra, eth_hdr->h_dest, ETH_ALEN); | ||
654 | |||
655 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA && | ||
656 | ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) { | ||
657 | if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS) | ||
658 | dev_dbg(adapter->dev, | ||
659 | "TDLS setup packet for %pM. Don't block\n", ra); | ||
660 | else | ||
661 | tdls_status = mwifiex_get_tdls_link_status(priv, ra); | ||
662 | } | ||
644 | 663 | ||
645 | if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { | 664 | if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { |
646 | dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); | 665 | dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); |
@@ -659,12 +678,27 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
659 | have only 1 raptr for a tid in case of infra */ | 678 | have only 1 raptr for a tid in case of infra */ |
660 | if (!mwifiex_queuing_ra_based(priv) && | 679 | if (!mwifiex_queuing_ra_based(priv) && |
661 | !mwifiex_is_skb_mgmt_frame(skb)) { | 680 | !mwifiex_is_skb_mgmt_frame(skb)) { |
662 | if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) | 681 | switch (tdls_status) { |
663 | ra_list = list_first_entry( | 682 | case TDLS_SETUP_COMPLETE: |
664 | &priv->wmm.tid_tbl_ptr[tid_down].ra_list, | 683 | ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, |
665 | struct mwifiex_ra_list_tbl, list); | 684 | ra); |
666 | else | 685 | tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; |
667 | ra_list = NULL; | 686 | break; |
687 | case TDLS_SETUP_INPROGRESS: | ||
688 | skb_queue_tail(&priv->tdls_txq, skb); | ||
689 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
690 | flags); | ||
691 | return; | ||
692 | default: | ||
693 | list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list; | ||
694 | if (!list_empty(&list_head)) | ||
695 | ra_list = list_first_entry( | ||
696 | &list_head, struct mwifiex_ra_list_tbl, | ||
697 | list); | ||
698 | else | ||
699 | ra_list = NULL; | ||
700 | break; | ||
701 | } | ||
668 | } else { | 702 | } else { |
669 | memcpy(ra, skb->data, ETH_ALEN); | 703 | memcpy(ra, skb->data, ETH_ALEN); |
670 | if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb)) | 704 | if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb)) |
@@ -684,9 +718,9 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, | |||
684 | ra_list->total_pkt_count++; | 718 | ra_list->total_pkt_count++; |
685 | 719 | ||
686 | if (atomic_read(&priv->wmm.highest_queued_prio) < | 720 | if (atomic_read(&priv->wmm.highest_queued_prio) < |
687 | tos_to_tid_inv[tid_down]) | 721 | priv->tos_to_tid_inv[tid_down]) |
688 | atomic_set(&priv->wmm.highest_queued_prio, | 722 | atomic_set(&priv->wmm.highest_queued_prio, |
689 | tos_to_tid_inv[tid_down]); | 723 | priv->tos_to_tid_inv[tid_down]); |
690 | 724 | ||
691 | atomic_inc(&priv->wmm.tx_pkts_queued); | 725 | atomic_inc(&priv->wmm.tx_pkts_queued); |
692 | 726 | ||
@@ -1219,15 +1253,24 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1219 | 1253 | ||
1220 | if (!ptr->is_11n_enabled || | 1254 | if (!ptr->is_11n_enabled || |
1221 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || | 1255 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || |
1222 | priv->wps.session_enable || | 1256 | priv->wps.session_enable) { |
1223 | ((priv->sec_info.wpa_enabled || | 1257 | if (ptr->is_11n_enabled && |
1224 | priv->sec_info.wpa2_enabled) && | 1258 | mwifiex_is_ba_stream_setup(priv, ptr, tid) && |
1225 | !priv->wpa_is_gtk_set)) { | 1259 | mwifiex_is_amsdu_in_ampdu_allowed(priv, ptr, tid) && |
1226 | mwifiex_send_single_packet(priv, ptr, ptr_index, flags); | 1260 | mwifiex_is_amsdu_allowed(priv, tid) && |
1227 | /* ra_list_spinlock has been freed in | 1261 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1228 | mwifiex_send_single_packet() */ | 1262 | adapter->tx_buf_size)) |
1263 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | ||
1264 | /* ra_list_spinlock has been freed in | ||
1265 | * mwifiex_11n_aggregate_pkt() | ||
1266 | */ | ||
1267 | else | ||
1268 | mwifiex_send_single_packet(priv, ptr, ptr_index, flags); | ||
1269 | /* ra_list_spinlock has been freed in | ||
1270 | * mwifiex_send_single_packet() | ||
1271 | */ | ||
1229 | } else { | 1272 | } else { |
1230 | if (mwifiex_is_ampdu_allowed(priv, tid) && | 1273 | if (mwifiex_is_ampdu_allowed(priv, ptr, tid) && |
1231 | ptr->ba_pkt_count > ptr->ba_packet_thr) { | 1274 | ptr->ba_pkt_count > ptr->ba_packet_thr) { |
1232 | if (mwifiex_space_avail_for_new_ba_stream(adapter)) { | 1275 | if (mwifiex_space_avail_for_new_ba_stream(adapter)) { |
1233 | mwifiex_create_ba_tbl(priv, ptr->ra, tid, | 1276 | mwifiex_create_ba_tbl(priv, ptr->ra, tid, |
@@ -1240,7 +1283,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1240 | mwifiex_send_delba(priv, tid_del, ra, 1); | 1283 | mwifiex_send_delba(priv, tid_del, ra, 1); |
1241 | } | 1284 | } |
1242 | } | 1285 | } |
1243 | if (enable_tx_amsdu && mwifiex_is_amsdu_allowed(priv, tid) && | 1286 | if (mwifiex_is_amsdu_allowed(priv, tid) && |
1244 | mwifiex_is_11n_aggragation_possible(priv, ptr, | 1287 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1245 | adapter->tx_buf_size)) | 1288 | adapter->tx_buf_size)) |
1246 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | 1289 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); |
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index 0f129d498fb1..83e42083ebff 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h | |||
@@ -34,6 +34,21 @@ enum ieee_types_wmm_ecw_bitmasks { | |||
34 | static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; | 34 | static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * This table inverses the tos_to_tid operation to get a priority | ||
38 | * which is in sequential order, and can be compared. | ||
39 | * Use this to compare the priority of two different TIDs. | ||
40 | */ | ||
41 | static const u8 tos_to_tid_inv[] = { | ||
42 | 0x02, /* from tos_to_tid[2] = 0 */ | ||
43 | 0x00, /* from tos_to_tid[0] = 1 */ | ||
44 | 0x01, /* from tos_to_tid[1] = 2 */ | ||
45 | 0x03, | ||
46 | 0x04, | ||
47 | 0x05, | ||
48 | 0x06, | ||
49 | 0x07}; | ||
50 | |||
51 | /* | ||
37 | * This function retrieves the TID of the given RA list. | 52 | * This function retrieves the TID of the given RA list. |
38 | */ | 53 | */ |
39 | static inline int | 54 | static inline int |
@@ -107,5 +122,8 @@ void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, | |||
107 | void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); | 122 | void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); |
108 | int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, | 123 | int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, |
109 | const struct host_cmd_ds_command *resp); | 124 | const struct host_cmd_ds_command *resp); |
125 | struct mwifiex_ra_list_tbl * | ||
126 | mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr); | ||
127 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); | ||
110 | 128 | ||
111 | #endif /* !_MWIFIEX_WMM_H_ */ | 129 | #endif /* !_MWIFIEX_WMM_H_ */ |