diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex')
41 files changed, 3804 insertions, 1134 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..b41155829220 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 | ||
@@ -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; |
@@ -534,6 +514,11 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
534 | return -1; | 514 | return -1; |
535 | } | 515 | } |
536 | 516 | ||
517 | if (adapter->is_cmd_timedout) { | ||
518 | dev_err(adapter->dev, "PREP_CMD: FW is in bad state\n"); | ||
519 | return -1; | ||
520 | } | ||
521 | |||
537 | if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { | 522 | if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { |
538 | if (cmd_no != HostCmd_CMD_FUNC_INIT) { | 523 | if (cmd_no != HostCmd_CMD_FUNC_INIT) { |
539 | dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); | 524 | dev_err(adapter->dev, "PREP_CMD: FW in reset state\n"); |
@@ -550,7 +535,7 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
550 | } | 535 | } |
551 | 536 | ||
552 | /* Initialize the command node */ | 537 | /* Initialize the command node */ |
553 | mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf); | 538 | mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf, sync); |
554 | 539 | ||
555 | if (!cmd_node->cmd_skb) { | 540 | if (!cmd_node->cmd_skb) { |
556 | dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); | 541 | dev_err(adapter->dev, "PREP_CMD: no free cmd buf\n"); |
@@ -595,7 +580,8 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
595 | } | 580 | } |
596 | 581 | ||
597 | /* Send command */ | 582 | /* Send command */ |
598 | if (cmd_no == HostCmd_CMD_802_11_SCAN) { | 583 | if (cmd_no == HostCmd_CMD_802_11_SCAN || |
584 | cmd_no == HostCmd_CMD_802_11_SCAN_EXT) { | ||
599 | mwifiex_queue_scan_cmd(priv, cmd_node); | 585 | mwifiex_queue_scan_cmd(priv, cmd_node); |
600 | } else { | 586 | } else { |
601 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | 587 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); |
@@ -785,7 +771,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
785 | unsigned long flags; | 771 | unsigned long flags; |
786 | 772 | ||
787 | /* Now we got response from FW, cancel the command timer */ | 773 | /* Now we got response from FW, cancel the command timer */ |
788 | del_timer(&adapter->cmd_timer); | 774 | del_timer_sync(&adapter->cmd_timer); |
789 | 775 | ||
790 | if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { | 776 | if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { |
791 | resp = (struct host_cmd_ds_command *) adapter->upld_buf; | 777 | resp = (struct host_cmd_ds_command *) adapter->upld_buf; |
@@ -794,7 +780,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | |||
794 | return -1; | 780 | return -1; |
795 | } | 781 | } |
796 | 782 | ||
797 | adapter->num_cmd_timeout = 0; | 783 | adapter->is_cmd_timedout = 0; |
798 | 784 | ||
799 | resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; | 785 | resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; |
800 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { | 786 | if (adapter->curr_cmd->cmd_flag & CMD_F_CANCELED) { |
@@ -905,8 +891,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
905 | struct cmd_ctrl_node *cmd_node; | 891 | struct cmd_ctrl_node *cmd_node; |
906 | struct timeval tstamp; | 892 | struct timeval tstamp; |
907 | 893 | ||
908 | adapter->num_cmd_timeout++; | 894 | adapter->is_cmd_timedout = 1; |
909 | adapter->dbg.num_cmd_timeout++; | ||
910 | if (!adapter->curr_cmd) { | 895 | if (!adapter->curr_cmd) { |
911 | dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); | 896 | dev_dbg(adapter->dev, "cmd: empty curr_cmd\n"); |
912 | return; | 897 | return; |
@@ -929,8 +914,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
929 | dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", | 914 | dev_err(adapter->dev, "num_cmd_h2c_failure = %d\n", |
930 | adapter->dbg.num_cmd_host_to_card_failure); | 915 | adapter->dbg.num_cmd_host_to_card_failure); |
931 | 916 | ||
932 | dev_err(adapter->dev, "num_cmd_timeout = %d\n", | 917 | dev_err(adapter->dev, "is_cmd_timedout = %d\n", |
933 | adapter->dbg.num_cmd_timeout); | 918 | adapter->is_cmd_timedout); |
934 | dev_err(adapter->dev, "num_tx_timeout = %d\n", | 919 | dev_err(adapter->dev, "num_tx_timeout = %d\n", |
935 | adapter->dbg.num_tx_timeout); | 920 | adapter->dbg.num_tx_timeout); |
936 | 921 | ||
@@ -987,7 +972,9 @@ void | |||
987 | mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | 972 | mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) |
988 | { | 973 | { |
989 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; | 974 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; |
990 | unsigned long flags; | 975 | unsigned long flags, cmd_flags; |
976 | struct mwifiex_private *priv; | ||
977 | int i; | ||
991 | 978 | ||
992 | /* Cancel current cmd */ | 979 | /* Cancel current cmd */ |
993 | if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { | 980 | if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { |
@@ -1027,9 +1014,21 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | |||
1027 | } | 1014 | } |
1028 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | 1015 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); |
1029 | 1016 | ||
1030 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | 1017 | if (adapter->scan_processing) { |
1031 | adapter->scan_processing = false; | 1018 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); |
1032 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 1019 | adapter->scan_processing = false; |
1020 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | ||
1021 | for (i = 0; i < adapter->priv_num; i++) { | ||
1022 | priv = adapter->priv[i]; | ||
1023 | if (!priv) | ||
1024 | continue; | ||
1025 | if (priv->scan_request) { | ||
1026 | dev_dbg(adapter->dev, "info: aborting scan\n"); | ||
1027 | cfg80211_scan_done(priv->scan_request, 1); | ||
1028 | priv->scan_request = NULL; | ||
1029 | } | ||
1030 | } | ||
1031 | } | ||
1033 | } | 1032 | } |
1034 | 1033 | ||
1035 | /* | 1034 | /* |
@@ -1048,7 +1047,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
1048 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | 1047 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; |
1049 | unsigned long cmd_flags; | 1048 | unsigned long cmd_flags; |
1050 | unsigned long scan_pending_q_flags; | 1049 | unsigned long scan_pending_q_flags; |
1051 | bool cancel_scan_cmd = false; | 1050 | struct mwifiex_private *priv; |
1051 | int i; | ||
1052 | 1052 | ||
1053 | if ((adapter->curr_cmd) && | 1053 | if ((adapter->curr_cmd) && |
1054 | (adapter->curr_cmd->wait_q_enabled)) { | 1054 | (adapter->curr_cmd->wait_q_enabled)) { |
@@ -1074,15 +1074,24 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) | |||
1074 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | 1074 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); |
1075 | spin_lock_irqsave(&adapter->scan_pending_q_lock, | 1075 | spin_lock_irqsave(&adapter->scan_pending_q_lock, |
1076 | scan_pending_q_flags); | 1076 | scan_pending_q_flags); |
1077 | cancel_scan_cmd = true; | ||
1078 | } | 1077 | } |
1079 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1078 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1080 | scan_pending_q_flags); | 1079 | scan_pending_q_flags); |
1081 | 1080 | ||
1082 | if (cancel_scan_cmd) { | 1081 | if (adapter->scan_processing) { |
1083 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); | 1082 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); |
1084 | adapter->scan_processing = false; | 1083 | adapter->scan_processing = false; |
1085 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); | 1084 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); |
1085 | for (i = 0; i < adapter->priv_num; i++) { | ||
1086 | priv = adapter->priv[i]; | ||
1087 | if (!priv) | ||
1088 | continue; | ||
1089 | if (priv->scan_request) { | ||
1090 | dev_dbg(adapter->dev, "info: aborting scan\n"); | ||
1091 | cfg80211_scan_done(priv->scan_request, 1); | ||
1092 | priv->scan_request = NULL; | ||
1093 | } | ||
1094 | } | ||
1086 | } | 1095 | } |
1087 | adapter->cmd_wait_q.status = -1; | 1096 | adapter->cmd_wait_q.status = -1; |
1088 | } | 1097 | } |
@@ -1454,7 +1463,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1454 | { | 1463 | { |
1455 | struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; | 1464 | struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; |
1456 | struct mwifiex_adapter *adapter = priv->adapter; | 1465 | struct mwifiex_adapter *adapter = priv->adapter; |
1457 | int i; | 1466 | struct mwifiex_ie_types_header *tlv; |
1467 | struct hw_spec_fw_api_rev *api_rev; | ||
1468 | u16 resp_size, api_id; | ||
1469 | int i, left_len, parsed_len = 0; | ||
1458 | 1470 | ||
1459 | adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); | 1471 | adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); |
1460 | 1472 | ||
@@ -1490,6 +1502,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1490 | } | 1502 | } |
1491 | 1503 | ||
1492 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); | 1504 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); |
1505 | adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff; | ||
1493 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); | 1506 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); |
1494 | 1507 | ||
1495 | if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { | 1508 | if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { |
@@ -1498,8 +1511,10 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1498 | /* Copy 11AC cap */ | 1511 | /* Copy 11AC cap */ |
1499 | adapter->hw_dot_11ac_dev_cap = | 1512 | adapter->hw_dot_11ac_dev_cap = |
1500 | le32_to_cpu(hw_spec->dot_11ac_dev_cap); | 1513 | le32_to_cpu(hw_spec->dot_11ac_dev_cap); |
1501 | adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap; | 1514 | 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; | 1515 | & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; |
1516 | adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap | ||
1517 | & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; | ||
1503 | 1518 | ||
1504 | /* Copy 11AC mcs */ | 1519 | /* Copy 11AC mcs */ |
1505 | adapter->hw_dot_11ac_mcs_support = | 1520 | adapter->hw_dot_11ac_mcs_support = |
@@ -1510,6 +1525,46 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1510 | adapter->is_hw_11ac_capable = false; | 1525 | adapter->is_hw_11ac_capable = false; |
1511 | } | 1526 | } |
1512 | 1527 | ||
1528 | resp_size = le16_to_cpu(resp->size) - S_DS_GEN; | ||
1529 | if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) { | ||
1530 | /* we have variable HW SPEC information */ | ||
1531 | left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec); | ||
1532 | while (left_len > sizeof(struct mwifiex_ie_types_header)) { | ||
1533 | tlv = (void *)&hw_spec->tlvs + parsed_len; | ||
1534 | switch (le16_to_cpu(tlv->type)) { | ||
1535 | case TLV_TYPE_FW_API_REV: | ||
1536 | api_rev = (struct hw_spec_fw_api_rev *)tlv; | ||
1537 | api_id = le16_to_cpu(api_rev->api_id); | ||
1538 | switch (api_id) { | ||
1539 | case KEY_API_VER_ID: | ||
1540 | adapter->fw_key_api_major_ver = | ||
1541 | api_rev->major_ver; | ||
1542 | adapter->fw_key_api_minor_ver = | ||
1543 | api_rev->minor_ver; | ||
1544 | dev_dbg(adapter->dev, | ||
1545 | "fw_key_api v%d.%d\n", | ||
1546 | adapter->fw_key_api_major_ver, | ||
1547 | adapter->fw_key_api_minor_ver); | ||
1548 | break; | ||
1549 | default: | ||
1550 | dev_warn(adapter->dev, | ||
1551 | "Unknown FW api_id: %d\n", | ||
1552 | api_id); | ||
1553 | break; | ||
1554 | } | ||
1555 | break; | ||
1556 | default: | ||
1557 | dev_warn(adapter->dev, | ||
1558 | "Unknown GET_HW_SPEC TLV type: %#x\n", | ||
1559 | le16_to_cpu(tlv->type)); | ||
1560 | break; | ||
1561 | } | ||
1562 | parsed_len += le16_to_cpu(tlv->len) + | ||
1563 | sizeof(struct mwifiex_ie_types_header); | ||
1564 | left_len -= parsed_len; | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1513 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", | 1568 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", |
1514 | adapter->fw_release_number); | 1569 | adapter->fw_release_number); |
1515 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", | 1570 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", |
@@ -1538,6 +1593,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1538 | 1593 | ||
1539 | adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); | 1594 | 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; | 1595 | adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; |
1596 | adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support; | ||
1541 | 1597 | ||
1542 | if (adapter->if_ops.update_mp_end_port) | 1598 | if (adapter->if_ops.update_mp_end_port) |
1543 | adapter->if_ops.update_mp_end_port(adapter, | 1599 | 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..7b4502fefec3 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -194,7 +194,7 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) | |||
194 | if (adapter->if_ops.cleanup_if) | 194 | if (adapter->if_ops.cleanup_if) |
195 | adapter->if_ops.cleanup_if(adapter); | 195 | adapter->if_ops.cleanup_if(adapter); |
196 | 196 | ||
197 | del_timer(&adapter->cmd_timer); | 197 | del_timer_sync(&adapter->cmd_timer); |
198 | 198 | ||
199 | /* Free private structures */ | 199 | /* Free private structures */ |
200 | for (i = 0; i < adapter->priv_num; i++) { | 200 | for (i = 0; i < adapter->priv_num; i++) { |
@@ -678,8 +678,8 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr) | |||
678 | memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); | 678 | memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); |
679 | 679 | ||
680 | /* Send request to firmware */ | 680 | /* Send request to firmware */ |
681 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS, | 681 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS, |
682 | HostCmd_ACT_GEN_SET, 0, NULL); | 682 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
683 | 683 | ||
684 | if (!ret) | 684 | if (!ret) |
685 | memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); | 685 | memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); |
@@ -871,7 +871,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
871 | adapter->is_suspended = false; | 871 | adapter->is_suspended = false; |
872 | adapter->hs_activated = false; | 872 | adapter->hs_activated = false; |
873 | init_waitqueue_head(&adapter->hs_activate_wait_q); | 873 | init_waitqueue_head(&adapter->hs_activate_wait_q); |
874 | adapter->cmd_wait_q_required = false; | ||
875 | init_waitqueue_head(&adapter->cmd_wait_q.wait); | 874 | init_waitqueue_head(&adapter->cmd_wait_q.wait); |
876 | adapter->cmd_wait_q.status = 0; | 875 | adapter->cmd_wait_q.status = 0; |
877 | adapter->scan_wait_q_woken = false; | 876 | adapter->scan_wait_q_woken = false; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index d8ad554ce39f..a67f7da12b30 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; |
@@ -725,12 +777,12 @@ struct mwifiex_adapter { | |||
725 | u8 event_body[MAX_EVENT_SIZE]; | 777 | u8 event_body[MAX_EVENT_SIZE]; |
726 | u32 hw_dot_11n_dev_cap; | 778 | u32 hw_dot_11n_dev_cap; |
727 | u8 hw_dev_mcs_support; | 779 | u8 hw_dev_mcs_support; |
780 | u8 user_dev_mcs_support; | ||
728 | u8 adhoc_11n_enabled; | 781 | u8 adhoc_11n_enabled; |
729 | u8 sec_chan_offset; | 782 | u8 sec_chan_offset; |
730 | struct mwifiex_dbg dbg; | 783 | struct mwifiex_dbg dbg; |
731 | u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; | 784 | u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; |
732 | u32 arp_filter_size; | 785 | u32 arp_filter_size; |
733 | u16 cmd_wait_q_required; | ||
734 | struct mwifiex_wait_queue cmd_wait_q; | 786 | struct mwifiex_wait_queue cmd_wait_q; |
735 | u8 scan_wait_q_woken; | 787 | u8 scan_wait_q_woken; |
736 | spinlock_t queue_lock; /* lock for tx queues */ | 788 | spinlock_t queue_lock; /* lock for tx queues */ |
@@ -753,6 +805,9 @@ struct mwifiex_adapter { | |||
753 | atomic_t is_tx_received; | 805 | atomic_t is_tx_received; |
754 | atomic_t pending_bridged_pkts; | 806 | atomic_t pending_bridged_pkts; |
755 | struct semaphore *card_sem; | 807 | struct semaphore *card_sem; |
808 | bool ext_scan; | ||
809 | u8 fw_api_ver; | ||
810 | u8 fw_key_api_major_ver, fw_key_api_minor_ver; | ||
756 | }; | 811 | }; |
757 | 812 | ||
758 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 813 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
@@ -788,11 +843,8 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter); | |||
788 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, | 843 | int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, |
789 | struct cmd_ctrl_node *cmd_node); | 844 | struct cmd_ctrl_node *cmd_node); |
790 | 845 | ||
791 | int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | 846 | int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, |
792 | u16 cmd_action, u32 cmd_oid, void *data_buf); | 847 | 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 | 848 | ||
797 | void mwifiex_cmd_timeout_func(unsigned long function_context); | 849 | void mwifiex_cmd_timeout_func(unsigned long function_context); |
798 | 850 | ||
@@ -880,6 +932,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, | |||
880 | void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason); | 932 | void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason); |
881 | u8 mwifiex_band_to_radio_type(u8 band); | 933 | u8 mwifiex_band_to_radio_type(u8 band); |
882 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); | 934 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); |
935 | void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter); | ||
883 | int mwifiex_adhoc_start(struct mwifiex_private *priv, | 936 | int mwifiex_adhoc_start(struct mwifiex_private *priv, |
884 | struct cfg80211_ssid *adhoc_ssid); | 937 | struct cfg80211_ssid *adhoc_ssid); |
885 | int mwifiex_adhoc_join(struct mwifiex_private *priv, | 938 | int mwifiex_adhoc_join(struct mwifiex_private *priv, |
@@ -938,6 +991,12 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv, | |||
938 | struct cfg80211_ap_settings *params); | 991 | struct cfg80211_ap_settings *params); |
939 | void mwifiex_set_ba_params(struct mwifiex_private *priv); | 992 | void mwifiex_set_ba_params(struct mwifiex_private *priv); |
940 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); | 993 | void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); |
994 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | ||
995 | struct host_cmd_ds_command *cmd, | ||
996 | void *data_buf); | ||
997 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv); | ||
998 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, | ||
999 | void *buf); | ||
941 | 1000 | ||
942 | /* | 1001 | /* |
943 | * This function checks if the queuing is RA based or not. | 1002 | * This function checks if the queuing is RA based or not. |
@@ -1078,7 +1137,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, | |||
1078 | const u8 *key, int key_len, u8 key_index, | 1137 | const u8 *key, int key_len, u8 key_index, |
1079 | const u8 *mac_addr, int disable); | 1138 | const u8 *mac_addr, int disable); |
1080 | 1139 | ||
1081 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); | 1140 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len); |
1082 | 1141 | ||
1083 | int mwifiex_get_ver_ext(struct mwifiex_private *priv); | 1142 | int mwifiex_get_ver_ext(struct mwifiex_private *priv); |
1084 | 1143 | ||
@@ -1159,6 +1218,32 @@ void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv); | |||
1159 | 1218 | ||
1160 | extern const struct ethtool_ops mwifiex_ethtool_ops; | 1219 | extern const struct ethtool_ops mwifiex_ethtool_ops; |
1161 | 1220 | ||
1221 | void mwifiex_del_all_sta_list(struct mwifiex_private *priv); | ||
1222 | void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac); | ||
1223 | void | ||
1224 | mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, | ||
1225 | int ies_len, struct mwifiex_sta_node *node); | ||
1226 | struct mwifiex_sta_node * | ||
1227 | mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac); | ||
1228 | struct mwifiex_sta_node * | ||
1229 | mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); | ||
1230 | int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer, | ||
1231 | u8 action_code, u8 dialog_token, | ||
1232 | u16 status_code, const u8 *extra_ies, | ||
1233 | size_t extra_ies_len); | ||
1234 | int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, | ||
1235 | u8 *peer, u8 action_code, u8 dialog_token, | ||
1236 | u16 status_code, const u8 *extra_ies, | ||
1237 | size_t extra_ies_len); | ||
1238 | void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, | ||
1239 | u8 *buf, int len); | ||
1240 | int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action); | ||
1241 | int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac); | ||
1242 | void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv); | ||
1243 | bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv); | ||
1244 | u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, | ||
1245 | u32 pri_chan, u8 chan_bw); | ||
1246 | |||
1162 | #ifdef CONFIG_DEBUG_FS | 1247 | #ifdef CONFIG_DEBUG_FS |
1163 | void mwifiex_debugfs_init(void); | 1248 | void mwifiex_debugfs_init(void); |
1164 | void mwifiex_debugfs_remove(void); | 1249 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 7fe7b53fb17a..57c353a94b29 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 | */ |
@@ -179,6 +190,7 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, | |||
179 | card->pcie.firmware = data->firmware; | 190 | card->pcie.firmware = data->firmware; |
180 | card->pcie.reg = data->reg; | 191 | card->pcie.reg = data->reg; |
181 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; | 192 | card->pcie.blksz_fw_dl = data->blksz_fw_dl; |
193 | card->pcie.tx_buf_size = data->tx_buf_size; | ||
182 | } | 194 | } |
183 | 195 | ||
184 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, | 196 | if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, |
@@ -199,7 +211,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
199 | struct pcie_service_card *card; | 211 | struct pcie_service_card *card; |
200 | struct mwifiex_adapter *adapter; | 212 | struct mwifiex_adapter *adapter; |
201 | struct mwifiex_private *priv; | 213 | struct mwifiex_private *priv; |
202 | int i; | ||
203 | 214 | ||
204 | card = pci_get_drvdata(pdev); | 215 | card = pci_get_drvdata(pdev); |
205 | if (!card) | 216 | if (!card) |
@@ -218,11 +229,7 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
218 | mwifiex_pcie_resume(&pdev->dev); | 229 | mwifiex_pcie_resume(&pdev->dev); |
219 | #endif | 230 | #endif |
220 | 231 | ||
221 | for (i = 0; i < adapter->priv_num; i++) | 232 | 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 | 233 | ||
227 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 234 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
228 | 235 | ||
@@ -320,6 +327,30 @@ static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) | |||
320 | return; | 327 | return; |
321 | } | 328 | } |
322 | 329 | ||
330 | static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, | ||
331 | u32 max_delay_loop_cnt) | ||
332 | { | ||
333 | struct pcie_service_card *card = adapter->card; | ||
334 | u8 *buffer; | ||
335 | u32 sleep_cookie, count; | ||
336 | |||
337 | for (count = 0; count < max_delay_loop_cnt; count++) { | ||
338 | buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN; | ||
339 | sleep_cookie = *(u32 *)buffer; | ||
340 | |||
341 | if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) { | ||
342 | dev_dbg(adapter->dev, | ||
343 | "sleep cookie found at count %d\n", count); | ||
344 | break; | ||
345 | } | ||
346 | usleep_range(20, 30); | ||
347 | } | ||
348 | |||
349 | if (count >= max_delay_loop_cnt) | ||
350 | dev_dbg(adapter->dev, | ||
351 | "max count reached while accessing sleep cookie\n"); | ||
352 | } | ||
353 | |||
323 | /* This function wakes up the card by reading fw_status register. */ | 354 | /* This function wakes up the card by reading fw_status register. */ |
324 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | 355 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) |
325 | { | 356 | { |
@@ -456,7 +487,7 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) | |||
456 | PCI_DMA_FROMDEVICE)) | 487 | PCI_DMA_FROMDEVICE)) |
457 | return -1; | 488 | return -1; |
458 | 489 | ||
459 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 490 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
460 | 491 | ||
461 | dev_dbg(adapter->dev, | 492 | dev_dbg(adapter->dev, |
462 | "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", | 493 | "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", |
@@ -513,7 +544,7 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) | |||
513 | PCI_DMA_FROMDEVICE)) | 544 | PCI_DMA_FROMDEVICE)) |
514 | return -1; | 545 | return -1; |
515 | 546 | ||
516 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 547 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
517 | 548 | ||
518 | dev_dbg(adapter->dev, | 549 | dev_dbg(adapter->dev, |
519 | "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", | 550 | "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", |
@@ -549,8 +580,8 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter) | |||
549 | desc2 = card->txbd_ring[i]; | 580 | desc2 = card->txbd_ring[i]; |
550 | if (card->tx_buf_list[i]) { | 581 | if (card->tx_buf_list[i]) { |
551 | skb = card->tx_buf_list[i]; | 582 | skb = card->tx_buf_list[i]; |
552 | pci_unmap_single(card->dev, desc2->paddr, | 583 | mwifiex_unmap_pci_memory(adapter, skb, |
553 | skb->len, PCI_DMA_TODEVICE); | 584 | PCI_DMA_TODEVICE); |
554 | dev_kfree_skb_any(skb); | 585 | dev_kfree_skb_any(skb); |
555 | } | 586 | } |
556 | memset(desc2, 0, sizeof(*desc2)); | 587 | memset(desc2, 0, sizeof(*desc2)); |
@@ -558,8 +589,8 @@ static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter) | |||
558 | desc = card->txbd_ring[i]; | 589 | desc = card->txbd_ring[i]; |
559 | if (card->tx_buf_list[i]) { | 590 | if (card->tx_buf_list[i]) { |
560 | skb = card->tx_buf_list[i]; | 591 | skb = card->tx_buf_list[i]; |
561 | pci_unmap_single(card->dev, desc->paddr, | 592 | mwifiex_unmap_pci_memory(adapter, skb, |
562 | skb->len, PCI_DMA_TODEVICE); | 593 | PCI_DMA_TODEVICE); |
563 | dev_kfree_skb_any(skb); | 594 | dev_kfree_skb_any(skb); |
564 | } | 595 | } |
565 | memset(desc, 0, sizeof(*desc)); | 596 | memset(desc, 0, sizeof(*desc)); |
@@ -587,8 +618,8 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter) | |||
587 | desc2 = card->rxbd_ring[i]; | 618 | desc2 = card->rxbd_ring[i]; |
588 | if (card->rx_buf_list[i]) { | 619 | if (card->rx_buf_list[i]) { |
589 | skb = card->rx_buf_list[i]; | 620 | skb = card->rx_buf_list[i]; |
590 | pci_unmap_single(card->dev, desc2->paddr, | 621 | mwifiex_unmap_pci_memory(adapter, skb, |
591 | skb->len, PCI_DMA_FROMDEVICE); | 622 | PCI_DMA_FROMDEVICE); |
592 | dev_kfree_skb_any(skb); | 623 | dev_kfree_skb_any(skb); |
593 | } | 624 | } |
594 | memset(desc2, 0, sizeof(*desc2)); | 625 | memset(desc2, 0, sizeof(*desc2)); |
@@ -596,8 +627,8 @@ static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter) | |||
596 | desc = card->rxbd_ring[i]; | 627 | desc = card->rxbd_ring[i]; |
597 | if (card->rx_buf_list[i]) { | 628 | if (card->rx_buf_list[i]) { |
598 | skb = card->rx_buf_list[i]; | 629 | skb = card->rx_buf_list[i]; |
599 | pci_unmap_single(card->dev, desc->paddr, | 630 | mwifiex_unmap_pci_memory(adapter, skb, |
600 | skb->len, PCI_DMA_FROMDEVICE); | 631 | PCI_DMA_FROMDEVICE); |
601 | dev_kfree_skb_any(skb); | 632 | dev_kfree_skb_any(skb); |
602 | } | 633 | } |
603 | memset(desc, 0, sizeof(*desc)); | 634 | memset(desc, 0, sizeof(*desc)); |
@@ -622,8 +653,8 @@ static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter) | |||
622 | desc = card->evtbd_ring[i]; | 653 | desc = card->evtbd_ring[i]; |
623 | if (card->evt_buf_list[i]) { | 654 | if (card->evt_buf_list[i]) { |
624 | skb = card->evt_buf_list[i]; | 655 | skb = card->evt_buf_list[i]; |
625 | pci_unmap_single(card->dev, desc->paddr, MAX_EVENT_SIZE, | 656 | mwifiex_unmap_pci_memory(adapter, skb, |
626 | PCI_DMA_FROMDEVICE); | 657 | PCI_DMA_FROMDEVICE); |
627 | dev_kfree_skb_any(skb); | 658 | dev_kfree_skb_any(skb); |
628 | } | 659 | } |
629 | card->evt_buf_list[i] = NULL; | 660 | card->evt_buf_list[i] = NULL; |
@@ -861,7 +892,6 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter) | |||
861 | static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) | 892 | static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) |
862 | { | 893 | { |
863 | struct pcie_service_card *card; | 894 | struct pcie_service_card *card; |
864 | dma_addr_t buf_pa; | ||
865 | 895 | ||
866 | if (!adapter) | 896 | if (!adapter) |
867 | return 0; | 897 | return 0; |
@@ -869,16 +899,14 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) | |||
869 | card = adapter->card; | 899 | card = adapter->card; |
870 | 900 | ||
871 | if (card && card->cmdrsp_buf) { | 901 | if (card && card->cmdrsp_buf) { |
872 | MWIFIEX_SKB_PACB(card->cmdrsp_buf, &buf_pa); | 902 | mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf, |
873 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 903 | PCI_DMA_FROMDEVICE); |
874 | PCI_DMA_FROMDEVICE); | ||
875 | dev_kfree_skb_any(card->cmdrsp_buf); | 904 | dev_kfree_skb_any(card->cmdrsp_buf); |
876 | } | 905 | } |
877 | 906 | ||
878 | if (card && card->cmd_buf) { | 907 | if (card && card->cmd_buf) { |
879 | MWIFIEX_SKB_PACB(card->cmd_buf, &buf_pa); | 908 | mwifiex_unmap_pci_memory(adapter, card->cmd_buf, |
880 | pci_unmap_single(card->dev, buf_pa, card->cmd_buf->len, | 909 | PCI_DMA_TODEVICE); |
881 | PCI_DMA_TODEVICE); | ||
882 | } | 910 | } |
883 | return 0; | 911 | return 0; |
884 | } | 912 | } |
@@ -956,7 +984,6 @@ static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter) | |||
956 | static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) | 984 | static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) |
957 | { | 985 | { |
958 | struct sk_buff *skb; | 986 | struct sk_buff *skb; |
959 | dma_addr_t buf_pa; | ||
960 | u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0; | 987 | u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0; |
961 | struct mwifiex_pcie_buf_desc *desc; | 988 | struct mwifiex_pcie_buf_desc *desc; |
962 | struct mwifiex_pfu_buf_desc *desc2; | 989 | struct mwifiex_pfu_buf_desc *desc2; |
@@ -986,13 +1013,13 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) | |||
986 | reg->tx_start_ptr; | 1013 | reg->tx_start_ptr; |
987 | 1014 | ||
988 | skb = card->tx_buf_list[wrdoneidx]; | 1015 | skb = card->tx_buf_list[wrdoneidx]; |
1016 | |||
989 | if (skb) { | 1017 | if (skb) { |
990 | dev_dbg(adapter->dev, | 1018 | dev_dbg(adapter->dev, |
991 | "SEND COMP: Detach skb %p at txbd_rdidx=%d\n", | 1019 | "SEND COMP: Detach skb %p at txbd_rdidx=%d\n", |
992 | skb, wrdoneidx); | 1020 | skb, wrdoneidx); |
993 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1021 | mwifiex_unmap_pci_memory(adapter, skb, |
994 | pci_unmap_single(card->dev, buf_pa, skb->len, | 1022 | PCI_DMA_TODEVICE); |
995 | PCI_DMA_TODEVICE); | ||
996 | 1023 | ||
997 | unmap_count++; | 1024 | unmap_count++; |
998 | 1025 | ||
@@ -1082,12 +1109,12 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | |||
1082 | tmp = (__le16 *)&payload[2]; | 1109 | tmp = (__le16 *)&payload[2]; |
1083 | *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); | 1110 | *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); |
1084 | 1111 | ||
1085 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , | 1112 | if (mwifiex_map_pci_memory(adapter, skb, skb->len, |
1086 | PCI_DMA_TODEVICE)) | 1113 | PCI_DMA_TODEVICE)) |
1087 | return -1; | 1114 | return -1; |
1088 | 1115 | ||
1089 | wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr; | 1116 | wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr; |
1090 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1117 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
1091 | card->tx_buf_list[wrindx] = skb; | 1118 | card->tx_buf_list[wrindx] = skb; |
1092 | 1119 | ||
1093 | if (reg->pfu_enabled) { | 1120 | if (reg->pfu_enabled) { |
@@ -1162,8 +1189,7 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, | |||
1162 | 1189 | ||
1163 | return -EINPROGRESS; | 1190 | return -EINPROGRESS; |
1164 | done_unmap: | 1191 | done_unmap: |
1165 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1192 | 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; | 1193 | card->tx_buf_list[wrindx] = NULL; |
1168 | if (reg->pfu_enabled) | 1194 | if (reg->pfu_enabled) |
1169 | memset(desc2, 0, sizeof(*desc2)); | 1195 | memset(desc2, 0, sizeof(*desc2)); |
@@ -1217,9 +1243,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
1217 | if (!skb_data) | 1243 | if (!skb_data) |
1218 | return -ENOMEM; | 1244 | return -ENOMEM; |
1219 | 1245 | ||
1220 | MWIFIEX_SKB_PACB(skb_data, &buf_pa); | 1246 | 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; | 1247 | card->rx_buf_list[rd_index] = NULL; |
1224 | 1248 | ||
1225 | /* Get data length from interface header - | 1249 | /* Get data length from interface header - |
@@ -1246,7 +1270,7 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
1246 | PCI_DMA_FROMDEVICE)) | 1270 | PCI_DMA_FROMDEVICE)) |
1247 | return -1; | 1271 | return -1; |
1248 | 1272 | ||
1249 | MWIFIEX_SKB_PACB(skb_tmp, &buf_pa); | 1273 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp); |
1250 | 1274 | ||
1251 | dev_dbg(adapter->dev, | 1275 | dev_dbg(adapter->dev, |
1252 | "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n", | 1276 | "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n", |
@@ -1322,7 +1346,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)) | 1346 | if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE)) |
1323 | return -1; | 1347 | return -1; |
1324 | 1348 | ||
1325 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1349 | buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); |
1326 | 1350 | ||
1327 | /* Write the lower 32bits of the physical address to low command | 1351 | /* Write the lower 32bits of the physical address to low command |
1328 | * address scratch register | 1352 | * address scratch register |
@@ -1331,8 +1355,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1331 | dev_err(adapter->dev, | 1355 | dev_err(adapter->dev, |
1332 | "%s: failed to write download command to boot code.\n", | 1356 | "%s: failed to write download command to boot code.\n", |
1333 | __func__); | 1357 | __func__); |
1334 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1358 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1335 | PCI_DMA_TODEVICE); | ||
1336 | return -1; | 1359 | return -1; |
1337 | } | 1360 | } |
1338 | 1361 | ||
@@ -1344,8 +1367,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1344 | dev_err(adapter->dev, | 1367 | dev_err(adapter->dev, |
1345 | "%s: failed to write download command to boot code.\n", | 1368 | "%s: failed to write download command to boot code.\n", |
1346 | __func__); | 1369 | __func__); |
1347 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1370 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1348 | PCI_DMA_TODEVICE); | ||
1349 | return -1; | 1371 | return -1; |
1350 | } | 1372 | } |
1351 | 1373 | ||
@@ -1354,8 +1376,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1354 | dev_err(adapter->dev, | 1376 | dev_err(adapter->dev, |
1355 | "%s: failed to write command len to cmd_size scratch reg\n", | 1377 | "%s: failed to write command len to cmd_size scratch reg\n", |
1356 | __func__); | 1378 | __func__); |
1357 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1379 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1358 | PCI_DMA_TODEVICE); | ||
1359 | return -1; | 1380 | return -1; |
1360 | } | 1381 | } |
1361 | 1382 | ||
@@ -1364,8 +1385,7 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1364 | CPU_INTR_DOOR_BELL)) { | 1385 | CPU_INTR_DOOR_BELL)) { |
1365 | dev_err(adapter->dev, | 1386 | dev_err(adapter->dev, |
1366 | "%s: failed to assert door-bell intr\n", __func__); | 1387 | "%s: failed to assert door-bell intr\n", __func__); |
1367 | pci_unmap_single(card->dev, buf_pa, | 1388 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1368 | MWIFIEX_UPLD_SIZE, PCI_DMA_TODEVICE); | ||
1369 | return -1; | 1389 | return -1; |
1370 | } | 1390 | } |
1371 | 1391 | ||
@@ -1439,7 +1459,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1439 | */ | 1459 | */ |
1440 | 1460 | ||
1441 | if (card->cmdrsp_buf) { | 1461 | if (card->cmdrsp_buf) { |
1442 | MWIFIEX_SKB_PACB(card->cmdrsp_buf, &cmdrsp_buf_pa); | 1462 | cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf); |
1443 | /* Write the lower 32bits of the cmdrsp buffer physical | 1463 | /* Write the lower 32bits of the cmdrsp buffer physical |
1444 | address */ | 1464 | address */ |
1445 | if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, | 1465 | if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, |
@@ -1460,7 +1480,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
1460 | } | 1480 | } |
1461 | } | 1481 | } |
1462 | 1482 | ||
1463 | MWIFIEX_SKB_PACB(card->cmd_buf, &cmd_buf_pa); | 1483 | cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf); |
1464 | /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */ | 1484 | /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */ |
1465 | if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, | 1485 | if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, |
1466 | (u32)cmd_buf_pa)) { | 1486 | (u32)cmd_buf_pa)) { |
@@ -1514,13 +1534,17 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1514 | int count = 0; | 1534 | int count = 0; |
1515 | u16 rx_len; | 1535 | u16 rx_len; |
1516 | __le16 pkt_len; | 1536 | __le16 pkt_len; |
1517 | dma_addr_t buf_pa; | ||
1518 | 1537 | ||
1519 | dev_dbg(adapter->dev, "info: Rx CMD Response\n"); | 1538 | dev_dbg(adapter->dev, "info: Rx CMD Response\n"); |
1520 | 1539 | ||
1521 | MWIFIEX_SKB_PACB(skb, &buf_pa); | 1540 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE); |
1522 | pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, | 1541 | |
1523 | PCI_DMA_FROMDEVICE); | 1542 | /* Unmap the command as a response has been received. */ |
1543 | if (card->cmd_buf) { | ||
1544 | mwifiex_unmap_pci_memory(adapter, card->cmd_buf, | ||
1545 | PCI_DMA_TODEVICE); | ||
1546 | card->cmd_buf = NULL; | ||
1547 | } | ||
1524 | 1548 | ||
1525 | pkt_len = *((__le16 *)skb->data); | 1549 | pkt_len = *((__le16 *)skb->data); |
1526 | rx_len = le16_to_cpu(pkt_len); | 1550 | rx_len = le16_to_cpu(pkt_len); |
@@ -1539,6 +1563,8 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1539 | "Write register failed\n"); | 1563 | "Write register failed\n"); |
1540 | return -1; | 1564 | return -1; |
1541 | } | 1565 | } |
1566 | mwifiex_delay_for_sleep_cookie(adapter, | ||
1567 | MWIFIEX_MAX_DELAY_COUNT); | ||
1542 | while (reg->sleep_cookie && (count++ < 10) && | 1568 | while (reg->sleep_cookie && (count++ < 10) && |
1543 | mwifiex_pcie_ok_to_access_hw(adapter)) | 1569 | mwifiex_pcie_ok_to_access_hw(adapter)) |
1544 | usleep_range(50, 60); | 1570 | usleep_range(50, 60); |
@@ -1552,8 +1578,6 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | |||
1552 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, | 1578 | if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, |
1553 | PCI_DMA_FROMDEVICE)) | 1579 | PCI_DMA_FROMDEVICE)) |
1554 | return -1; | 1580 | return -1; |
1555 | |||
1556 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1557 | } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { | 1581 | } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { |
1558 | adapter->curr_cmd->resp_skb = skb; | 1582 | adapter->curr_cmd->resp_skb = skb; |
1559 | adapter->cmd_resp_received = true; | 1583 | adapter->cmd_resp_received = true; |
@@ -1588,8 +1612,6 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, | |||
1588 | struct sk_buff *skb) | 1612 | struct sk_buff *skb) |
1589 | { | 1613 | { |
1590 | struct pcie_service_card *card = adapter->card; | 1614 | struct pcie_service_card *card = adapter->card; |
1591 | dma_addr_t buf_pa; | ||
1592 | struct sk_buff *skb_tmp; | ||
1593 | 1615 | ||
1594 | if (skb) { | 1616 | if (skb) { |
1595 | card->cmdrsp_buf = skb; | 1617 | card->cmdrsp_buf = skb; |
@@ -1599,14 +1621,6 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, | |||
1599 | return -1; | 1621 | return -1; |
1600 | } | 1622 | } |
1601 | 1623 | ||
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; | 1624 | return 0; |
1611 | } | 1625 | } |
1612 | 1626 | ||
@@ -1619,7 +1633,6 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) | |||
1619 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | 1633 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; |
1620 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | 1634 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; |
1621 | u32 wrptr, event; | 1635 | u32 wrptr, event; |
1622 | dma_addr_t buf_pa; | ||
1623 | struct mwifiex_evt_buf_desc *desc; | 1636 | struct mwifiex_evt_buf_desc *desc; |
1624 | 1637 | ||
1625 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) | 1638 | if (!mwifiex_pcie_ok_to_access_hw(adapter)) |
@@ -1655,9 +1668,7 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) | |||
1655 | 1668 | ||
1656 | dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr); | 1669 | dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr); |
1657 | skb_cmd = card->evt_buf_list[rdptr]; | 1670 | skb_cmd = card->evt_buf_list[rdptr]; |
1658 | MWIFIEX_SKB_PACB(skb_cmd, &buf_pa); | 1671 | 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 | 1672 | ||
1662 | /* Take the pointer and set it to event pointer in adapter | 1673 | /* Take the pointer and set it to event pointer in adapter |
1663 | and will return back after event handling callback */ | 1674 | and will return back after event handling callback */ |
@@ -1703,7 +1714,6 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1703 | int ret = 0; | 1714 | int ret = 0; |
1704 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; | 1715 | u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; |
1705 | u32 wrptr; | 1716 | u32 wrptr; |
1706 | dma_addr_t buf_pa; | ||
1707 | struct mwifiex_evt_buf_desc *desc; | 1717 | struct mwifiex_evt_buf_desc *desc; |
1708 | 1718 | ||
1709 | if (!skb) | 1719 | if (!skb) |
@@ -1728,11 +1738,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, | |||
1728 | MAX_EVENT_SIZE, | 1738 | MAX_EVENT_SIZE, |
1729 | PCI_DMA_FROMDEVICE)) | 1739 | PCI_DMA_FROMDEVICE)) |
1730 | return -1; | 1740 | return -1; |
1731 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1732 | card->evt_buf_list[rdptr] = skb; | 1741 | card->evt_buf_list[rdptr] = skb; |
1733 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1734 | desc = card->evtbd_ring[rdptr]; | 1742 | desc = card->evtbd_ring[rdptr]; |
1735 | desc->paddr = buf_pa; | 1743 | desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb); |
1736 | desc->len = (u16)skb->len; | 1744 | desc->len = (u16)skb->len; |
1737 | desc->flags = 0; | 1745 | desc->flags = 0; |
1738 | skb = NULL; | 1746 | skb = NULL; |
@@ -1782,7 +1790,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1782 | struct sk_buff *skb; | 1790 | struct sk_buff *skb; |
1783 | u32 txlen, tx_blocks = 0, tries, len; | 1791 | u32 txlen, tx_blocks = 0, tries, len; |
1784 | u32 block_retry_cnt = 0; | 1792 | u32 block_retry_cnt = 0; |
1785 | dma_addr_t buf_pa; | ||
1786 | struct pcie_service_card *card = adapter->card; | 1793 | struct pcie_service_card *card = adapter->card; |
1787 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; | 1794 | const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; |
1788 | 1795 | ||
@@ -1880,8 +1887,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1880 | goto done; | 1887 | goto done; |
1881 | } | 1888 | } |
1882 | 1889 | ||
1883 | MWIFIEX_SKB_PACB(skb, &buf_pa); | ||
1884 | |||
1885 | /* Wait for the command done interrupt */ | 1890 | /* Wait for the command done interrupt */ |
1886 | do { | 1891 | do { |
1887 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, | 1892 | if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, |
@@ -1889,16 +1894,15 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
1889 | dev_err(adapter->dev, "%s: Failed to read " | 1894 | dev_err(adapter->dev, "%s: Failed to read " |
1890 | "interrupt status during fw dnld.\n", | 1895 | "interrupt status during fw dnld.\n", |
1891 | __func__); | 1896 | __func__); |
1892 | pci_unmap_single(card->dev, buf_pa, skb->len, | 1897 | mwifiex_unmap_pci_memory(adapter, skb, |
1893 | PCI_DMA_TODEVICE); | 1898 | PCI_DMA_TODEVICE); |
1894 | ret = -1; | 1899 | ret = -1; |
1895 | goto done; | 1900 | goto done; |
1896 | } | 1901 | } |
1897 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == | 1902 | } while ((ireg_intr & CPU_INTR_DOOR_BELL) == |
1898 | CPU_INTR_DOOR_BELL); | 1903 | CPU_INTR_DOOR_BELL); |
1899 | 1904 | ||
1900 | pci_unmap_single(card->dev, buf_pa, skb->len, | 1905 | mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); |
1901 | PCI_DMA_TODEVICE); | ||
1902 | 1906 | ||
1903 | offset += txlen; | 1907 | offset += txlen; |
1904 | } while (true); | 1908 | } while (true); |
@@ -2338,6 +2342,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
2338 | } | 2342 | } |
2339 | 2343 | ||
2340 | adapter->dev = &pdev->dev; | 2344 | adapter->dev = &pdev->dev; |
2345 | adapter->tx_buf_size = card->pcie.tx_buf_size; | ||
2341 | strcpy(adapter->fw_name, card->pcie.firmware); | 2346 | strcpy(adapter->fw_name, card->pcie.firmware); |
2342 | 2347 | ||
2343 | return 0; | 2348 | 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..f13924447a2c 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -595,7 +595,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, | |||
595 | struct mwifiex_chan_scan_param_set *tmp_chan_list; | 595 | struct mwifiex_chan_scan_param_set *tmp_chan_list; |
596 | struct mwifiex_chan_scan_param_set *start_chan; | 596 | struct mwifiex_chan_scan_param_set *start_chan; |
597 | 597 | ||
598 | u32 tlv_idx, rates_size; | 598 | u32 tlv_idx, rates_size, cmd_no; |
599 | u32 total_scan_time; | 599 | u32 total_scan_time; |
600 | u32 done_early; | 600 | u32 done_early; |
601 | u8 radio_type; | 601 | u8 radio_type; |
@@ -733,9 +733,13 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, | |||
733 | 733 | ||
734 | /* Send the scan command to the firmware with the specified | 734 | /* Send the scan command to the firmware with the specified |
735 | cfg */ | 735 | cfg */ |
736 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN, | 736 | if (priv->adapter->ext_scan) |
737 | HostCmd_ACT_GEN_SET, 0, | 737 | cmd_no = HostCmd_CMD_802_11_SCAN_EXT; |
738 | scan_cfg_out); | 738 | else |
739 | cmd_no = HostCmd_CMD_802_11_SCAN; | ||
740 | |||
741 | ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET, | ||
742 | 0, scan_cfg_out, false); | ||
739 | 743 | ||
740 | /* rate IE is updated per scan command but same starting | 744 | /* rate IE is updated per scan command but same starting |
741 | * pointer is used each time so that rate IE from earlier | 745 | * pointer is used each time so that rate IE from earlier |
@@ -786,6 +790,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
786 | struct mwifiex_adapter *adapter = priv->adapter; | 790 | struct mwifiex_adapter *adapter = priv->adapter; |
787 | struct mwifiex_ie_types_num_probes *num_probes_tlv; | 791 | struct mwifiex_ie_types_num_probes *num_probes_tlv; |
788 | struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; | 792 | struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; |
793 | struct mwifiex_ie_types_bssid_list *bssid_tlv; | ||
789 | u8 *tlv_pos; | 794 | u8 *tlv_pos; |
790 | u32 num_probes; | 795 | u32 num_probes; |
791 | u32 ssid_len; | 796 | u32 ssid_len; |
@@ -848,6 +853,17 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
848 | user_scan_in->specific_bssid, | 853 | user_scan_in->specific_bssid, |
849 | sizeof(scan_cfg_out->specific_bssid)); | 854 | sizeof(scan_cfg_out->specific_bssid)); |
850 | 855 | ||
856 | if (adapter->ext_scan && | ||
857 | !is_zero_ether_addr(scan_cfg_out->specific_bssid)) { | ||
858 | bssid_tlv = | ||
859 | (struct mwifiex_ie_types_bssid_list *)tlv_pos; | ||
860 | bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID); | ||
861 | bssid_tlv->header.len = cpu_to_le16(ETH_ALEN); | ||
862 | memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid, | ||
863 | ETH_ALEN); | ||
864 | tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list); | ||
865 | } | ||
866 | |||
851 | for (i = 0; i < user_scan_in->num_ssids; i++) { | 867 | for (i = 0; i < user_scan_in->num_ssids; i++) { |
852 | ssid_len = user_scan_in->ssid_list[i].ssid_len; | 868 | ssid_len = user_scan_in->ssid_list[i].ssid_len; |
853 | 869 | ||
@@ -941,7 +957,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
941 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); | 957 | cpu_to_le16(sizeof(struct ieee80211_ht_cap)); |
942 | radio_type = | 958 | radio_type = |
943 | mwifiex_band_to_radio_type(priv->adapter->config_bands); | 959 | mwifiex_band_to_radio_type(priv->adapter->config_bands); |
944 | mwifiex_fill_cap_info(priv, radio_type, ht_cap); | 960 | mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); |
945 | tlv_pos += sizeof(struct mwifiex_ie_types_htcap); | 961 | tlv_pos += sizeof(struct mwifiex_ie_types_htcap); |
946 | } | 962 | } |
947 | 963 | ||
@@ -1576,6 +1592,228 @@ done: | |||
1576 | return 0; | 1592 | return 0; |
1577 | } | 1593 | } |
1578 | 1594 | ||
1595 | static int | ||
1596 | mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, | ||
1597 | u32 *bytes_left, u64 fw_tsf, u8 *radio_type, | ||
1598 | bool ext_scan, s32 rssi_val) | ||
1599 | { | ||
1600 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1601 | struct mwifiex_chan_freq_power *cfp; | ||
1602 | struct cfg80211_bss *bss; | ||
1603 | u8 bssid[ETH_ALEN]; | ||
1604 | s32 rssi; | ||
1605 | const u8 *ie_buf; | ||
1606 | size_t ie_len; | ||
1607 | u16 channel = 0; | ||
1608 | u16 beacon_size = 0; | ||
1609 | u32 curr_bcn_bytes; | ||
1610 | u32 freq; | ||
1611 | u16 beacon_period; | ||
1612 | u16 cap_info_bitmap; | ||
1613 | u8 *current_ptr; | ||
1614 | u64 timestamp; | ||
1615 | struct mwifiex_fixed_bcn_param *bcn_param; | ||
1616 | struct mwifiex_bss_priv *bss_priv; | ||
1617 | |||
1618 | if (*bytes_left >= sizeof(beacon_size)) { | ||
1619 | /* Extract & convert beacon size from command buffer */ | ||
1620 | memcpy(&beacon_size, *bss_info, sizeof(beacon_size)); | ||
1621 | *bytes_left -= sizeof(beacon_size); | ||
1622 | *bss_info += sizeof(beacon_size); | ||
1623 | } | ||
1624 | |||
1625 | if (!beacon_size || beacon_size > *bytes_left) { | ||
1626 | *bss_info += *bytes_left; | ||
1627 | *bytes_left = 0; | ||
1628 | return -EFAULT; | ||
1629 | } | ||
1630 | |||
1631 | /* Initialize the current working beacon pointer for this BSS | ||
1632 | * iteration | ||
1633 | */ | ||
1634 | current_ptr = *bss_info; | ||
1635 | |||
1636 | /* Advance the return beacon pointer past the current beacon */ | ||
1637 | *bss_info += beacon_size; | ||
1638 | *bytes_left -= beacon_size; | ||
1639 | |||
1640 | curr_bcn_bytes = beacon_size; | ||
1641 | |||
1642 | /* First 5 fields are bssid, RSSI(for legacy scan only), | ||
1643 | * time stamp, beacon interval, and capability information | ||
1644 | */ | ||
1645 | if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) + | ||
1646 | sizeof(struct mwifiex_fixed_bcn_param)) { | ||
1647 | dev_err(adapter->dev, "InterpretIE: not enough bytes left\n"); | ||
1648 | return -EFAULT; | ||
1649 | } | ||
1650 | |||
1651 | memcpy(bssid, current_ptr, ETH_ALEN); | ||
1652 | current_ptr += ETH_ALEN; | ||
1653 | curr_bcn_bytes -= ETH_ALEN; | ||
1654 | |||
1655 | if (!ext_scan) { | ||
1656 | rssi = (s32) *(u8 *)current_ptr; | ||
1657 | rssi = (-rssi) * 100; /* Convert dBm to mBm */ | ||
1658 | current_ptr += sizeof(u8); | ||
1659 | curr_bcn_bytes -= sizeof(u8); | ||
1660 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); | ||
1661 | } else { | ||
1662 | rssi = rssi_val; | ||
1663 | } | ||
1664 | |||
1665 | bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr; | ||
1666 | current_ptr += sizeof(*bcn_param); | ||
1667 | curr_bcn_bytes -= sizeof(*bcn_param); | ||
1668 | |||
1669 | timestamp = le64_to_cpu(bcn_param->timestamp); | ||
1670 | beacon_period = le16_to_cpu(bcn_param->beacon_period); | ||
1671 | |||
1672 | cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); | ||
1673 | dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", | ||
1674 | cap_info_bitmap); | ||
1675 | |||
1676 | /* Rest of the current buffer are IE's */ | ||
1677 | ie_buf = current_ptr; | ||
1678 | ie_len = curr_bcn_bytes; | ||
1679 | dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n", | ||
1680 | curr_bcn_bytes); | ||
1681 | |||
1682 | while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) { | ||
1683 | u8 element_id, element_len; | ||
1684 | |||
1685 | element_id = *current_ptr; | ||
1686 | element_len = *(current_ptr + 1); | ||
1687 | if (curr_bcn_bytes < element_len + | ||
1688 | sizeof(struct ieee_types_header)) { | ||
1689 | dev_err(adapter->dev, | ||
1690 | "%s: bytes left < IE length\n", __func__); | ||
1691 | return -EFAULT; | ||
1692 | } | ||
1693 | if (element_id == WLAN_EID_DS_PARAMS) { | ||
1694 | channel = *(current_ptr + | ||
1695 | sizeof(struct ieee_types_header)); | ||
1696 | break; | ||
1697 | } | ||
1698 | |||
1699 | current_ptr += element_len + sizeof(struct ieee_types_header); | ||
1700 | curr_bcn_bytes -= element_len + | ||
1701 | sizeof(struct ieee_types_header); | ||
1702 | } | ||
1703 | |||
1704 | if (channel) { | ||
1705 | struct ieee80211_channel *chan; | ||
1706 | u8 band; | ||
1707 | |||
1708 | /* Skip entry if on csa closed channel */ | ||
1709 | if (channel == priv->csa_chan) { | ||
1710 | dev_dbg(adapter->dev, | ||
1711 | "Dropping entry on csa closed channel\n"); | ||
1712 | return 0; | ||
1713 | } | ||
1714 | |||
1715 | band = BAND_G; | ||
1716 | if (radio_type) | ||
1717 | band = mwifiex_radio_type_to_band(*radio_type & | ||
1718 | (BIT(0) | BIT(1))); | ||
1719 | |||
1720 | cfp = mwifiex_get_cfp(priv, band, channel, 0); | ||
1721 | |||
1722 | freq = cfp ? cfp->freq : 0; | ||
1723 | |||
1724 | chan = ieee80211_get_channel(priv->wdev->wiphy, freq); | ||
1725 | |||
1726 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
1727 | bss = cfg80211_inform_bss(priv->wdev->wiphy, | ||
1728 | chan, bssid, timestamp, | ||
1729 | cap_info_bitmap, beacon_period, | ||
1730 | ie_buf, ie_len, rssi, GFP_KERNEL); | ||
1731 | bss_priv = (struct mwifiex_bss_priv *)bss->priv; | ||
1732 | bss_priv->band = band; | ||
1733 | bss_priv->fw_tsf = fw_tsf; | ||
1734 | if (priv->media_connected && | ||
1735 | !memcmp(bssid, priv->curr_bss_params.bss_descriptor | ||
1736 | .mac_address, ETH_ALEN)) | ||
1737 | mwifiex_update_curr_bss_params(priv, bss); | ||
1738 | cfg80211_put_bss(priv->wdev->wiphy, bss); | ||
1739 | } | ||
1740 | } else { | ||
1741 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | ||
1742 | } | ||
1743 | |||
1744 | return 0; | ||
1745 | } | ||
1746 | |||
1747 | static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) | ||
1748 | { | ||
1749 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1750 | struct cmd_ctrl_node *cmd_node; | ||
1751 | unsigned long flags; | ||
1752 | |||
1753 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | ||
1754 | if (list_empty(&adapter->scan_pending_q)) { | ||
1755 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | ||
1756 | spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); | ||
1757 | adapter->scan_processing = false; | ||
1758 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | ||
1759 | |||
1760 | /* Need to indicate IOCTL complete */ | ||
1761 | if (adapter->curr_cmd->wait_q_enabled) { | ||
1762 | adapter->cmd_wait_q.status = 0; | ||
1763 | if (!priv->scan_request) { | ||
1764 | dev_dbg(adapter->dev, | ||
1765 | "complete internal scan\n"); | ||
1766 | mwifiex_complete_cmd(adapter, | ||
1767 | adapter->curr_cmd); | ||
1768 | } | ||
1769 | } | ||
1770 | if (priv->report_scan_result) | ||
1771 | priv->report_scan_result = false; | ||
1772 | |||
1773 | if (priv->scan_request) { | ||
1774 | dev_dbg(adapter->dev, "info: notifying scan done\n"); | ||
1775 | cfg80211_scan_done(priv->scan_request, 0); | ||
1776 | priv->scan_request = NULL; | ||
1777 | } else { | ||
1778 | priv->scan_aborting = false; | ||
1779 | dev_dbg(adapter->dev, "info: scan already aborted\n"); | ||
1780 | } | ||
1781 | } else { | ||
1782 | if ((priv->scan_aborting && !priv->scan_request) || | ||
1783 | priv->scan_block) { | ||
1784 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1785 | flags); | ||
1786 | adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; | ||
1787 | mod_timer(&priv->scan_delay_timer, jiffies); | ||
1788 | dev_dbg(priv->adapter->dev, | ||
1789 | "info: %s: triggerring scan abort\n", __func__); | ||
1790 | } else if (!mwifiex_wmm_lists_empty(adapter) && | ||
1791 | (priv->scan_request && (priv->scan_request->flags & | ||
1792 | NL80211_SCAN_FLAG_LOW_PRIORITY))) { | ||
1793 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1794 | flags); | ||
1795 | adapter->scan_delay_cnt = 1; | ||
1796 | mod_timer(&priv->scan_delay_timer, jiffies + | ||
1797 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); | ||
1798 | dev_dbg(priv->adapter->dev, | ||
1799 | "info: %s: deferring scan\n", __func__); | ||
1800 | } else { | ||
1801 | /* Get scan command from scan_pending_q and put to | ||
1802 | * cmd_pending_q | ||
1803 | */ | ||
1804 | cmd_node = list_first_entry(&adapter->scan_pending_q, | ||
1805 | struct cmd_ctrl_node, list); | ||
1806 | list_del(&cmd_node->list); | ||
1807 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1808 | flags); | ||
1809 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | ||
1810 | true); | ||
1811 | } | ||
1812 | } | ||
1813 | |||
1814 | return; | ||
1815 | } | ||
1816 | |||
1579 | /* | 1817 | /* |
1580 | * This function handles the command response of scan. | 1818 | * This function handles the command response of scan. |
1581 | * | 1819 | * |
@@ -1600,7 +1838,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1600 | { | 1838 | { |
1601 | int ret = 0; | 1839 | int ret = 0; |
1602 | struct mwifiex_adapter *adapter = priv->adapter; | 1840 | struct mwifiex_adapter *adapter = priv->adapter; |
1603 | struct cmd_ctrl_node *cmd_node; | ||
1604 | struct host_cmd_ds_802_11_scan_rsp *scan_rsp; | 1841 | struct host_cmd_ds_802_11_scan_rsp *scan_rsp; |
1605 | struct mwifiex_ie_types_data *tlv_data; | 1842 | struct mwifiex_ie_types_data *tlv_data; |
1606 | struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; | 1843 | struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; |
@@ -1609,12 +1846,11 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1609 | u32 bytes_left; | 1846 | u32 bytes_left; |
1610 | u32 idx; | 1847 | u32 idx; |
1611 | u32 tlv_buf_size; | 1848 | u32 tlv_buf_size; |
1612 | struct mwifiex_chan_freq_power *cfp; | ||
1613 | struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; | 1849 | struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; |
1614 | struct chan_band_param_set *chan_band; | 1850 | struct chan_band_param_set *chan_band; |
1615 | u8 is_bgscan_resp; | 1851 | u8 is_bgscan_resp; |
1616 | unsigned long flags; | 1852 | __le64 fw_tsf = 0; |
1617 | struct cfg80211_bss *bss; | 1853 | u8 *radio_type; |
1618 | 1854 | ||
1619 | is_bgscan_resp = (le16_to_cpu(resp->command) | 1855 | is_bgscan_resp = (le16_to_cpu(resp->command) |
1620 | == HostCmd_CMD_802_11_BG_SCAN_QUERY); | 1856 | == HostCmd_CMD_802_11_BG_SCAN_QUERY); |
@@ -1676,220 +1912,194 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1676 | &chan_band_tlv); | 1912 | &chan_band_tlv); |
1677 | 1913 | ||
1678 | for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { | 1914 | for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { |
1679 | u8 bssid[ETH_ALEN]; | 1915 | /* |
1680 | s32 rssi; | 1916 | * If the TSF TLV was appended to the scan results, save this |
1681 | const u8 *ie_buf; | 1917 | * entry's TSF value in the fw_tsf field. It is the firmware's |
1682 | size_t ie_len; | 1918 | * TSF value at the time the beacon or probe response was |
1683 | u16 channel = 0; | 1919 | * received. |
1684 | __le64 fw_tsf = 0; | 1920 | */ |
1685 | u16 beacon_size = 0; | 1921 | if (tsf_tlv) |
1686 | u32 curr_bcn_bytes; | 1922 | memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], |
1687 | u32 freq; | 1923 | 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 | 1924 | ||
1702 | if (!beacon_size || beacon_size > bytes_left) { | 1925 | if (chan_band_tlv) { |
1703 | bss_info += bytes_left; | 1926 | chan_band = &chan_band_tlv->chan_band_param[idx]; |
1704 | bytes_left = 0; | 1927 | radio_type = &chan_band->radio_type; |
1705 | ret = -1; | 1928 | } else { |
1706 | goto check_next_scan; | 1929 | radio_type = NULL; |
1707 | } | 1930 | } |
1708 | 1931 | ||
1709 | /* Initialize the current working beacon pointer for this BSS | 1932 | ret = mwifiex_parse_single_response_buf(priv, &bss_info, |
1710 | * iteration */ | 1933 | &bytes_left, |
1711 | current_ptr = bss_info; | 1934 | le64_to_cpu(fw_tsf), |
1935 | radio_type, false, 0); | ||
1936 | if (ret) | ||
1937 | goto check_next_scan; | ||
1938 | } | ||
1712 | 1939 | ||
1713 | /* Advance the return beacon pointer past the current beacon */ | 1940 | check_next_scan: |
1714 | bss_info += beacon_size; | 1941 | mwifiex_check_next_scan_command(priv); |
1715 | bytes_left -= beacon_size; | 1942 | return ret; |
1943 | } | ||
1716 | 1944 | ||
1717 | curr_bcn_bytes = beacon_size; | 1945 | /* |
1946 | * This function prepares an extended scan command to be sent to the firmware | ||
1947 | * | ||
1948 | * This uses the scan command configuration sent to the command processing | ||
1949 | * module in command preparation stage to configure a extended scan command | ||
1950 | * structure to send to firmware. | ||
1951 | */ | ||
1952 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | ||
1953 | struct host_cmd_ds_command *cmd, | ||
1954 | void *data_buf) | ||
1955 | { | ||
1956 | struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan; | ||
1957 | struct mwifiex_scan_cmd_config *scan_cfg = data_buf; | ||
1718 | 1958 | ||
1719 | /* | 1959 | 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 | 1960 | ||
1732 | memcpy(bssid, bcn_param->bssid, ETH_ALEN); | 1961 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT); |
1733 | 1962 | ||
1734 | rssi = (s32) bcn_param->rssi; | 1963 | /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ |
1735 | rssi = (-rssi) * 100; /* Convert dBm to mBm */ | 1964 | cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved) |
1736 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); | 1965 | + scan_cfg->tlv_buf_len + S_DS_GEN)); |
1737 | 1966 | ||
1738 | timestamp = le64_to_cpu(bcn_param->timestamp); | 1967 | return 0; |
1739 | beacon_period = le16_to_cpu(bcn_param->beacon_period); | 1968 | } |
1740 | 1969 | ||
1741 | cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); | 1970 | /* This function handles the command response of extended scan */ |
1742 | dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n", | 1971 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv) |
1743 | cap_info_bitmap); | 1972 | { |
1973 | dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n"); | ||
1974 | return 0; | ||
1975 | } | ||
1744 | 1976 | ||
1745 | /* Rest of the current buffer are IE's */ | 1977 | /* This function This function handles the event extended scan report. It |
1746 | ie_buf = current_ptr; | 1978 | * parses extended scan results and informs to cfg80211 stack. |
1747 | ie_len = curr_bcn_bytes; | 1979 | */ |
1748 | dev_dbg(adapter->dev, | 1980 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, |
1749 | "info: InterpretIE: IELength for this AP = %d\n", | 1981 | void *buf) |
1750 | curr_bcn_bytes); | 1982 | { |
1983 | int ret = 0; | ||
1984 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1985 | u8 *bss_info; | ||
1986 | u32 bytes_left, bytes_left_for_tlv, idx; | ||
1987 | u16 type, len; | ||
1988 | struct mwifiex_ie_types_data *tlv; | ||
1989 | struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv; | ||
1990 | struct mwifiex_ie_types_bss_scan_info *scan_info_tlv; | ||
1991 | u8 *radio_type; | ||
1992 | u64 fw_tsf = 0; | ||
1993 | s32 rssi = 0; | ||
1994 | struct mwifiex_event_scan_result *event_scan = buf; | ||
1995 | u8 num_of_set = event_scan->num_of_set; | ||
1996 | u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result); | ||
1997 | u16 scan_resp_size = le16_to_cpu(event_scan->buf_size); | ||
1998 | |||
1999 | if (num_of_set > MWIFIEX_MAX_AP) { | ||
2000 | dev_err(adapter->dev, | ||
2001 | "EXT_SCAN: Invalid number of AP returned (%d)!!\n", | ||
2002 | num_of_set); | ||
2003 | ret = -1; | ||
2004 | goto check_next_scan; | ||
2005 | } | ||
1751 | 2006 | ||
1752 | while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) { | 2007 | bytes_left = scan_resp_size; |
1753 | u8 element_id, element_len; | 2008 | dev_dbg(adapter->dev, |
2009 | "EXT_SCAN: size %d, returned %d APs...", | ||
2010 | scan_resp_size, num_of_set); | ||
1754 | 2011 | ||
1755 | element_id = *current_ptr; | 2012 | 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 | 2013 | ||
1769 | current_ptr += element_len + | 2014 | for (idx = 0; idx < num_of_set && bytes_left; idx++) { |
1770 | sizeof(struct ieee_types_header); | 2015 | type = le16_to_cpu(tlv->header.type); |
1771 | curr_bcn_bytes -= element_len + | 2016 | len = le16_to_cpu(tlv->header.len); |
1772 | sizeof(struct ieee_types_header); | 2017 | if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) { |
2018 | dev_err(adapter->dev, "EXT_SCAN: Error bytes left < TLV length\n"); | ||
2019 | break; | ||
1773 | } | 2020 | } |
2021 | scan_rsp_tlv = NULL; | ||
2022 | scan_info_tlv = NULL; | ||
2023 | bytes_left_for_tlv = bytes_left; | ||
1774 | 2024 | ||
1775 | /* | 2025 | /* BSS response TLV with beacon or probe response buffer |
1776 | * If the TSF TLV was appended to the scan results, save this | 2026 | * 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 | */ | 2027 | */ |
1781 | if (tsf_tlv) | 2028 | if (type != TLV_TYPE_BSS_SCAN_RSP) |
1782 | memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], | 2029 | break; |
1783 | sizeof(fw_tsf)); | ||
1784 | |||
1785 | if (channel) { | ||
1786 | struct ieee80211_channel *chan; | ||
1787 | u8 band; | ||
1788 | 2030 | ||
1789 | /* Skip entry if on csa closed channel */ | 2031 | bss_info = (u8 *)tlv; |
1790 | if (channel == priv->csa_chan) { | 2032 | scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv; |
1791 | dev_dbg(adapter->dev, | 2033 | tlv = (struct mwifiex_ie_types_data *)(tlv->data + len); |
1792 | "Dropping entry on csa closed channel\n"); | 2034 | bytes_left_for_tlv -= |
2035 | (len + sizeof(struct mwifiex_ie_types_header)); | ||
2036 | |||
2037 | while (bytes_left_for_tlv >= | ||
2038 | sizeof(struct mwifiex_ie_types_header) && | ||
2039 | le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) { | ||
2040 | type = le16_to_cpu(tlv->header.type); | ||
2041 | len = le16_to_cpu(tlv->header.len); | ||
2042 | if (bytes_left_for_tlv < | ||
2043 | sizeof(struct mwifiex_ie_types_header) + len) { | ||
2044 | dev_err(adapter->dev, | ||
2045 | "EXT_SCAN: Error in processing TLV, bytes left < TLV length\n"); | ||
2046 | scan_rsp_tlv = NULL; | ||
2047 | bytes_left_for_tlv = 0; | ||
1793 | continue; | 2048 | continue; |
1794 | } | 2049 | } |
1795 | 2050 | switch (type) { | |
1796 | band = BAND_G; | 2051 | case TLV_TYPE_BSS_SCAN_INFO: |
1797 | if (chan_band_tlv) { | 2052 | scan_info_tlv = |
1798 | chan_band = | 2053 | (struct mwifiex_ie_types_bss_scan_info *)tlv; |
1799 | &chan_band_tlv->chan_band_param[idx]; | 2054 | if (len != |
1800 | band = mwifiex_radio_type_to_band( | 2055 | sizeof(struct mwifiex_ie_types_bss_scan_info) - |
1801 | chan_band->radio_type | 2056 | sizeof(struct mwifiex_ie_types_header)) { |
1802 | & (BIT(0) | BIT(1))); | 2057 | bytes_left_for_tlv = 0; |
1803 | } | 2058 | continue; |
1804 | 2059 | } | |
1805 | cfp = mwifiex_get_cfp(priv, band, channel, 0); | 2060 | break; |
1806 | 2061 | default: | |
1807 | freq = cfp ? cfp->freq : 0; | 2062 | 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 | } | 2063 | } |
1827 | } else { | 2064 | tlv = (struct mwifiex_ie_types_data *)(tlv->data + len); |
1828 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | 2065 | bytes_left -= |
2066 | (len + sizeof(struct mwifiex_ie_types_header)); | ||
2067 | bytes_left_for_tlv -= | ||
2068 | (len + sizeof(struct mwifiex_ie_types_header)); | ||
1829 | } | 2069 | } |
1830 | } | ||
1831 | 2070 | ||
1832 | check_next_scan: | 2071 | if (!scan_rsp_tlv) |
1833 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | 2072 | 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 | 2073 | ||
1840 | /* Need to indicate IOCTL complete */ | 2074 | /* Advance pointer to the beacon buffer length and |
1841 | if (adapter->curr_cmd->wait_q_enabled) { | 2075 | * update the bytes count so that the function |
1842 | adapter->cmd_wait_q.status = 0; | 2076 | * wlan_interpret_bss_desc_with_ie() can handle the |
1843 | if (!priv->scan_request) { | 2077 | * scan buffer withut any change |
1844 | dev_dbg(adapter->dev, | 2078 | */ |
1845 | "complete internal scan\n"); | 2079 | bss_info += sizeof(u16); |
1846 | mwifiex_complete_cmd(adapter, | 2080 | bytes_left -= sizeof(u16); |
1847 | adapter->curr_cmd); | ||
1848 | } | ||
1849 | } | ||
1850 | if (priv->report_scan_result) | ||
1851 | priv->report_scan_result = false; | ||
1852 | 2081 | ||
1853 | if (priv->scan_request) { | 2082 | if (scan_info_tlv) { |
1854 | dev_dbg(adapter->dev, "info: notifying scan done\n"); | 2083 | rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi)); |
1855 | cfg80211_scan_done(priv->scan_request, 0); | 2084 | rssi *= 100; /* Convert dBm to mBm */ |
1856 | priv->scan_request = NULL; | 2085 | dev_dbg(adapter->dev, |
1857 | } else { | 2086 | "info: InterpretIE: RSSI=%d\n", rssi); |
1858 | priv->scan_aborting = false; | 2087 | fw_tsf = le64_to_cpu(scan_info_tlv->tsf); |
1859 | dev_dbg(adapter->dev, "info: scan already aborted\n"); | 2088 | 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 { | 2089 | } else { |
1881 | /* Get scan command from scan_pending_q and put to | 2090 | 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 | } | 2091 | } |
2092 | ret = mwifiex_parse_single_response_buf(priv, &bss_info, | ||
2093 | &bytes_left, fw_tsf, | ||
2094 | radio_type, true, rssi); | ||
2095 | if (ret) | ||
2096 | goto check_next_scan; | ||
1891 | } | 2097 | } |
1892 | 2098 | ||
2099 | check_next_scan: | ||
2100 | if (!event_scan->more_event) | ||
2101 | mwifiex_check_next_scan_command(priv); | ||
2102 | |||
1893 | return ret; | 2103 | return ret; |
1894 | } | 2104 | } |
1895 | 2105 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index b44a31523461..e0dcd3ed7a69 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); |
@@ -1760,6 +1756,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
1760 | 1756 | ||
1761 | /* save adapter pointer in card */ | 1757 | /* save adapter pointer in card */ |
1762 | card->adapter = adapter; | 1758 | card->adapter = adapter; |
1759 | adapter->tx_buf_size = card->tx_buf_size; | ||
1763 | 1760 | ||
1764 | sdio_claim_host(func); | 1761 | sdio_claim_host(func); |
1765 | 1762 | ||
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..33170af150f6 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -108,19 +108,19 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
108 | "info: Set multicast list=%d\n", | 108 | "info: Set multicast list=%d\n", |
109 | mcast_list->num_multicast_addr); | 109 | mcast_list->num_multicast_addr); |
110 | /* Send multicast addresses to firmware */ | 110 | /* Send multicast addresses to firmware */ |
111 | ret = mwifiex_send_cmd_async(priv, | 111 | ret = mwifiex_send_cmd(priv, |
112 | HostCmd_CMD_MAC_MULTICAST_ADR, | 112 | HostCmd_CMD_MAC_MULTICAST_ADR, |
113 | HostCmd_ACT_GEN_SET, 0, | 113 | HostCmd_ACT_GEN_SET, 0, |
114 | mcast_list); | 114 | mcast_list, false); |
115 | } | 115 | } |
116 | } | 116 | } |
117 | dev_dbg(priv->adapter->dev, | 117 | dev_dbg(priv->adapter->dev, |
118 | "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", | 118 | "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", |
119 | old_pkt_filter, priv->curr_pkt_filter); | 119 | old_pkt_filter, priv->curr_pkt_filter); |
120 | if (old_pkt_filter != priv->curr_pkt_filter) { | 120 | if (old_pkt_filter != priv->curr_pkt_filter) { |
121 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, | 121 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
122 | HostCmd_ACT_GEN_SET, | 122 | HostCmd_ACT_GEN_SET, |
123 | 0, &priv->curr_pkt_filter); | 123 | 0, &priv->curr_pkt_filter, false); |
124 | } | 124 | } |
125 | 125 | ||
126 | return ret; | 126 | return ret; |
@@ -237,8 +237,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, | |||
237 | 237 | ||
238 | rcu_read_unlock(); | 238 | rcu_read_unlock(); |
239 | 239 | ||
240 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, | 240 | if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, |
241 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 241 | HostCmd_ACT_GEN_SET, 0, NULL, false)) { |
242 | wiphy_err(priv->adapter->wiphy, | 242 | wiphy_err(priv->adapter->wiphy, |
243 | "11D: setting domain info in FW\n"); | 243 | "11D: setting domain info in FW\n"); |
244 | return -1; | 244 | return -1; |
@@ -290,7 +290,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
290 | 290 | ||
291 | if (mwifiex_band_to_radio_type(bss_desc->bss_band) == | 291 | if (mwifiex_band_to_radio_type(bss_desc->bss_band) == |
292 | HostCmd_SCAN_RADIO_TYPE_BG) | 292 | HostCmd_SCAN_RADIO_TYPE_BG) |
293 | config_bands = BAND_B | BAND_G | BAND_GN | BAND_GAC; | 293 | config_bands = BAND_B | BAND_G | BAND_GN; |
294 | else | 294 | else |
295 | config_bands = BAND_A | BAND_AN | BAND_AAC; | 295 | config_bands = BAND_A | BAND_AN | BAND_AAC; |
296 | 296 | ||
@@ -429,16 +429,13 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, | |||
429 | status = -1; | 429 | status = -1; |
430 | break; | 430 | break; |
431 | } | 431 | } |
432 | if (cmd_type == MWIFIEX_SYNC_CMD) | 432 | |
433 | status = mwifiex_send_cmd_sync(priv, | 433 | status = mwifiex_send_cmd(priv, |
434 | HostCmd_CMD_802_11_HS_CFG_ENH, | 434 | HostCmd_CMD_802_11_HS_CFG_ENH, |
435 | HostCmd_ACT_GEN_SET, 0, | 435 | HostCmd_ACT_GEN_SET, 0, |
436 | &adapter->hs_cfg); | 436 | &adapter->hs_cfg, |
437 | else | 437 | cmd_type == MWIFIEX_SYNC_CMD); |
438 | status = mwifiex_send_cmd_async(priv, | 438 | |
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) | 439 | if (hs_cfg->conditions == HS_CFG_CANCEL) |
443 | /* Restore previous condition */ | 440 | /* Restore previous condition */ |
444 | adapter->hs_cfg.conditions = | 441 | adapter->hs_cfg.conditions = |
@@ -586,8 +583,8 @@ int mwifiex_disable_auto_ds(struct mwifiex_private *priv) | |||
586 | 583 | ||
587 | auto_ds.auto_ds = DEEP_SLEEP_OFF; | 584 | auto_ds.auto_ds = DEEP_SLEEP_OFF; |
588 | 585 | ||
589 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, | 586 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
590 | DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds); | 587 | DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, true); |
591 | } | 588 | } |
592 | EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds); | 589 | EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds); |
593 | 590 | ||
@@ -601,8 +598,8 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate) | |||
601 | { | 598 | { |
602 | int ret; | 599 | int ret; |
603 | 600 | ||
604 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, | 601 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, |
605 | HostCmd_ACT_GEN_GET, 0, NULL); | 602 | HostCmd_ACT_GEN_GET, 0, NULL, true); |
606 | 603 | ||
607 | if (!ret) { | 604 | if (!ret) { |
608 | if (priv->is_data_rate_auto) | 605 | if (priv->is_data_rate_auto) |
@@ -698,8 +695,8 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, | |||
698 | pg->power_max = (s8) dbm; | 695 | pg->power_max = (s8) dbm; |
699 | pg->ht_bandwidth = HT_BW_40; | 696 | pg->ht_bandwidth = HT_BW_40; |
700 | } | 697 | } |
701 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TXPWR_CFG, | 698 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_TXPWR_CFG, |
702 | HostCmd_ACT_GEN_SET, 0, buf); | 699 | HostCmd_ACT_GEN_SET, 0, buf, true); |
703 | 700 | ||
704 | kfree(buf); | 701 | kfree(buf); |
705 | return ret; | 702 | return ret; |
@@ -722,12 +719,11 @@ int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) | |||
722 | else | 719 | else |
723 | adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; | 720 | adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; |
724 | sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; | 721 | sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; |
725 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_PS_MODE_ENH, | 722 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
726 | sub_cmd, BITMAP_STA_PS, NULL); | 723 | sub_cmd, BITMAP_STA_PS, NULL, true); |
727 | if ((!ret) && (sub_cmd == DIS_AUTO_PS)) | 724 | if ((!ret) && (sub_cmd == DIS_AUTO_PS)) |
728 | ret = mwifiex_send_cmd_async(priv, | 725 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
729 | HostCmd_CMD_802_11_PS_MODE_ENH, | 726 | GET_PS, 0, NULL, false); |
730 | GET_PS, 0, NULL); | ||
731 | 727 | ||
732 | return ret; | 728 | return ret; |
733 | } | 729 | } |
@@ -851,9 +847,9 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, | |||
851 | struct mwifiex_ds_encrypt_key *encrypt_key) | 847 | struct mwifiex_ds_encrypt_key *encrypt_key) |
852 | { | 848 | { |
853 | 849 | ||
854 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_KEY_MATERIAL, | 850 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
855 | HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, | 851 | HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, |
856 | encrypt_key); | 852 | encrypt_key, true); |
857 | } | 853 | } |
858 | 854 | ||
859 | /* | 855 | /* |
@@ -865,6 +861,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, | 861 | static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, |
866 | struct mwifiex_ds_encrypt_key *encrypt_key) | 862 | struct mwifiex_ds_encrypt_key *encrypt_key) |
867 | { | 863 | { |
864 | struct mwifiex_adapter *adapter = priv->adapter; | ||
868 | int ret; | 865 | int ret; |
869 | struct mwifiex_wep_key *wep_key; | 866 | struct mwifiex_wep_key *wep_key; |
870 | int index; | 867 | int index; |
@@ -879,10 +876,17 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, | |||
879 | /* Copy the required key as the current key */ | 876 | /* Copy the required key as the current key */ |
880 | wep_key = &priv->wep_key[index]; | 877 | wep_key = &priv->wep_key[index]; |
881 | if (!wep_key->key_length) { | 878 | if (!wep_key->key_length) { |
882 | dev_err(priv->adapter->dev, | 879 | dev_err(adapter->dev, |
883 | "key not set, so cannot enable it\n"); | 880 | "key not set, so cannot enable it\n"); |
884 | return -1; | 881 | return -1; |
885 | } | 882 | } |
883 | |||
884 | if (adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2) { | ||
885 | memcpy(encrypt_key->key_material, | ||
886 | wep_key->key_material, wep_key->key_length); | ||
887 | encrypt_key->key_len = wep_key->key_length; | ||
888 | } | ||
889 | |||
886 | priv->wep_key_curr_index = (u16) index; | 890 | priv->wep_key_curr_index = (u16) index; |
887 | priv->sec_info.wep_enabled = 1; | 891 | priv->sec_info.wep_enabled = 1; |
888 | } else { | 892 | } else { |
@@ -897,21 +901,32 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, | |||
897 | priv->sec_info.wep_enabled = 1; | 901 | priv->sec_info.wep_enabled = 1; |
898 | } | 902 | } |
899 | if (wep_key->key_length) { | 903 | if (wep_key->key_length) { |
904 | void *enc_key; | ||
905 | |||
906 | if (encrypt_key->key_disable) | ||
907 | memset(&priv->wep_key[index], 0, | ||
908 | sizeof(struct mwifiex_wep_key)); | ||
909 | |||
910 | if (adapter->fw_key_api_major_ver == FW_KEY_API_VER_MAJOR_V2) | ||
911 | enc_key = encrypt_key; | ||
912 | else | ||
913 | enc_key = NULL; | ||
914 | |||
900 | /* Send request to firmware */ | 915 | /* Send request to firmware */ |
901 | ret = mwifiex_send_cmd_async(priv, | 916 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
902 | HostCmd_CMD_802_11_KEY_MATERIAL, | 917 | HostCmd_ACT_GEN_SET, 0, enc_key, false); |
903 | HostCmd_ACT_GEN_SET, 0, NULL); | ||
904 | if (ret) | 918 | if (ret) |
905 | return ret; | 919 | return ret; |
906 | } | 920 | } |
921 | |||
907 | if (priv->sec_info.wep_enabled) | 922 | if (priv->sec_info.wep_enabled) |
908 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; | 923 | priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; |
909 | else | 924 | else |
910 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; | 925 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; |
911 | 926 | ||
912 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, | 927 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, |
913 | HostCmd_ACT_GEN_SET, 0, | 928 | HostCmd_ACT_GEN_SET, 0, |
914 | &priv->curr_pkt_filter); | 929 | &priv->curr_pkt_filter, true); |
915 | 930 | ||
916 | return ret; | 931 | return ret; |
917 | } | 932 | } |
@@ -946,10 +961,9 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, | |||
946 | */ | 961 | */ |
947 | /* Send the key as PTK to firmware */ | 962 | /* Send the key as PTK to firmware */ |
948 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; | 963 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; |
949 | ret = mwifiex_send_cmd_async(priv, | 964 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
950 | HostCmd_CMD_802_11_KEY_MATERIAL, | 965 | HostCmd_ACT_GEN_SET, |
951 | HostCmd_ACT_GEN_SET, | 966 | KEY_INFO_ENABLED, encrypt_key, false); |
952 | KEY_INFO_ENABLED, encrypt_key); | ||
953 | if (ret) | 967 | if (ret) |
954 | return ret; | 968 | return ret; |
955 | 969 | ||
@@ -973,15 +987,13 @@ static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, | |||
973 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; | 987 | encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; |
974 | 988 | ||
975 | if (remove_key) | 989 | if (remove_key) |
976 | ret = mwifiex_send_cmd_sync(priv, | 990 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
977 | HostCmd_CMD_802_11_KEY_MATERIAL, | 991 | HostCmd_ACT_GEN_SET, |
978 | HostCmd_ACT_GEN_SET, | 992 | !KEY_INFO_ENABLED, encrypt_key, true); |
979 | !KEY_INFO_ENABLED, encrypt_key); | ||
980 | else | 993 | else |
981 | ret = mwifiex_send_cmd_sync(priv, | 994 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, |
982 | HostCmd_CMD_802_11_KEY_MATERIAL, | 995 | HostCmd_ACT_GEN_SET, |
983 | HostCmd_ACT_GEN_SET, | 996 | KEY_INFO_ENABLED, encrypt_key, true); |
984 | KEY_INFO_ENABLED, encrypt_key); | ||
985 | 997 | ||
986 | return ret; | 998 | return ret; |
987 | } | 999 | } |
@@ -1044,19 +1056,27 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, | |||
1044 | 1056 | ||
1045 | memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); | 1057 | memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); |
1046 | encrypt_key.key_len = key_len; | 1058 | encrypt_key.key_len = key_len; |
1059 | encrypt_key.key_index = key_index; | ||
1047 | 1060 | ||
1048 | if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC) | 1061 | if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC) |
1049 | encrypt_key.is_igtk_key = true; | 1062 | encrypt_key.is_igtk_key = true; |
1050 | 1063 | ||
1051 | if (!disable) { | 1064 | if (!disable) { |
1052 | encrypt_key.key_index = key_index; | ||
1053 | if (key_len) | 1065 | if (key_len) |
1054 | memcpy(encrypt_key.key_material, key, key_len); | 1066 | memcpy(encrypt_key.key_material, key, key_len); |
1067 | else | ||
1068 | encrypt_key.is_current_wep_key = true; | ||
1069 | |||
1055 | if (mac_addr) | 1070 | if (mac_addr) |
1056 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | 1071 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); |
1057 | if (kp && kp->seq && kp->seq_len) | 1072 | if (kp && kp->seq && kp->seq_len) { |
1058 | memcpy(encrypt_key.pn, kp->seq, kp->seq_len); | 1073 | memcpy(encrypt_key.pn, kp->seq, kp->seq_len); |
1074 | encrypt_key.pn_len = kp->seq_len; | ||
1075 | encrypt_key.is_rx_seq_valid = true; | ||
1076 | } | ||
1059 | } else { | 1077 | } else { |
1078 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) | ||
1079 | return 0; | ||
1060 | encrypt_key.key_disable = true; | 1080 | encrypt_key.key_disable = true; |
1061 | if (mac_addr) | 1081 | if (mac_addr) |
1062 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | 1082 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); |
@@ -1077,8 +1097,8 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv) | |||
1077 | struct mwifiex_ver_ext ver_ext; | 1097 | struct mwifiex_ver_ext ver_ext; |
1078 | 1098 | ||
1079 | memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); | 1099 | memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); |
1080 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_VERSION_EXT, | 1100 | if (mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT, |
1081 | HostCmd_ACT_GEN_GET, 0, &ver_ext)) | 1101 | HostCmd_ACT_GEN_GET, 0, &ver_ext, true)) |
1082 | return -1; | 1102 | return -1; |
1083 | 1103 | ||
1084 | return 0; | 1104 | return 0; |
@@ -1103,8 +1123,8 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, | |||
1103 | ieee80211_frequency_to_channel(chan->center_freq); | 1123 | ieee80211_frequency_to_channel(chan->center_freq); |
1104 | roc_cfg.duration = cpu_to_le32(duration); | 1124 | roc_cfg.duration = cpu_to_le32(duration); |
1105 | } | 1125 | } |
1106 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_REMAIN_ON_CHAN, | 1126 | if (mwifiex_send_cmd(priv, HostCmd_CMD_REMAIN_ON_CHAN, |
1107 | action, 0, &roc_cfg)) { | 1127 | action, 0, &roc_cfg, true)) { |
1108 | dev_err(priv->adapter->dev, "failed to remain on channel\n"); | 1128 | dev_err(priv->adapter->dev, "failed to remain on channel\n"); |
1109 | return -1; | 1129 | return -1; |
1110 | } | 1130 | } |
@@ -1136,8 +1156,8 @@ mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role) | |||
1136 | break; | 1156 | break; |
1137 | } | 1157 | } |
1138 | 1158 | ||
1139 | mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, | 1159 | mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, |
1140 | HostCmd_ACT_GEN_SET, 0, NULL); | 1160 | HostCmd_ACT_GEN_SET, 0, NULL, true); |
1141 | 1161 | ||
1142 | return mwifiex_sta_init_cmd(priv, false); | 1162 | return mwifiex_sta_init_cmd(priv, false); |
1143 | } | 1163 | } |
@@ -1152,8 +1172,8 @@ int | |||
1152 | mwifiex_get_stats_info(struct mwifiex_private *priv, | 1172 | mwifiex_get_stats_info(struct mwifiex_private *priv, |
1153 | struct mwifiex_ds_get_stats *log) | 1173 | struct mwifiex_ds_get_stats *log) |
1154 | { | 1174 | { |
1155 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, | 1175 | return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_GET_LOG, |
1156 | HostCmd_ACT_GEN_GET, 0, log); | 1176 | HostCmd_ACT_GEN_GET, 0, log, true); |
1157 | } | 1177 | } |
1158 | 1178 | ||
1159 | /* | 1179 | /* |
@@ -1195,8 +1215,7 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, | |||
1195 | return -1; | 1215 | return -1; |
1196 | } | 1216 | } |
1197 | 1217 | ||
1198 | return mwifiex_send_cmd_sync(priv, cmd_no, action, 0, reg_rw); | 1218 | return mwifiex_send_cmd(priv, cmd_no, action, 0, reg_rw, true); |
1199 | |||
1200 | } | 1219 | } |
1201 | 1220 | ||
1202 | /* | 1221 | /* |
@@ -1261,8 +1280,8 @@ mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, | |||
1261 | rd_eeprom.byte_count = cpu_to_le16((u16) bytes); | 1280 | rd_eeprom.byte_count = cpu_to_le16((u16) bytes); |
1262 | 1281 | ||
1263 | /* Send request to firmware */ | 1282 | /* Send request to firmware */ |
1264 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, | 1283 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, |
1265 | HostCmd_ACT_GEN_GET, 0, &rd_eeprom); | 1284 | HostCmd_ACT_GEN_GET, 0, &rd_eeprom, true); |
1266 | 1285 | ||
1267 | if (!ret) | 1286 | if (!ret) |
1268 | memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); | 1287 | memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); |
@@ -1391,7 +1410,7 @@ static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, | |||
1391 | * with requisite parameters and calls the IOCTL handler. | 1410 | * with requisite parameters and calls the IOCTL handler. |
1392 | */ | 1411 | */ |
1393 | int | 1412 | int |
1394 | mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len) | 1413 | mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len) |
1395 | { | 1414 | { |
1396 | struct mwifiex_ds_misc_gen_ie gen_ie; | 1415 | struct mwifiex_ds_misc_gen_ie gen_ie; |
1397 | 1416 | ||
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..8cec6e4ba8c4 --- /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 (*(u8 *)(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE) | ||
734 | return; | ||
735 | if (*(u8 *)(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS) | ||
736 | return; | ||
737 | |||
738 | peer = buf + ETH_ALEN; | ||
739 | action = *(u8 *)(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..ae30c390ebd3 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -766,11 +766,13 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
766 | switch (le16_to_cpu(card->udev->descriptor.idProduct)) { | 766 | switch (le16_to_cpu(card->udev->descriptor.idProduct)) { |
767 | case USB8897_PID_1: | 767 | case USB8897_PID_1: |
768 | case USB8897_PID_2: | 768 | case USB8897_PID_2: |
769 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; | ||
769 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); | 770 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); |
770 | break; | 771 | break; |
771 | case USB8797_PID_1: | 772 | case USB8797_PID_1: |
772 | case USB8797_PID_2: | 773 | case USB8797_PID_2: |
773 | default: | 774 | default: |
775 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | ||
774 | strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME); | 776 | strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME); |
775 | break; | 777 | break; |
776 | } | 778 | } |
@@ -1024,7 +1026,6 @@ static void mwifiex_usb_cleanup_module(void) | |||
1024 | 1026 | ||
1025 | if (usb_card && usb_card->adapter) { | 1027 | if (usb_card && usb_card->adapter) { |
1026 | struct mwifiex_adapter *adapter = usb_card->adapter; | 1028 | struct mwifiex_adapter *adapter = usb_card->adapter; |
1027 | int i; | ||
1028 | 1029 | ||
1029 | /* In case driver is removed when asynchronous FW downloading is | 1030 | /* In case driver is removed when asynchronous FW downloading is |
1030 | * in progress | 1031 | * in progress |
@@ -1035,11 +1036,8 @@ static void mwifiex_usb_cleanup_module(void) | |||
1035 | if (adapter->is_suspended) | 1036 | if (adapter->is_suspended) |
1036 | mwifiex_usb_resume(usb_card->intf); | 1037 | mwifiex_usb_resume(usb_card->intf); |
1037 | #endif | 1038 | #endif |
1038 | for (i = 0; i < adapter->priv_num; i++) | 1039 | |
1039 | if ((GET_BSS_ROLE(adapter->priv[i]) == | 1040 | mwifiex_deauthenticate_all(adapter); |
1040 | MWIFIEX_BSS_ROLE_STA) && | ||
1041 | adapter->priv[i]->media_connected) | ||
1042 | mwifiex_deauthenticate(adapter->priv[i], NULL); | ||
1043 | 1041 | ||
1044 | mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, | 1042 | mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, |
1045 | MWIFIEX_BSS_ROLE_ANY), | 1043 | 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_ */ |