diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-01-03 15:16:34 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-03 15:16:34 -0500 |
commit | 57adc1fcbae2c13104ce291b40f23e40a414fa87 (patch) | |
tree | a22d95cd3a96cbd515cd24fb0833739576c5e92f /drivers/net/wireless/ath/ath6kl | |
parent | faa85aa24286a9e14ae7cc797352350c3ac39986 (diff) | |
parent | dc0d633e35643662f27a0b1c531da3cd6b204b9c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/b43/dma.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl')
22 files changed, 1809 insertions, 653 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index 3d5f8be20eac..d755a5e7ed20 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig | |||
@@ -1,12 +1,29 @@ | |||
1 | config ATH6KL | 1 | config ATH6KL |
2 | tristate "Atheros ath6kl support" | 2 | tristate "Atheros mobile chipsets support" |
3 | |||
4 | config ATH6KL_SDIO | ||
5 | tristate "Atheros ath6kl SDIO support" | ||
6 | depends on ATH6KL | ||
3 | depends on MMC | 7 | depends on MMC |
4 | depends on CFG80211 | 8 | depends on CFG80211 |
5 | ---help--- | 9 | ---help--- |
6 | This module adds support for wireless adapters based on | 10 | This module adds support for wireless adapters based on |
7 | Atheros AR6003 chipset running over SDIO. If you choose to | 11 | Atheros AR6003 and AR6004 chipsets running over SDIO. If you |
8 | build it as a module, it will be called ath6kl. Pls note | 12 | choose to build it as a module, it will be called ath6kl_sdio. |
9 | that AR6002 and AR6001 are not supported by this driver. | 13 | Please note that AR6002 and AR6001 are not supported by this |
14 | driver. | ||
15 | |||
16 | config ATH6KL_USB | ||
17 | tristate "Atheros ath6kl USB support" | ||
18 | depends on ATH6KL | ||
19 | depends on USB | ||
20 | depends on CFG80211 | ||
21 | depends on EXPERIMENTAL | ||
22 | ---help--- | ||
23 | This module adds support for wireless adapters based on | ||
24 | Atheros AR6004 chipset running over USB. This is still under | ||
25 | implementation and it isn't functional. If you choose to | ||
26 | build it as a module, it will be called ath6kl_usb. | ||
10 | 27 | ||
11 | config ATH6KL_DEBUG | 28 | config ATH6KL_DEBUG |
12 | bool "Atheros ath6kl debugging" | 29 | bool "Atheros ath6kl debugging" |
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index 707069303550..e14cef9c3c0e 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile | |||
@@ -21,17 +21,30 @@ | |||
21 | # Author(s): ="Atheros" | 21 | # Author(s): ="Atheros" |
22 | #------------------------------------------------------------------------------ | 22 | #------------------------------------------------------------------------------ |
23 | 23 | ||
24 | obj-$(CONFIG_ATH6KL) := ath6kl.o | 24 | obj-$(CONFIG_ATH6KL_SDIO) := ath6kl_sdio.o |
25 | ath6kl-y += debug.o | 25 | ath6kl_sdio-y += debug.o |
26 | ath6kl-y += hif.o | 26 | ath6kl_sdio-y += hif.o |
27 | ath6kl-y += htc.o | 27 | ath6kl_sdio-y += htc.o |
28 | ath6kl-y += bmi.o | 28 | ath6kl_sdio-y += bmi.o |
29 | ath6kl-y += cfg80211.o | 29 | ath6kl_sdio-y += cfg80211.o |
30 | ath6kl-y += init.o | 30 | ath6kl_sdio-y += init.o |
31 | ath6kl-y += main.o | 31 | ath6kl_sdio-y += main.o |
32 | ath6kl-y += txrx.o | 32 | ath6kl_sdio-y += txrx.o |
33 | ath6kl-y += wmi.o | 33 | ath6kl_sdio-y += wmi.o |
34 | ath6kl-y += sdio.o | 34 | ath6kl_sdio-y += sdio.o |
35 | ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o | 35 | ath6kl_sdio-$(CONFIG_NL80211_TESTMODE) += testmode.o |
36 | |||
37 | obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o | ||
38 | ath6kl_usb-y += debug.o | ||
39 | ath6kl_usb-y += hif.o | ||
40 | ath6kl_usb-y += htc.o | ||
41 | ath6kl_usb-y += bmi.o | ||
42 | ath6kl_usb-y += cfg80211.o | ||
43 | ath6kl_usb-y += init.o | ||
44 | ath6kl_usb-y += main.o | ||
45 | ath6kl_usb-y += txrx.o | ||
46 | ath6kl_usb-y += wmi.o | ||
47 | ath6kl_usb-y += usb.o | ||
48 | ath6kl_usb-$(CONFIG_NL80211_TESTMODE) += testmode.o | ||
36 | 49 | ||
37 | ccflags-y += -D__CHECK_ENDIAN__ | 50 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c index a962fe4c6b7e..aef00d5a1438 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.c +++ b/drivers/net/wireless/ath/ath6kl/bmi.c | |||
@@ -19,165 +19,6 @@ | |||
19 | #include "target.h" | 19 | #include "target.h" |
20 | #include "debug.h" | 20 | #include "debug.h" |
21 | 21 | ||
22 | static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar) | ||
23 | { | ||
24 | u32 addr; | ||
25 | unsigned long timeout; | ||
26 | int ret; | ||
27 | |||
28 | ar->bmi.cmd_credits = 0; | ||
29 | |||
30 | /* Read the counter register to get the command credits */ | ||
31 | addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; | ||
32 | |||
33 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); | ||
34 | while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) { | ||
35 | |||
36 | /* | ||
37 | * Hit the credit counter with a 4-byte access, the first byte | ||
38 | * read will hit the counter and cause a decrement, while the | ||
39 | * remaining 3 bytes has no effect. The rationale behind this | ||
40 | * is to make all HIF accesses 4-byte aligned. | ||
41 | */ | ||
42 | ret = hif_read_write_sync(ar, addr, | ||
43 | (u8 *)&ar->bmi.cmd_credits, 4, | ||
44 | HIF_RD_SYNC_BYTE_INC); | ||
45 | if (ret) { | ||
46 | ath6kl_err("Unable to decrement the command credit count register: %d\n", | ||
47 | ret); | ||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | /* The counter is only 8 bits. | ||
52 | * Ignore anything in the upper 3 bytes | ||
53 | */ | ||
54 | ar->bmi.cmd_credits &= 0xFF; | ||
55 | } | ||
56 | |||
57 | if (!ar->bmi.cmd_credits) { | ||
58 | ath6kl_err("bmi communication timeout\n"); | ||
59 | return -ETIMEDOUT; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar) | ||
66 | { | ||
67 | unsigned long timeout; | ||
68 | u32 rx_word = 0; | ||
69 | int ret = 0; | ||
70 | |||
71 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); | ||
72 | while (time_before(jiffies, timeout) && !rx_word) { | ||
73 | ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS, | ||
74 | (u8 *)&rx_word, sizeof(rx_word), | ||
75 | HIF_RD_SYNC_BYTE_INC); | ||
76 | if (ret) { | ||
77 | ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n"); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | /* all we really want is one bit */ | ||
82 | rx_word &= (1 << ENDPOINT1); | ||
83 | } | ||
84 | |||
85 | if (!rx_word) { | ||
86 | ath6kl_err("bmi_recv_buf FIFO empty\n"); | ||
87 | return -EINVAL; | ||
88 | } | ||
89 | |||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len) | ||
94 | { | ||
95 | int ret; | ||
96 | u32 addr; | ||
97 | |||
98 | ret = ath6kl_get_bmi_cmd_credits(ar); | ||
99 | if (ret) | ||
100 | return ret; | ||
101 | |||
102 | addr = ar->mbox_info.htc_addr; | ||
103 | |||
104 | ret = hif_read_write_sync(ar, addr, buf, len, | ||
105 | HIF_WR_SYNC_BYTE_INC); | ||
106 | if (ret) | ||
107 | ath6kl_err("unable to send the bmi data to the device\n"); | ||
108 | |||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len) | ||
113 | { | ||
114 | int ret; | ||
115 | u32 addr; | ||
116 | |||
117 | /* | ||
118 | * During normal bootup, small reads may be required. | ||
119 | * Rather than issue an HIF Read and then wait as the Target | ||
120 | * adds successive bytes to the FIFO, we wait here until | ||
121 | * we know that response data is available. | ||
122 | * | ||
123 | * This allows us to cleanly timeout on an unexpected | ||
124 | * Target failure rather than risk problems at the HIF level. | ||
125 | * In particular, this avoids SDIO timeouts and possibly garbage | ||
126 | * data on some host controllers. And on an interconnect | ||
127 | * such as Compact Flash (as well as some SDIO masters) which | ||
128 | * does not provide any indication on data timeout, it avoids | ||
129 | * a potential hang or garbage response. | ||
130 | * | ||
131 | * Synchronization is more difficult for reads larger than the | ||
132 | * size of the MBOX FIFO (128B), because the Target is unable | ||
133 | * to push the 129th byte of data until AFTER the Host posts an | ||
134 | * HIF Read and removes some FIFO data. So for large reads the | ||
135 | * Host proceeds to post an HIF Read BEFORE all the data is | ||
136 | * actually available to read. Fortunately, large BMI reads do | ||
137 | * not occur in practice -- they're supported for debug/development. | ||
138 | * | ||
139 | * So Host/Target BMI synchronization is divided into these cases: | ||
140 | * CASE 1: length < 4 | ||
141 | * Should not happen | ||
142 | * | ||
143 | * CASE 2: 4 <= length <= 128 | ||
144 | * Wait for first 4 bytes to be in FIFO | ||
145 | * If CONSERVATIVE_BMI_READ is enabled, also wait for | ||
146 | * a BMI command credit, which indicates that the ENTIRE | ||
147 | * response is available in the the FIFO | ||
148 | * | ||
149 | * CASE 3: length > 128 | ||
150 | * Wait for the first 4 bytes to be in FIFO | ||
151 | * | ||
152 | * For most uses, a small timeout should be sufficient and we will | ||
153 | * usually see a response quickly; but there may be some unusual | ||
154 | * (debug) cases of BMI_EXECUTE where we want an larger timeout. | ||
155 | * For now, we use an unbounded busy loop while waiting for | ||
156 | * BMI_EXECUTE. | ||
157 | * | ||
158 | * If BMI_EXECUTE ever needs to support longer-latency execution, | ||
159 | * especially in production, this code needs to be enhanced to sleep | ||
160 | * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently | ||
161 | * a function of Host processor speed. | ||
162 | */ | ||
163 | if (len >= 4) { /* NB: Currently, always true */ | ||
164 | ret = ath6kl_bmi_get_rx_lkahd(ar); | ||
165 | if (ret) | ||
166 | return ret; | ||
167 | } | ||
168 | |||
169 | addr = ar->mbox_info.htc_addr; | ||
170 | ret = hif_read_write_sync(ar, addr, buf, len, | ||
171 | HIF_RD_SYNC_BYTE_INC); | ||
172 | if (ret) { | ||
173 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | ||
174 | ret); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | int ath6kl_bmi_done(struct ath6kl *ar) | 22 | int ath6kl_bmi_done(struct ath6kl *ar) |
182 | { | 23 | { |
183 | int ret; | 24 | int ret; |
@@ -190,7 +31,7 @@ int ath6kl_bmi_done(struct ath6kl *ar) | |||
190 | 31 | ||
191 | ar->bmi.done_sent = true; | 32 | ar->bmi.done_sent = true; |
192 | 33 | ||
193 | ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid)); | 34 | ret = ath6kl_hif_bmi_write(ar, (u8 *)&cid, sizeof(cid)); |
194 | if (ret) { | 35 | if (ret) { |
195 | ath6kl_err("Unable to send bmi done: %d\n", ret); | 36 | ath6kl_err("Unable to send bmi done: %d\n", ret); |
196 | return ret; | 37 | return ret; |
@@ -210,14 +51,20 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
210 | return -EACCES; | 51 | return -EACCES; |
211 | } | 52 | } |
212 | 53 | ||
213 | ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid)); | 54 | ret = ath6kl_hif_bmi_write(ar, (u8 *)&cid, sizeof(cid)); |
214 | if (ret) { | 55 | if (ret) { |
215 | ath6kl_err("Unable to send get target info: %d\n", ret); | 56 | ath6kl_err("Unable to send get target info: %d\n", ret); |
216 | return ret; | 57 | return ret; |
217 | } | 58 | } |
218 | 59 | ||
219 | ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version, | 60 | if (ar->hif_type == ATH6KL_HIF_TYPE_USB) { |
220 | sizeof(targ_info->version)); | 61 | ret = ath6kl_hif_bmi_read(ar, (u8 *)targ_info, |
62 | sizeof(*targ_info)); | ||
63 | } else { | ||
64 | ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, | ||
65 | sizeof(targ_info->version)); | ||
66 | } | ||
67 | |||
221 | if (ret) { | 68 | if (ret) { |
222 | ath6kl_err("Unable to recv target info: %d\n", ret); | 69 | ath6kl_err("Unable to recv target info: %d\n", ret); |
223 | return ret; | 70 | return ret; |
@@ -225,7 +72,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
225 | 72 | ||
226 | if (le32_to_cpu(targ_info->version) == TARGET_VERSION_SENTINAL) { | 73 | if (le32_to_cpu(targ_info->version) == TARGET_VERSION_SENTINAL) { |
227 | /* Determine how many bytes are in the Target's targ_info */ | 74 | /* Determine how many bytes are in the Target's targ_info */ |
228 | ret = ath6kl_bmi_recv_buf(ar, | 75 | ret = ath6kl_hif_bmi_read(ar, |
229 | (u8 *)&targ_info->byte_count, | 76 | (u8 *)&targ_info->byte_count, |
230 | sizeof(targ_info->byte_count)); | 77 | sizeof(targ_info->byte_count)); |
231 | if (ret) { | 78 | if (ret) { |
@@ -244,7 +91,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, | |||
244 | } | 91 | } |
245 | 92 | ||
246 | /* Read the remainder of the targ_info */ | 93 | /* Read the remainder of the targ_info */ |
247 | ret = ath6kl_bmi_recv_buf(ar, | 94 | ret = ath6kl_hif_bmi_read(ar, |
248 | ((u8 *)targ_info) + | 95 | ((u8 *)targ_info) + |
249 | sizeof(targ_info->byte_count), | 96 | sizeof(targ_info->byte_count), |
250 | sizeof(*targ_info) - | 97 | sizeof(*targ_info) - |
@@ -276,8 +123,8 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
276 | return -EACCES; | 123 | return -EACCES; |
277 | } | 124 | } |
278 | 125 | ||
279 | size = BMI_DATASZ_MAX + sizeof(cid) + sizeof(addr) + sizeof(len); | 126 | size = ar->bmi.max_data_size + sizeof(cid) + sizeof(addr) + sizeof(len); |
280 | if (size > MAX_BMI_CMDBUF_SZ) { | 127 | if (size > ar->bmi.max_cmd_size) { |
281 | WARN_ON(1); | 128 | WARN_ON(1); |
282 | return -EINVAL; | 129 | return -EINVAL; |
283 | } | 130 | } |
@@ -290,8 +137,8 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
290 | len_remain = len; | 137 | len_remain = len; |
291 | 138 | ||
292 | while (len_remain) { | 139 | while (len_remain) { |
293 | rx_len = (len_remain < BMI_DATASZ_MAX) ? | 140 | rx_len = (len_remain < ar->bmi.max_data_size) ? |
294 | len_remain : BMI_DATASZ_MAX; | 141 | len_remain : ar->bmi.max_data_size; |
295 | offset = 0; | 142 | offset = 0; |
296 | memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); | 143 | memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); |
297 | offset += sizeof(cid); | 144 | offset += sizeof(cid); |
@@ -300,13 +147,13 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
300 | memcpy(&(ar->bmi.cmd_buf[offset]), &rx_len, sizeof(rx_len)); | 147 | memcpy(&(ar->bmi.cmd_buf[offset]), &rx_len, sizeof(rx_len)); |
301 | offset += sizeof(len); | 148 | offset += sizeof(len); |
302 | 149 | ||
303 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 150 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
304 | if (ret) { | 151 | if (ret) { |
305 | ath6kl_err("Unable to write to the device: %d\n", | 152 | ath6kl_err("Unable to write to the device: %d\n", |
306 | ret); | 153 | ret); |
307 | return ret; | 154 | return ret; |
308 | } | 155 | } |
309 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len); | 156 | ret = ath6kl_hif_bmi_read(ar, ar->bmi.cmd_buf, rx_len); |
310 | if (ret) { | 157 | if (ret) { |
311 | ath6kl_err("Unable to read from the device: %d\n", | 158 | ath6kl_err("Unable to read from the device: %d\n", |
312 | ret); | 159 | ret); |
@@ -326,7 +173,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
326 | u32 offset; | 173 | u32 offset; |
327 | u32 len_remain, tx_len; | 174 | u32 len_remain, tx_len; |
328 | const u32 header = sizeof(cid) + sizeof(addr) + sizeof(len); | 175 | const u32 header = sizeof(cid) + sizeof(addr) + sizeof(len); |
329 | u8 aligned_buf[BMI_DATASZ_MAX]; | 176 | u8 aligned_buf[400]; |
330 | u8 *src; | 177 | u8 *src; |
331 | 178 | ||
332 | if (ar->bmi.done_sent) { | 179 | if (ar->bmi.done_sent) { |
@@ -334,12 +181,15 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
334 | return -EACCES; | 181 | return -EACCES; |
335 | } | 182 | } |
336 | 183 | ||
337 | if ((BMI_DATASZ_MAX + header) > MAX_BMI_CMDBUF_SZ) { | 184 | if ((ar->bmi.max_data_size + header) > ar->bmi.max_cmd_size) { |
338 | WARN_ON(1); | 185 | WARN_ON(1); |
339 | return -EINVAL; | 186 | return -EINVAL; |
340 | } | 187 | } |
341 | 188 | ||
342 | memset(ar->bmi.cmd_buf, 0, BMI_DATASZ_MAX + header); | 189 | if (WARN_ON(ar->bmi.max_data_size > sizeof(aligned_buf))) |
190 | return -E2BIG; | ||
191 | |||
192 | memset(ar->bmi.cmd_buf, 0, ar->bmi.max_data_size + header); | ||
343 | 193 | ||
344 | ath6kl_dbg(ATH6KL_DBG_BMI, | 194 | ath6kl_dbg(ATH6KL_DBG_BMI, |
345 | "bmi write memory: addr: 0x%x, len: %d\n", addr, len); | 195 | "bmi write memory: addr: 0x%x, len: %d\n", addr, len); |
@@ -348,7 +198,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
348 | while (len_remain) { | 198 | while (len_remain) { |
349 | src = &buf[len - len_remain]; | 199 | src = &buf[len - len_remain]; |
350 | 200 | ||
351 | if (len_remain < (BMI_DATASZ_MAX - header)) { | 201 | if (len_remain < (ar->bmi.max_data_size - header)) { |
352 | if (len_remain & 3) { | 202 | if (len_remain & 3) { |
353 | /* align it with 4 bytes */ | 203 | /* align it with 4 bytes */ |
354 | len_remain = len_remain + | 204 | len_remain = len_remain + |
@@ -358,7 +208,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
358 | } | 208 | } |
359 | tx_len = len_remain; | 209 | tx_len = len_remain; |
360 | } else { | 210 | } else { |
361 | tx_len = (BMI_DATASZ_MAX - header); | 211 | tx_len = (ar->bmi.max_data_size - header); |
362 | } | 212 | } |
363 | 213 | ||
364 | offset = 0; | 214 | offset = 0; |
@@ -371,7 +221,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) | |||
371 | memcpy(&(ar->bmi.cmd_buf[offset]), src, tx_len); | 221 | memcpy(&(ar->bmi.cmd_buf[offset]), src, tx_len); |
372 | offset += tx_len; | 222 | offset += tx_len; |
373 | 223 | ||
374 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 224 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
375 | if (ret) { | 225 | if (ret) { |
376 | ath6kl_err("Unable to write to the device: %d\n", | 226 | ath6kl_err("Unable to write to the device: %d\n", |
377 | ret); | 227 | ret); |
@@ -396,7 +246,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param) | |||
396 | } | 246 | } |
397 | 247 | ||
398 | size = sizeof(cid) + sizeof(addr) + sizeof(param); | 248 | size = sizeof(cid) + sizeof(addr) + sizeof(param); |
399 | if (size > MAX_BMI_CMDBUF_SZ) { | 249 | if (size > ar->bmi.max_cmd_size) { |
400 | WARN_ON(1); | 250 | WARN_ON(1); |
401 | return -EINVAL; | 251 | return -EINVAL; |
402 | } | 252 | } |
@@ -413,13 +263,13 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param) | |||
413 | memcpy(&(ar->bmi.cmd_buf[offset]), param, sizeof(*param)); | 263 | memcpy(&(ar->bmi.cmd_buf[offset]), param, sizeof(*param)); |
414 | offset += sizeof(*param); | 264 | offset += sizeof(*param); |
415 | 265 | ||
416 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 266 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
417 | if (ret) { | 267 | if (ret) { |
418 | ath6kl_err("Unable to write to the device: %d\n", ret); | 268 | ath6kl_err("Unable to write to the device: %d\n", ret); |
419 | return ret; | 269 | return ret; |
420 | } | 270 | } |
421 | 271 | ||
422 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param)); | 272 | ret = ath6kl_hif_bmi_read(ar, ar->bmi.cmd_buf, sizeof(*param)); |
423 | if (ret) { | 273 | if (ret) { |
424 | ath6kl_err("Unable to read from the device: %d\n", ret); | 274 | ath6kl_err("Unable to read from the device: %d\n", ret); |
425 | return ret; | 275 | return ret; |
@@ -443,7 +293,7 @@ int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr) | |||
443 | } | 293 | } |
444 | 294 | ||
445 | size = sizeof(cid) + sizeof(addr); | 295 | size = sizeof(cid) + sizeof(addr); |
446 | if (size > MAX_BMI_CMDBUF_SZ) { | 296 | if (size > ar->bmi.max_cmd_size) { |
447 | WARN_ON(1); | 297 | WARN_ON(1); |
448 | return -EINVAL; | 298 | return -EINVAL; |
449 | } | 299 | } |
@@ -457,7 +307,7 @@ int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr) | |||
457 | memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); | 307 | memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); |
458 | offset += sizeof(addr); | 308 | offset += sizeof(addr); |
459 | 309 | ||
460 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 310 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
461 | if (ret) { | 311 | if (ret) { |
462 | ath6kl_err("Unable to write to the device: %d\n", ret); | 312 | ath6kl_err("Unable to write to the device: %d\n", ret); |
463 | return ret; | 313 | return ret; |
@@ -479,7 +329,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param) | |||
479 | } | 329 | } |
480 | 330 | ||
481 | size = sizeof(cid) + sizeof(addr); | 331 | size = sizeof(cid) + sizeof(addr); |
482 | if (size > MAX_BMI_CMDBUF_SZ) { | 332 | if (size > ar->bmi.max_cmd_size) { |
483 | WARN_ON(1); | 333 | WARN_ON(1); |
484 | return -EINVAL; | 334 | return -EINVAL; |
485 | } | 335 | } |
@@ -493,13 +343,13 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param) | |||
493 | memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); | 343 | memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); |
494 | offset += sizeof(addr); | 344 | offset += sizeof(addr); |
495 | 345 | ||
496 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 346 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
497 | if (ret) { | 347 | if (ret) { |
498 | ath6kl_err("Unable to write to the device: %d\n", ret); | 348 | ath6kl_err("Unable to write to the device: %d\n", ret); |
499 | return ret; | 349 | return ret; |
500 | } | 350 | } |
501 | 351 | ||
502 | ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param)); | 352 | ret = ath6kl_hif_bmi_read(ar, ar->bmi.cmd_buf, sizeof(*param)); |
503 | if (ret) { | 353 | if (ret) { |
504 | ath6kl_err("Unable to read from the device: %d\n", ret); | 354 | ath6kl_err("Unable to read from the device: %d\n", ret); |
505 | return ret; | 355 | return ret; |
@@ -522,7 +372,7 @@ int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param) | |||
522 | } | 372 | } |
523 | 373 | ||
524 | size = sizeof(cid) + sizeof(addr) + sizeof(param); | 374 | size = sizeof(cid) + sizeof(addr) + sizeof(param); |
525 | if (size > MAX_BMI_CMDBUF_SZ) { | 375 | if (size > ar->bmi.max_cmd_size) { |
526 | WARN_ON(1); | 376 | WARN_ON(1); |
527 | return -EINVAL; | 377 | return -EINVAL; |
528 | } | 378 | } |
@@ -540,7 +390,7 @@ int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param) | |||
540 | memcpy(&(ar->bmi.cmd_buf[offset]), ¶m, sizeof(param)); | 390 | memcpy(&(ar->bmi.cmd_buf[offset]), ¶m, sizeof(param)); |
541 | offset += sizeof(param); | 391 | offset += sizeof(param); |
542 | 392 | ||
543 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 393 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
544 | if (ret) { | 394 | if (ret) { |
545 | ath6kl_err("Unable to write to the device: %d\n", ret); | 395 | ath6kl_err("Unable to write to the device: %d\n", ret); |
546 | return ret; | 396 | return ret; |
@@ -563,8 +413,8 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len) | |||
563 | return -EACCES; | 413 | return -EACCES; |
564 | } | 414 | } |
565 | 415 | ||
566 | size = BMI_DATASZ_MAX + header; | 416 | size = ar->bmi.max_data_size + header; |
567 | if (size > MAX_BMI_CMDBUF_SZ) { | 417 | if (size > ar->bmi.max_cmd_size) { |
568 | WARN_ON(1); | 418 | WARN_ON(1); |
569 | return -EINVAL; | 419 | return -EINVAL; |
570 | } | 420 | } |
@@ -575,8 +425,8 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len) | |||
575 | 425 | ||
576 | len_remain = len; | 426 | len_remain = len; |
577 | while (len_remain) { | 427 | while (len_remain) { |
578 | tx_len = (len_remain < (BMI_DATASZ_MAX - header)) ? | 428 | tx_len = (len_remain < (ar->bmi.max_data_size - header)) ? |
579 | len_remain : (BMI_DATASZ_MAX - header); | 429 | len_remain : (ar->bmi.max_data_size - header); |
580 | 430 | ||
581 | offset = 0; | 431 | offset = 0; |
582 | memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); | 432 | memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid)); |
@@ -587,7 +437,7 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len) | |||
587 | tx_len); | 437 | tx_len); |
588 | offset += tx_len; | 438 | offset += tx_len; |
589 | 439 | ||
590 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 440 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
591 | if (ret) { | 441 | if (ret) { |
592 | ath6kl_err("Unable to write to the device: %d\n", | 442 | ath6kl_err("Unable to write to the device: %d\n", |
593 | ret); | 443 | ret); |
@@ -613,7 +463,7 @@ int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr) | |||
613 | } | 463 | } |
614 | 464 | ||
615 | size = sizeof(cid) + sizeof(addr); | 465 | size = sizeof(cid) + sizeof(addr); |
616 | if (size > MAX_BMI_CMDBUF_SZ) { | 466 | if (size > ar->bmi.max_cmd_size) { |
617 | WARN_ON(1); | 467 | WARN_ON(1); |
618 | return -EINVAL; | 468 | return -EINVAL; |
619 | } | 469 | } |
@@ -629,7 +479,7 @@ int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr) | |||
629 | memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); | 479 | memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr)); |
630 | offset += sizeof(addr); | 480 | offset += sizeof(addr); |
631 | 481 | ||
632 | ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset); | 482 | ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); |
633 | if (ret) { | 483 | if (ret) { |
634 | ath6kl_err("Unable to start LZ stream to the device: %d\n", | 484 | ath6kl_err("Unable to start LZ stream to the device: %d\n", |
635 | ret); | 485 | ret); |
@@ -677,8 +527,13 @@ void ath6kl_bmi_reset(struct ath6kl *ar) | |||
677 | 527 | ||
678 | int ath6kl_bmi_init(struct ath6kl *ar) | 528 | int ath6kl_bmi_init(struct ath6kl *ar) |
679 | { | 529 | { |
680 | ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC); | 530 | if (WARN_ON(ar->bmi.max_data_size == 0)) |
531 | return -EINVAL; | ||
532 | |||
533 | /* cmd + addr + len + data_size */ | ||
534 | ar->bmi.max_cmd_size = ar->bmi.max_data_size + (sizeof(u32) * 3); | ||
681 | 535 | ||
536 | ar->bmi.cmd_buf = kzalloc(ar->bmi.max_cmd_size, GFP_ATOMIC); | ||
682 | if (!ar->bmi.cmd_buf) | 537 | if (!ar->bmi.cmd_buf) |
683 | return -ENOMEM; | 538 | return -ENOMEM; |
684 | 539 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h index 009e8f650ab1..f1ca6812456d 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.h +++ b/drivers/net/wireless/ath/ath6kl/bmi.h | |||
@@ -44,12 +44,6 @@ | |||
44 | * BMI handles all required Target-side cache flushing. | 44 | * BMI handles all required Target-side cache flushing. |
45 | */ | 45 | */ |
46 | 46 | ||
47 | #define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \ | ||
48 | (sizeof(u32) * 3 /* cmd + addr + len */)) | ||
49 | |||
50 | /* Maximum data size used for BMI transfers */ | ||
51 | #define BMI_DATASZ_MAX 256 | ||
52 | |||
53 | /* BMI Commands */ | 47 | /* BMI Commands */ |
54 | 48 | ||
55 | #define BMI_NO_COMMAND 0 | 49 | #define BMI_NO_COMMAND 0 |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 02526044acb9..6c59a217b1a1 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -23,10 +23,8 @@ | |||
23 | #include "testmode.h" | 23 | #include "testmode.h" |
24 | 24 | ||
25 | static unsigned int ath6kl_p2p; | 25 | static unsigned int ath6kl_p2p; |
26 | static unsigned int multi_norm_if_support; | ||
27 | 26 | ||
28 | module_param(ath6kl_p2p, uint, 0644); | 27 | module_param(ath6kl_p2p, uint, 0644); |
29 | module_param(multi_norm_if_support, uint, 0644); | ||
30 | 28 | ||
31 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | 29 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ |
32 | .bitrate = (_rate), \ | 30 | .bitrate = (_rate), \ |
@@ -127,6 +125,37 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = { | |||
127 | 125 | ||
128 | #define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */ | 126 | #define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */ |
129 | 127 | ||
128 | /* returns true if scheduled scan was stopped */ | ||
129 | static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif) | ||
130 | { | ||
131 | struct ath6kl *ar = vif->ar; | ||
132 | |||
133 | if (ar->state != ATH6KL_STATE_SCHED_SCAN) | ||
134 | return false; | ||
135 | |||
136 | del_timer_sync(&vif->sched_scan_timer); | ||
137 | |||
138 | ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
139 | ATH6KL_HOST_MODE_AWAKE); | ||
140 | |||
141 | ar->state = ATH6KL_STATE_ON; | ||
142 | |||
143 | return true; | ||
144 | } | ||
145 | |||
146 | static void ath6kl_cfg80211_sscan_disable(struct ath6kl_vif *vif) | ||
147 | { | ||
148 | struct ath6kl *ar = vif->ar; | ||
149 | bool stopped; | ||
150 | |||
151 | stopped = __ath6kl_cfg80211_sscan_stop(vif); | ||
152 | |||
153 | if (!stopped) | ||
154 | return; | ||
155 | |||
156 | cfg80211_sched_scan_stopped(ar->wiphy); | ||
157 | } | ||
158 | |||
130 | static int ath6kl_set_wpa_version(struct ath6kl_vif *vif, | 159 | static int ath6kl_set_wpa_version(struct ath6kl_vif *vif, |
131 | enum nl80211_wpa_versions wpa_version) | 160 | enum nl80211_wpa_versions wpa_version) |
132 | { | 161 | { |
@@ -205,6 +234,10 @@ static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast) | |||
205 | *ar_cipher = AES_CRYPT; | 234 | *ar_cipher = AES_CRYPT; |
206 | *ar_cipher_len = 0; | 235 | *ar_cipher_len = 0; |
207 | break; | 236 | break; |
237 | case WLAN_CIPHER_SUITE_SMS4: | ||
238 | *ar_cipher = WAPI_CRYPT; | ||
239 | *ar_cipher_len = 0; | ||
240 | break; | ||
208 | default: | 241 | default: |
209 | ath6kl_err("cipher 0x%x not supported\n", cipher); | 242 | ath6kl_err("cipher 0x%x not supported\n", cipher); |
210 | return -ENOTSUPP; | 243 | return -ENOTSUPP; |
@@ -355,7 +388,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, | |||
355 | 388 | ||
356 | if (type == NL80211_IFTYPE_STATION || | 389 | if (type == NL80211_IFTYPE_STATION || |
357 | type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) { | 390 | type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) { |
358 | for (i = 0; i < MAX_NUM_VIF; i++) { | 391 | for (i = 0; i < ar->vif_max; i++) { |
359 | if ((ar->avail_idx_map >> i) & BIT(0)) { | 392 | if ((ar->avail_idx_map >> i) & BIT(0)) { |
360 | *if_idx = i; | 393 | *if_idx = i; |
361 | return true; | 394 | return true; |
@@ -365,7 +398,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, | |||
365 | 398 | ||
366 | if (type == NL80211_IFTYPE_P2P_CLIENT || | 399 | if (type == NL80211_IFTYPE_P2P_CLIENT || |
367 | type == NL80211_IFTYPE_P2P_GO) { | 400 | type == NL80211_IFTYPE_P2P_GO) { |
368 | for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++) { | 401 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) { |
369 | if ((ar->avail_idx_map >> i) & BIT(0)) { | 402 | if ((ar->avail_idx_map >> i) & BIT(0)) { |
370 | *if_idx = i; | 403 | *if_idx = i; |
371 | return true; | 404 | return true; |
@@ -382,6 +415,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
382 | struct ath6kl *ar = ath6kl_priv(dev); | 415 | struct ath6kl *ar = ath6kl_priv(dev); |
383 | struct ath6kl_vif *vif = netdev_priv(dev); | 416 | struct ath6kl_vif *vif = netdev_priv(dev); |
384 | int status; | 417 | int status; |
418 | u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE; | ||
419 | |||
420 | ath6kl_cfg80211_sscan_disable(vif); | ||
385 | 421 | ||
386 | vif->sme_state = SME_CONNECTING; | 422 | vif->sme_state = SME_CONNECTING; |
387 | 423 | ||
@@ -427,9 +463,12 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
427 | 463 | ||
428 | if (sme->ie && (sme->ie_len > 0)) { | 464 | if (sme->ie && (sme->ie_len > 0)) { |
429 | status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); | 465 | status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); |
430 | if (status) | 466 | if (status) { |
467 | up(&ar->sem); | ||
431 | return status; | 468 | return status; |
432 | } | 469 | } |
470 | } else | ||
471 | ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG; | ||
433 | 472 | ||
434 | if (test_bit(CONNECTED, &vif->flags) && | 473 | if (test_bit(CONNECTED, &vif->flags) && |
435 | vif->ssid_len == sme->ssid_len && | 474 | vif->ssid_len == sme->ssid_len && |
@@ -519,6 +558,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
519 | 558 | ||
520 | vif->nw_type = vif->next_mode; | 559 | vif->nw_type = vif->next_mode; |
521 | 560 | ||
561 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) | ||
562 | nw_subtype = SUBTYPE_P2PCLIENT; | ||
563 | |||
522 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | 564 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
523 | "%s: connect called with authmode %d dot11 auth %d" | 565 | "%s: connect called with authmode %d dot11 auth %d" |
524 | " PW crypto %d PW crypto len %d GRP crypto %d" | 566 | " PW crypto %d PW crypto len %d GRP crypto %d" |
@@ -536,7 +578,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
536 | vif->grp_crypto, vif->grp_crypto_len, | 578 | vif->grp_crypto, vif->grp_crypto_len, |
537 | vif->ssid_len, vif->ssid, | 579 | vif->ssid_len, vif->ssid, |
538 | vif->req_bssid, vif->ch_hint, | 580 | vif->req_bssid, vif->ch_hint, |
539 | ar->connect_ctrl_flags); | 581 | ar->connect_ctrl_flags, nw_subtype); |
540 | 582 | ||
541 | up(&ar->sem); | 583 | up(&ar->sem); |
542 | 584 | ||
@@ -563,17 +605,28 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
563 | return 0; | 605 | return 0; |
564 | } | 606 | } |
565 | 607 | ||
566 | static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, const u8 *bssid, | 608 | static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, |
609 | enum network_type nw_type, | ||
610 | const u8 *bssid, | ||
567 | struct ieee80211_channel *chan, | 611 | struct ieee80211_channel *chan, |
568 | const u8 *beacon_ie, size_t beacon_ie_len) | 612 | const u8 *beacon_ie, size_t beacon_ie_len) |
569 | { | 613 | { |
570 | struct ath6kl *ar = vif->ar; | 614 | struct ath6kl *ar = vif->ar; |
571 | struct cfg80211_bss *bss; | 615 | struct cfg80211_bss *bss; |
616 | u16 cap_mask, cap_val; | ||
572 | u8 *ie; | 617 | u8 *ie; |
573 | 618 | ||
619 | if (nw_type & ADHOC_NETWORK) { | ||
620 | cap_mask = WLAN_CAPABILITY_IBSS; | ||
621 | cap_val = WLAN_CAPABILITY_IBSS; | ||
622 | } else { | ||
623 | cap_mask = WLAN_CAPABILITY_ESS; | ||
624 | cap_val = WLAN_CAPABILITY_ESS; | ||
625 | } | ||
626 | |||
574 | bss = cfg80211_get_bss(ar->wiphy, chan, bssid, | 627 | bss = cfg80211_get_bss(ar->wiphy, chan, bssid, |
575 | vif->ssid, vif->ssid_len, WLAN_CAPABILITY_ESS, | 628 | vif->ssid, vif->ssid_len, |
576 | WLAN_CAPABILITY_ESS); | 629 | cap_mask, cap_val); |
577 | if (bss == NULL) { | 630 | if (bss == NULL) { |
578 | /* | 631 | /* |
579 | * Since cfg80211 may not yet know about the BSS, | 632 | * Since cfg80211 may not yet know about the BSS, |
@@ -591,13 +644,12 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, const u8 *bssid, | |||
591 | memcpy(ie + 2, vif->ssid, vif->ssid_len); | 644 | memcpy(ie + 2, vif->ssid, vif->ssid_len); |
592 | memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len); | 645 | memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len); |
593 | bss = cfg80211_inform_bss(ar->wiphy, chan, | 646 | bss = cfg80211_inform_bss(ar->wiphy, chan, |
594 | bssid, 0, WLAN_CAPABILITY_ESS, 100, | 647 | bssid, 0, cap_val, 100, |
595 | ie, 2 + vif->ssid_len + beacon_ie_len, | 648 | ie, 2 + vif->ssid_len + beacon_ie_len, |
596 | 0, GFP_KERNEL); | 649 | 0, GFP_KERNEL); |
597 | if (bss) | 650 | if (bss) |
598 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for " | 651 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to " |
599 | "%pM prior to indicating connect/roamed " | 652 | "cfg80211\n", bssid); |
600 | "event\n", bssid); | ||
601 | kfree(ie); | 653 | kfree(ie); |
602 | } else | 654 | } else |
603 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " | 655 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " |
@@ -660,16 +712,16 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
660 | 712 | ||
661 | chan = ieee80211_get_channel(ar->wiphy, (int) channel); | 713 | chan = ieee80211_get_channel(ar->wiphy, (int) channel); |
662 | 714 | ||
663 | 715 | if (ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, assoc_info, | |
664 | if (nw_type & ADHOC_NETWORK) { | 716 | beacon_ie_len) < 0) { |
665 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); | 717 | ath6kl_err("could not add cfg80211 bss entry\n"); |
666 | return; | 718 | return; |
667 | } | 719 | } |
668 | 720 | ||
669 | if (ath6kl_add_bss_if_needed(vif, bssid, chan, assoc_info, | 721 | if (nw_type & ADHOC_NETWORK) { |
670 | beacon_ie_len) < 0) { | 722 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", |
671 | ath6kl_err("could not add cfg80211 bss entry for " | 723 | nw_type & ADHOC_CREATOR ? "creator" : "joiner"); |
672 | "connect/roamed notification\n"); | 724 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); |
673 | return; | 725 | return; |
674 | } | 726 | } |
675 | 727 | ||
@@ -691,12 +743,14 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
691 | static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy, | 743 | static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy, |
692 | struct net_device *dev, u16 reason_code) | 744 | struct net_device *dev, u16 reason_code) |
693 | { | 745 | { |
694 | struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev); | 746 | struct ath6kl *ar = ath6kl_priv(dev); |
695 | struct ath6kl_vif *vif = netdev_priv(dev); | 747 | struct ath6kl_vif *vif = netdev_priv(dev); |
696 | 748 | ||
697 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__, | 749 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__, |
698 | reason_code); | 750 | reason_code); |
699 | 751 | ||
752 | ath6kl_cfg80211_sscan_disable(vif); | ||
753 | |||
700 | if (!ath6kl_cfg80211_ready(vif)) | 754 | if (!ath6kl_cfg80211_ready(vif)) |
701 | return -EIO; | 755 | return -EIO; |
702 | 756 | ||
@@ -789,7 +843,7 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
789 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | 843 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, |
790 | struct cfg80211_scan_request *request) | 844 | struct cfg80211_scan_request *request) |
791 | { | 845 | { |
792 | struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); | 846 | struct ath6kl *ar = ath6kl_priv(ndev); |
793 | struct ath6kl_vif *vif = netdev_priv(ndev); | 847 | struct ath6kl_vif *vif = netdev_priv(ndev); |
794 | s8 n_channels = 0; | 848 | s8 n_channels = 0; |
795 | u16 *channels = NULL; | 849 | u16 *channels = NULL; |
@@ -799,6 +853,8 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
799 | if (!ath6kl_cfg80211_ready(vif)) | 853 | if (!ath6kl_cfg80211_ready(vif)) |
800 | return -EIO; | 854 | return -EIO; |
801 | 855 | ||
856 | ath6kl_cfg80211_sscan_disable(vif); | ||
857 | |||
802 | if (!ar->usr_bss_filter) { | 858 | if (!ar->usr_bss_filter) { |
803 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); | 859 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); |
804 | ret = ath6kl_wmi_bssfilter_cmd( | 860 | ret = ath6kl_wmi_bssfilter_cmd( |
@@ -824,6 +880,10 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
824 | request->ssids[i].ssid); | 880 | request->ssids[i].ssid); |
825 | } | 881 | } |
826 | 882 | ||
883 | /* | ||
884 | * FIXME: we should clear the IE in fw if it's not set so just | ||
885 | * remove the check altogether | ||
886 | */ | ||
827 | if (request->ie) { | 887 | if (request->ie) { |
828 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, | 888 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, |
829 | WMI_FRAME_PROBE_REQ, | 889 | WMI_FRAME_PROBE_REQ, |
@@ -860,9 +920,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
860 | if (test_bit(CONNECTED, &vif->flags)) | 920 | if (test_bit(CONNECTED, &vif->flags)) |
861 | force_fg_scan = 1; | 921 | force_fg_scan = 1; |
862 | 922 | ||
863 | ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx, WMI_LONG_SCAN, | 923 | if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, |
864 | force_fg_scan, false, 0, 0, n_channels, | 924 | ar->fw_capabilities)) { |
865 | channels); | 925 | /* |
926 | * If capable of doing P2P mgmt operations using | ||
927 | * station interface, send additional information like | ||
928 | * supported rates to advertise and xmit rates for | ||
929 | * probe requests | ||
930 | */ | ||
931 | ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx, | ||
932 | WMI_LONG_SCAN, force_fg_scan, | ||
933 | false, 0, 0, n_channels, | ||
934 | channels, request->no_cck, | ||
935 | request->rates); | ||
936 | } else { | ||
937 | ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx, | ||
938 | WMI_LONG_SCAN, force_fg_scan, | ||
939 | false, 0, 0, n_channels, | ||
940 | channels); | ||
941 | } | ||
866 | if (ret) | 942 | if (ret) |
867 | ath6kl_err("wmi_startscan_cmd failed\n"); | 943 | ath6kl_err("wmi_startscan_cmd failed\n"); |
868 | else | 944 | else |
@@ -905,7 +981,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
905 | const u8 *mac_addr, | 981 | const u8 *mac_addr, |
906 | struct key_params *params) | 982 | struct key_params *params) |
907 | { | 983 | { |
908 | struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); | 984 | struct ath6kl *ar = ath6kl_priv(ndev); |
909 | struct ath6kl_vif *vif = netdev_priv(ndev); | 985 | struct ath6kl_vif *vif = netdev_priv(ndev); |
910 | struct ath6kl_key *key = NULL; | 986 | struct ath6kl_key *key = NULL; |
911 | u8 key_usage; | 987 | u8 key_usage; |
@@ -937,13 +1013,19 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
937 | key_usage = GROUP_USAGE; | 1013 | key_usage = GROUP_USAGE; |
938 | 1014 | ||
939 | if (params) { | 1015 | if (params) { |
1016 | int seq_len = params->seq_len; | ||
1017 | if (params->cipher == WLAN_CIPHER_SUITE_SMS4 && | ||
1018 | seq_len > ATH6KL_KEY_SEQ_LEN) { | ||
1019 | /* Only first half of the WPI PN is configured */ | ||
1020 | seq_len = ATH6KL_KEY_SEQ_LEN; | ||
1021 | } | ||
940 | if (params->key_len > WLAN_MAX_KEY_LEN || | 1022 | if (params->key_len > WLAN_MAX_KEY_LEN || |
941 | params->seq_len > sizeof(key->seq)) | 1023 | seq_len > sizeof(key->seq)) |
942 | return -EINVAL; | 1024 | return -EINVAL; |
943 | 1025 | ||
944 | key->key_len = params->key_len; | 1026 | key->key_len = params->key_len; |
945 | memcpy(key->key, params->key, key->key_len); | 1027 | memcpy(key->key, params->key, key->key_len); |
946 | key->seq_len = params->seq_len; | 1028 | key->seq_len = seq_len; |
947 | memcpy(key->seq, params->seq, key->seq_len); | 1029 | memcpy(key->seq, params->seq, key->seq_len); |
948 | key->cipher = params->cipher; | 1030 | key->cipher = params->cipher; |
949 | } | 1031 | } |
@@ -961,6 +1043,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
961 | case WLAN_CIPHER_SUITE_CCMP: | 1043 | case WLAN_CIPHER_SUITE_CCMP: |
962 | key_type = AES_CRYPT; | 1044 | key_type = AES_CRYPT; |
963 | break; | 1045 | break; |
1046 | case WLAN_CIPHER_SUITE_SMS4: | ||
1047 | key_type = WAPI_CRYPT; | ||
1048 | break; | ||
964 | 1049 | ||
965 | default: | 1050 | default: |
966 | return -ENOTSUPP; | 1051 | return -ENOTSUPP; |
@@ -976,10 +1061,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
976 | __func__, key_index, key->key_len, key_type, | 1061 | __func__, key_index, key->key_len, key_type, |
977 | key_usage, key->seq_len); | 1062 | key_usage, key->seq_len); |
978 | 1063 | ||
979 | vif->def_txkey_index = key_index; | ||
980 | |||
981 | if (vif->nw_type == AP_NETWORK && !pairwise && | 1064 | if (vif->nw_type == AP_NETWORK && !pairwise && |
982 | (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) { | 1065 | (key_type == TKIP_CRYPT || key_type == AES_CRYPT || |
1066 | key_type == WAPI_CRYPT) && params) { | ||
983 | ar->ap_mode_bkey.valid = true; | 1067 | ar->ap_mode_bkey.valid = true; |
984 | ar->ap_mode_bkey.key_index = key_index; | 1068 | ar->ap_mode_bkey.key_index = key_index; |
985 | ar->ap_mode_bkey.key_type = key_type; | 1069 | ar->ap_mode_bkey.key_type = key_type; |
@@ -1012,8 +1096,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1012 | return 0; | 1096 | return 0; |
1013 | } | 1097 | } |
1014 | 1098 | ||
1015 | return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, | 1099 | return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, key_index, |
1016 | vif->def_txkey_index, | ||
1017 | key_type, key_usage, key->key_len, | 1100 | key_type, key_usage, key->key_len, |
1018 | key->seq, key->seq_len, key->key, | 1101 | key->seq, key->seq_len, key->key, |
1019 | KEY_OP_INIT_VAL, | 1102 | KEY_OP_INIT_VAL, |
@@ -1024,7 +1107,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1024 | u8 key_index, bool pairwise, | 1107 | u8 key_index, bool pairwise, |
1025 | const u8 *mac_addr) | 1108 | const u8 *mac_addr) |
1026 | { | 1109 | { |
1027 | struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); | 1110 | struct ath6kl *ar = ath6kl_priv(ndev); |
1028 | struct ath6kl_vif *vif = netdev_priv(ndev); | 1111 | struct ath6kl_vif *vif = netdev_priv(ndev); |
1029 | 1112 | ||
1030 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); | 1113 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index); |
@@ -1090,7 +1173,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, | |||
1090 | u8 key_index, bool unicast, | 1173 | u8 key_index, bool unicast, |
1091 | bool multicast) | 1174 | bool multicast) |
1092 | { | 1175 | { |
1093 | struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev); | 1176 | struct ath6kl *ar = ath6kl_priv(ndev); |
1094 | struct ath6kl_vif *vif = netdev_priv(ndev); | 1177 | struct ath6kl_vif *vif = netdev_priv(ndev); |
1095 | struct ath6kl_key *key = NULL; | 1178 | struct ath6kl_key *key = NULL; |
1096 | u8 key_usage; | 1179 | u8 key_usage; |
@@ -1181,11 +1264,12 @@ static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1181 | */ | 1264 | */ |
1182 | static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy, | 1265 | static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy, |
1183 | enum nl80211_tx_power_setting type, | 1266 | enum nl80211_tx_power_setting type, |
1184 | int dbm) | 1267 | int mbm) |
1185 | { | 1268 | { |
1186 | struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); | 1269 | struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); |
1187 | struct ath6kl_vif *vif; | 1270 | struct ath6kl_vif *vif; |
1188 | u8 ath6kl_dbm; | 1271 | u8 ath6kl_dbm; |
1272 | int dbm = MBM_TO_DBM(mbm); | ||
1189 | 1273 | ||
1190 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__, | 1274 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__, |
1191 | type, dbm); | 1275 | type, dbm); |
@@ -1288,7 +1372,7 @@ static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy, | |||
1288 | struct net_device *ndev; | 1372 | struct net_device *ndev; |
1289 | u8 if_idx, nw_type; | 1373 | u8 if_idx, nw_type; |
1290 | 1374 | ||
1291 | if (ar->num_vif == MAX_NUM_VIF) { | 1375 | if (ar->num_vif == ar->vif_max) { |
1292 | ath6kl_err("Reached maximum number of supported vif\n"); | 1376 | ath6kl_err("Reached maximum number of supported vif\n"); |
1293 | return ERR_PTR(-EINVAL); | 1377 | return ERR_PTR(-EINVAL); |
1294 | } | 1378 | } |
@@ -1333,9 +1417,6 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, | |||
1333 | 1417 | ||
1334 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type); | 1418 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type); |
1335 | 1419 | ||
1336 | if (!ath6kl_cfg80211_ready(vif)) | ||
1337 | return -EIO; | ||
1338 | |||
1339 | switch (type) { | 1420 | switch (type) { |
1340 | case NL80211_IFTYPE_STATION: | 1421 | case NL80211_IFTYPE_STATION: |
1341 | vif->next_mode = INFRA_NETWORK; | 1422 | vif->next_mode = INFRA_NETWORK; |
@@ -1426,7 +1507,7 @@ static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy, | |||
1426 | vif->grp_crypto, vif->grp_crypto_len, | 1507 | vif->grp_crypto, vif->grp_crypto_len, |
1427 | vif->ssid_len, vif->ssid, | 1508 | vif->ssid_len, vif->ssid, |
1428 | vif->req_bssid, vif->ch_hint, | 1509 | vif->req_bssid, vif->ch_hint, |
1429 | ar->connect_ctrl_flags); | 1510 | ar->connect_ctrl_flags, SUBTYPE_NONE); |
1430 | set_bit(CONNECT_PEND, &vif->flags); | 1511 | set_bit(CONNECT_PEND, &vif->flags); |
1431 | 1512 | ||
1432 | return 0; | 1513 | return 0; |
@@ -1453,6 +1534,7 @@ static const u32 cipher_suites[] = { | |||
1453 | WLAN_CIPHER_SUITE_TKIP, | 1534 | WLAN_CIPHER_SUITE_TKIP, |
1454 | WLAN_CIPHER_SUITE_CCMP, | 1535 | WLAN_CIPHER_SUITE_CCMP, |
1455 | CCKM_KRK_CIPHER_SUITE, | 1536 | CCKM_KRK_CIPHER_SUITE, |
1537 | WLAN_CIPHER_SUITE_SMS4, | ||
1456 | }; | 1538 | }; |
1457 | 1539 | ||
1458 | static bool is_rate_legacy(s32 rate) | 1540 | static bool is_rate_legacy(s32 rate) |
@@ -1779,7 +1861,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
1779 | 1861 | ||
1780 | case ATH6KL_CFG_SUSPEND_DEEPSLEEP: | 1862 | case ATH6KL_CFG_SUSPEND_DEEPSLEEP: |
1781 | 1863 | ||
1782 | ath6kl_cfg80211_stop(ar); | 1864 | ath6kl_cfg80211_stop_all(ar); |
1783 | 1865 | ||
1784 | /* save the current power mode before enabling power save */ | 1866 | /* save the current power mode before enabling power save */ |
1785 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | 1867 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; |
@@ -1796,7 +1878,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
1796 | 1878 | ||
1797 | case ATH6KL_CFG_SUSPEND_CUTPOWER: | 1879 | case ATH6KL_CFG_SUSPEND_CUTPOWER: |
1798 | 1880 | ||
1799 | ath6kl_cfg80211_stop(ar); | 1881 | ath6kl_cfg80211_stop_all(ar); |
1800 | 1882 | ||
1801 | if (ar->state == ATH6KL_STATE_OFF) { | 1883 | if (ar->state == ATH6KL_STATE_OFF) { |
1802 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, | 1884 | ath6kl_dbg(ATH6KL_DBG_SUSPEND, |
@@ -1816,6 +1898,13 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
1816 | 1898 | ||
1817 | break; | 1899 | break; |
1818 | 1900 | ||
1901 | case ATH6KL_CFG_SUSPEND_SCHED_SCAN: | ||
1902 | /* | ||
1903 | * Nothing needed for schedule scan, firmware is already in | ||
1904 | * wow mode and sleeping most of the time. | ||
1905 | */ | ||
1906 | break; | ||
1907 | |||
1819 | default: | 1908 | default: |
1820 | break; | 1909 | break; |
1821 | } | 1910 | } |
@@ -1864,6 +1953,9 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar) | |||
1864 | } | 1953 | } |
1865 | break; | 1954 | break; |
1866 | 1955 | ||
1956 | case ATH6KL_STATE_SCHED_SCAN: | ||
1957 | break; | ||
1958 | |||
1867 | default: | 1959 | default: |
1868 | break; | 1960 | break; |
1869 | } | 1961 | } |
@@ -1987,7 +2079,7 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
1987 | int ies_len; | 2079 | int ies_len; |
1988 | struct wmi_connect_cmd p; | 2080 | struct wmi_connect_cmd p; |
1989 | int res; | 2081 | int res; |
1990 | int i; | 2082 | int i, ret; |
1991 | 2083 | ||
1992 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add); | 2084 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add); |
1993 | 2085 | ||
@@ -2045,7 +2137,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
2045 | if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) | 2137 | if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) |
2046 | return -EOPNOTSUPP; /* TODO */ | 2138 | return -EOPNOTSUPP; /* TODO */ |
2047 | 2139 | ||
2048 | vif->dot11_auth_mode = OPEN_AUTH; | 2140 | ret = ath6kl_set_auth_type(vif, info->auth_type); |
2141 | if (ret) | ||
2142 | return ret; | ||
2049 | 2143 | ||
2050 | memset(&p, 0, sizeof(p)); | 2144 | memset(&p, 0, sizeof(p)); |
2051 | 2145 | ||
@@ -2081,6 +2175,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
2081 | case WLAN_CIPHER_SUITE_CCMP: | 2175 | case WLAN_CIPHER_SUITE_CCMP: |
2082 | p.prwise_crypto_type |= AES_CRYPT; | 2176 | p.prwise_crypto_type |= AES_CRYPT; |
2083 | break; | 2177 | break; |
2178 | case WLAN_CIPHER_SUITE_SMS4: | ||
2179 | p.prwise_crypto_type |= WAPI_CRYPT; | ||
2180 | break; | ||
2084 | } | 2181 | } |
2085 | } | 2182 | } |
2086 | if (p.prwise_crypto_type == 0) { | 2183 | if (p.prwise_crypto_type == 0) { |
@@ -2100,6 +2197,9 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
2100 | case WLAN_CIPHER_SUITE_CCMP: | 2197 | case WLAN_CIPHER_SUITE_CCMP: |
2101 | p.grp_crypto_type = AES_CRYPT; | 2198 | p.grp_crypto_type = AES_CRYPT; |
2102 | break; | 2199 | break; |
2200 | case WLAN_CIPHER_SUITE_SMS4: | ||
2201 | p.grp_crypto_type = WAPI_CRYPT; | ||
2202 | break; | ||
2103 | default: | 2203 | default: |
2104 | p.grp_crypto_type = NONE_CRYPT; | 2204 | p.grp_crypto_type = NONE_CRYPT; |
2105 | break; | 2205 | break; |
@@ -2114,6 +2214,16 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
2114 | p.dot11_auth_mode = vif->dot11_auth_mode; | 2214 | p.dot11_auth_mode = vif->dot11_auth_mode; |
2115 | p.ch = cpu_to_le16(vif->next_chan); | 2215 | p.ch = cpu_to_le16(vif->next_chan); |
2116 | 2216 | ||
2217 | if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { | ||
2218 | p.nw_subtype = SUBTYPE_P2PGO; | ||
2219 | } else { | ||
2220 | /* | ||
2221 | * Due to firmware limitation, it is not possible to | ||
2222 | * do P2P mgmt operations in AP mode | ||
2223 | */ | ||
2224 | p.nw_subtype = SUBTYPE_NONE; | ||
2225 | } | ||
2226 | |||
2117 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); | 2227 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); |
2118 | if (res < 0) | 2228 | if (res < 0) |
2119 | return res; | 2229 | return res; |
@@ -2279,9 +2389,23 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2279 | } | 2389 | } |
2280 | 2390 | ||
2281 | *cookie = id; | 2391 | *cookie = id; |
2282 | return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id, | 2392 | |
2283 | chan->center_freq, wait, | 2393 | if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, |
2284 | buf, len); | 2394 | ar->fw_capabilities)) { |
2395 | /* | ||
2396 | * If capable of doing P2P mgmt operations using | ||
2397 | * station interface, send additional information like | ||
2398 | * supported rates to advertise and xmit rates for | ||
2399 | * probe requests | ||
2400 | */ | ||
2401 | return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id, | ||
2402 | chan->center_freq, wait, | ||
2403 | buf, len, no_cck); | ||
2404 | } else { | ||
2405 | return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id, | ||
2406 | chan->center_freq, wait, | ||
2407 | buf, len); | ||
2408 | } | ||
2285 | } | 2409 | } |
2286 | 2410 | ||
2287 | static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, | 2411 | static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, |
@@ -2302,6 +2426,90 @@ static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, | |||
2302 | } | 2426 | } |
2303 | } | 2427 | } |
2304 | 2428 | ||
2429 | static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | ||
2430 | struct net_device *dev, | ||
2431 | struct cfg80211_sched_scan_request *request) | ||
2432 | { | ||
2433 | struct ath6kl *ar = ath6kl_priv(dev); | ||
2434 | struct ath6kl_vif *vif = netdev_priv(dev); | ||
2435 | u16 interval; | ||
2436 | int ret; | ||
2437 | u8 i; | ||
2438 | |||
2439 | if (ar->state != ATH6KL_STATE_ON) | ||
2440 | return -EIO; | ||
2441 | |||
2442 | if (vif->sme_state != SME_DISCONNECTED) | ||
2443 | return -EBUSY; | ||
2444 | |||
2445 | for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { | ||
2446 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
2447 | i, DISABLE_SSID_FLAG, | ||
2448 | 0, NULL); | ||
2449 | } | ||
2450 | |||
2451 | /* fw uses seconds, also make sure that it's >0 */ | ||
2452 | interval = max_t(u16, 1, request->interval / 1000); | ||
2453 | |||
2454 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, | ||
2455 | interval, interval, | ||
2456 | 10, 0, 0, 0, 3, 0, 0, 0); | ||
2457 | |||
2458 | if (request->n_ssids && request->ssids[0].ssid_len) { | ||
2459 | for (i = 0; i < request->n_ssids; i++) { | ||
2460 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
2461 | i, SPECIFIC_SSID_FLAG, | ||
2462 | request->ssids[i].ssid_len, | ||
2463 | request->ssids[i].ssid); | ||
2464 | } | ||
2465 | } | ||
2466 | |||
2467 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
2468 | ATH6KL_WOW_MODE_ENABLE, | ||
2469 | WOW_FILTER_SSID, | ||
2470 | WOW_HOST_REQ_DELAY); | ||
2471 | if (ret) { | ||
2472 | ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret); | ||
2473 | return ret; | ||
2474 | } | ||
2475 | |||
2476 | /* this also clears IE in fw if it's not set */ | ||
2477 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, | ||
2478 | WMI_FRAME_PROBE_REQ, | ||
2479 | request->ie, request->ie_len); | ||
2480 | if (ret) { | ||
2481 | ath6kl_warn("Failed to set probe request IE for scheduled scan: %d", | ||
2482 | ret); | ||
2483 | return ret; | ||
2484 | } | ||
2485 | |||
2486 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | ||
2487 | ATH6KL_HOST_MODE_ASLEEP); | ||
2488 | if (ret) { | ||
2489 | ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n", | ||
2490 | ret); | ||
2491 | return ret; | ||
2492 | } | ||
2493 | |||
2494 | ar->state = ATH6KL_STATE_SCHED_SCAN; | ||
2495 | |||
2496 | return ret; | ||
2497 | } | ||
2498 | |||
2499 | static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy, | ||
2500 | struct net_device *dev) | ||
2501 | { | ||
2502 | struct ath6kl_vif *vif = netdev_priv(dev); | ||
2503 | bool stopped; | ||
2504 | |||
2505 | stopped = __ath6kl_cfg80211_sscan_stop(vif); | ||
2506 | |||
2507 | if (!stopped) | ||
2508 | return -EIO; | ||
2509 | |||
2510 | return 0; | ||
2511 | } | ||
2512 | |||
2305 | static const struct ieee80211_txrx_stypes | 2513 | static const struct ieee80211_txrx_stypes |
2306 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { | 2514 | ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { |
2307 | [NL80211_IFTYPE_STATION] = { | 2515 | [NL80211_IFTYPE_STATION] = { |
@@ -2359,25 +2567,17 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
2359 | .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, | 2567 | .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, |
2360 | .mgmt_tx = ath6kl_mgmt_tx, | 2568 | .mgmt_tx = ath6kl_mgmt_tx, |
2361 | .mgmt_frame_register = ath6kl_mgmt_frame_register, | 2569 | .mgmt_frame_register = ath6kl_mgmt_frame_register, |
2570 | .sched_scan_start = ath6kl_cfg80211_sscan_start, | ||
2571 | .sched_scan_stop = ath6kl_cfg80211_sscan_stop, | ||
2362 | }; | 2572 | }; |
2363 | 2573 | ||
2364 | void ath6kl_cfg80211_stop(struct ath6kl *ar) | 2574 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) |
2365 | { | 2575 | { |
2366 | struct ath6kl_vif *vif; | 2576 | ath6kl_cfg80211_sscan_disable(vif); |
2367 | |||
2368 | /* FIXME: for multi vif */ | ||
2369 | vif = ath6kl_vif_first(ar); | ||
2370 | if (!vif) { | ||
2371 | /* save the current power mode before enabling power save */ | ||
2372 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | ||
2373 | |||
2374 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) | ||
2375 | ath6kl_warn("ath6kl_deep_sleep_enable: " | ||
2376 | "wmi_powermode_cmd failed\n"); | ||
2377 | return; | ||
2378 | } | ||
2379 | 2577 | ||
2380 | switch (vif->sme_state) { | 2578 | switch (vif->sme_state) { |
2579 | case SME_DISCONNECTED: | ||
2580 | break; | ||
2381 | case SME_CONNECTING: | 2581 | case SME_CONNECTING: |
2382 | cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0, | 2582 | cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0, |
2383 | NULL, 0, | 2583 | NULL, 0, |
@@ -2385,33 +2585,50 @@ void ath6kl_cfg80211_stop(struct ath6kl *ar) | |||
2385 | GFP_KERNEL); | 2585 | GFP_KERNEL); |
2386 | break; | 2586 | break; |
2387 | case SME_CONNECTED: | 2587 | case SME_CONNECTED: |
2388 | default: | ||
2389 | /* | ||
2390 | * FIXME: oddly enough smeState is in DISCONNECTED during | ||
2391 | * suspend, why? Need to send disconnected event in that | ||
2392 | * state. | ||
2393 | */ | ||
2394 | cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL); | 2588 | cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL); |
2395 | break; | 2589 | break; |
2396 | } | 2590 | } |
2397 | 2591 | ||
2398 | if (test_bit(CONNECTED, &vif->flags) || | 2592 | if (test_bit(CONNECTED, &vif->flags) || |
2399 | test_bit(CONNECT_PEND, &vif->flags)) | 2593 | test_bit(CONNECT_PEND, &vif->flags)) |
2400 | ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx); | 2594 | ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx); |
2401 | 2595 | ||
2402 | vif->sme_state = SME_DISCONNECTED; | 2596 | vif->sme_state = SME_DISCONNECTED; |
2403 | clear_bit(CONNECTED, &vif->flags); | 2597 | clear_bit(CONNECTED, &vif->flags); |
2404 | clear_bit(CONNECT_PEND, &vif->flags); | 2598 | clear_bit(CONNECT_PEND, &vif->flags); |
2405 | 2599 | ||
2406 | /* disable scanning */ | 2600 | /* disable scanning */ |
2407 | if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, 0, 0, | 2601 | if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF, |
2408 | 0, 0, 0, 0, 0, 0, 0) != 0) | 2602 | 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0) |
2409 | printk(KERN_WARNING "ath6kl: failed to disable scan " | 2603 | ath6kl_warn("failed to disable scan during stop\n"); |
2410 | "during suspend\n"); | ||
2411 | 2604 | ||
2412 | ath6kl_cfg80211_scan_complete_event(vif, true); | 2605 | ath6kl_cfg80211_scan_complete_event(vif, true); |
2413 | } | 2606 | } |
2414 | 2607 | ||
2608 | void ath6kl_cfg80211_stop_all(struct ath6kl *ar) | ||
2609 | { | ||
2610 | struct ath6kl_vif *vif; | ||
2611 | |||
2612 | vif = ath6kl_vif_first(ar); | ||
2613 | if (!vif) { | ||
2614 | /* save the current power mode before enabling power save */ | ||
2615 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | ||
2616 | |||
2617 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) | ||
2618 | ath6kl_warn("ath6kl_deep_sleep_enable: " | ||
2619 | "wmi_powermode_cmd failed\n"); | ||
2620 | return; | ||
2621 | } | ||
2622 | |||
2623 | /* | ||
2624 | * FIXME: we should take ar->list_lock to protect changes in the | ||
2625 | * vif_list, but that's not trivial to do as ath6kl_cfg80211_stop() | ||
2626 | * sleeps. | ||
2627 | */ | ||
2628 | list_for_each_entry(vif, &ar->vif_list, list) | ||
2629 | ath6kl_cfg80211_stop(vif); | ||
2630 | } | ||
2631 | |||
2415 | struct ath6kl *ath6kl_core_alloc(struct device *dev) | 2632 | struct ath6kl *ath6kl_core_alloc(struct device *dev) |
2416 | { | 2633 | { |
2417 | struct ath6kl *ar; | 2634 | struct ath6kl *ar; |
@@ -2427,17 +2644,12 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) | |||
2427 | } | 2644 | } |
2428 | 2645 | ||
2429 | ar = wiphy_priv(wiphy); | 2646 | ar = wiphy_priv(wiphy); |
2430 | if (!multi_norm_if_support) | 2647 | ar->p2p = !!ath6kl_p2p; |
2431 | ar->p2p = !!ath6kl_p2p; | ||
2432 | ar->wiphy = wiphy; | 2648 | ar->wiphy = wiphy; |
2433 | ar->dev = dev; | 2649 | ar->dev = dev; |
2434 | 2650 | ||
2435 | if (multi_norm_if_support) | 2651 | ar->vif_max = 1; |
2436 | ar->max_norm_iface = 2; | ||
2437 | else | ||
2438 | ar->max_norm_iface = 1; | ||
2439 | 2652 | ||
2440 | /* FIXME: Remove this once the multivif support is enabled */ | ||
2441 | ar->max_norm_iface = 1; | 2653 | ar->max_norm_iface = 1; |
2442 | 2654 | ||
2443 | spin_lock_init(&ar->lock); | 2655 | spin_lock_init(&ar->lock); |
@@ -2459,9 +2671,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) | |||
2459 | ar->tx_pwr = 0; | 2671 | ar->tx_pwr = 0; |
2460 | 2672 | ||
2461 | ar->intra_bss = 1; | 2673 | ar->intra_bss = 1; |
2462 | memset(&ar->sc_params, 0, sizeof(ar->sc_params)); | ||
2463 | ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT; | ||
2464 | ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS; | ||
2465 | ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; | 2674 | ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; |
2466 | 2675 | ||
2467 | ar->state = ATH6KL_STATE_OFF; | 2676 | ar->state = ATH6KL_STATE_OFF; |
@@ -2522,6 +2731,8 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar) | |||
2522 | wiphy->wowlan.pattern_min_len = 1; | 2731 | wiphy->wowlan.pattern_min_len = 1; |
2523 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | 2732 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; |
2524 | 2733 | ||
2734 | wiphy->max_sched_scan_ssids = 10; | ||
2735 | |||
2525 | ret = wiphy_register(wiphy); | 2736 | ret = wiphy_register(wiphy); |
2526 | if (ret < 0) { | 2737 | if (ret < 0) { |
2527 | ath6kl_err("couldn't register wiphy device\n"); | 2738 | ath6kl_err("couldn't register wiphy device\n"); |
@@ -2541,6 +2752,9 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif) | |||
2541 | 2752 | ||
2542 | setup_timer(&vif->disconnect_timer, disconnect_timer_handler, | 2753 | setup_timer(&vif->disconnect_timer, disconnect_timer_handler, |
2543 | (unsigned long) vif->ndev); | 2754 | (unsigned long) vif->ndev); |
2755 | setup_timer(&vif->sched_scan_timer, ath6kl_wmi_sscan_timer, | ||
2756 | (unsigned long) vif); | ||
2757 | |||
2544 | set_bit(WMM_ENABLED, &vif->flags); | 2758 | set_bit(WMM_ENABLED, &vif->flags); |
2545 | spin_lock_init(&vif->if_lock); | 2759 | spin_lock_init(&vif->if_lock); |
2546 | 2760 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 59fa9d859def..81f20a572315 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h | |||
@@ -20,7 +20,8 @@ | |||
20 | enum ath6kl_cfg_suspend_mode { | 20 | enum ath6kl_cfg_suspend_mode { |
21 | ATH6KL_CFG_SUSPEND_DEEPSLEEP, | 21 | ATH6KL_CFG_SUSPEND_DEEPSLEEP, |
22 | ATH6KL_CFG_SUSPEND_CUTPOWER, | 22 | ATH6KL_CFG_SUSPEND_CUTPOWER, |
23 | ATH6KL_CFG_SUSPEND_WOW | 23 | ATH6KL_CFG_SUSPEND_WOW, |
24 | ATH6KL_CFG_SUSPEND_SCHED_SCAN, | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | 27 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, |
@@ -52,6 +53,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, | |||
52 | 53 | ||
53 | int ath6kl_cfg80211_resume(struct ath6kl *ar); | 54 | int ath6kl_cfg80211_resume(struct ath6kl *ar); |
54 | 55 | ||
55 | void ath6kl_cfg80211_stop(struct ath6kl *ar); | 56 | void ath6kl_cfg80211_stop(struct ath6kl_vif *vif); |
57 | void ath6kl_cfg80211_stop_all(struct ath6kl *ar); | ||
56 | 58 | ||
57 | #endif /* ATH6KL_CFG80211_H */ | 59 | #endif /* ATH6KL_CFG80211_H */ |
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index 41e465f29e63..bfd6597763da 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h | |||
@@ -71,6 +71,7 @@ enum crypto_type { | |||
71 | WEP_CRYPT = 0x02, | 71 | WEP_CRYPT = 0x02, |
72 | TKIP_CRYPT = 0x04, | 72 | TKIP_CRYPT = 0x04, |
73 | AES_CRYPT = 0x08, | 73 | AES_CRYPT = 0x08, |
74 | WAPI_CRYPT = 0x10, | ||
74 | }; | 75 | }; |
75 | 76 | ||
76 | struct htc_endpoint_credit_dist; | 77 | struct htc_endpoint_credit_dist; |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index e7e095e536a7..c863a28f2e0c 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -70,10 +70,20 @@ enum ath6kl_fw_ie_type { | |||
70 | ATH6KL_FW_IE_RESERVED_RAM_SIZE = 5, | 70 | ATH6KL_FW_IE_RESERVED_RAM_SIZE = 5, |
71 | ATH6KL_FW_IE_CAPABILITIES = 6, | 71 | ATH6KL_FW_IE_CAPABILITIES = 6, |
72 | ATH6KL_FW_IE_PATCH_ADDR = 7, | 72 | ATH6KL_FW_IE_PATCH_ADDR = 7, |
73 | ATH6KL_FW_IE_BOARD_ADDR = 8, | ||
74 | ATH6KL_FW_IE_VIF_MAX = 9, | ||
73 | }; | 75 | }; |
74 | 76 | ||
75 | enum ath6kl_fw_capability { | 77 | enum ath6kl_fw_capability { |
76 | ATH6KL_FW_CAPABILITY_HOST_P2P = 0, | 78 | ATH6KL_FW_CAPABILITY_HOST_P2P = 0, |
79 | ATH6KL_FW_CAPABILITY_SCHED_SCAN = 1, | ||
80 | |||
81 | /* | ||
82 | * Firmware is capable of supporting P2P mgmt operations on a | ||
83 | * station interface. After group formation, the station | ||
84 | * interface will become a P2P client/GO interface as the case may be | ||
85 | */ | ||
86 | ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, | ||
77 | 87 | ||
78 | /* this needs to be last */ | 88 | /* this needs to be last */ |
79 | ATH6KL_FW_CAPABILITY_MAX, | 89 | ATH6KL_FW_CAPABILITY_MAX, |
@@ -88,37 +98,47 @@ struct ath6kl_fw_ie { | |||
88 | }; | 98 | }; |
89 | 99 | ||
90 | /* AR6003 1.0 definitions */ | 100 | /* AR6003 1.0 definitions */ |
91 | #define AR6003_REV1_VERSION 0x300002ba | 101 | #define AR6003_HW_1_0_VERSION 0x300002ba |
92 | 102 | ||
93 | /* AR6003 2.0 definitions */ | 103 | /* AR6003 2.0 definitions */ |
94 | #define AR6003_REV2_VERSION 0x30000384 | 104 | #define AR6003_HW_2_0_VERSION 0x30000384 |
95 | #define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910 | 105 | #define AR6003_HW_2_0_PATCH_DOWNLOAD_ADDRESS 0x57e910 |
96 | #define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" | 106 | #define AR6003_HW_2_0_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" |
97 | #define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" | 107 | #define AR6003_HW_2_0_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" |
98 | #define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" | 108 | #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" |
99 | #define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" | 109 | #define AR6003_HW_2_0_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" |
100 | #define AR6003_REV2_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin" | 110 | #define AR6003_HW_2_0_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin" |
101 | #define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" | 111 | #define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" |
102 | #define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin" | 112 | #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ |
113 | "ath6k/AR6003/hw2.0/bdata.SD31.bin" | ||
103 | 114 | ||
104 | /* AR6003 3.0 definitions */ | 115 | /* AR6003 3.0 definitions */ |
105 | #define AR6003_REV3_VERSION 0x30000582 | 116 | #define AR6003_HW_2_1_1_VERSION 0x30000582 |
106 | #define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" | 117 | #define AR6003_HW_2_1_1_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" |
107 | #define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" | 118 | #define AR6003_HW_2_1_1_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" |
108 | #define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" | 119 | #define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE \ |
109 | #define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" | 120 | "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" |
110 | #define AR6003_REV3_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin" | 121 | #define AR6003_HW_2_1_1_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" |
111 | #define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" | 122 | #define AR6003_HW_2_1_1_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin" |
112 | #define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \ | 123 | #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" |
113 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" | 124 | #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ |
125 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" | ||
114 | 126 | ||
115 | /* AR6004 1.0 definitions */ | 127 | /* AR6004 1.0 definitions */ |
116 | #define AR6004_REV1_VERSION 0x30000623 | 128 | #define AR6004_HW_1_0_VERSION 0x30000623 |
117 | #define AR6004_REV1_FIRMWARE_FILE "ath6k/AR6004/hw6.1/fw.ram.bin" | 129 | #define AR6004_HW_1_0_FIRMWARE_2_FILE "ath6k/AR6004/hw1.0/fw-2.bin" |
118 | #define AR6004_REV1_FIRMWARE_2_FILE "ath6k/AR6004/hw6.1/fw-2.bin" | 130 | #define AR6004_HW_1_0_FIRMWARE_FILE "ath6k/AR6004/hw1.0/fw.ram.bin" |
119 | #define AR6004_REV1_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.bin" | 131 | #define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin" |
120 | #define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin" | 132 | #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ |
121 | #define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin" | 133 | "ath6k/AR6004/hw1.0/bdata.DB132.bin" |
134 | |||
135 | /* AR6004 1.1 definitions */ | ||
136 | #define AR6004_HW_1_1_VERSION 0x30000001 | ||
137 | #define AR6004_HW_1_1_FIRMWARE_2_FILE "ath6k/AR6004/hw1.1/fw-2.bin" | ||
138 | #define AR6004_HW_1_1_FIRMWARE_FILE "ath6k/AR6004/hw1.1/fw.ram.bin" | ||
139 | #define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin" | ||
140 | #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ | ||
141 | "ath6k/AR6004/hw1.1/bdata.DB132.bin" | ||
122 | 142 | ||
123 | /* Per STA data, used in AP mode */ | 143 | /* Per STA data, used in AP mode */ |
124 | #define STA_PS_AWAKE BIT(0) | 144 | #define STA_PS_AWAKE BIT(0) |
@@ -272,6 +292,8 @@ struct ath6kl_bmi { | |||
272 | u32 cmd_credits; | 292 | u32 cmd_credits; |
273 | bool done_sent; | 293 | bool done_sent; |
274 | u8 *cmd_buf; | 294 | u8 *cmd_buf; |
295 | u32 max_data_size; | ||
296 | u32 max_cmd_size; | ||
275 | }; | 297 | }; |
276 | 298 | ||
277 | struct target_stats { | 299 | struct target_stats { |
@@ -381,7 +403,16 @@ struct ath6kl_req_key { | |||
381 | u8 key_len; | 403 | u8 key_len; |
382 | }; | 404 | }; |
383 | 405 | ||
384 | #define MAX_NUM_VIF 1 | 406 | enum ath6kl_hif_type { |
407 | ATH6KL_HIF_TYPE_SDIO, | ||
408 | ATH6KL_HIF_TYPE_USB, | ||
409 | }; | ||
410 | |||
411 | /* | ||
412 | * Driver's maximum limit, note that some firmwares support only one vif | ||
413 | * and the runtime (current) limit must be checked from ar->vif_max. | ||
414 | */ | ||
415 | #define ATH6KL_VIF_MAX 3 | ||
385 | 416 | ||
386 | /* vif flags info */ | 417 | /* vif flags info */ |
387 | enum ath6kl_vif_state { | 418 | enum ath6kl_vif_state { |
@@ -424,7 +455,10 @@ struct ath6kl_vif { | |||
424 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; | 455 | struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; |
425 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; | 456 | struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; |
426 | struct aggr_info *aggr_cntxt; | 457 | struct aggr_info *aggr_cntxt; |
458 | |||
427 | struct timer_list disconnect_timer; | 459 | struct timer_list disconnect_timer; |
460 | struct timer_list sched_scan_timer; | ||
461 | |||
428 | struct cfg80211_scan_request *scan_req; | 462 | struct cfg80211_scan_request *scan_req; |
429 | enum sme_state sme_state; | 463 | enum sme_state sme_state; |
430 | int reconnect_flag; | 464 | int reconnect_flag; |
@@ -442,6 +476,8 @@ struct ath6kl_vif { | |||
442 | #define WOW_LIST_ID 0 | 476 | #define WOW_LIST_ID 0 |
443 | #define WOW_HOST_REQ_DELAY 500 /* ms */ | 477 | #define WOW_HOST_REQ_DELAY 500 /* ms */ |
444 | 478 | ||
479 | #define ATH6KL_SCHED_SCAN_RESULT_DELAY 5000 /* ms */ | ||
480 | |||
445 | /* Flag info */ | 481 | /* Flag info */ |
446 | enum ath6kl_dev_state { | 482 | enum ath6kl_dev_state { |
447 | WMI_ENABLED, | 483 | WMI_ENABLED, |
@@ -460,6 +496,7 @@ enum ath6kl_state { | |||
460 | ATH6KL_STATE_DEEPSLEEP, | 496 | ATH6KL_STATE_DEEPSLEEP, |
461 | ATH6KL_STATE_CUTPOWER, | 497 | ATH6KL_STATE_CUTPOWER, |
462 | ATH6KL_STATE_WOW, | 498 | ATH6KL_STATE_WOW, |
499 | ATH6KL_STATE_SCHED_SCAN, | ||
463 | }; | 500 | }; |
464 | 501 | ||
465 | struct ath6kl { | 502 | struct ath6kl { |
@@ -474,11 +511,13 @@ struct ath6kl { | |||
474 | int tx_pending[ENDPOINT_MAX]; | 511 | int tx_pending[ENDPOINT_MAX]; |
475 | int total_tx_data_pend; | 512 | int total_tx_data_pend; |
476 | struct htc_target *htc_target; | 513 | struct htc_target *htc_target; |
514 | enum ath6kl_hif_type hif_type; | ||
477 | void *hif_priv; | 515 | void *hif_priv; |
478 | struct list_head vif_list; | 516 | struct list_head vif_list; |
479 | /* Lock to avoid race in vif_list entries among add/del/traverse */ | 517 | /* Lock to avoid race in vif_list entries among add/del/traverse */ |
480 | spinlock_t list_lock; | 518 | spinlock_t list_lock; |
481 | u8 num_vif; | 519 | u8 num_vif; |
520 | unsigned int vif_max; | ||
482 | u8 max_norm_iface; | 521 | u8 max_norm_iface; |
483 | u8 avail_idx_map; | 522 | u8 avail_idx_map; |
484 | spinlock_t lock; | 523 | spinlock_t lock; |
@@ -517,7 +556,6 @@ struct ath6kl { | |||
517 | struct list_head amsdu_rx_buffer_queue; | 556 | struct list_head amsdu_rx_buffer_queue; |
518 | u8 rx_meta_ver; | 557 | u8 rx_meta_ver; |
519 | enum wlan_low_pwr_state wlan_pwr_state; | 558 | enum wlan_low_pwr_state wlan_pwr_state; |
520 | struct wmi_scan_params_cmd sc_params; | ||
521 | u8 mac_addr[ETH_ALEN]; | 559 | u8 mac_addr[ETH_ALEN]; |
522 | #define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 | 560 | #define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 |
523 | struct { | 561 | struct { |
@@ -525,12 +563,25 @@ struct ath6kl { | |||
525 | size_t rx_report_len; | 563 | size_t rx_report_len; |
526 | } tm; | 564 | } tm; |
527 | 565 | ||
528 | struct { | 566 | struct ath6kl_hw { |
567 | u32 id; | ||
568 | const char *name; | ||
529 | u32 dataset_patch_addr; | 569 | u32 dataset_patch_addr; |
530 | u32 app_load_addr; | 570 | u32 app_load_addr; |
531 | u32 app_start_override_addr; | 571 | u32 app_start_override_addr; |
532 | u32 board_ext_data_addr; | 572 | u32 board_ext_data_addr; |
533 | u32 reserved_ram_size; | 573 | u32 reserved_ram_size; |
574 | u32 board_addr; | ||
575 | u32 refclk_hz; | ||
576 | u32 uarttx_pin; | ||
577 | |||
578 | const char *fw_otp; | ||
579 | const char *fw; | ||
580 | const char *fw_tcmd; | ||
581 | const char *fw_patch; | ||
582 | const char *fw_api2; | ||
583 | const char *fw_board; | ||
584 | const char *fw_default_board; | ||
534 | } hw; | 585 | } hw; |
535 | 586 | ||
536 | u16 conf_flags; | 587 | u16 conf_flags; |
@@ -583,7 +634,7 @@ struct ath6kl { | |||
583 | #endif /* CONFIG_ATH6KL_DEBUG */ | 634 | #endif /* CONFIG_ATH6KL_DEBUG */ |
584 | }; | 635 | }; |
585 | 636 | ||
586 | static inline void *ath6kl_priv(struct net_device *dev) | 637 | static inline struct ath6kl *ath6kl_priv(struct net_device *dev) |
587 | { | 638 | { |
588 | return ((struct ath6kl_vif *) netdev_priv(dev))->ar; | 639 | return ((struct ath6kl_vif *) netdev_priv(dev))->ar; |
589 | } | 640 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 9eff0d010bb1..eb808b46f94c 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -1551,10 +1551,10 @@ static ssize_t ath6kl_listen_int_read(struct file *file, | |||
1551 | size_t count, loff_t *ppos) | 1551 | size_t count, loff_t *ppos) |
1552 | { | 1552 | { |
1553 | struct ath6kl *ar = file->private_data; | 1553 | struct ath6kl *ar = file->private_data; |
1554 | char buf[16]; | 1554 | char buf[32]; |
1555 | int len; | 1555 | int len; |
1556 | 1556 | ||
1557 | len = snprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t, | 1557 | len = scnprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t, |
1558 | ar->listen_intvl_b); | 1558 | ar->listen_intvl_b); |
1559 | 1559 | ||
1560 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 1560 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 9853c9c125c1..e569c652e35c 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -41,6 +41,7 @@ enum ATH6K_DEBUG_MASK { | |||
41 | ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ | 41 | ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ |
42 | ATH6KL_DBG_WMI_DUMP = BIT(19), | 42 | ATH6KL_DBG_WMI_DUMP = BIT(19), |
43 | ATH6KL_DBG_SUSPEND = BIT(20), | 43 | ATH6KL_DBG_SUSPEND = BIT(20), |
44 | ATH6KL_DBG_USB = BIT(21), | ||
44 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ | 45 | ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ |
45 | }; | 46 | }; |
46 | 47 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h index eed22870448b..2fe1dadfc77a 100644 --- a/drivers/net/wireless/ath/ath6kl/hif-ops.h +++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h | |||
@@ -91,6 +91,36 @@ static inline int ath6kl_hif_suspend(struct ath6kl *ar, | |||
91 | return ar->hif_ops->suspend(ar, wow); | 91 | return ar->hif_ops->suspend(ar, wow); |
92 | } | 92 | } |
93 | 93 | ||
94 | /* | ||
95 | * Read from the ATH6KL through its diagnostic window. No cooperation from | ||
96 | * the Target is required for this. | ||
97 | */ | ||
98 | static inline int ath6kl_hif_diag_read32(struct ath6kl *ar, u32 address, | ||
99 | u32 *value) | ||
100 | { | ||
101 | return ar->hif_ops->diag_read32(ar, address, value); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Write to the ATH6KL through its diagnostic window. No cooperation from | ||
106 | * the Target is required for this. | ||
107 | */ | ||
108 | static inline int ath6kl_hif_diag_write32(struct ath6kl *ar, u32 address, | ||
109 | __le32 value) | ||
110 | { | ||
111 | return ar->hif_ops->diag_write32(ar, address, value); | ||
112 | } | ||
113 | |||
114 | static inline int ath6kl_hif_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | ||
115 | { | ||
116 | return ar->hif_ops->bmi_read(ar, buf, len); | ||
117 | } | ||
118 | |||
119 | static inline int ath6kl_hif_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | ||
120 | { | ||
121 | return ar->hif_ops->bmi_write(ar, buf, len); | ||
122 | } | ||
123 | |||
94 | static inline int ath6kl_hif_resume(struct ath6kl *ar) | 124 | static inline int ath6kl_hif_resume(struct ath6kl *ar) |
95 | { | 125 | { |
96 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif resume\n"); | 126 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif resume\n"); |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index e57da35e59fa..0772ef650174 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c | |||
@@ -689,6 +689,11 @@ int ath6kl_hif_setup(struct ath6kl_device *dev) | |||
689 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", | 689 | ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", |
690 | dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); | 690 | dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); |
691 | 691 | ||
692 | /* usb doesn't support enabling interrupts */ | ||
693 | /* FIXME: remove check once USB support is implemented */ | ||
694 | if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) | ||
695 | return 0; | ||
696 | |||
692 | status = ath6kl_hif_disable_intrs(dev); | 697 | status = ath6kl_hif_disable_intrs(dev); |
693 | 698 | ||
694 | fail_setup: | 699 | fail_setup: |
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h index f2dc3bcdae4a..699a036f3a44 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.h +++ b/drivers/net/wireless/ath/ath6kl/hif.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #define MAX_SCATTER_REQ_TRANSFER_SIZE (32 * 1024) | 35 | #define MAX_SCATTER_REQ_TRANSFER_SIZE (32 * 1024) |
36 | 36 | ||
37 | #define MANUFACTURER_ID_AR6003_BASE 0x300 | 37 | #define MANUFACTURER_ID_AR6003_BASE 0x300 |
38 | #define MANUFACTURER_ID_AR6004_BASE 0x400 | ||
38 | /* SDIO manufacturer ID and Codes */ | 39 | /* SDIO manufacturer ID and Codes */ |
39 | #define MANUFACTURER_ID_ATH6KL_BASE_MASK 0xFF00 | 40 | #define MANUFACTURER_ID_ATH6KL_BASE_MASK 0xFF00 |
40 | #define MANUFACTURER_CODE 0x271 /* Atheros */ | 41 | #define MANUFACTURER_CODE 0x271 /* Atheros */ |
@@ -244,6 +245,10 @@ struct ath6kl_hif_ops { | |||
244 | void (*cleanup_scatter)(struct ath6kl *ar); | 245 | void (*cleanup_scatter)(struct ath6kl *ar); |
245 | int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow); | 246 | int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow); |
246 | int (*resume)(struct ath6kl *ar); | 247 | int (*resume)(struct ath6kl *ar); |
248 | int (*diag_read32)(struct ath6kl *ar, u32 address, u32 *value); | ||
249 | int (*diag_write32)(struct ath6kl *ar, u32 address, __le32 value); | ||
250 | int (*bmi_read)(struct ath6kl *ar, u8 *buf, u32 len); | ||
251 | int (*bmi_write)(struct ath6kl *ar, u8 *buf, u32 len); | ||
247 | int (*power_on)(struct ath6kl *ar); | 252 | int (*power_on)(struct ath6kl *ar); |
248 | int (*power_off)(struct ath6kl *ar); | 253 | int (*power_off)(struct ath6kl *ar); |
249 | void (*stop)(struct ath6kl *ar); | 254 | void (*stop)(struct ath6kl *ar); |
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index f3b63ca25c7e..b01702258faf 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c | |||
@@ -2543,6 +2543,12 @@ int ath6kl_htc_wait_target(struct htc_target *target) | |||
2543 | struct htc_service_connect_resp resp; | 2543 | struct htc_service_connect_resp resp; |
2544 | int status; | 2544 | int status; |
2545 | 2545 | ||
2546 | /* FIXME: remove once USB support is implemented */ | ||
2547 | if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) { | ||
2548 | ath6kl_err("HTC doesn't support USB yet. Patience!\n"); | ||
2549 | return -EOPNOTSUPP; | ||
2550 | } | ||
2551 | |||
2546 | /* we should be getting 1 control message that the target is ready */ | 2552 | /* we should be getting 1 control message that the target is ready */ |
2547 | packet = htc_wait_for_ctrl_msg(target); | 2553 | packet = htc_wait_for_ctrl_msg(target); |
2548 | 2554 | ||
@@ -2772,7 +2778,9 @@ void ath6kl_htc_cleanup(struct htc_target *target) | |||
2772 | { | 2778 | { |
2773 | struct htc_packet *packet, *tmp_packet; | 2779 | struct htc_packet *packet, *tmp_packet; |
2774 | 2780 | ||
2775 | ath6kl_hif_cleanup_scatter(target->dev->ar); | 2781 | /* FIXME: remove check once USB support is implemented */ |
2782 | if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB) | ||
2783 | ath6kl_hif_cleanup_scatter(target->dev->ar); | ||
2776 | 2784 | ||
2777 | list_for_each_entry_safe(packet, tmp_packet, | 2785 | list_for_each_entry_safe(packet, tmp_packet, |
2778 | &target->free_ctrl_txbuf, list) { | 2786 | &target->free_ctrl_txbuf, list) { |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 5acb4a4b93bf..7f55be3092d1 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -33,6 +33,80 @@ module_param(debug_mask, uint, 0644); | |||
33 | module_param(testmode, uint, 0644); | 33 | module_param(testmode, uint, 0644); |
34 | module_param(suspend_cutpower, bool, 0444); | 34 | module_param(suspend_cutpower, bool, 0444); |
35 | 35 | ||
36 | static const struct ath6kl_hw hw_list[] = { | ||
37 | { | ||
38 | .id = AR6003_HW_2_0_VERSION, | ||
39 | .name = "ar6003 hw 2.0", | ||
40 | .dataset_patch_addr = 0x57e884, | ||
41 | .app_load_addr = 0x543180, | ||
42 | .board_ext_data_addr = 0x57e500, | ||
43 | .reserved_ram_size = 6912, | ||
44 | .refclk_hz = 26000000, | ||
45 | .uarttx_pin = 8, | ||
46 | |||
47 | /* hw2.0 needs override address hardcoded */ | ||
48 | .app_start_override_addr = 0x944C00, | ||
49 | |||
50 | .fw_otp = AR6003_HW_2_0_OTP_FILE, | ||
51 | .fw = AR6003_HW_2_0_FIRMWARE_FILE, | ||
52 | .fw_tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, | ||
53 | .fw_patch = AR6003_HW_2_0_PATCH_FILE, | ||
54 | .fw_api2 = AR6003_HW_2_0_FIRMWARE_2_FILE, | ||
55 | .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, | ||
56 | .fw_default_board = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE, | ||
57 | }, | ||
58 | { | ||
59 | .id = AR6003_HW_2_1_1_VERSION, | ||
60 | .name = "ar6003 hw 2.1.1", | ||
61 | .dataset_patch_addr = 0x57ff74, | ||
62 | .app_load_addr = 0x1234, | ||
63 | .board_ext_data_addr = 0x542330, | ||
64 | .reserved_ram_size = 512, | ||
65 | .refclk_hz = 26000000, | ||
66 | .uarttx_pin = 8, | ||
67 | |||
68 | .fw_otp = AR6003_HW_2_1_1_OTP_FILE, | ||
69 | .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, | ||
70 | .fw_tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, | ||
71 | .fw_patch = AR6003_HW_2_1_1_PATCH_FILE, | ||
72 | .fw_api2 = AR6003_HW_2_1_1_FIRMWARE_2_FILE, | ||
73 | .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, | ||
74 | .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE, | ||
75 | }, | ||
76 | { | ||
77 | .id = AR6004_HW_1_0_VERSION, | ||
78 | .name = "ar6004 hw 1.0", | ||
79 | .dataset_patch_addr = 0x57e884, | ||
80 | .app_load_addr = 0x1234, | ||
81 | .board_ext_data_addr = 0x437000, | ||
82 | .reserved_ram_size = 19456, | ||
83 | .board_addr = 0x433900, | ||
84 | .refclk_hz = 26000000, | ||
85 | .uarttx_pin = 11, | ||
86 | |||
87 | .fw = AR6004_HW_1_0_FIRMWARE_FILE, | ||
88 | .fw_api2 = AR6004_HW_1_0_FIRMWARE_2_FILE, | ||
89 | .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, | ||
90 | .fw_default_board = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE, | ||
91 | }, | ||
92 | { | ||
93 | .id = AR6004_HW_1_1_VERSION, | ||
94 | .name = "ar6004 hw 1.1", | ||
95 | .dataset_patch_addr = 0x57e884, | ||
96 | .app_load_addr = 0x1234, | ||
97 | .board_ext_data_addr = 0x437000, | ||
98 | .reserved_ram_size = 11264, | ||
99 | .board_addr = 0x43d400, | ||
100 | .refclk_hz = 40000000, | ||
101 | .uarttx_pin = 11, | ||
102 | |||
103 | .fw = AR6004_HW_1_1_FIRMWARE_FILE, | ||
104 | .fw_api2 = AR6004_HW_1_1_FIRMWARE_2_FILE, | ||
105 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, | ||
106 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, | ||
107 | }, | ||
108 | }; | ||
109 | |||
36 | /* | 110 | /* |
37 | * Include definitions here that can be used to tune the WLAN module | 111 | * Include definitions here that can be used to tune the WLAN module |
38 | * behavior. Different customers can tune the behavior as per their needs, | 112 | * behavior. Different customers can tune the behavior as per their needs, |
@@ -58,7 +132,6 @@ module_param(suspend_cutpower, bool, 0444); | |||
58 | */ | 132 | */ |
59 | #define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 | 133 | #define WLAN_CONFIG_DISCONNECT_TIMEOUT 10 |
60 | 134 | ||
61 | #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8 | ||
62 | 135 | ||
63 | #define ATH6KL_DATA_OFFSET 64 | 136 | #define ATH6KL_DATA_OFFSET 64 |
64 | struct sk_buff *ath6kl_buf_alloc(int size) | 137 | struct sk_buff *ath6kl_buf_alloc(int size) |
@@ -348,11 +421,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
348 | status = -EIO; | 421 | status = -EIO; |
349 | } | 422 | } |
350 | 423 | ||
351 | /* | 424 | if (ar->p2p && (ar->vif_max == 1 || idx)) { |
352 | * FIXME: Make sure p2p configurations are not applied to | ||
353 | * non-p2p capable interfaces when multivif support is enabled. | ||
354 | */ | ||
355 | if (ar->p2p) { | ||
356 | ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx, | 425 | ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx, |
357 | P2P_FLAG_CAPABILITIES_REQ | | 426 | P2P_FLAG_CAPABILITIES_REQ | |
358 | P2P_FLAG_MACADDR_REQ | | 427 | P2P_FLAG_MACADDR_REQ | |
@@ -365,11 +434,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
365 | } | 434 | } |
366 | } | 435 | } |
367 | 436 | ||
368 | /* | 437 | if (ar->p2p && (ar->vif_max == 1 || idx)) { |
369 | * FIXME: Make sure p2p configurations are not applied to | ||
370 | * non-p2p capable interfaces when multivif support is enabled. | ||
371 | */ | ||
372 | if (ar->p2p) { | ||
373 | /* Enable Probe Request reporting for P2P */ | 438 | /* Enable Probe Request reporting for P2P */ |
374 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); | 439 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); |
375 | if (ret) { | 440 | if (ret) { |
@@ -385,7 +450,7 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
385 | { | 450 | { |
386 | u32 param, ram_reserved_size; | 451 | u32 param, ram_reserved_size; |
387 | u8 fw_iftype, fw_mode = 0, fw_submode = 0; | 452 | u8 fw_iftype, fw_mode = 0, fw_submode = 0; |
388 | int i; | 453 | int i, status; |
389 | 454 | ||
390 | /* | 455 | /* |
391 | * Note: Even though the firmware interface type is | 456 | * Note: Even though the firmware interface type is |
@@ -397,7 +462,7 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
397 | */ | 462 | */ |
398 | fw_iftype = HI_OPTION_FW_MODE_BSS_STA; | 463 | fw_iftype = HI_OPTION_FW_MODE_BSS_STA; |
399 | 464 | ||
400 | for (i = 0; i < MAX_NUM_VIF; i++) | 465 | for (i = 0; i < ar->vif_max; i++) |
401 | fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS); | 466 | fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS); |
402 | 467 | ||
403 | /* | 468 | /* |
@@ -411,15 +476,11 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
411 | fw_submode |= HI_OPTION_FW_SUBMODE_NONE << | 476 | fw_submode |= HI_OPTION_FW_SUBMODE_NONE << |
412 | (i * HI_OPTION_FW_SUBMODE_BITS); | 477 | (i * HI_OPTION_FW_SUBMODE_BITS); |
413 | 478 | ||
414 | for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++) | 479 | for (i = ar->max_norm_iface; i < ar->vif_max; i++) |
415 | fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV << | 480 | fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV << |
416 | (i * HI_OPTION_FW_SUBMODE_BITS); | 481 | (i * HI_OPTION_FW_SUBMODE_BITS); |
417 | 482 | ||
418 | /* | 483 | if (ar->p2p && ar->vif_max == 1) |
419 | * FIXME: This needs to be removed once the multivif | ||
420 | * support is enabled. | ||
421 | */ | ||
422 | if (ar->p2p) | ||
423 | fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV; | 484 | fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV; |
424 | 485 | ||
425 | param = HTC_PROTOCOL_VERSION; | 486 | param = HTC_PROTOCOL_VERSION; |
@@ -442,7 +503,7 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
442 | return -EIO; | 503 | return -EIO; |
443 | } | 504 | } |
444 | 505 | ||
445 | param |= (MAX_NUM_VIF << HI_OPTION_NUM_DEV_SHIFT); | 506 | param |= (ar->vif_max << HI_OPTION_NUM_DEV_SHIFT); |
446 | param |= fw_mode << HI_OPTION_FW_MODE_SHIFT; | 507 | param |= fw_mode << HI_OPTION_FW_MODE_SHIFT; |
447 | param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT; | 508 | param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT; |
448 | 509 | ||
@@ -491,6 +552,24 @@ int ath6kl_configure_target(struct ath6kl *ar) | |||
491 | /* use default number of control buffers */ | 552 | /* use default number of control buffers */ |
492 | return -EIO; | 553 | return -EIO; |
493 | 554 | ||
555 | /* Configure GPIO AR600x UART */ | ||
556 | param = ar->hw.uarttx_pin; | ||
557 | status = ath6kl_bmi_write(ar, | ||
558 | ath6kl_get_hi_item_addr(ar, | ||
559 | HI_ITEM(hi_dbg_uart_txpin)), | ||
560 | (u8 *)¶m, 4); | ||
561 | if (status) | ||
562 | return status; | ||
563 | |||
564 | /* Configure target refclk_hz */ | ||
565 | param = ar->hw.refclk_hz; | ||
566 | status = ath6kl_bmi_write(ar, | ||
567 | ath6kl_get_hi_item_addr(ar, | ||
568 | HI_ITEM(hi_refclk_hz)), | ||
569 | (u8 *)¶m, 4); | ||
570 | if (status) | ||
571 | return status; | ||
572 | |||
494 | return 0; | 573 | return 0; |
495 | } | 574 | } |
496 | 575 | ||
@@ -550,11 +629,11 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, | |||
550 | static const char *get_target_ver_dir(const struct ath6kl *ar) | 629 | static const char *get_target_ver_dir(const struct ath6kl *ar) |
551 | { | 630 | { |
552 | switch (ar->version.target_ver) { | 631 | switch (ar->version.target_ver) { |
553 | case AR6003_REV1_VERSION: | 632 | case AR6003_HW_1_0_VERSION: |
554 | return "ath6k/AR6003/hw1.0"; | 633 | return "ath6k/AR6003/hw1.0"; |
555 | case AR6003_REV2_VERSION: | 634 | case AR6003_HW_2_0_VERSION: |
556 | return "ath6k/AR6003/hw2.0"; | 635 | return "ath6k/AR6003/hw2.0"; |
557 | case AR6003_REV3_VERSION: | 636 | case AR6003_HW_2_1_1_VERSION: |
558 | return "ath6k/AR6003/hw2.1.1"; | 637 | return "ath6k/AR6003/hw2.1.1"; |
559 | } | 638 | } |
560 | ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, | 639 | ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, |
@@ -612,17 +691,10 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
612 | if (ar->fw_board != NULL) | 691 | if (ar->fw_board != NULL) |
613 | return 0; | 692 | return 0; |
614 | 693 | ||
615 | switch (ar->version.target_ver) { | 694 | if (WARN_ON(ar->hw.fw_board == NULL)) |
616 | case AR6003_REV2_VERSION: | 695 | return -EINVAL; |
617 | filename = AR6003_REV2_BOARD_DATA_FILE; | 696 | |
618 | break; | 697 | filename = ar->hw.fw_board; |
619 | case AR6004_REV1_VERSION: | ||
620 | filename = AR6004_REV1_BOARD_DATA_FILE; | ||
621 | break; | ||
622 | default: | ||
623 | filename = AR6003_REV3_BOARD_DATA_FILE; | ||
624 | break; | ||
625 | } | ||
626 | 698 | ||
627 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, | 699 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, |
628 | &ar->fw_board_len); | 700 | &ar->fw_board_len); |
@@ -640,17 +712,7 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) | |||
640 | ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", | 712 | ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n", |
641 | filename, ret); | 713 | filename, ret); |
642 | 714 | ||
643 | switch (ar->version.target_ver) { | 715 | filename = ar->hw.fw_default_board; |
644 | case AR6003_REV2_VERSION: | ||
645 | filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE; | ||
646 | break; | ||
647 | case AR6004_REV1_VERSION: | ||
648 | filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE; | ||
649 | break; | ||
650 | default: | ||
651 | filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE; | ||
652 | break; | ||
653 | } | ||
654 | 716 | ||
655 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, | 717 | ret = ath6kl_get_fw(ar, filename, &ar->fw_board, |
656 | &ar->fw_board_len); | 718 | &ar->fw_board_len); |
@@ -674,19 +736,14 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar) | |||
674 | if (ar->fw_otp != NULL) | 736 | if (ar->fw_otp != NULL) |
675 | return 0; | 737 | return 0; |
676 | 738 | ||
677 | switch (ar->version.target_ver) { | 739 | if (ar->hw.fw_otp == NULL) { |
678 | case AR6003_REV2_VERSION: | 740 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
679 | filename = AR6003_REV2_OTP_FILE; | 741 | "no OTP file configured for this hw\n"); |
680 | break; | ||
681 | case AR6004_REV1_VERSION: | ||
682 | ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n"); | ||
683 | return 0; | 742 | return 0; |
684 | break; | ||
685 | default: | ||
686 | filename = AR6003_REV3_OTP_FILE; | ||
687 | break; | ||
688 | } | 743 | } |
689 | 744 | ||
745 | filename = ar->hw.fw_otp; | ||
746 | |||
690 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, | 747 | ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, |
691 | &ar->fw_otp_len); | 748 | &ar->fw_otp_len); |
692 | if (ret) { | 749 | if (ret) { |
@@ -707,38 +764,22 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar) | |||
707 | return 0; | 764 | return 0; |
708 | 765 | ||
709 | if (testmode) { | 766 | if (testmode) { |
710 | switch (ar->version.target_ver) { | 767 | if (ar->hw.fw_tcmd == NULL) { |
711 | case AR6003_REV2_VERSION: | 768 | ath6kl_warn("testmode not supported\n"); |
712 | filename = AR6003_REV2_TCMD_FIRMWARE_FILE; | ||
713 | break; | ||
714 | case AR6003_REV3_VERSION: | ||
715 | filename = AR6003_REV3_TCMD_FIRMWARE_FILE; | ||
716 | break; | ||
717 | case AR6004_REV1_VERSION: | ||
718 | ath6kl_warn("testmode not supported with ar6004\n"); | ||
719 | return -EOPNOTSUPP; | 769 | return -EOPNOTSUPP; |
720 | default: | ||
721 | ath6kl_warn("unknown target version: 0x%x\n", | ||
722 | ar->version.target_ver); | ||
723 | return -EINVAL; | ||
724 | } | 770 | } |
725 | 771 | ||
772 | filename = ar->hw.fw_tcmd; | ||
773 | |||
726 | set_bit(TESTMODE, &ar->flag); | 774 | set_bit(TESTMODE, &ar->flag); |
727 | 775 | ||
728 | goto get_fw; | 776 | goto get_fw; |
729 | } | 777 | } |
730 | 778 | ||
731 | switch (ar->version.target_ver) { | 779 | if (WARN_ON(ar->hw.fw == NULL)) |
732 | case AR6003_REV2_VERSION: | 780 | return -EINVAL; |
733 | filename = AR6003_REV2_FIRMWARE_FILE; | 781 | |
734 | break; | 782 | filename = ar->hw.fw; |
735 | case AR6004_REV1_VERSION: | ||
736 | filename = AR6004_REV1_FIRMWARE_FILE; | ||
737 | break; | ||
738 | default: | ||
739 | filename = AR6003_REV3_FIRMWARE_FILE; | ||
740 | break; | ||
741 | } | ||
742 | 783 | ||
743 | get_fw: | 784 | get_fw: |
744 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); | 785 | ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); |
@@ -756,27 +797,20 @@ static int ath6kl_fetch_patch_file(struct ath6kl *ar) | |||
756 | const char *filename; | 797 | const char *filename; |
757 | int ret; | 798 | int ret; |
758 | 799 | ||
759 | switch (ar->version.target_ver) { | 800 | if (ar->fw_patch != NULL) |
760 | case AR6003_REV2_VERSION: | ||
761 | filename = AR6003_REV2_PATCH_FILE; | ||
762 | break; | ||
763 | case AR6004_REV1_VERSION: | ||
764 | /* FIXME: implement for AR6004 */ | ||
765 | return 0; | 801 | return 0; |
766 | break; | ||
767 | default: | ||
768 | filename = AR6003_REV3_PATCH_FILE; | ||
769 | break; | ||
770 | } | ||
771 | 802 | ||
772 | if (ar->fw_patch == NULL) { | 803 | if (ar->hw.fw_patch == NULL) |
773 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, | 804 | return 0; |
774 | &ar->fw_patch_len); | 805 | |
775 | if (ret) { | 806 | filename = ar->hw.fw_patch; |
776 | ath6kl_err("Failed to get patch file %s: %d\n", | 807 | |
777 | filename, ret); | 808 | ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, |
778 | return ret; | 809 | &ar->fw_patch_len); |
779 | } | 810 | if (ret) { |
811 | ath6kl_err("Failed to get patch file %s: %d\n", | ||
812 | filename, ret); | ||
813 | return ret; | ||
780 | } | 814 | } |
781 | 815 | ||
782 | return 0; | 816 | return 0; |
@@ -811,19 +845,10 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | |||
811 | int ret, ie_id, i, index, bit; | 845 | int ret, ie_id, i, index, bit; |
812 | __le32 *val; | 846 | __le32 *val; |
813 | 847 | ||
814 | switch (ar->version.target_ver) { | 848 | if (ar->hw.fw_api2 == NULL) |
815 | case AR6003_REV2_VERSION: | ||
816 | filename = AR6003_REV2_FIRMWARE_2_FILE; | ||
817 | break; | ||
818 | case AR6003_REV3_VERSION: | ||
819 | filename = AR6003_REV3_FIRMWARE_2_FILE; | ||
820 | break; | ||
821 | case AR6004_REV1_VERSION: | ||
822 | filename = AR6004_REV1_FIRMWARE_2_FILE; | ||
823 | break; | ||
824 | default: | ||
825 | return -EOPNOTSUPP; | 849 | return -EOPNOTSUPP; |
826 | } | 850 | |
851 | filename = ar->hw.fw_api2; | ||
827 | 852 | ||
828 | ret = request_firmware(&fw, filename, ar->dev); | 853 | ret = request_firmware(&fw, filename, ar->dev); |
829 | if (ret) | 854 | if (ret) |
@@ -913,12 +938,15 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | |||
913 | ar->hw.reserved_ram_size); | 938 | ar->hw.reserved_ram_size); |
914 | break; | 939 | break; |
915 | case ATH6KL_FW_IE_CAPABILITIES: | 940 | case ATH6KL_FW_IE_CAPABILITIES: |
941 | if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8)) | ||
942 | break; | ||
943 | |||
916 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 944 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
917 | "found firmware capabilities ie (%zd B)\n", | 945 | "found firmware capabilities ie (%zd B)\n", |
918 | ie_len); | 946 | ie_len); |
919 | 947 | ||
920 | for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { | 948 | for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { |
921 | index = ALIGN(i, 8) / 8; | 949 | index = i / 8; |
922 | bit = i % 8; | 950 | bit = i % 8; |
923 | 951 | ||
924 | if (data[index] & (1 << bit)) | 952 | if (data[index] & (1 << bit)) |
@@ -937,9 +965,34 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) | |||
937 | ar->hw.dataset_patch_addr = le32_to_cpup(val); | 965 | ar->hw.dataset_patch_addr = le32_to_cpup(val); |
938 | 966 | ||
939 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 967 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
940 | "found patch address ie 0x%d\n", | 968 | "found patch address ie 0x%x\n", |
941 | ar->hw.dataset_patch_addr); | 969 | ar->hw.dataset_patch_addr); |
942 | break; | 970 | break; |
971 | case ATH6KL_FW_IE_BOARD_ADDR: | ||
972 | if (ie_len != sizeof(*val)) | ||
973 | break; | ||
974 | |||
975 | val = (__le32 *) data; | ||
976 | ar->hw.board_addr = le32_to_cpup(val); | ||
977 | |||
978 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
979 | "found board address ie 0x%x\n", | ||
980 | ar->hw.board_addr); | ||
981 | break; | ||
982 | case ATH6KL_FW_IE_VIF_MAX: | ||
983 | if (ie_len != sizeof(*val)) | ||
984 | break; | ||
985 | |||
986 | val = (__le32 *) data; | ||
987 | ar->vif_max = min_t(unsigned int, le32_to_cpup(val), | ||
988 | ATH6KL_VIF_MAX); | ||
989 | |||
990 | if (ar->vif_max > 1 && !ar->p2p) | ||
991 | ar->max_norm_iface = 2; | ||
992 | |||
993 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
994 | "found vif max ie %d\n", ar->vif_max); | ||
995 | break; | ||
943 | default: | 996 | default: |
944 | ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n", | 997 | ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n", |
945 | le32_to_cpup(&hdr->id)); | 998 | le32_to_cpup(&hdr->id)); |
@@ -994,8 +1047,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
994 | * For AR6004, host determine Target RAM address for | 1047 | * For AR6004, host determine Target RAM address for |
995 | * writing board data. | 1048 | * writing board data. |
996 | */ | 1049 | */ |
997 | if (ar->target_type == TARGET_TYPE_AR6004) { | 1050 | if (ar->hw.board_addr != 0) { |
998 | board_address = AR6004_REV1_BOARD_DATA_ADDRESS; | 1051 | board_address = ar->hw.board_addr; |
999 | ath6kl_bmi_write(ar, | 1052 | ath6kl_bmi_write(ar, |
1000 | ath6kl_get_hi_item_addr(ar, | 1053 | ath6kl_get_hi_item_addr(ar, |
1001 | HI_ITEM(hi_board_data)), | 1054 | HI_ITEM(hi_board_data)), |
@@ -1013,7 +1066,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
1013 | HI_ITEM(hi_board_ext_data)), | 1066 | HI_ITEM(hi_board_ext_data)), |
1014 | (u8 *) &board_ext_address, 4); | 1067 | (u8 *) &board_ext_address, 4); |
1015 | 1068 | ||
1016 | if (board_ext_address == 0) { | 1069 | if (ar->target_type == TARGET_TYPE_AR6003 && |
1070 | board_ext_address == 0) { | ||
1017 | ath6kl_err("Failed to get board file target address.\n"); | 1071 | ath6kl_err("Failed to get board file target address.\n"); |
1018 | return -EINVAL; | 1072 | return -EINVAL; |
1019 | } | 1073 | } |
@@ -1033,8 +1087,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) | |||
1033 | break; | 1087 | break; |
1034 | } | 1088 | } |
1035 | 1089 | ||
1036 | if (ar->fw_board_len == (board_data_size + | 1090 | if (board_ext_address && |
1037 | board_ext_data_size)) { | 1091 | ar->fw_board_len == (board_data_size + board_ext_data_size)) { |
1038 | 1092 | ||
1039 | /* write extended board data */ | 1093 | /* write extended board data */ |
1040 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 1094 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
@@ -1092,8 +1146,8 @@ static int ath6kl_upload_otp(struct ath6kl *ar) | |||
1092 | bool from_hw = false; | 1146 | bool from_hw = false; |
1093 | int ret; | 1147 | int ret; |
1094 | 1148 | ||
1095 | if (WARN_ON(ar->fw_otp == NULL)) | 1149 | if (ar->fw_otp == NULL) |
1096 | return -ENOENT; | 1150 | return 0; |
1097 | 1151 | ||
1098 | address = ar->hw.app_load_addr; | 1152 | address = ar->hw.app_load_addr; |
1099 | 1153 | ||
@@ -1142,7 +1196,7 @@ static int ath6kl_upload_firmware(struct ath6kl *ar) | |||
1142 | int ret; | 1196 | int ret; |
1143 | 1197 | ||
1144 | if (WARN_ON(ar->fw == NULL)) | 1198 | if (WARN_ON(ar->fw == NULL)) |
1145 | return -ENOENT; | 1199 | return 0; |
1146 | 1200 | ||
1147 | address = ar->hw.app_load_addr; | 1201 | address = ar->hw.app_load_addr; |
1148 | 1202 | ||
@@ -1172,8 +1226,8 @@ static int ath6kl_upload_patch(struct ath6kl *ar) | |||
1172 | u32 address, param; | 1226 | u32 address, param; |
1173 | int ret; | 1227 | int ret; |
1174 | 1228 | ||
1175 | if (WARN_ON(ar->fw_patch == NULL)) | 1229 | if (ar->fw_patch == NULL) |
1176 | return -ENOENT; | 1230 | return 0; |
1177 | 1231 | ||
1178 | address = ar->hw.dataset_patch_addr; | 1232 | address = ar->hw.dataset_patch_addr; |
1179 | 1233 | ||
@@ -1258,7 +1312,7 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1258 | return status; | 1312 | return status; |
1259 | 1313 | ||
1260 | /* WAR to avoid SDIO CRC err */ | 1314 | /* WAR to avoid SDIO CRC err */ |
1261 | if (ar->version.target_ver == AR6003_REV2_VERSION) { | 1315 | if (ar->version.target_ver == AR6003_HW_2_0_VERSION) { |
1262 | ath6kl_err("temporary war to avoid sdio crc error\n"); | 1316 | ath6kl_err("temporary war to avoid sdio crc error\n"); |
1263 | 1317 | ||
1264 | param = 0x20; | 1318 | param = 0x20; |
@@ -1315,47 +1369,29 @@ static int ath6kl_init_upload(struct ath6kl *ar) | |||
1315 | if (status) | 1369 | if (status) |
1316 | return status; | 1370 | return status; |
1317 | 1371 | ||
1318 | /* Configure GPIO AR6003 UART */ | ||
1319 | param = CONFIG_AR600x_DEBUG_UART_TX_PIN; | ||
1320 | status = ath6kl_bmi_write(ar, | ||
1321 | ath6kl_get_hi_item_addr(ar, | ||
1322 | HI_ITEM(hi_dbg_uart_txpin)), | ||
1323 | (u8 *)¶m, 4); | ||
1324 | |||
1325 | return status; | 1372 | return status; |
1326 | } | 1373 | } |
1327 | 1374 | ||
1328 | static int ath6kl_init_hw_params(struct ath6kl *ar) | 1375 | static int ath6kl_init_hw_params(struct ath6kl *ar) |
1329 | { | 1376 | { |
1330 | switch (ar->version.target_ver) { | 1377 | const struct ath6kl_hw *hw; |
1331 | case AR6003_REV2_VERSION: | 1378 | int i; |
1332 | ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; | ||
1333 | ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS; | ||
1334 | ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS; | ||
1335 | ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE; | ||
1336 | 1379 | ||
1337 | /* hw2.0 needs override address hardcoded */ | 1380 | for (i = 0; i < ARRAY_SIZE(hw_list); i++) { |
1338 | ar->hw.app_start_override_addr = 0x944C00; | 1381 | hw = &hw_list[i]; |
1339 | 1382 | ||
1340 | break; | 1383 | if (hw->id == ar->version.target_ver) |
1341 | case AR6003_REV3_VERSION: | 1384 | break; |
1342 | ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS; | 1385 | } |
1343 | ar->hw.app_load_addr = 0x1234; | 1386 | |
1344 | ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS; | 1387 | if (i == ARRAY_SIZE(hw_list)) { |
1345 | ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE; | ||
1346 | break; | ||
1347 | case AR6004_REV1_VERSION: | ||
1348 | ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS; | ||
1349 | ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS; | ||
1350 | ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS; | ||
1351 | ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE; | ||
1352 | break; | ||
1353 | default: | ||
1354 | ath6kl_err("Unsupported hardware version: 0x%x\n", | 1388 | ath6kl_err("Unsupported hardware version: 0x%x\n", |
1355 | ar->version.target_ver); | 1389 | ar->version.target_ver); |
1356 | return -EINVAL; | 1390 | return -EINVAL; |
1357 | } | 1391 | } |
1358 | 1392 | ||
1393 | ar->hw = *hw; | ||
1394 | |||
1359 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 1395 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
1360 | "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n", | 1396 | "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n", |
1361 | ar->version.target_ver, ar->target_type, | 1397 | ar->version.target_ver, ar->target_type, |
@@ -1364,10 +1400,25 @@ static int ath6kl_init_hw_params(struct ath6kl *ar) | |||
1364 | "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x", | 1400 | "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x", |
1365 | ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr, | 1401 | ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr, |
1366 | ar->hw.reserved_ram_size); | 1402 | ar->hw.reserved_ram_size); |
1403 | ath6kl_dbg(ATH6KL_DBG_BOOT, | ||
1404 | "refclk_hz %d uarttx_pin %d", | ||
1405 | ar->hw.refclk_hz, ar->hw.uarttx_pin); | ||
1367 | 1406 | ||
1368 | return 0; | 1407 | return 0; |
1369 | } | 1408 | } |
1370 | 1409 | ||
1410 | static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type) | ||
1411 | { | ||
1412 | switch (type) { | ||
1413 | case ATH6KL_HIF_TYPE_SDIO: | ||
1414 | return "sdio"; | ||
1415 | case ATH6KL_HIF_TYPE_USB: | ||
1416 | return "usb"; | ||
1417 | } | ||
1418 | |||
1419 | return NULL; | ||
1420 | } | ||
1421 | |||
1371 | int ath6kl_init_hw_start(struct ath6kl *ar) | 1422 | int ath6kl_init_hw_start(struct ath6kl *ar) |
1372 | { | 1423 | { |
1373 | long timeleft; | 1424 | long timeleft; |
@@ -1428,6 +1479,15 @@ int ath6kl_init_hw_start(struct ath6kl *ar) | |||
1428 | 1479 | ||
1429 | ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n"); | 1480 | ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n"); |
1430 | 1481 | ||
1482 | |||
1483 | if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { | ||
1484 | ath6kl_info("%s %s fw %s%s\n", | ||
1485 | ar->hw.name, | ||
1486 | ath6kl_init_get_hif_name(ar->hif_type), | ||
1487 | ar->wiphy->fw_version, | ||
1488 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); | ||
1489 | } | ||
1490 | |||
1431 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { | 1491 | if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { |
1432 | ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", | 1492 | ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n", |
1433 | ATH6KL_ABI_VERSION, ar->version.abi_ver); | 1493 | ATH6KL_ABI_VERSION, ar->version.abi_ver); |
@@ -1448,7 +1508,7 @@ int ath6kl_init_hw_start(struct ath6kl *ar) | |||
1448 | if ((ath6kl_set_host_app_area(ar)) != 0) | 1508 | if ((ath6kl_set_host_app_area(ar)) != 0) |
1449 | ath6kl_err("unable to set the host app area\n"); | 1509 | ath6kl_err("unable to set the host app area\n"); |
1450 | 1510 | ||
1451 | for (i = 0; i < MAX_NUM_VIF; i++) { | 1511 | for (i = 0; i < ar->vif_max; i++) { |
1452 | ret = ath6kl_target_config_wlan_params(ar, i); | 1512 | ret = ath6kl_target_config_wlan_params(ar, i); |
1453 | if (ret) | 1513 | if (ret) |
1454 | goto err_htc_stop; | 1514 | goto err_htc_stop; |
@@ -1558,7 +1618,7 @@ int ath6kl_core_init(struct ath6kl *ar) | |||
1558 | goto err_node_cleanup; | 1618 | goto err_node_cleanup; |
1559 | } | 1619 | } |
1560 | 1620 | ||
1561 | for (i = 0; i < MAX_NUM_VIF; i++) | 1621 | for (i = 0; i < ar->vif_max; i++) |
1562 | ar->avail_idx_map |= BIT(i); | 1622 | ar->avail_idx_map |= BIT(i); |
1563 | 1623 | ||
1564 | rtnl_lock(); | 1624 | rtnl_lock(); |
@@ -1603,7 +1663,17 @@ int ath6kl_core_init(struct ath6kl *ar) | |||
1603 | 1663 | ||
1604 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 1664 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
1605 | WIPHY_FLAG_HAVE_AP_SME | | 1665 | WIPHY_FLAG_HAVE_AP_SME | |
1606 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 1666 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
1667 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
1668 | |||
1669 | if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) | ||
1670 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
1671 | |||
1672 | ar->wiphy->probe_resp_offload = | ||
1673 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
1674 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
1675 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | | ||
1676 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; | ||
1607 | 1677 | ||
1608 | set_bit(FIRST_BOOT, &ar->flag); | 1678 | set_bit(FIRST_BOOT, &ar->flag); |
1609 | 1679 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 5e5f4ca8f3f0..eea3c747653e 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -175,64 +175,6 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie) | |||
175 | ar->cookie_count++; | 175 | ar->cookie_count++; |
176 | } | 176 | } |
177 | 177 | ||
178 | /* set the window address register (using 4-byte register access ). */ | ||
179 | static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | ||
180 | { | ||
181 | int status; | ||
182 | s32 i; | ||
183 | __le32 addr_val; | ||
184 | |||
185 | /* | ||
186 | * Write bytes 1,2,3 of the register to set the upper address bytes, | ||
187 | * the LSB is written last to initiate the access cycle | ||
188 | */ | ||
189 | |||
190 | for (i = 1; i <= 3; i++) { | ||
191 | /* | ||
192 | * Fill the buffer with the address byte value we want to | ||
193 | * hit 4 times. No need to worry about endianness as the | ||
194 | * same byte is copied to all four bytes of addr_val at | ||
195 | * any time. | ||
196 | */ | ||
197 | memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4); | ||
198 | |||
199 | /* | ||
200 | * Hit each byte of the register address with a 4-byte | ||
201 | * write operation to the same address, this is a harmless | ||
202 | * operation. | ||
203 | */ | ||
204 | status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val, | ||
205 | 4, HIF_WR_SYNC_BYTE_FIX); | ||
206 | if (status) | ||
207 | break; | ||
208 | } | ||
209 | |||
210 | if (status) { | ||
211 | ath6kl_err("failed to write initial bytes of 0x%x to window reg: 0x%X\n", | ||
212 | addr, reg_addr); | ||
213 | return status; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Write the address register again, this time write the whole | ||
218 | * 4-byte value. The effect here is that the LSB write causes the | ||
219 | * cycle to start, the extra 3 byte write to bytes 1,2,3 has no | ||
220 | * effect since we are writing the same values again | ||
221 | */ | ||
222 | addr_val = cpu_to_le32(addr); | ||
223 | status = hif_read_write_sync(ar, reg_addr, | ||
224 | (u8 *)&(addr_val), | ||
225 | 4, HIF_WR_SYNC_BYTE_INC); | ||
226 | |||
227 | if (status) { | ||
228 | ath6kl_err("failed to write 0x%x to window reg: 0x%X\n", | ||
229 | addr, reg_addr); | ||
230 | return status; | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | /* | 178 | /* |
237 | * Read from the hardware through its diagnostic window. No cooperation | 179 | * Read from the hardware through its diagnostic window. No cooperation |
238 | * from the firmware is required for this. | 180 | * from the firmware is required for this. |
@@ -241,14 +183,7 @@ int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value) | |||
241 | { | 183 | { |
242 | int ret; | 184 | int ret; |
243 | 185 | ||
244 | /* set window register to start read cycle */ | 186 | ret = ath6kl_hif_diag_read32(ar, address, value); |
245 | ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address); | ||
246 | if (ret) | ||
247 | return ret; | ||
248 | |||
249 | /* read the data */ | ||
250 | ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value, | ||
251 | sizeof(*value), HIF_RD_SYNC_BYTE_INC); | ||
252 | if (ret) { | 187 | if (ret) { |
253 | ath6kl_warn("failed to read32 through diagnose window: %d\n", | 188 | ath6kl_warn("failed to read32 through diagnose window: %d\n", |
254 | ret); | 189 | ret); |
@@ -266,18 +201,15 @@ int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value) | |||
266 | { | 201 | { |
267 | int ret; | 202 | int ret; |
268 | 203 | ||
269 | /* set write data */ | 204 | ret = ath6kl_hif_diag_write32(ar, address, value); |
270 | ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value, | 205 | |
271 | sizeof(value), HIF_WR_SYNC_BYTE_INC); | ||
272 | if (ret) { | 206 | if (ret) { |
273 | ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", | 207 | ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", |
274 | address, value); | 208 | address, value); |
275 | return ret; | 209 | return ret; |
276 | } | 210 | } |
277 | 211 | ||
278 | /* set window register, which starts the write cycle */ | 212 | return 0; |
279 | return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, | ||
280 | address); | ||
281 | } | 213 | } |
282 | 214 | ||
283 | int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length) | 215 | int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length) |
@@ -465,7 +397,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) | |||
465 | case NONE_AUTH: | 397 | case NONE_AUTH: |
466 | if (vif->prwise_crypto == WEP_CRYPT) | 398 | if (vif->prwise_crypto == WEP_CRYPT) |
467 | ath6kl_install_static_wep_keys(vif); | 399 | ath6kl_install_static_wep_keys(vif); |
468 | break; | 400 | if (!ik->valid || ik->key_type != WAPI_CRYPT) |
401 | break; | ||
402 | /* for WAPI, we need to set the delayed group key, continue: */ | ||
469 | case WPA_PSK_AUTH: | 403 | case WPA_PSK_AUTH: |
470 | case WPA2_PSK_AUTH: | 404 | case WPA2_PSK_AUTH: |
471 | case (WPA_PSK_AUTH | WPA2_PSK_AUTH): | 405 | case (WPA_PSK_AUTH | WPA2_PSK_AUTH): |
@@ -534,6 +468,18 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, | |||
534 | wpa_ie = pos; /* WPS IE */ | 468 | wpa_ie = pos; /* WPS IE */ |
535 | break; /* overrides WPA/RSN IE */ | 469 | break; /* overrides WPA/RSN IE */ |
536 | } | 470 | } |
471 | } else if (pos[0] == 0x44 && wpa_ie == NULL) { | ||
472 | /* | ||
473 | * Note: WAPI Parameter Set IE re-uses Element ID that | ||
474 | * was officially allocated for BSS AC Access Delay. As | ||
475 | * such, we need to be a bit more careful on when | ||
476 | * parsing the frame. However, BSS AC Access Delay | ||
477 | * element is not supposed to be included in | ||
478 | * (Re)Association Request frames, so this should not | ||
479 | * cause problems. | ||
480 | */ | ||
481 | wpa_ie = pos; /* WAPI IE */ | ||
482 | break; | ||
537 | } | 483 | } |
538 | pos += 2 + pos[1]; | 484 | pos += 2 + pos[1]; |
539 | } | 485 | } |
@@ -581,20 +527,6 @@ void ath6kl_disconnect(struct ath6kl_vif *vif) | |||
581 | 527 | ||
582 | /* WMI Event handlers */ | 528 | /* WMI Event handlers */ |
583 | 529 | ||
584 | static const char *get_hw_id_string(u32 id) | ||
585 | { | ||
586 | switch (id) { | ||
587 | case AR6003_REV1_VERSION: | ||
588 | return "1.0"; | ||
589 | case AR6003_REV2_VERSION: | ||
590 | return "2.0"; | ||
591 | case AR6003_REV3_VERSION: | ||
592 | return "2.1.1"; | ||
593 | default: | ||
594 | return "unknown"; | ||
595 | } | ||
596 | } | ||
597 | |||
598 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) | 530 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) |
599 | { | 531 | { |
600 | struct ath6kl *ar = devt; | 532 | struct ath6kl *ar = devt; |
@@ -617,13 +549,6 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) | |||
617 | /* indicate to the waiting thread that the ready event was received */ | 549 | /* indicate to the waiting thread that the ready event was received */ |
618 | set_bit(WMI_READY, &ar->flag); | 550 | set_bit(WMI_READY, &ar->flag); |
619 | wake_up(&ar->event_wq); | 551 | wake_up(&ar->event_wq); |
620 | |||
621 | if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { | ||
622 | ath6kl_info("hw %s fw %s%s\n", | ||
623 | get_hw_id_string(ar->wiphy->hw_version), | ||
624 | ar->wiphy->fw_version, | ||
625 | test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); | ||
626 | } | ||
627 | } | 552 | } |
628 | 553 | ||
629 | void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status) | 554 | void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status) |
@@ -1077,21 +1002,11 @@ static int ath6kl_open(struct net_device *dev) | |||
1077 | 1002 | ||
1078 | static int ath6kl_close(struct net_device *dev) | 1003 | static int ath6kl_close(struct net_device *dev) |
1079 | { | 1004 | { |
1080 | struct ath6kl *ar = ath6kl_priv(dev); | ||
1081 | struct ath6kl_vif *vif = netdev_priv(dev); | 1005 | struct ath6kl_vif *vif = netdev_priv(dev); |
1082 | 1006 | ||
1083 | netif_stop_queue(dev); | 1007 | netif_stop_queue(dev); |
1084 | 1008 | ||
1085 | ath6kl_disconnect(vif); | 1009 | ath6kl_cfg80211_stop(vif); |
1086 | |||
1087 | if (test_bit(WMI_READY, &ar->flag)) { | ||
1088 | if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, | ||
1089 | 0, 0, 0, 0, 0, 0, 0, 0, 0)) | ||
1090 | return -EIO; | ||
1091 | |||
1092 | } | ||
1093 | |||
1094 | ath6kl_cfg80211_scan_complete_event(vif, true); | ||
1095 | 1010 | ||
1096 | clear_bit(WLAN_ENABLED, &vif->flags); | 1011 | clear_bit(WLAN_ENABLED, &vif->flags); |
1097 | 1012 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index e69ca5ee5bb1..15c3f56caf4f 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -40,8 +40,12 @@ struct ath6kl_sdio { | |||
40 | struct bus_request bus_req[BUS_REQUEST_MAX_NUM]; | 40 | struct bus_request bus_req[BUS_REQUEST_MAX_NUM]; |
41 | 41 | ||
42 | struct ath6kl *ar; | 42 | struct ath6kl *ar; |
43 | |||
43 | u8 *dma_buffer; | 44 | u8 *dma_buffer; |
44 | 45 | ||
46 | /* protects access to dma_buffer */ | ||
47 | struct mutex dma_buffer_mutex; | ||
48 | |||
45 | /* scatter request list head */ | 49 | /* scatter request list head */ |
46 | struct list_head scat_req; | 50 | struct list_head scat_req; |
47 | 51 | ||
@@ -396,6 +400,7 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf, | |||
396 | if (buf_needs_bounce(buf)) { | 400 | if (buf_needs_bounce(buf)) { |
397 | if (!ar_sdio->dma_buffer) | 401 | if (!ar_sdio->dma_buffer) |
398 | return -ENOMEM; | 402 | return -ENOMEM; |
403 | mutex_lock(&ar_sdio->dma_buffer_mutex); | ||
399 | tbuf = ar_sdio->dma_buffer; | 404 | tbuf = ar_sdio->dma_buffer; |
400 | memcpy(tbuf, buf, len); | 405 | memcpy(tbuf, buf, len); |
401 | bounced = true; | 406 | bounced = true; |
@@ -406,6 +411,9 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf, | |||
406 | if ((request & HIF_READ) && bounced) | 411 | if ((request & HIF_READ) && bounced) |
407 | memcpy(buf, tbuf, len); | 412 | memcpy(buf, tbuf, len); |
408 | 413 | ||
414 | if (bounced) | ||
415 | mutex_unlock(&ar_sdio->dma_buffer_mutex); | ||
416 | |||
409 | return ret; | 417 | return ret; |
410 | } | 418 | } |
411 | 419 | ||
@@ -799,7 +807,28 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
799 | return ret; | 807 | return ret; |
800 | } | 808 | } |
801 | 809 | ||
802 | if ((flags & MMC_PM_WAKE_SDIO_IRQ) && wow) { | 810 | if (!(flags & MMC_PM_WAKE_SDIO_IRQ)) |
811 | goto deepsleep; | ||
812 | |||
813 | /* sdio irq wakes up host */ | ||
814 | |||
815 | if (ar->state == ATH6KL_STATE_SCHED_SCAN) { | ||
816 | ret = ath6kl_cfg80211_suspend(ar, | ||
817 | ATH6KL_CFG_SUSPEND_SCHED_SCAN, | ||
818 | NULL); | ||
819 | if (ret) { | ||
820 | ath6kl_warn("Schedule scan suspend failed: %d", ret); | ||
821 | return ret; | ||
822 | } | ||
823 | |||
824 | ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ); | ||
825 | if (ret) | ||
826 | ath6kl_warn("set sdio wake irq flag failed: %d\n", ret); | ||
827 | |||
828 | return ret; | ||
829 | } | ||
830 | |||
831 | if (wow) { | ||
803 | /* | 832 | /* |
804 | * The host sdio controller is capable of keep power and | 833 | * The host sdio controller is capable of keep power and |
805 | * sdio irq wake up at this point. It's fine to continue | 834 | * sdio irq wake up at this point. It's fine to continue |
@@ -816,6 +845,7 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
816 | return ret; | 845 | return ret; |
817 | } | 846 | } |
818 | 847 | ||
848 | deepsleep: | ||
819 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL); | 849 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_DEEPSLEEP, NULL); |
820 | } | 850 | } |
821 | 851 | ||
@@ -839,6 +869,8 @@ static int ath6kl_sdio_resume(struct ath6kl *ar) | |||
839 | 869 | ||
840 | case ATH6KL_STATE_WOW: | 870 | case ATH6KL_STATE_WOW: |
841 | break; | 871 | break; |
872 | case ATH6KL_STATE_SCHED_SCAN: | ||
873 | break; | ||
842 | } | 874 | } |
843 | 875 | ||
844 | ath6kl_cfg80211_resume(ar); | 876 | ath6kl_cfg80211_resume(ar); |
@@ -846,6 +878,264 @@ static int ath6kl_sdio_resume(struct ath6kl *ar) | |||
846 | return 0; | 878 | return 0; |
847 | } | 879 | } |
848 | 880 | ||
881 | /* set the window address register (using 4-byte register access ). */ | ||
882 | static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | ||
883 | { | ||
884 | int status; | ||
885 | u8 addr_val[4]; | ||
886 | s32 i; | ||
887 | |||
888 | /* | ||
889 | * Write bytes 1,2,3 of the register to set the upper address bytes, | ||
890 | * the LSB is written last to initiate the access cycle | ||
891 | */ | ||
892 | |||
893 | for (i = 1; i <= 3; i++) { | ||
894 | /* | ||
895 | * Fill the buffer with the address byte value we want to | ||
896 | * hit 4 times. | ||
897 | */ | ||
898 | memset(addr_val, ((u8 *)&addr)[i], 4); | ||
899 | |||
900 | /* | ||
901 | * Hit each byte of the register address with a 4-byte | ||
902 | * write operation to the same address, this is a harmless | ||
903 | * operation. | ||
904 | */ | ||
905 | status = ath6kl_sdio_read_write_sync(ar, reg_addr + i, addr_val, | ||
906 | 4, HIF_WR_SYNC_BYTE_FIX); | ||
907 | if (status) | ||
908 | break; | ||
909 | } | ||
910 | |||
911 | if (status) { | ||
912 | ath6kl_err("%s: failed to write initial bytes of 0x%x " | ||
913 | "to window reg: 0x%X\n", __func__, | ||
914 | addr, reg_addr); | ||
915 | return status; | ||
916 | } | ||
917 | |||
918 | /* | ||
919 | * Write the address register again, this time write the whole | ||
920 | * 4-byte value. The effect here is that the LSB write causes the | ||
921 | * cycle to start, the extra 3 byte write to bytes 1,2,3 has no | ||
922 | * effect since we are writing the same values again | ||
923 | */ | ||
924 | status = ath6kl_sdio_read_write_sync(ar, reg_addr, (u8 *)(&addr), | ||
925 | 4, HIF_WR_SYNC_BYTE_INC); | ||
926 | |||
927 | if (status) { | ||
928 | ath6kl_err("%s: failed to write 0x%x to window reg: 0x%X\n", | ||
929 | __func__, addr, reg_addr); | ||
930 | return status; | ||
931 | } | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | static int ath6kl_sdio_diag_read32(struct ath6kl *ar, u32 address, u32 *data) | ||
937 | { | ||
938 | int status; | ||
939 | |||
940 | /* set window register to start read cycle */ | ||
941 | status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, | ||
942 | address); | ||
943 | |||
944 | if (status) | ||
945 | return status; | ||
946 | |||
947 | /* read the data */ | ||
948 | status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS, | ||
949 | (u8 *)data, sizeof(u32), HIF_RD_SYNC_BYTE_INC); | ||
950 | if (status) { | ||
951 | ath6kl_err("%s: failed to read from window data addr\n", | ||
952 | __func__); | ||
953 | return status; | ||
954 | } | ||
955 | |||
956 | return status; | ||
957 | } | ||
958 | |||
959 | static int ath6kl_sdio_diag_write32(struct ath6kl *ar, u32 address, | ||
960 | __le32 data) | ||
961 | { | ||
962 | int status; | ||
963 | u32 val = (__force u32) data; | ||
964 | |||
965 | /* set write data */ | ||
966 | status = ath6kl_sdio_read_write_sync(ar, WINDOW_DATA_ADDRESS, | ||
967 | (u8 *) &val, sizeof(u32), HIF_WR_SYNC_BYTE_INC); | ||
968 | if (status) { | ||
969 | ath6kl_err("%s: failed to write 0x%x to window data addr\n", | ||
970 | __func__, data); | ||
971 | return status; | ||
972 | } | ||
973 | |||
974 | /* set window register, which starts the write cycle */ | ||
975 | return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS, | ||
976 | address); | ||
977 | } | ||
978 | |||
979 | static int ath6kl_sdio_bmi_credits(struct ath6kl *ar) | ||
980 | { | ||
981 | u32 addr; | ||
982 | unsigned long timeout; | ||
983 | int ret; | ||
984 | |||
985 | ar->bmi.cmd_credits = 0; | ||
986 | |||
987 | /* Read the counter register to get the command credits */ | ||
988 | addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; | ||
989 | |||
990 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); | ||
991 | while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) { | ||
992 | |||
993 | /* | ||
994 | * Hit the credit counter with a 4-byte access, the first byte | ||
995 | * read will hit the counter and cause a decrement, while the | ||
996 | * remaining 3 bytes has no effect. The rationale behind this | ||
997 | * is to make all HIF accesses 4-byte aligned. | ||
998 | */ | ||
999 | ret = ath6kl_sdio_read_write_sync(ar, addr, | ||
1000 | (u8 *)&ar->bmi.cmd_credits, 4, | ||
1001 | HIF_RD_SYNC_BYTE_INC); | ||
1002 | if (ret) { | ||
1003 | ath6kl_err("Unable to decrement the command credit " | ||
1004 | "count register: %d\n", ret); | ||
1005 | return ret; | ||
1006 | } | ||
1007 | |||
1008 | /* The counter is only 8 bits. | ||
1009 | * Ignore anything in the upper 3 bytes | ||
1010 | */ | ||
1011 | ar->bmi.cmd_credits &= 0xFF; | ||
1012 | } | ||
1013 | |||
1014 | if (!ar->bmi.cmd_credits) { | ||
1015 | ath6kl_err("bmi communication timeout\n"); | ||
1016 | return -ETIMEDOUT; | ||
1017 | } | ||
1018 | |||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar) | ||
1023 | { | ||
1024 | unsigned long timeout; | ||
1025 | u32 rx_word = 0; | ||
1026 | int ret = 0; | ||
1027 | |||
1028 | timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT); | ||
1029 | while ((time_before(jiffies, timeout)) && !rx_word) { | ||
1030 | ret = ath6kl_sdio_read_write_sync(ar, | ||
1031 | RX_LOOKAHEAD_VALID_ADDRESS, | ||
1032 | (u8 *)&rx_word, sizeof(rx_word), | ||
1033 | HIF_RD_SYNC_BYTE_INC); | ||
1034 | if (ret) { | ||
1035 | ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n"); | ||
1036 | return ret; | ||
1037 | } | ||
1038 | |||
1039 | /* all we really want is one bit */ | ||
1040 | rx_word &= (1 << ENDPOINT1); | ||
1041 | } | ||
1042 | |||
1043 | if (!rx_word) { | ||
1044 | ath6kl_err("bmi_recv_buf FIFO empty\n"); | ||
1045 | return -EINVAL; | ||
1046 | } | ||
1047 | |||
1048 | return ret; | ||
1049 | } | ||
1050 | |||
1051 | static int ath6kl_sdio_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | ||
1052 | { | ||
1053 | int ret; | ||
1054 | u32 addr; | ||
1055 | |||
1056 | ret = ath6kl_sdio_bmi_credits(ar); | ||
1057 | if (ret) | ||
1058 | return ret; | ||
1059 | |||
1060 | addr = ar->mbox_info.htc_addr; | ||
1061 | |||
1062 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, | ||
1063 | HIF_WR_SYNC_BYTE_INC); | ||
1064 | if (ret) | ||
1065 | ath6kl_err("unable to send the bmi data to the device\n"); | ||
1066 | |||
1067 | return ret; | ||
1068 | } | ||
1069 | |||
1070 | static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | ||
1071 | { | ||
1072 | int ret; | ||
1073 | u32 addr; | ||
1074 | |||
1075 | /* | ||
1076 | * During normal bootup, small reads may be required. | ||
1077 | * Rather than issue an HIF Read and then wait as the Target | ||
1078 | * adds successive bytes to the FIFO, we wait here until | ||
1079 | * we know that response data is available. | ||
1080 | * | ||
1081 | * This allows us to cleanly timeout on an unexpected | ||
1082 | * Target failure rather than risk problems at the HIF level. | ||
1083 | * In particular, this avoids SDIO timeouts and possibly garbage | ||
1084 | * data on some host controllers. And on an interconnect | ||
1085 | * such as Compact Flash (as well as some SDIO masters) which | ||
1086 | * does not provide any indication on data timeout, it avoids | ||
1087 | * a potential hang or garbage response. | ||
1088 | * | ||
1089 | * Synchronization is more difficult for reads larger than the | ||
1090 | * size of the MBOX FIFO (128B), because the Target is unable | ||
1091 | * to push the 129th byte of data until AFTER the Host posts an | ||
1092 | * HIF Read and removes some FIFO data. So for large reads the | ||
1093 | * Host proceeds to post an HIF Read BEFORE all the data is | ||
1094 | * actually available to read. Fortunately, large BMI reads do | ||
1095 | * not occur in practice -- they're supported for debug/development. | ||
1096 | * | ||
1097 | * So Host/Target BMI synchronization is divided into these cases: | ||
1098 | * CASE 1: length < 4 | ||
1099 | * Should not happen | ||
1100 | * | ||
1101 | * CASE 2: 4 <= length <= 128 | ||
1102 | * Wait for first 4 bytes to be in FIFO | ||
1103 | * If CONSERVATIVE_BMI_READ is enabled, also wait for | ||
1104 | * a BMI command credit, which indicates that the ENTIRE | ||
1105 | * response is available in the the FIFO | ||
1106 | * | ||
1107 | * CASE 3: length > 128 | ||
1108 | * Wait for the first 4 bytes to be in FIFO | ||
1109 | * | ||
1110 | * For most uses, a small timeout should be sufficient and we will | ||
1111 | * usually see a response quickly; but there may be some unusual | ||
1112 | * (debug) cases of BMI_EXECUTE where we want an larger timeout. | ||
1113 | * For now, we use an unbounded busy loop while waiting for | ||
1114 | * BMI_EXECUTE. | ||
1115 | * | ||
1116 | * If BMI_EXECUTE ever needs to support longer-latency execution, | ||
1117 | * especially in production, this code needs to be enhanced to sleep | ||
1118 | * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently | ||
1119 | * a function of Host processor speed. | ||
1120 | */ | ||
1121 | if (len >= 4) { /* NB: Currently, always true */ | ||
1122 | ret = ath6kl_bmi_get_rx_lkahd(ar); | ||
1123 | if (ret) | ||
1124 | return ret; | ||
1125 | } | ||
1126 | |||
1127 | addr = ar->mbox_info.htc_addr; | ||
1128 | ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, | ||
1129 | HIF_RD_SYNC_BYTE_INC); | ||
1130 | if (ret) { | ||
1131 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | ||
1132 | ret); | ||
1133 | return ret; | ||
1134 | } | ||
1135 | |||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
849 | static void ath6kl_sdio_stop(struct ath6kl *ar) | 1139 | static void ath6kl_sdio_stop(struct ath6kl *ar) |
850 | { | 1140 | { |
851 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); | 1141 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); |
@@ -890,6 +1180,10 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | |||
890 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, | 1180 | .cleanup_scatter = ath6kl_sdio_cleanup_scatter, |
891 | .suspend = ath6kl_sdio_suspend, | 1181 | .suspend = ath6kl_sdio_suspend, |
892 | .resume = ath6kl_sdio_resume, | 1182 | .resume = ath6kl_sdio_resume, |
1183 | .diag_read32 = ath6kl_sdio_diag_read32, | ||
1184 | .diag_write32 = ath6kl_sdio_diag_write32, | ||
1185 | .bmi_read = ath6kl_sdio_bmi_read, | ||
1186 | .bmi_write = ath6kl_sdio_bmi_write, | ||
893 | .power_on = ath6kl_sdio_power_on, | 1187 | .power_on = ath6kl_sdio_power_on, |
894 | .power_off = ath6kl_sdio_power_off, | 1188 | .power_off = ath6kl_sdio_power_off, |
895 | .stop = ath6kl_sdio_stop, | 1189 | .stop = ath6kl_sdio_stop, |
@@ -958,6 +1252,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
958 | spin_lock_init(&ar_sdio->lock); | 1252 | spin_lock_init(&ar_sdio->lock); |
959 | spin_lock_init(&ar_sdio->scat_lock); | 1253 | spin_lock_init(&ar_sdio->scat_lock); |
960 | spin_lock_init(&ar_sdio->wr_async_lock); | 1254 | spin_lock_init(&ar_sdio->wr_async_lock); |
1255 | mutex_init(&ar_sdio->dma_buffer_mutex); | ||
961 | 1256 | ||
962 | INIT_LIST_HEAD(&ar_sdio->scat_req); | 1257 | INIT_LIST_HEAD(&ar_sdio->scat_req); |
963 | INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); | 1258 | INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); |
@@ -976,8 +1271,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func, | |||
976 | } | 1271 | } |
977 | 1272 | ||
978 | ar_sdio->ar = ar; | 1273 | ar_sdio->ar = ar; |
1274 | ar->hif_type = ATH6KL_HIF_TYPE_SDIO; | ||
979 | ar->hif_priv = ar_sdio; | 1275 | ar->hif_priv = ar_sdio; |
980 | ar->hif_ops = &ath6kl_sdio_ops; | 1276 | ar->hif_ops = &ath6kl_sdio_ops; |
1277 | ar->bmi.max_data_size = 256; | ||
981 | 1278 | ||
982 | ath6kl_sdio_set_mbox_info(ar); | 1279 | ath6kl_sdio_set_mbox_info(ar); |
983 | 1280 | ||
@@ -1027,13 +1324,15 @@ static void ath6kl_sdio_remove(struct sdio_func *func) | |||
1027 | static const struct sdio_device_id ath6kl_sdio_devices[] = { | 1324 | static const struct sdio_device_id ath6kl_sdio_devices[] = { |
1028 | {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0))}, | 1325 | {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0))}, |
1029 | {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))}, | 1326 | {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))}, |
1327 | {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x0))}, | ||
1328 | {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x1))}, | ||
1030 | {}, | 1329 | {}, |
1031 | }; | 1330 | }; |
1032 | 1331 | ||
1033 | MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); | 1332 | MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); |
1034 | 1333 | ||
1035 | static struct sdio_driver ath6kl_sdio_driver = { | 1334 | static struct sdio_driver ath6kl_sdio_driver = { |
1036 | .name = "ath6kl", | 1335 | .name = "ath6kl_sdio", |
1037 | .id_table = ath6kl_sdio_devices, | 1336 | .id_table = ath6kl_sdio_devices, |
1038 | .probe = ath6kl_sdio_probe, | 1337 | .probe = ath6kl_sdio_probe, |
1039 | .remove = ath6kl_sdio_remove, | 1338 | .remove = ath6kl_sdio_remove, |
@@ -1063,13 +1362,19 @@ MODULE_AUTHOR("Atheros Communications, Inc."); | |||
1063 | MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices"); | 1362 | MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices"); |
1064 | MODULE_LICENSE("Dual BSD/GPL"); | 1363 | MODULE_LICENSE("Dual BSD/GPL"); |
1065 | 1364 | ||
1066 | MODULE_FIRMWARE(AR6003_REV2_OTP_FILE); | 1365 | MODULE_FIRMWARE(AR6003_HW_2_0_OTP_FILE); |
1067 | MODULE_FIRMWARE(AR6003_REV2_FIRMWARE_FILE); | 1366 | MODULE_FIRMWARE(AR6003_HW_2_0_FIRMWARE_FILE); |
1068 | MODULE_FIRMWARE(AR6003_REV2_PATCH_FILE); | 1367 | MODULE_FIRMWARE(AR6003_HW_2_0_PATCH_FILE); |
1069 | MODULE_FIRMWARE(AR6003_REV2_BOARD_DATA_FILE); | 1368 | MODULE_FIRMWARE(AR6003_HW_2_0_BOARD_DATA_FILE); |
1070 | MODULE_FIRMWARE(AR6003_REV2_DEFAULT_BOARD_DATA_FILE); | 1369 | MODULE_FIRMWARE(AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE); |
1071 | MODULE_FIRMWARE(AR6003_REV3_OTP_FILE); | 1370 | MODULE_FIRMWARE(AR6003_HW_2_1_1_OTP_FILE); |
1072 | MODULE_FIRMWARE(AR6003_REV3_FIRMWARE_FILE); | 1371 | MODULE_FIRMWARE(AR6003_HW_2_1_1_FIRMWARE_FILE); |
1073 | MODULE_FIRMWARE(AR6003_REV3_PATCH_FILE); | 1372 | MODULE_FIRMWARE(AR6003_HW_2_1_1_PATCH_FILE); |
1074 | MODULE_FIRMWARE(AR6003_REV3_BOARD_DATA_FILE); | 1373 | MODULE_FIRMWARE(AR6003_HW_2_1_1_BOARD_DATA_FILE); |
1075 | MODULE_FIRMWARE(AR6003_REV3_DEFAULT_BOARD_DATA_FILE); | 1374 | MODULE_FIRMWARE(AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE); |
1375 | MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); | ||
1376 | MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); | ||
1377 | MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | ||
1378 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); | ||
1379 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | ||
1380 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index 687e2b350e8f..108a723a1085 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #define AR6003_BOARD_DATA_SZ 1024 | 20 | #define AR6003_BOARD_DATA_SZ 1024 |
21 | #define AR6003_BOARD_EXT_DATA_SZ 768 | 21 | #define AR6003_BOARD_EXT_DATA_SZ 768 |
22 | 22 | ||
23 | #define AR6004_BOARD_DATA_SZ 7168 | 23 | #define AR6004_BOARD_DATA_SZ 6144 |
24 | #define AR6004_BOARD_EXT_DATA_SZ 0 | 24 | #define AR6004_BOARD_EXT_DATA_SZ 0 |
25 | 25 | ||
26 | #define RESET_CONTROL_ADDRESS 0x00000000 | 26 | #define RESET_CONTROL_ADDRESS 0x00000000 |
@@ -334,20 +334,6 @@ struct host_interest { | |||
334 | (((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \ | 334 | (((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \ |
335 | (((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0)) | 335 | (((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0)) |
336 | 336 | ||
337 | #define AR6003_REV2_APP_LOAD_ADDRESS 0x543180 | ||
338 | #define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500 | ||
339 | #define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884 | ||
340 | #define AR6003_REV2_RAM_RESERVE_SIZE 6912 | ||
341 | |||
342 | #define AR6003_REV3_APP_LOAD_ADDRESS 0x545000 | ||
343 | #define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330 | ||
344 | #define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74 | ||
345 | #define AR6003_REV3_RAM_RESERVE_SIZE 512 | ||
346 | |||
347 | #define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400 | ||
348 | #define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000 | ||
349 | #define AR6004_REV1_RAM_RESERVE_SIZE 11264 | ||
350 | |||
351 | #define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 | 337 | #define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 |
352 | 338 | ||
353 | struct ath6kl_dbglog_buf { | 339 | struct ath6kl_dbglog_buf { |
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index d9cff2b950b1..506a3031a885 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -453,11 +453,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | |||
453 | set_bit(WMI_CTRL_EP_FULL, &ar->flag); | 453 | set_bit(WMI_CTRL_EP_FULL, &ar->flag); |
454 | spin_unlock_bh(&ar->lock); | 454 | spin_unlock_bh(&ar->lock); |
455 | ath6kl_err("wmi ctrl ep is full\n"); | 455 | ath6kl_err("wmi ctrl ep is full\n"); |
456 | goto stop_adhoc_netq; | 456 | return action; |
457 | } | 457 | } |
458 | 458 | ||
459 | if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG) | 459 | if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG) |
460 | goto stop_adhoc_netq; | 460 | return action; |
461 | 461 | ||
462 | /* | 462 | /* |
463 | * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for | 463 | * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for |
@@ -465,20 +465,18 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | |||
465 | */ | 465 | */ |
466 | if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] < | 466 | if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] < |
467 | ar->hiac_stream_active_pri && | 467 | ar->hiac_stream_active_pri && |
468 | ar->cookie_count <= MAX_HI_COOKIE_NUM) { | 468 | ar->cookie_count <= MAX_HI_COOKIE_NUM) |
469 | /* | 469 | /* |
470 | * Give preference to the highest priority stream by | 470 | * Give preference to the highest priority stream by |
471 | * dropping the packets which overflowed. | 471 | * dropping the packets which overflowed. |
472 | */ | 472 | */ |
473 | action = HTC_SEND_FULL_DROP; | 473 | action = HTC_SEND_FULL_DROP; |
474 | goto stop_adhoc_netq; | ||
475 | } | ||
476 | 474 | ||
477 | stop_adhoc_netq: | ||
478 | /* FIXME: Locking */ | 475 | /* FIXME: Locking */ |
479 | spin_lock_bh(&ar->list_lock); | 476 | spin_lock_bh(&ar->list_lock); |
480 | list_for_each_entry(vif, &ar->vif_list, list) { | 477 | list_for_each_entry(vif, &ar->vif_list, list) { |
481 | if (vif->nw_type == ADHOC_NETWORK) { | 478 | if (vif->nw_type == ADHOC_NETWORK || |
479 | action != HTC_SEND_FULL_DROP) { | ||
482 | spin_unlock_bh(&ar->list_lock); | 480 | spin_unlock_bh(&ar->list_lock); |
483 | 481 | ||
484 | spin_lock_bh(&vif->if_lock); | 482 | spin_lock_bh(&vif->if_lock); |
@@ -543,7 +541,7 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) | |||
543 | int status; | 541 | int status; |
544 | enum htc_endpoint_id eid; | 542 | enum htc_endpoint_id eid; |
545 | bool wake_event = false; | 543 | bool wake_event = false; |
546 | bool flushing[MAX_NUM_VIF] = {false}; | 544 | bool flushing[ATH6KL_VIF_MAX] = {false}; |
547 | u8 if_idx; | 545 | u8 if_idx; |
548 | struct ath6kl_vif *vif; | 546 | struct ath6kl_vif *vif; |
549 | 547 | ||
@@ -571,8 +569,6 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) | |||
571 | if (!skb || !skb->data) | 569 | if (!skb || !skb->data) |
572 | goto fatal; | 570 | goto fatal; |
573 | 571 | ||
574 | packet->buf = skb->data; | ||
575 | |||
576 | __skb_queue_tail(&skb_queue, skb); | 572 | __skb_queue_tail(&skb_queue, skb); |
577 | 573 | ||
578 | if (!status && (packet->act_len != skb->len)) | 574 | if (!status && (packet->act_len != skb->len)) |
@@ -593,10 +589,10 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) | |||
593 | 589 | ||
594 | if (eid == ar->ctrl_ep) { | 590 | if (eid == ar->ctrl_ep) { |
595 | if_idx = wmi_cmd_hdr_get_if_idx( | 591 | if_idx = wmi_cmd_hdr_get_if_idx( |
596 | (struct wmi_cmd_hdr *) skb->data); | 592 | (struct wmi_cmd_hdr *) packet->buf); |
597 | } else { | 593 | } else { |
598 | if_idx = wmi_data_hdr_get_if_idx( | 594 | if_idx = wmi_data_hdr_get_if_idx( |
599 | (struct wmi_data_hdr *) skb->data); | 595 | (struct wmi_data_hdr *) packet->buf); |
600 | } | 596 | } |
601 | 597 | ||
602 | vif = ath6kl_get_vif_by_index(ar, if_idx); | 598 | vif = ath6kl_get_vif_by_index(ar, if_idx); |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c new file mode 100644 index 000000000000..e3cf397fcafe --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | |||
20 | #include "debug.h" | ||
21 | #include "core.h" | ||
22 | |||
23 | /* usb device object */ | ||
24 | struct ath6kl_usb { | ||
25 | struct usb_device *udev; | ||
26 | struct usb_interface *interface; | ||
27 | u8 *diag_cmd_buffer; | ||
28 | u8 *diag_resp_buffer; | ||
29 | struct ath6kl *ar; | ||
30 | }; | ||
31 | |||
32 | /* diagnostic command defnitions */ | ||
33 | #define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1 | ||
34 | #define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2 | ||
35 | #define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3 | ||
36 | #define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4 | ||
37 | |||
38 | #define ATH6KL_USB_CTRL_DIAG_CC_READ 0 | ||
39 | #define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1 | ||
40 | |||
41 | struct ath6kl_usb_ctrl_diag_cmd_write { | ||
42 | __le32 cmd; | ||
43 | __le32 address; | ||
44 | __le32 value; | ||
45 | __le32 _pad[1]; | ||
46 | } __packed; | ||
47 | |||
48 | struct ath6kl_usb_ctrl_diag_cmd_read { | ||
49 | __le32 cmd; | ||
50 | __le32 address; | ||
51 | } __packed; | ||
52 | |||
53 | struct ath6kl_usb_ctrl_diag_resp_read { | ||
54 | __le32 value; | ||
55 | } __packed; | ||
56 | |||
57 | #define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)) | ||
58 | #define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read)) | ||
59 | |||
60 | static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) | ||
61 | { | ||
62 | usb_set_intfdata(ar_usb->interface, NULL); | ||
63 | |||
64 | kfree(ar_usb->diag_cmd_buffer); | ||
65 | kfree(ar_usb->diag_resp_buffer); | ||
66 | |||
67 | kfree(ar_usb); | ||
68 | } | ||
69 | |||
70 | static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) | ||
71 | { | ||
72 | struct ath6kl_usb *ar_usb = NULL; | ||
73 | struct usb_device *dev = interface_to_usbdev(interface); | ||
74 | int status = 0; | ||
75 | |||
76 | ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL); | ||
77 | if (ar_usb == NULL) | ||
78 | goto fail_ath6kl_usb_create; | ||
79 | |||
80 | memset(ar_usb, 0, sizeof(struct ath6kl_usb)); | ||
81 | usb_set_intfdata(interface, ar_usb); | ||
82 | ar_usb->udev = dev; | ||
83 | ar_usb->interface = interface; | ||
84 | |||
85 | ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL); | ||
86 | if (ar_usb->diag_cmd_buffer == NULL) { | ||
87 | status = -ENOMEM; | ||
88 | goto fail_ath6kl_usb_create; | ||
89 | } | ||
90 | |||
91 | ar_usb->diag_resp_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_RESP, | ||
92 | GFP_KERNEL); | ||
93 | if (ar_usb->diag_resp_buffer == NULL) { | ||
94 | status = -ENOMEM; | ||
95 | goto fail_ath6kl_usb_create; | ||
96 | } | ||
97 | |||
98 | fail_ath6kl_usb_create: | ||
99 | if (status != 0) { | ||
100 | ath6kl_usb_destroy(ar_usb); | ||
101 | ar_usb = NULL; | ||
102 | } | ||
103 | return ar_usb; | ||
104 | } | ||
105 | |||
106 | static void ath6kl_usb_device_detached(struct usb_interface *interface) | ||
107 | { | ||
108 | struct ath6kl_usb *ar_usb; | ||
109 | |||
110 | ar_usb = usb_get_intfdata(interface); | ||
111 | if (ar_usb == NULL) | ||
112 | return; | ||
113 | |||
114 | ath6kl_stop_txrx(ar_usb->ar); | ||
115 | |||
116 | ath6kl_core_cleanup(ar_usb->ar); | ||
117 | |||
118 | ath6kl_usb_destroy(ar_usb); | ||
119 | } | ||
120 | |||
121 | static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, | ||
122 | u8 req, u16 value, u16 index, void *data, | ||
123 | u32 size) | ||
124 | { | ||
125 | u8 *buf = NULL; | ||
126 | int ret; | ||
127 | |||
128 | if (size > 0) { | ||
129 | buf = kmalloc(size, GFP_KERNEL); | ||
130 | if (buf == NULL) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | memcpy(buf, data, size); | ||
134 | } | ||
135 | |||
136 | /* note: if successful returns number of bytes transfered */ | ||
137 | ret = usb_control_msg(ar_usb->udev, | ||
138 | usb_sndctrlpipe(ar_usb->udev, 0), | ||
139 | req, | ||
140 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
141 | USB_RECIP_DEVICE, value, index, buf, | ||
142 | size, 1000); | ||
143 | |||
144 | if (ret < 0) { | ||
145 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | ||
146 | __func__, ret); | ||
147 | } | ||
148 | |||
149 | kfree(buf); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, | ||
155 | u8 req, u16 value, u16 index, void *data, | ||
156 | u32 size) | ||
157 | { | ||
158 | u8 *buf = NULL; | ||
159 | int ret; | ||
160 | |||
161 | if (size > 0) { | ||
162 | buf = kmalloc(size, GFP_KERNEL); | ||
163 | if (buf == NULL) | ||
164 | return -ENOMEM; | ||
165 | } | ||
166 | |||
167 | /* note: if successful returns number of bytes transfered */ | ||
168 | ret = usb_control_msg(ar_usb->udev, | ||
169 | usb_rcvctrlpipe(ar_usb->udev, 0), | ||
170 | req, | ||
171 | USB_DIR_IN | USB_TYPE_VENDOR | | ||
172 | USB_RECIP_DEVICE, value, index, buf, | ||
173 | size, 2 * HZ); | ||
174 | |||
175 | if (ret < 0) { | ||
176 | ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", | ||
177 | __func__, ret); | ||
178 | } | ||
179 | |||
180 | memcpy((u8 *) data, buf, size); | ||
181 | |||
182 | kfree(buf); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int ath6kl_usb_ctrl_msg_exchange(struct ath6kl_usb *ar_usb, | ||
188 | u8 req_val, u8 *req_buf, u32 req_len, | ||
189 | u8 resp_val, u8 *resp_buf, u32 *resp_len) | ||
190 | { | ||
191 | int ret; | ||
192 | |||
193 | /* send command */ | ||
194 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0, | ||
195 | req_buf, req_len); | ||
196 | |||
197 | if (ret != 0) | ||
198 | return ret; | ||
199 | |||
200 | if (resp_buf == NULL) { | ||
201 | /* no expected response */ | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | /* get response */ | ||
206 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0, | ||
207 | resp_buf, *resp_len); | ||
208 | |||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) | ||
213 | { | ||
214 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
215 | struct ath6kl_usb_ctrl_diag_resp_read *resp; | ||
216 | struct ath6kl_usb_ctrl_diag_cmd_read *cmd; | ||
217 | u32 resp_len; | ||
218 | int ret; | ||
219 | |||
220 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_read *) ar_usb->diag_cmd_buffer; | ||
221 | |||
222 | memset(cmd, 0, sizeof(*cmd)); | ||
223 | cmd->cmd = ATH6KL_USB_CTRL_DIAG_CC_READ; | ||
224 | cmd->address = cpu_to_le32(address); | ||
225 | resp_len = sizeof(*resp); | ||
226 | |||
227 | ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, | ||
228 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | ||
229 | (u8 *) cmd, | ||
230 | sizeof(struct ath6kl_usb_ctrl_diag_cmd_write), | ||
231 | ATH6KL_USB_CONTROL_REQ_DIAG_RESP, | ||
232 | ar_usb->diag_resp_buffer, &resp_len); | ||
233 | |||
234 | if (ret) | ||
235 | return ret; | ||
236 | |||
237 | resp = (struct ath6kl_usb_ctrl_diag_resp_read *) | ||
238 | ar_usb->diag_resp_buffer; | ||
239 | |||
240 | *data = le32_to_cpu(resp->value); | ||
241 | |||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) | ||
246 | { | ||
247 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
248 | struct ath6kl_usb_ctrl_diag_cmd_write *cmd; | ||
249 | |||
250 | cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; | ||
251 | |||
252 | memset(cmd, 0, sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)); | ||
253 | cmd->cmd = cpu_to_le32(ATH6KL_USB_CTRL_DIAG_CC_WRITE); | ||
254 | cmd->address = cpu_to_le32(address); | ||
255 | cmd->value = data; | ||
256 | |||
257 | return ath6kl_usb_ctrl_msg_exchange(ar_usb, | ||
258 | ATH6KL_USB_CONTROL_REQ_DIAG_CMD, | ||
259 | (u8 *) cmd, | ||
260 | sizeof(*cmd), | ||
261 | 0, NULL, NULL); | ||
262 | |||
263 | } | ||
264 | |||
265 | static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) | ||
266 | { | ||
267 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
268 | int ret; | ||
269 | |||
270 | /* get response */ | ||
271 | ret = ath6kl_usb_submit_ctrl_in(ar_usb, | ||
272 | ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, | ||
273 | 0, 0, buf, len); | ||
274 | if (ret != 0) { | ||
275 | ath6kl_err("Unable to read the bmi data from the device: %d\n", | ||
276 | ret); | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) | ||
284 | { | ||
285 | struct ath6kl_usb *ar_usb = ar->hif_priv; | ||
286 | int ret; | ||
287 | |||
288 | /* send command */ | ||
289 | ret = ath6kl_usb_submit_ctrl_out(ar_usb, | ||
290 | ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, | ||
291 | 0, 0, buf, len); | ||
292 | if (ret != 0) { | ||
293 | ath6kl_err("unable to send the bmi data to the device: %d\n", | ||
294 | ret); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int ath6kl_usb_power_on(struct ath6kl *ar) | ||
302 | { | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int ath6kl_usb_power_off(struct ath6kl *ar) | ||
307 | { | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { | ||
312 | .diag_read32 = ath6kl_usb_diag_read32, | ||
313 | .diag_write32 = ath6kl_usb_diag_write32, | ||
314 | .bmi_read = ath6kl_usb_bmi_read, | ||
315 | .bmi_write = ath6kl_usb_bmi_write, | ||
316 | .power_on = ath6kl_usb_power_on, | ||
317 | .power_off = ath6kl_usb_power_off, | ||
318 | }; | ||
319 | |||
320 | /* ath6kl usb driver registered functions */ | ||
321 | static int ath6kl_usb_probe(struct usb_interface *interface, | ||
322 | const struct usb_device_id *id) | ||
323 | { | ||
324 | struct usb_device *dev = interface_to_usbdev(interface); | ||
325 | struct ath6kl *ar; | ||
326 | struct ath6kl_usb *ar_usb = NULL; | ||
327 | int vendor_id, product_id; | ||
328 | int ret = 0; | ||
329 | |||
330 | usb_get_dev(dev); | ||
331 | |||
332 | vendor_id = le16_to_cpu(dev->descriptor.idVendor); | ||
333 | product_id = le16_to_cpu(dev->descriptor.idProduct); | ||
334 | |||
335 | ath6kl_dbg(ATH6KL_DBG_USB, "vendor_id = %04x\n", vendor_id); | ||
336 | ath6kl_dbg(ATH6KL_DBG_USB, "product_id = %04x\n", product_id); | ||
337 | |||
338 | if (interface->cur_altsetting) | ||
339 | ath6kl_dbg(ATH6KL_DBG_USB, "USB Interface %d\n", | ||
340 | interface->cur_altsetting->desc.bInterfaceNumber); | ||
341 | |||
342 | |||
343 | if (dev->speed == USB_SPEED_HIGH) | ||
344 | ath6kl_dbg(ATH6KL_DBG_USB, "USB 2.0 Host\n"); | ||
345 | else | ||
346 | ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n"); | ||
347 | |||
348 | ar_usb = ath6kl_usb_create(interface); | ||
349 | |||
350 | if (ar_usb == NULL) { | ||
351 | ret = -ENOMEM; | ||
352 | goto err_usb_put; | ||
353 | } | ||
354 | |||
355 | ar = ath6kl_core_alloc(&ar_usb->udev->dev); | ||
356 | if (ar == NULL) { | ||
357 | ath6kl_err("Failed to alloc ath6kl core\n"); | ||
358 | ret = -ENOMEM; | ||
359 | goto err_usb_destroy; | ||
360 | } | ||
361 | |||
362 | ar->hif_priv = ar_usb; | ||
363 | ar->hif_type = ATH6KL_HIF_TYPE_USB; | ||
364 | ar->hif_ops = &ath6kl_usb_ops; | ||
365 | ar->mbox_info.block_size = 16; | ||
366 | ar->bmi.max_data_size = 252; | ||
367 | |||
368 | ar_usb->ar = ar; | ||
369 | |||
370 | ret = ath6kl_core_init(ar); | ||
371 | if (ret) { | ||
372 | ath6kl_err("Failed to init ath6kl core: %d\n", ret); | ||
373 | goto err_core_free; | ||
374 | } | ||
375 | |||
376 | return ret; | ||
377 | |||
378 | err_core_free: | ||
379 | ath6kl_core_free(ar); | ||
380 | err_usb_destroy: | ||
381 | ath6kl_usb_destroy(ar_usb); | ||
382 | err_usb_put: | ||
383 | usb_put_dev(dev); | ||
384 | |||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | static void ath6kl_usb_remove(struct usb_interface *interface) | ||
389 | { | ||
390 | usb_put_dev(interface_to_usbdev(interface)); | ||
391 | ath6kl_usb_device_detached(interface); | ||
392 | } | ||
393 | |||
394 | /* table of devices that work with this driver */ | ||
395 | static struct usb_device_id ath6kl_usb_ids[] = { | ||
396 | {USB_DEVICE(0x0cf3, 0x9374)}, | ||
397 | { /* Terminating entry */ }, | ||
398 | }; | ||
399 | |||
400 | MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids); | ||
401 | |||
402 | static struct usb_driver ath6kl_usb_driver = { | ||
403 | .name = "ath6kl_usb", | ||
404 | .probe = ath6kl_usb_probe, | ||
405 | .disconnect = ath6kl_usb_remove, | ||
406 | .id_table = ath6kl_usb_ids, | ||
407 | }; | ||
408 | |||
409 | static int ath6kl_usb_init(void) | ||
410 | { | ||
411 | usb_register(&ath6kl_usb_driver); | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static void ath6kl_usb_exit(void) | ||
416 | { | ||
417 | usb_deregister(&ath6kl_usb_driver); | ||
418 | } | ||
419 | |||
420 | module_init(ath6kl_usb_init); | ||
421 | module_exit(ath6kl_usb_exit); | ||
422 | |||
423 | MODULE_AUTHOR("Atheros Communications, Inc."); | ||
424 | MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices"); | ||
425 | MODULE_LICENSE("Dual BSD/GPL"); | ||
426 | MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); | ||
427 | MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); | ||
428 | MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | ||
429 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); | ||
430 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | ||
431 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 922344d3b262..f6f2aa27fc20 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -85,7 +85,7 @@ struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx) | |||
85 | { | 85 | { |
86 | struct ath6kl_vif *vif, *found = NULL; | 86 | struct ath6kl_vif *vif, *found = NULL; |
87 | 87 | ||
88 | if (WARN_ON(if_idx > (MAX_NUM_VIF - 1))) | 88 | if (WARN_ON(if_idx > (ar->vif_max - 1))) |
89 | return NULL; | 89 | return NULL; |
90 | 90 | ||
91 | /* FIXME: Locking */ | 91 | /* FIXME: Locking */ |
@@ -187,7 +187,7 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, | |||
187 | struct wmi_data_hdr *data_hdr; | 187 | struct wmi_data_hdr *data_hdr; |
188 | int ret; | 188 | int ret; |
189 | 189 | ||
190 | if (WARN_ON(skb == NULL || (if_idx > MAX_NUM_VIF - 1))) | 190 | if (WARN_ON(skb == NULL || (if_idx > wmi->parent_dev->vif_max - 1))) |
191 | return -EINVAL; | 191 | return -EINVAL; |
192 | 192 | ||
193 | if (tx_meta_info) { | 193 | if (tx_meta_info) { |
@@ -977,6 +977,13 @@ static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
977 | return 0; | 977 | return 0; |
978 | } | 978 | } |
979 | 979 | ||
980 | void ath6kl_wmi_sscan_timer(unsigned long ptr) | ||
981 | { | ||
982 | struct ath6kl_vif *vif = (struct ath6kl_vif *) ptr; | ||
983 | |||
984 | cfg80211_sched_scan_results(vif->ar->wiphy); | ||
985 | } | ||
986 | |||
980 | static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, | 987 | static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, |
981 | struct ath6kl_vif *vif) | 988 | struct ath6kl_vif *vif) |
982 | { | 989 | { |
@@ -1066,6 +1073,21 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
1066 | return -ENOMEM; | 1073 | return -ENOMEM; |
1067 | cfg80211_put_bss(bss); | 1074 | cfg80211_put_bss(bss); |
1068 | 1075 | ||
1076 | /* | ||
1077 | * Firmware doesn't return any event when scheduled scan has | ||
1078 | * finished, so we need to use a timer to find out when there are | ||
1079 | * no more results. | ||
1080 | * | ||
1081 | * The timer is started from the first bss info received, otherwise | ||
1082 | * the timer would not ever fire if the scan interval is short | ||
1083 | * enough. | ||
1084 | */ | ||
1085 | if (ar->state == ATH6KL_STATE_SCHED_SCAN && | ||
1086 | !timer_pending(&vif->sched_scan_timer)) { | ||
1087 | mod_timer(&vif->sched_scan_timer, jiffies + | ||
1088 | msecs_to_jiffies(ATH6KL_SCHED_SCAN_RESULT_DELAY)); | ||
1089 | } | ||
1090 | |||
1069 | return 0; | 1091 | return 0; |
1070 | } | 1092 | } |
1071 | 1093 | ||
@@ -1620,7 +1642,7 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb, | |||
1620 | int ret; | 1642 | int ret; |
1621 | u16 info1; | 1643 | u16 info1; |
1622 | 1644 | ||
1623 | if (WARN_ON(skb == NULL || (if_idx > (MAX_NUM_VIF - 1)))) | 1645 | if (WARN_ON(skb == NULL || (if_idx > (wmi->parent_dev->vif_max - 1)))) |
1624 | return -EINVAL; | 1646 | return -EINVAL; |
1625 | 1647 | ||
1626 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n", | 1648 | ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n", |
@@ -1682,7 +1704,8 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx, | |||
1682 | u8 pairwise_crypto_len, | 1704 | u8 pairwise_crypto_len, |
1683 | enum crypto_type group_crypto, | 1705 | enum crypto_type group_crypto, |
1684 | u8 group_crypto_len, int ssid_len, u8 *ssid, | 1706 | u8 group_crypto_len, int ssid_len, u8 *ssid, |
1685 | u8 *bssid, u16 channel, u32 ctrl_flags) | 1707 | u8 *bssid, u16 channel, u32 ctrl_flags, |
1708 | u8 nw_subtype) | ||
1686 | { | 1709 | { |
1687 | struct sk_buff *skb; | 1710 | struct sk_buff *skb; |
1688 | struct wmi_connect_cmd *cc; | 1711 | struct wmi_connect_cmd *cc; |
@@ -1722,6 +1745,7 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx, | |||
1722 | cc->grp_crypto_len = group_crypto_len; | 1745 | cc->grp_crypto_len = group_crypto_len; |
1723 | cc->ch = cpu_to_le16(channel); | 1746 | cc->ch = cpu_to_le16(channel); |
1724 | cc->ctrl_flags = cpu_to_le32(ctrl_flags); | 1747 | cc->ctrl_flags = cpu_to_le32(ctrl_flags); |
1748 | cc->nw_subtype = nw_subtype; | ||
1725 | 1749 | ||
1726 | if (bssid != NULL) | 1750 | if (bssid != NULL) |
1727 | memcpy(cc->bssid, bssid, ETH_ALEN); | 1751 | memcpy(cc->bssid, bssid, ETH_ALEN); |
@@ -1774,6 +1798,72 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx) | |||
1774 | return ret; | 1798 | return ret; |
1775 | } | 1799 | } |
1776 | 1800 | ||
1801 | int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | ||
1802 | enum wmi_scan_type scan_type, | ||
1803 | u32 force_fgscan, u32 is_legacy, | ||
1804 | u32 home_dwell_time, u32 force_scan_interval, | ||
1805 | s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates) | ||
1806 | { | ||
1807 | struct sk_buff *skb; | ||
1808 | struct wmi_begin_scan_cmd *sc; | ||
1809 | s8 size; | ||
1810 | int i, band, ret; | ||
1811 | struct ath6kl *ar = wmi->parent_dev; | ||
1812 | int num_rates; | ||
1813 | |||
1814 | size = sizeof(struct wmi_begin_scan_cmd); | ||
1815 | |||
1816 | if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN)) | ||
1817 | return -EINVAL; | ||
1818 | |||
1819 | if (num_chan > WMI_MAX_CHANNELS) | ||
1820 | return -EINVAL; | ||
1821 | |||
1822 | if (num_chan) | ||
1823 | size += sizeof(u16) * (num_chan - 1); | ||
1824 | |||
1825 | skb = ath6kl_wmi_get_new_buf(size); | ||
1826 | if (!skb) | ||
1827 | return -ENOMEM; | ||
1828 | |||
1829 | sc = (struct wmi_begin_scan_cmd *) skb->data; | ||
1830 | sc->scan_type = scan_type; | ||
1831 | sc->force_fg_scan = cpu_to_le32(force_fgscan); | ||
1832 | sc->is_legacy = cpu_to_le32(is_legacy); | ||
1833 | sc->home_dwell_time = cpu_to_le32(home_dwell_time); | ||
1834 | sc->force_scan_intvl = cpu_to_le32(force_scan_interval); | ||
1835 | sc->no_cck = cpu_to_le32(no_cck); | ||
1836 | sc->num_ch = num_chan; | ||
1837 | |||
1838 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1839 | struct ieee80211_supported_band *sband = | ||
1840 | ar->wiphy->bands[band]; | ||
1841 | u32 ratemask = rates[band]; | ||
1842 | u8 *supp_rates = sc->supp_rates[band].rates; | ||
1843 | num_rates = 0; | ||
1844 | |||
1845 | for (i = 0; i < sband->n_bitrates; i++) { | ||
1846 | if ((BIT(i) & ratemask) == 0) | ||
1847 | continue; /* skip rate */ | ||
1848 | supp_rates[num_rates++] = | ||
1849 | (u8) (sband->bitrates[i].bitrate / 5); | ||
1850 | } | ||
1851 | sc->supp_rates[band].nrates = num_rates; | ||
1852 | } | ||
1853 | |||
1854 | for (i = 0; i < num_chan; i++) | ||
1855 | sc->ch_list[i] = cpu_to_le16(ch_list[i]); | ||
1856 | |||
1857 | ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_BEGIN_SCAN_CMDID, | ||
1858 | NO_SYNC_WMIFLAG); | ||
1859 | |||
1860 | return ret; | ||
1861 | } | ||
1862 | |||
1863 | /* ath6kl_wmi_start_scan_cmd is to be deprecated. Use | ||
1864 | * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P | ||
1865 | * mgmt operations using station interface. | ||
1866 | */ | ||
1777 | int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx, | 1867 | int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx, |
1778 | enum wmi_scan_type scan_type, | 1868 | enum wmi_scan_type scan_type, |
1779 | u32 force_fgscan, u32 is_legacy, | 1869 | u32 force_fgscan, u32 is_legacy, |
@@ -2940,7 +3030,10 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, | |||
2940 | p = (struct wmi_set_appie_cmd *) skb->data; | 3030 | p = (struct wmi_set_appie_cmd *) skb->data; |
2941 | p->mgmt_frm_type = mgmt_frm_type; | 3031 | p->mgmt_frm_type = mgmt_frm_type; |
2942 | p->ie_len = ie_len; | 3032 | p->ie_len = ie_len; |
2943 | memcpy(p->ie_info, ie, ie_len); | 3033 | |
3034 | if (ie != NULL && ie_len > 0) | ||
3035 | memcpy(p->ie_info, ie, ie_len); | ||
3036 | |||
2944 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID, | 3037 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID, |
2945 | NO_SYNC_WMIFLAG); | 3038 | NO_SYNC_WMIFLAG); |
2946 | } | 3039 | } |
@@ -2981,6 +3074,10 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur) | |||
2981 | NO_SYNC_WMIFLAG); | 3074 | NO_SYNC_WMIFLAG); |
2982 | } | 3075 | } |
2983 | 3076 | ||
3077 | /* ath6kl_wmi_send_action_cmd is to be deprecated. Use | ||
3078 | * ath6kl_wmi_send_mgmt_cmd instead. The new function supports P2P | ||
3079 | * mgmt operations using station interface. | ||
3080 | */ | ||
2984 | int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, | 3081 | int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, |
2985 | u32 wait, const u8 *data, u16 data_len) | 3082 | u32 wait, const u8 *data, u16 data_len) |
2986 | { | 3083 | { |
@@ -3018,14 +3115,57 @@ int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, | |||
3018 | NO_SYNC_WMIFLAG); | 3115 | NO_SYNC_WMIFLAG); |
3019 | } | 3116 | } |
3020 | 3117 | ||
3118 | int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, | ||
3119 | u32 wait, const u8 *data, u16 data_len, | ||
3120 | u32 no_cck) | ||
3121 | { | ||
3122 | struct sk_buff *skb; | ||
3123 | struct wmi_send_mgmt_cmd *p; | ||
3124 | u8 *buf; | ||
3125 | |||
3126 | if (wait) | ||
3127 | return -EINVAL; /* Offload for wait not supported */ | ||
3128 | |||
3129 | buf = kmalloc(data_len, GFP_KERNEL); | ||
3130 | if (!buf) | ||
3131 | return -ENOMEM; | ||
3132 | |||
3133 | skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); | ||
3134 | if (!skb) { | ||
3135 | kfree(buf); | ||
3136 | return -ENOMEM; | ||
3137 | } | ||
3138 | |||
3139 | kfree(wmi->last_mgmt_tx_frame); | ||
3140 | memcpy(buf, data, data_len); | ||
3141 | wmi->last_mgmt_tx_frame = buf; | ||
3142 | wmi->last_mgmt_tx_frame_len = data_len; | ||
3143 | |||
3144 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " | ||
3145 | "len=%u\n", id, freq, wait, data_len); | ||
3146 | p = (struct wmi_send_mgmt_cmd *) skb->data; | ||
3147 | p->id = cpu_to_le32(id); | ||
3148 | p->freq = cpu_to_le32(freq); | ||
3149 | p->wait = cpu_to_le32(wait); | ||
3150 | p->no_cck = cpu_to_le32(no_cck); | ||
3151 | p->len = cpu_to_le16(data_len); | ||
3152 | memcpy(p->data, data, data_len); | ||
3153 | return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_MGMT_CMDID, | ||
3154 | NO_SYNC_WMIFLAG); | ||
3155 | } | ||
3156 | |||
3021 | int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, | 3157 | int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, |
3022 | const u8 *dst, const u8 *data, | 3158 | const u8 *dst, const u8 *data, |
3023 | u16 data_len) | 3159 | u16 data_len) |
3024 | { | 3160 | { |
3025 | struct sk_buff *skb; | 3161 | struct sk_buff *skb; |
3026 | struct wmi_p2p_probe_response_cmd *p; | 3162 | struct wmi_p2p_probe_response_cmd *p; |
3163 | size_t cmd_len = sizeof(*p) + data_len; | ||
3027 | 3164 | ||
3028 | skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); | 3165 | if (data_len == 0) |
3166 | cmd_len++; /* work around target minimum length requirement */ | ||
3167 | |||
3168 | skb = ath6kl_wmi_get_new_buf(cmd_len); | ||
3029 | if (!skb) | 3169 | if (!skb) |
3030 | return -ENOMEM; | 3170 | return -ENOMEM; |
3031 | 3171 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 76342d5a1906..42ac311eda4e 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -329,6 +329,10 @@ enum wmi_cmd_id { | |||
329 | WMI_SYNCHRONIZE_CMDID, | 329 | WMI_SYNCHRONIZE_CMDID, |
330 | WMI_CREATE_PSTREAM_CMDID, | 330 | WMI_CREATE_PSTREAM_CMDID, |
331 | WMI_DELETE_PSTREAM_CMDID, | 331 | WMI_DELETE_PSTREAM_CMDID, |
332 | /* WMI_START_SCAN_CMDID is to be deprecated. Use | ||
333 | * WMI_BEGIN_SCAN_CMDID instead. The new cmd supports P2P mgmt | ||
334 | * operations using station interface. | ||
335 | */ | ||
332 | WMI_START_SCAN_CMDID, | 336 | WMI_START_SCAN_CMDID, |
333 | WMI_SET_SCAN_PARAMS_CMDID, | 337 | WMI_SET_SCAN_PARAMS_CMDID, |
334 | WMI_SET_BSS_FILTER_CMDID, | 338 | WMI_SET_BSS_FILTER_CMDID, |
@@ -542,12 +546,61 @@ enum wmi_cmd_id { | |||
542 | WMI_GTK_OFFLOAD_OP_CMDID, | 546 | WMI_GTK_OFFLOAD_OP_CMDID, |
543 | WMI_REMAIN_ON_CHNL_CMDID, | 547 | WMI_REMAIN_ON_CHNL_CMDID, |
544 | WMI_CANCEL_REMAIN_ON_CHNL_CMDID, | 548 | WMI_CANCEL_REMAIN_ON_CHNL_CMDID, |
549 | /* WMI_SEND_ACTION_CMDID is to be deprecated. Use | ||
550 | * WMI_SEND_MGMT_CMDID instead. The new cmd supports P2P mgmt | ||
551 | * operations using station interface. | ||
552 | */ | ||
545 | WMI_SEND_ACTION_CMDID, | 553 | WMI_SEND_ACTION_CMDID, |
546 | WMI_PROBE_REQ_REPORT_CMDID, | 554 | WMI_PROBE_REQ_REPORT_CMDID, |
547 | WMI_DISABLE_11B_RATES_CMDID, | 555 | WMI_DISABLE_11B_RATES_CMDID, |
548 | WMI_SEND_PROBE_RESPONSE_CMDID, | 556 | WMI_SEND_PROBE_RESPONSE_CMDID, |
549 | WMI_GET_P2P_INFO_CMDID, | 557 | WMI_GET_P2P_INFO_CMDID, |
550 | WMI_AP_JOIN_BSS_CMDID, | 558 | WMI_AP_JOIN_BSS_CMDID, |
559 | |||
560 | WMI_SMPS_ENABLE_CMDID, | ||
561 | WMI_SMPS_CONFIG_CMDID, | ||
562 | WMI_SET_RATECTRL_PARM_CMDID, | ||
563 | /* LPL specific commands*/ | ||
564 | WMI_LPL_FORCE_ENABLE_CMDID, | ||
565 | WMI_LPL_SET_POLICY_CMDID, | ||
566 | WMI_LPL_GET_POLICY_CMDID, | ||
567 | WMI_LPL_GET_HWSTATE_CMDID, | ||
568 | WMI_LPL_SET_PARAMS_CMDID, | ||
569 | WMI_LPL_GET_PARAMS_CMDID, | ||
570 | |||
571 | WMI_SET_BUNDLE_PARAM_CMDID, | ||
572 | |||
573 | /*GreenTx specific commands*/ | ||
574 | |||
575 | WMI_GREENTX_PARAMS_CMDID, | ||
576 | |||
577 | WMI_RTT_MEASREQ_CMDID, | ||
578 | WMI_RTT_CAPREQ_CMDID, | ||
579 | WMI_RTT_STATUSREQ_CMDID, | ||
580 | |||
581 | /* WPS Commands */ | ||
582 | WMI_WPS_START_CMDID, | ||
583 | WMI_GET_WPS_STATUS_CMDID, | ||
584 | |||
585 | /* More P2P commands */ | ||
586 | WMI_SET_NOA_CMDID, | ||
587 | WMI_GET_NOA_CMDID, | ||
588 | WMI_SET_OPPPS_CMDID, | ||
589 | WMI_GET_OPPPS_CMDID, | ||
590 | WMI_ADD_PORT_CMDID, | ||
591 | WMI_DEL_PORT_CMDID, | ||
592 | |||
593 | /* 802.11w cmd */ | ||
594 | WMI_SET_RSN_CAP_CMDID, | ||
595 | WMI_GET_RSN_CAP_CMDID, | ||
596 | WMI_SET_IGTK_CMDID, | ||
597 | |||
598 | WMI_RX_FILTER_COALESCE_FILTER_OP_CMDID, | ||
599 | WMI_RX_FILTER_SET_FRAME_TEST_LIST_CMDID, | ||
600 | |||
601 | WMI_SEND_MGMT_CMDID, | ||
602 | WMI_BEGIN_SCAN_CMDID, | ||
603 | |||
551 | }; | 604 | }; |
552 | 605 | ||
553 | enum wmi_mgmt_frame_type { | 606 | enum wmi_mgmt_frame_type { |
@@ -567,6 +620,14 @@ enum network_type { | |||
567 | AP_NETWORK = 0x10, | 620 | AP_NETWORK = 0x10, |
568 | }; | 621 | }; |
569 | 622 | ||
623 | enum network_subtype { | ||
624 | SUBTYPE_NONE, | ||
625 | SUBTYPE_BT, | ||
626 | SUBTYPE_P2PDEV, | ||
627 | SUBTYPE_P2PCLIENT, | ||
628 | SUBTYPE_P2PGO, | ||
629 | }; | ||
630 | |||
570 | enum dot11_auth_mode { | 631 | enum dot11_auth_mode { |
571 | OPEN_AUTH = 0x01, | 632 | OPEN_AUTH = 0x01, |
572 | SHARED_AUTH = 0x02, | 633 | SHARED_AUTH = 0x02, |
@@ -639,6 +700,7 @@ struct wmi_connect_cmd { | |||
639 | __le16 ch; | 700 | __le16 ch; |
640 | u8 bssid[ETH_ALEN]; | 701 | u8 bssid[ETH_ALEN]; |
641 | __le32 ctrl_flags; | 702 | __le32 ctrl_flags; |
703 | u8 nw_subtype; | ||
642 | } __packed; | 704 | } __packed; |
643 | 705 | ||
644 | /* WMI_RECONNECT_CMDID */ | 706 | /* WMI_RECONNECT_CMDID */ |
@@ -726,7 +788,12 @@ enum wmi_scan_type { | |||
726 | WMI_SHORT_SCAN = 1, | 788 | WMI_SHORT_SCAN = 1, |
727 | }; | 789 | }; |
728 | 790 | ||
729 | struct wmi_start_scan_cmd { | 791 | struct wmi_supp_rates { |
792 | u8 nrates; | ||
793 | u8 rates[ATH6KL_RATE_MAXSIZE]; | ||
794 | }; | ||
795 | |||
796 | struct wmi_begin_scan_cmd { | ||
730 | __le32 force_fg_scan; | 797 | __le32 force_fg_scan; |
731 | 798 | ||
732 | /* for legacy cisco AP compatibility */ | 799 | /* for legacy cisco AP compatibility */ |
@@ -738,9 +805,15 @@ struct wmi_start_scan_cmd { | |||
738 | /* time interval between scans (msec) */ | 805 | /* time interval between scans (msec) */ |
739 | __le32 force_scan_intvl; | 806 | __le32 force_scan_intvl; |
740 | 807 | ||
808 | /* no CCK rates */ | ||
809 | __le32 no_cck; | ||
810 | |||
741 | /* enum wmi_scan_type */ | 811 | /* enum wmi_scan_type */ |
742 | u8 scan_type; | 812 | u8 scan_type; |
743 | 813 | ||
814 | /* Supported rates to advertise in the probe request frames */ | ||
815 | struct wmi_supp_rates supp_rates[IEEE80211_NUM_BANDS]; | ||
816 | |||
744 | /* how many channels follow */ | 817 | /* how many channels follow */ |
745 | u8 num_ch; | 818 | u8 num_ch; |
746 | 819 | ||
@@ -748,8 +821,31 @@ struct wmi_start_scan_cmd { | |||
748 | __le16 ch_list[1]; | 821 | __le16 ch_list[1]; |
749 | } __packed; | 822 | } __packed; |
750 | 823 | ||
751 | /* WMI_SET_SCAN_PARAMS_CMDID */ | 824 | /* wmi_start_scan_cmd is to be deprecated. Use |
752 | #define WMI_SHORTSCANRATIO_DEFAULT 3 | 825 | * wmi_begin_scan_cmd instead. The new structure supports P2P mgmt |
826 | * operations using station interface. | ||
827 | */ | ||
828 | struct wmi_start_scan_cmd { | ||
829 | __le32 force_fg_scan; | ||
830 | |||
831 | /* for legacy cisco AP compatibility */ | ||
832 | __le32 is_legacy; | ||
833 | |||
834 | /* max duration in the home channel(msec) */ | ||
835 | __le32 home_dwell_time; | ||
836 | |||
837 | /* time interval between scans (msec) */ | ||
838 | __le32 force_scan_intvl; | ||
839 | |||
840 | /* enum wmi_scan_type */ | ||
841 | u8 scan_type; | ||
842 | |||
843 | /* how many channels follow */ | ||
844 | u8 num_ch; | ||
845 | |||
846 | /* channels in Mhz */ | ||
847 | __le16 ch_list[1]; | ||
848 | } __packed; | ||
753 | 849 | ||
754 | /* | 850 | /* |
755 | * Warning: scan control flag value of 0xFF is used to disable | 851 | * Warning: scan control flag value of 0xFF is used to disable |
@@ -783,13 +879,6 @@ enum wmi_scan_ctrl_flags_bits { | |||
783 | ENABLE_SCAN_ABORT_EVENT = 0x40 | 879 | ENABLE_SCAN_ABORT_EVENT = 0x40 |
784 | }; | 880 | }; |
785 | 881 | ||
786 | #define DEFAULT_SCAN_CTRL_FLAGS \ | ||
787 | (CONNECT_SCAN_CTRL_FLAGS | \ | ||
788 | SCAN_CONNECTED_CTRL_FLAGS | \ | ||
789 | ACTIVE_SCAN_CTRL_FLAGS | \ | ||
790 | ROAM_SCAN_CTRL_FLAGS | \ | ||
791 | ENABLE_AUTO_CTRL_FLAGS) | ||
792 | |||
793 | struct wmi_scan_params_cmd { | 882 | struct wmi_scan_params_cmd { |
794 | /* sec */ | 883 | /* sec */ |
795 | __le16 fg_start_period; | 884 | __le16 fg_start_period; |
@@ -1818,7 +1907,7 @@ struct wmi_set_ip_cmd { | |||
1818 | } __packed; | 1907 | } __packed; |
1819 | 1908 | ||
1820 | enum ath6kl_wow_filters { | 1909 | enum ath6kl_wow_filters { |
1821 | WOW_FILTER_SSID = BIT(0), | 1910 | WOW_FILTER_SSID = BIT(1), |
1822 | WOW_FILTER_OPTION_MAGIC_PACKET = BIT(2), | 1911 | WOW_FILTER_OPTION_MAGIC_PACKET = BIT(2), |
1823 | WOW_FILTER_OPTION_EAP_REQ = BIT(3), | 1912 | WOW_FILTER_OPTION_EAP_REQ = BIT(3), |
1824 | WOW_FILTER_OPTION_PATTERNS = BIT(4), | 1913 | WOW_FILTER_OPTION_PATTERNS = BIT(4), |
@@ -1963,7 +2052,7 @@ struct wmi_tx_complete_event { | |||
1963 | * !!! Warning !!! | 2052 | * !!! Warning !!! |
1964 | * -Changing the following values needs compilation of both driver and firmware | 2053 | * -Changing the following values needs compilation of both driver and firmware |
1965 | */ | 2054 | */ |
1966 | #define AP_MAX_NUM_STA 8 | 2055 | #define AP_MAX_NUM_STA 10 |
1967 | 2056 | ||
1968 | /* Spl. AID used to set DTIM flag in the beacons */ | 2057 | /* Spl. AID used to set DTIM flag in the beacons */ |
1969 | #define MCAST_AID 0xFF | 2058 | #define MCAST_AID 0xFF |
@@ -2046,6 +2135,10 @@ struct wmi_remain_on_chnl_cmd { | |||
2046 | __le32 duration; | 2135 | __le32 duration; |
2047 | } __packed; | 2136 | } __packed; |
2048 | 2137 | ||
2138 | /* wmi_send_action_cmd is to be deprecated. Use | ||
2139 | * wmi_send_mgmt_cmd instead. The new structure supports P2P mgmt | ||
2140 | * operations using station interface. | ||
2141 | */ | ||
2049 | struct wmi_send_action_cmd { | 2142 | struct wmi_send_action_cmd { |
2050 | __le32 id; | 2143 | __le32 id; |
2051 | __le32 freq; | 2144 | __le32 freq; |
@@ -2054,6 +2147,15 @@ struct wmi_send_action_cmd { | |||
2054 | u8 data[0]; | 2147 | u8 data[0]; |
2055 | } __packed; | 2148 | } __packed; |
2056 | 2149 | ||
2150 | struct wmi_send_mgmt_cmd { | ||
2151 | __le32 id; | ||
2152 | __le32 freq; | ||
2153 | __le32 wait; | ||
2154 | __le32 no_cck; | ||
2155 | __le16 len; | ||
2156 | u8 data[0]; | ||
2157 | } __packed; | ||
2158 | |||
2057 | struct wmi_tx_status_event { | 2159 | struct wmi_tx_status_event { |
2058 | __le32 id; | 2160 | __le32 id; |
2059 | u8 ack_status; | 2161 | u8 ack_status; |
@@ -2242,7 +2344,8 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx, | |||
2242 | u8 pairwise_crypto_len, | 2344 | u8 pairwise_crypto_len, |
2243 | enum crypto_type group_crypto, | 2345 | enum crypto_type group_crypto, |
2244 | u8 group_crypto_len, int ssid_len, u8 *ssid, | 2346 | u8 group_crypto_len, int ssid_len, u8 *ssid, |
2245 | u8 *bssid, u16 channel, u32 ctrl_flags); | 2347 | u8 *bssid, u16 channel, u32 ctrl_flags, |
2348 | u8 nw_subtype); | ||
2246 | 2349 | ||
2247 | int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid, | 2350 | int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid, |
2248 | u16 channel); | 2351 | u16 channel); |
@@ -2252,6 +2355,14 @@ int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx, | |||
2252 | u32 force_fgscan, u32 is_legacy, | 2355 | u32 force_fgscan, u32 is_legacy, |
2253 | u32 home_dwell_time, u32 force_scan_interval, | 2356 | u32 home_dwell_time, u32 force_scan_interval, |
2254 | s8 num_chan, u16 *ch_list); | 2357 | s8 num_chan, u16 *ch_list); |
2358 | |||
2359 | int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | ||
2360 | enum wmi_scan_type scan_type, | ||
2361 | u32 force_fgscan, u32 is_legacy, | ||
2362 | u32 home_dwell_time, u32 force_scan_interval, | ||
2363 | s8 num_chan, u16 *ch_list, u32 no_cck, | ||
2364 | u32 *rates); | ||
2365 | |||
2255 | int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec, | 2366 | int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec, |
2256 | u16 fg_end_sec, u16 bg_sec, | 2367 | u16 fg_end_sec, u16 bg_sec, |
2257 | u16 minact_chdw_msec, u16 maxact_chdw_msec, | 2368 | u16 minact_chdw_msec, u16 maxact_chdw_msec, |
@@ -2346,6 +2457,10 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, | |||
2346 | int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, | 2457 | int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, |
2347 | u32 wait, const u8 *data, u16 data_len); | 2458 | u32 wait, const u8 *data, u16 data_len); |
2348 | 2459 | ||
2460 | int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, | ||
2461 | u32 wait, const u8 *data, u16 data_len, | ||
2462 | u32 no_cck); | ||
2463 | |||
2349 | int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, | 2464 | int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, |
2350 | const u8 *dst, const u8 *data, | 2465 | const u8 *dst, const u8 *data, |
2351 | u16 data_len); | 2466 | u16 data_len); |
@@ -2359,6 +2474,8 @@ int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx); | |||
2359 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, | 2474 | int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, |
2360 | const u8 *ie, u8 ie_len); | 2475 | const u8 *ie, u8 ie_len); |
2361 | 2476 | ||
2477 | void ath6kl_wmi_sscan_timer(unsigned long ptr); | ||
2478 | |||
2362 | struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx); | 2479 | struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx); |
2363 | void *ath6kl_wmi_init(struct ath6kl *devt); | 2480 | void *ath6kl_wmi_init(struct ath6kl *devt); |
2364 | void ath6kl_wmi_shutdown(struct wmi *wmi); | 2481 | void ath6kl_wmi_shutdown(struct wmi *wmi); |