Commit | Line | Data |
---|---|---|
fb9987d0 | 1 | /* |
5b68138e | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
fb9987d0 S |
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 | ||
78fa99ab | 17 | #include <asm/unaligned.h> |
fb9987d0 S |
18 | #include "htc.h" |
19 | ||
d0ee0ebe | 20 | /* identify firmware images */ |
ce18f391 SM |
21 | #define FIRMWARE_AR7010_1_1 "htc_7010.fw" |
22 | #define FIRMWARE_AR9271 "htc_9271.fw" | |
d0ee0ebe | 23 | |
d0ee0ebe JL |
24 | MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); |
25 | MODULE_FIRMWARE(FIRMWARE_AR9271); | |
26 | ||
fb9987d0 | 27 | static struct usb_device_id ath9k_hif_usb_ids[] = { |
4e63f768 S |
28 | { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ |
29 | { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ | |
4e63f768 | 30 | { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ |
4e63f768 S |
31 | { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ |
32 | { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ | |
33 | { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ | |
ac618d70 | 34 | { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */ |
32b08955 RM |
35 | { USB_DEVICE(0x13D3, 0x3348) }, /* Azurewave */ |
36 | { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */ | |
37 | { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */ | |
4e63f768 | 38 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ |
32b08955 | 39 | { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ |
452d7dd8 | 40 | { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ |
8c34559b | 41 | { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ |
0b5ead91 SM |
42 | |
43 | { USB_DEVICE(0x0cf3, 0x7015), | |
44 | .driver_info = AR9287_USB }, /* Atheros */ | |
64f12170 | 45 | { USB_DEVICE(0x1668, 0x1200), |
0b5ead91 SM |
46 | .driver_info = AR9287_USB }, /* Verizon */ |
47 | ||
48 | { USB_DEVICE(0x0cf3, 0x7010), | |
49 | .driver_info = AR9280_USB }, /* Atheros */ | |
50 | { USB_DEVICE(0x0846, 0x9018), | |
51 | .driver_info = AR9280_USB }, /* Netgear WNDA3200 */ | |
52 | { USB_DEVICE(0x083A, 0xA704), | |
53 | .driver_info = AR9280_USB }, /* SMC Networks */ | |
5cf6fa78 MSS |
54 | { USB_DEVICE(0x0411, 0x017f), |
55 | .driver_info = AR9280_USB }, /* Sony UWA-BR100 */ | |
0b5ead91 | 56 | |
36bcce43 SM |
57 | { USB_DEVICE(0x0cf3, 0x20ff), |
58 | .driver_info = STORAGE_DEVICE }, | |
59 | ||
fb9987d0 S |
60 | { }, |
61 | }; | |
62 | ||
63 | MODULE_DEVICE_TABLE(usb, ath9k_hif_usb_ids); | |
64 | ||
65 | static int __hif_usb_tx(struct hif_device_usb *hif_dev); | |
66 | ||
67 | static void hif_usb_regout_cb(struct urb *urb) | |
68 | { | |
69 | struct cmd_buf *cmd = (struct cmd_buf *)urb->context; | |
fb9987d0 S |
70 | |
71 | switch (urb->status) { | |
72 | case 0: | |
73 | break; | |
74 | case -ENOENT: | |
75 | case -ECONNRESET: | |
fb9987d0 S |
76 | case -ENODEV: |
77 | case -ESHUTDOWN: | |
6f0f2669 | 78 | goto free; |
fb9987d0 S |
79 | default: |
80 | break; | |
81 | } | |
82 | ||
83 | if (cmd) { | |
84 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | |
2f80194c | 85 | cmd->skb, true); |
fb9987d0 | 86 | kfree(cmd); |
fb9987d0 | 87 | } |
6f0f2669 S |
88 | |
89 | return; | |
90 | free: | |
0fa35a58 | 91 | kfree_skb(cmd->skb); |
6f0f2669 | 92 | kfree(cmd); |
fb9987d0 S |
93 | } |
94 | ||
95 | static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |
96 | struct sk_buff *skb) | |
97 | { | |
98 | struct urb *urb; | |
99 | struct cmd_buf *cmd; | |
100 | int ret = 0; | |
101 | ||
102 | urb = usb_alloc_urb(0, GFP_KERNEL); | |
103 | if (urb == NULL) | |
104 | return -ENOMEM; | |
105 | ||
106 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | |
107 | if (cmd == NULL) { | |
108 | usb_free_urb(urb); | |
109 | return -ENOMEM; | |
110 | } | |
111 | ||
112 | cmd->skb = skb; | |
113 | cmd->hif_dev = hif_dev; | |
114 | ||
4a0e8ecc RM |
115 | usb_fill_bulk_urb(urb, hif_dev->udev, |
116 | usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE), | |
fb9987d0 | 117 | skb->data, skb->len, |
4a0e8ecc | 118 | hif_usb_regout_cb, cmd); |
fb9987d0 | 119 | |
6f0f2669 | 120 | usb_anchor_urb(urb, &hif_dev->regout_submitted); |
fb9987d0 S |
121 | ret = usb_submit_urb(urb, GFP_KERNEL); |
122 | if (ret) { | |
6f0f2669 | 123 | usb_unanchor_urb(urb); |
fb9987d0 S |
124 | kfree(cmd); |
125 | } | |
6f0f2669 | 126 | usb_free_urb(urb); |
fb9987d0 S |
127 | |
128 | return ret; | |
129 | } | |
130 | ||
2f80194c SM |
131 | static void hif_usb_mgmt_cb(struct urb *urb) |
132 | { | |
133 | struct cmd_buf *cmd = (struct cmd_buf *)urb->context; | |
02c5172c | 134 | struct hif_device_usb *hif_dev; |
2f80194c SM |
135 | bool txok = true; |
136 | ||
137 | if (!cmd || !cmd->skb || !cmd->hif_dev) | |
138 | return; | |
139 | ||
02c5172c RM |
140 | hif_dev = cmd->hif_dev; |
141 | ||
2f80194c SM |
142 | switch (urb->status) { |
143 | case 0: | |
144 | break; | |
145 | case -ENOENT: | |
146 | case -ECONNRESET: | |
147 | case -ENODEV: | |
148 | case -ESHUTDOWN: | |
149 | txok = false; | |
150 | ||
151 | /* | |
152 | * If the URBs are being flushed, no need to complete | |
153 | * this packet. | |
154 | */ | |
155 | spin_lock(&hif_dev->tx.tx_lock); | |
156 | if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { | |
157 | spin_unlock(&hif_dev->tx.tx_lock); | |
158 | dev_kfree_skb_any(cmd->skb); | |
159 | kfree(cmd); | |
160 | return; | |
161 | } | |
162 | spin_unlock(&hif_dev->tx.tx_lock); | |
163 | ||
164 | break; | |
165 | default: | |
166 | txok = false; | |
167 | break; | |
168 | } | |
169 | ||
170 | skb_pull(cmd->skb, 4); | |
171 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | |
172 | cmd->skb, txok); | |
173 | kfree(cmd); | |
174 | } | |
175 | ||
176 | static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev, | |
177 | struct sk_buff *skb) | |
178 | { | |
179 | struct urb *urb; | |
180 | struct cmd_buf *cmd; | |
181 | int ret = 0; | |
182 | __le16 *hdr; | |
183 | ||
184 | urb = usb_alloc_urb(0, GFP_ATOMIC); | |
185 | if (urb == NULL) | |
186 | return -ENOMEM; | |
187 | ||
188 | cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); | |
189 | if (cmd == NULL) { | |
190 | usb_free_urb(urb); | |
191 | return -ENOMEM; | |
192 | } | |
193 | ||
194 | cmd->skb = skb; | |
195 | cmd->hif_dev = hif_dev; | |
196 | ||
197 | hdr = (__le16 *) skb_push(skb, 4); | |
198 | *hdr++ = cpu_to_le16(skb->len - 4); | |
199 | *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); | |
200 | ||
201 | usb_fill_bulk_urb(urb, hif_dev->udev, | |
202 | usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), | |
203 | skb->data, skb->len, | |
204 | hif_usb_mgmt_cb, cmd); | |
205 | ||
206 | usb_anchor_urb(urb, &hif_dev->mgmt_submitted); | |
207 | ret = usb_submit_urb(urb, GFP_ATOMIC); | |
208 | if (ret) { | |
209 | usb_unanchor_urb(urb); | |
210 | kfree(cmd); | |
211 | } | |
212 | usb_free_urb(urb); | |
213 | ||
214 | return ret; | |
215 | } | |
216 | ||
c11d8f89 S |
217 | static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, |
218 | struct sk_buff_head *list) | |
219 | { | |
220 | struct sk_buff *skb; | |
221 | ||
222 | while ((skb = __skb_dequeue(list)) != NULL) { | |
223 | dev_kfree_skb_any(skb); | |
b587fc81 SM |
224 | } |
225 | } | |
226 | ||
227 | static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, | |
228 | struct sk_buff_head *queue, | |
229 | bool txok) | |
230 | { | |
231 | struct sk_buff *skb; | |
232 | ||
233 | while ((skb = __skb_dequeue(queue)) != NULL) { | |
234 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | |
235 | skb, txok); | |
dfa8fc69 JL |
236 | if (txok) |
237 | TX_STAT_INC(skb_success); | |
238 | else | |
239 | TX_STAT_INC(skb_failed); | |
c11d8f89 S |
240 | } |
241 | } | |
242 | ||
fb9987d0 S |
243 | static void hif_usb_tx_cb(struct urb *urb) |
244 | { | |
245 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; | |
690e781c | 246 | struct hif_device_usb *hif_dev; |
b587fc81 | 247 | bool txok = true; |
fb9987d0 | 248 | |
690e781c | 249 | if (!tx_buf || !tx_buf->hif_dev) |
fb9987d0 S |
250 | return; |
251 | ||
690e781c DC |
252 | hif_dev = tx_buf->hif_dev; |
253 | ||
fb9987d0 S |
254 | switch (urb->status) { |
255 | case 0: | |
256 | break; | |
257 | case -ENOENT: | |
258 | case -ECONNRESET: | |
fb9987d0 S |
259 | case -ENODEV: |
260 | case -ESHUTDOWN: | |
b587fc81 | 261 | txok = false; |
ff8f59b5 SM |
262 | |
263 | /* | |
264 | * If the URBs are being flushed, no need to add this | |
265 | * URB to the free list. | |
266 | */ | |
267 | spin_lock(&hif_dev->tx.tx_lock); | |
268 | if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { | |
269 | spin_unlock(&hif_dev->tx.tx_lock); | |
b587fc81 | 270 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); |
ff8f59b5 SM |
271 | return; |
272 | } | |
273 | spin_unlock(&hif_dev->tx.tx_lock); | |
274 | ||
b587fc81 | 275 | break; |
fb9987d0 | 276 | default: |
b587fc81 | 277 | txok = false; |
fb9987d0 S |
278 | break; |
279 | } | |
280 | ||
b587fc81 | 281 | ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok); |
c11d8f89 | 282 | |
c11d8f89 S |
283 | /* Re-initialize the SKB queue */ |
284 | tx_buf->len = tx_buf->offset = 0; | |
285 | __skb_queue_head_init(&tx_buf->skb_queue); | |
286 | ||
287 | /* Add this TX buffer to the free list */ | |
288 | spin_lock(&hif_dev->tx.tx_lock); | |
289 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | |
290 | hif_dev->tx.tx_buf_cnt++; | |
291 | if (!(hif_dev->tx.flags & HIF_USB_TX_STOP)) | |
292 | __hif_usb_tx(hif_dev); /* Check for pending SKBs */ | |
293 | TX_STAT_INC(buf_completed); | |
294 | spin_unlock(&hif_dev->tx.tx_lock); | |
f8e1d080 ML |
295 | } |
296 | ||
fb9987d0 S |
297 | /* TX lock has to be taken */ |
298 | static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |
299 | { | |
300 | struct tx_buf *tx_buf = NULL; | |
301 | struct sk_buff *nskb = NULL; | |
302 | int ret = 0, i; | |
2c27392d | 303 | u16 tx_skb_cnt = 0; |
fb9987d0 | 304 | u8 *buf; |
2c27392d | 305 | __le16 *hdr; |
fb9987d0 S |
306 | |
307 | if (hif_dev->tx.tx_skb_cnt == 0) | |
308 | return 0; | |
309 | ||
310 | /* Check if a free TX buffer is available */ | |
311 | if (list_empty(&hif_dev->tx.tx_buf)) | |
312 | return 0; | |
313 | ||
314 | tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list); | |
c11d8f89 | 315 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending); |
fb9987d0 S |
316 | hif_dev->tx.tx_buf_cnt--; |
317 | ||
318 | tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); | |
319 | ||
320 | for (i = 0; i < tx_skb_cnt; i++) { | |
321 | nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue); | |
322 | ||
323 | /* Should never be NULL */ | |
324 | BUG_ON(!nskb); | |
325 | ||
326 | hif_dev->tx.tx_skb_cnt--; | |
327 | ||
328 | buf = tx_buf->buf; | |
329 | buf += tx_buf->offset; | |
2c27392d SM |
330 | hdr = (__le16 *)buf; |
331 | *hdr++ = cpu_to_le16(nskb->len); | |
332 | *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); | |
fb9987d0 S |
333 | buf += 4; |
334 | memcpy(buf, nskb->data, nskb->len); | |
335 | tx_buf->len = nskb->len + 4; | |
336 | ||
337 | if (i < (tx_skb_cnt - 1)) | |
338 | tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4; | |
339 | ||
340 | if (i == (tx_skb_cnt - 1)) | |
341 | tx_buf->len += tx_buf->offset; | |
342 | ||
343 | __skb_queue_tail(&tx_buf->skb_queue, nskb); | |
344 | TX_STAT_INC(skb_queued); | |
345 | } | |
346 | ||
347 | usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev, | |
348 | usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), | |
349 | tx_buf->buf, tx_buf->len, | |
350 | hif_usb_tx_cb, tx_buf); | |
351 | ||
352 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); | |
353 | if (ret) { | |
354 | tx_buf->len = tx_buf->offset = 0; | |
b587fc81 | 355 | ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false); |
fb9987d0 S |
356 | __skb_queue_head_init(&tx_buf->skb_queue); |
357 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | |
358 | hif_dev->tx.tx_buf_cnt++; | |
359 | } | |
360 | ||
361 | if (!ret) | |
362 | TX_STAT_INC(buf_queued); | |
363 | ||
364 | return ret; | |
365 | } | |
366 | ||
40dc9e4b | 367 | static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) |
fb9987d0 | 368 | { |
40dc9e4b | 369 | struct ath9k_htc_tx_ctl *tx_ctl; |
fb9987d0 | 370 | unsigned long flags; |
2f80194c | 371 | int ret = 0; |
fb9987d0 S |
372 | |
373 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | |
374 | ||
375 | if (hif_dev->tx.flags & HIF_USB_TX_STOP) { | |
376 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | |
377 | return -ENODEV; | |
378 | } | |
379 | ||
380 | /* Check if the max queue count has been reached */ | |
381 | if (hif_dev->tx.tx_skb_cnt > MAX_TX_BUF_NUM) { | |
382 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | |
383 | return -ENOMEM; | |
384 | } | |
385 | ||
2f80194c | 386 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
fb9987d0 | 387 | |
40dc9e4b SM |
388 | tx_ctl = HTC_SKB_CB(skb); |
389 | ||
2f80194c SM |
390 | /* Mgmt/Beacon frames don't use the TX buffer pool */ |
391 | if ((tx_ctl->type == ATH9K_HTC_MGMT) || | |
392 | (tx_ctl->type == ATH9K_HTC_BEACON)) { | |
393 | ret = hif_usb_send_mgmt(hif_dev, skb); | |
394 | } | |
395 | ||
396 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | |
397 | ||
398 | if ((tx_ctl->type == ATH9K_HTC_NORMAL) || | |
399 | (tx_ctl->type == ATH9K_HTC_AMPDU)) { | |
400 | __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); | |
401 | hif_dev->tx.tx_skb_cnt++; | |
402 | } | |
fb9987d0 S |
403 | |
404 | /* Check if AMPDUs have to be sent immediately */ | |
2f80194c | 405 | if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && |
fb9987d0 S |
406 | (hif_dev->tx.tx_skb_cnt < 2)) { |
407 | __hif_usb_tx(hif_dev); | |
408 | } | |
409 | ||
410 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | |
411 | ||
2f80194c | 412 | return ret; |
fb9987d0 S |
413 | } |
414 | ||
e1fe7c38 | 415 | static void hif_usb_start(void *hif_handle) |
fb9987d0 S |
416 | { |
417 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | |
418 | unsigned long flags; | |
419 | ||
420 | hif_dev->flags |= HIF_USB_START; | |
421 | ||
422 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | |
423 | hif_dev->tx.flags &= ~HIF_USB_TX_STOP; | |
424 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | |
425 | } | |
426 | ||
e1fe7c38 | 427 | static void hif_usb_stop(void *hif_handle) |
fb9987d0 S |
428 | { |
429 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | |
ff8f59b5 | 430 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; |
fb9987d0 S |
431 | unsigned long flags; |
432 | ||
433 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | |
b587fc81 | 434 | ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false); |
fb9987d0 S |
435 | hif_dev->tx.tx_skb_cnt = 0; |
436 | hif_dev->tx.flags |= HIF_USB_TX_STOP; | |
437 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | |
ff8f59b5 SM |
438 | |
439 | /* The pending URBs have to be canceled. */ | |
440 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, | |
441 | &hif_dev->tx.tx_pending, list) { | |
442 | usb_kill_urb(tx_buf->urb); | |
443 | } | |
2f80194c SM |
444 | |
445 | usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); | |
fb9987d0 S |
446 | } |
447 | ||
40dc9e4b | 448 | static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) |
fb9987d0 S |
449 | { |
450 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | |
451 | int ret = 0; | |
452 | ||
453 | switch (pipe_id) { | |
454 | case USB_WLAN_TX_PIPE: | |
40dc9e4b | 455 | ret = hif_usb_send_tx(hif_dev, skb); |
fb9987d0 S |
456 | break; |
457 | case USB_REG_OUT_PIPE: | |
458 | ret = hif_usb_send_regout(hif_dev, skb); | |
459 | break; | |
460 | default: | |
6335ed0f S |
461 | dev_err(&hif_dev->udev->dev, |
462 | "ath9k_htc: Invalid TX pipe: %d\n", pipe_id); | |
fb9987d0 S |
463 | ret = -EINVAL; |
464 | break; | |
465 | } | |
466 | ||
467 | return ret; | |
468 | } | |
469 | ||
84c9e164 SM |
470 | static inline bool check_index(struct sk_buff *skb, u8 idx) |
471 | { | |
472 | struct ath9k_htc_tx_ctl *tx_ctl; | |
473 | ||
474 | tx_ctl = HTC_SKB_CB(skb); | |
475 | ||
476 | if ((tx_ctl->type == ATH9K_HTC_AMPDU) && | |
477 | (tx_ctl->sta_idx == idx)) | |
478 | return true; | |
479 | ||
480 | return false; | |
481 | } | |
482 | ||
483 | static void hif_usb_sta_drain(void *hif_handle, u8 idx) | |
484 | { | |
485 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | |
486 | struct sk_buff *skb, *tmp; | |
487 | unsigned long flags; | |
488 | ||
489 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | |
490 | ||
491 | skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) { | |
492 | if (check_index(skb, idx)) { | |
493 | __skb_unlink(skb, &hif_dev->tx.tx_skb_queue); | |
494 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | |
495 | skb, false); | |
496 | hif_dev->tx.tx_skb_cnt--; | |
497 | TX_STAT_INC(skb_failed); | |
498 | } | |
499 | } | |
500 | ||
501 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | |
502 | } | |
503 | ||
fb9987d0 S |
504 | static struct ath9k_htc_hif hif_usb = { |
505 | .transport = ATH9K_HIF_USB, | |
506 | .name = "ath9k_hif_usb", | |
507 | ||
508 | .control_ul_pipe = USB_REG_OUT_PIPE, | |
509 | .control_dl_pipe = USB_REG_IN_PIPE, | |
510 | ||
511 | .start = hif_usb_start, | |
512 | .stop = hif_usb_stop, | |
84c9e164 | 513 | .sta_drain = hif_usb_sta_drain, |
fb9987d0 S |
514 | .send = hif_usb_send, |
515 | }; | |
516 | ||
517 | static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |
518 | struct sk_buff *skb) | |
519 | { | |
c503269a | 520 | struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; |
44b23b48 JP |
521 | int index = 0, i = 0, len = skb->len; |
522 | int rx_remain_len, rx_pkt_len; | |
523 | u16 pool_index = 0; | |
fb9987d0 S |
524 | u8 *ptr; |
525 | ||
46baa1a2 S |
526 | spin_lock(&hif_dev->rx_lock); |
527 | ||
fb9987d0 S |
528 | rx_remain_len = hif_dev->rx_remain_len; |
529 | rx_pkt_len = hif_dev->rx_transfer_len; | |
530 | ||
531 | if (rx_remain_len != 0) { | |
532 | struct sk_buff *remain_skb = hif_dev->remain_skb; | |
533 | ||
534 | if (remain_skb) { | |
535 | ptr = (u8 *) remain_skb->data; | |
536 | ||
537 | index = rx_remain_len; | |
538 | rx_remain_len -= hif_dev->rx_pad_len; | |
539 | ptr += rx_pkt_len; | |
540 | ||
541 | memcpy(ptr, skb->data, rx_remain_len); | |
542 | ||
543 | rx_pkt_len += rx_remain_len; | |
544 | hif_dev->rx_remain_len = 0; | |
545 | skb_put(remain_skb, rx_pkt_len); | |
546 | ||
547 | skb_pool[pool_index++] = remain_skb; | |
548 | ||
549 | } else { | |
550 | index = rx_remain_len; | |
551 | } | |
552 | } | |
553 | ||
46baa1a2 S |
554 | spin_unlock(&hif_dev->rx_lock); |
555 | ||
fb9987d0 | 556 | while (index < len) { |
44b23b48 JP |
557 | u16 pkt_len; |
558 | u16 pkt_tag; | |
559 | u16 pad_len; | |
560 | int chk_idx; | |
561 | ||
fb9987d0 S |
562 | ptr = (u8 *) skb->data; |
563 | ||
78fa99ab PR |
564 | pkt_len = get_unaligned_le16(ptr + index); |
565 | pkt_tag = get_unaligned_le16(ptr + index + 2); | |
fb9987d0 | 566 | |
44b23b48 JP |
567 | if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { |
568 | RX_STAT_INC(skb_dropped); | |
569 | return; | |
570 | } | |
571 | ||
572 | pad_len = 4 - (pkt_len & 0x3); | |
573 | if (pad_len == 4) | |
574 | pad_len = 0; | |
575 | ||
576 | chk_idx = index; | |
577 | index = index + 4 + pkt_len + pad_len; | |
578 | ||
579 | if (index > MAX_RX_BUF_SIZE) { | |
580 | spin_lock(&hif_dev->rx_lock); | |
581 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; | |
582 | hif_dev->rx_transfer_len = | |
583 | MAX_RX_BUF_SIZE - chk_idx - 4; | |
584 | hif_dev->rx_pad_len = pad_len; | |
585 | ||
586 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); | |
587 | if (!nskb) { | |
588 | dev_err(&hif_dev->udev->dev, | |
589 | "ath9k_htc: RX memory allocation error\n"); | |
46baa1a2 | 590 | spin_unlock(&hif_dev->rx_lock); |
44b23b48 | 591 | goto err; |
fb9987d0 | 592 | } |
44b23b48 JP |
593 | skb_reserve(nskb, 32); |
594 | RX_STAT_INC(skb_allocated); | |
595 | ||
596 | memcpy(nskb->data, &(skb->data[chk_idx+4]), | |
597 | hif_dev->rx_transfer_len); | |
598 | ||
599 | /* Record the buffer pointer */ | |
600 | hif_dev->remain_skb = nskb; | |
601 | spin_unlock(&hif_dev->rx_lock); | |
fb9987d0 | 602 | } else { |
44b23b48 JP |
603 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); |
604 | if (!nskb) { | |
605 | dev_err(&hif_dev->udev->dev, | |
606 | "ath9k_htc: RX memory allocation error\n"); | |
607 | goto err; | |
608 | } | |
609 | skb_reserve(nskb, 32); | |
610 | RX_STAT_INC(skb_allocated); | |
611 | ||
612 | memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); | |
613 | skb_put(nskb, pkt_len); | |
614 | skb_pool[pool_index++] = nskb; | |
fb9987d0 S |
615 | } |
616 | } | |
617 | ||
618 | err: | |
fb9987d0 S |
619 | for (i = 0; i < pool_index; i++) { |
620 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], | |
621 | skb_pool[i]->len, USB_WLAN_RX_PIPE); | |
622 | RX_STAT_INC(skb_completed); | |
623 | } | |
624 | } | |
625 | ||
626 | static void ath9k_hif_usb_rx_cb(struct urb *urb) | |
627 | { | |
628 | struct sk_buff *skb = (struct sk_buff *) urb->context; | |
b2767363 | 629 | struct hif_device_usb *hif_dev = |
fb9987d0 S |
630 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
631 | int ret; | |
632 | ||
6335ed0f S |
633 | if (!skb) |
634 | return; | |
635 | ||
fb9987d0 S |
636 | if (!hif_dev) |
637 | goto free; | |
638 | ||
639 | switch (urb->status) { | |
640 | case 0: | |
641 | break; | |
642 | case -ENOENT: | |
643 | case -ECONNRESET: | |
644 | case -ENODEV: | |
645 | case -ESHUTDOWN: | |
646 | goto free; | |
647 | default: | |
648 | goto resubmit; | |
649 | } | |
650 | ||
651 | if (likely(urb->actual_length != 0)) { | |
652 | skb_put(skb, urb->actual_length); | |
fb9987d0 | 653 | ath9k_hif_usb_rx_stream(hif_dev, skb); |
fb9987d0 S |
654 | } |
655 | ||
656 | resubmit: | |
657 | skb_reset_tail_pointer(skb); | |
658 | skb_trim(skb, 0); | |
659 | ||
6335ed0f | 660 | usb_anchor_urb(urb, &hif_dev->rx_submitted); |
fb9987d0 | 661 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
6335ed0f S |
662 | if (ret) { |
663 | usb_unanchor_urb(urb); | |
fb9987d0 | 664 | goto free; |
6335ed0f | 665 | } |
fb9987d0 S |
666 | |
667 | return; | |
668 | free: | |
f28a7b30 | 669 | kfree_skb(skb); |
fb9987d0 S |
670 | } |
671 | ||
672 | static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |
673 | { | |
674 | struct sk_buff *skb = (struct sk_buff *) urb->context; | |
675 | struct sk_buff *nskb; | |
b2767363 | 676 | struct hif_device_usb *hif_dev = |
fb9987d0 S |
677 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
678 | int ret; | |
679 | ||
6335ed0f S |
680 | if (!skb) |
681 | return; | |
682 | ||
fb9987d0 S |
683 | if (!hif_dev) |
684 | goto free; | |
685 | ||
686 | switch (urb->status) { | |
687 | case 0: | |
688 | break; | |
689 | case -ENOENT: | |
690 | case -ECONNRESET: | |
691 | case -ENODEV: | |
692 | case -ESHUTDOWN: | |
693 | goto free; | |
694 | default: | |
3deff760 SM |
695 | skb_reset_tail_pointer(skb); |
696 | skb_trim(skb, 0); | |
697 | ||
fb9987d0 S |
698 | goto resubmit; |
699 | } | |
700 | ||
701 | if (likely(urb->actual_length != 0)) { | |
702 | skb_put(skb, urb->actual_length); | |
703 | ||
5ab0af32 S |
704 | /* Process the command first */ |
705 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb, | |
706 | skb->len, USB_REG_IN_PIPE); | |
707 | ||
708 | ||
e6c6d33c | 709 | nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); |
5ab0af32 S |
710 | if (!nskb) { |
711 | dev_err(&hif_dev->udev->dev, | |
712 | "ath9k_htc: REG_IN memory allocation failure\n"); | |
713 | urb->context = NULL; | |
714 | return; | |
715 | } | |
fb9987d0 | 716 | |
490b3f4e | 717 | usb_fill_bulk_urb(urb, hif_dev->udev, |
0f529e98 RM |
718 | usb_rcvbulkpipe(hif_dev->udev, |
719 | USB_REG_IN_PIPE), | |
fb9987d0 | 720 | nskb->data, MAX_REG_IN_BUF_SIZE, |
490b3f4e | 721 | ath9k_hif_usb_reg_in_cb, nskb); |
fb9987d0 S |
722 | } |
723 | ||
724 | resubmit: | |
3deff760 | 725 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); |
fb9987d0 | 726 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
3deff760 SM |
727 | if (ret) { |
728 | usb_unanchor_urb(urb); | |
fb9987d0 | 729 | goto free; |
3deff760 | 730 | } |
fb9987d0 S |
731 | |
732 | return; | |
733 | free: | |
e6c6d33c | 734 | kfree_skb(skb); |
6335ed0f | 735 | urb->context = NULL; |
fb9987d0 S |
736 | } |
737 | ||
738 | static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | |
739 | { | |
fb9987d0 | 740 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; |
ff8f59b5 | 741 | unsigned long flags; |
fb9987d0 | 742 | |
c11d8f89 S |
743 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, |
744 | &hif_dev->tx.tx_buf, list) { | |
745 | usb_kill_urb(tx_buf->urb); | |
fb9987d0 S |
746 | list_del(&tx_buf->list); |
747 | usb_free_urb(tx_buf->urb); | |
748 | kfree(tx_buf->buf); | |
749 | kfree(tx_buf); | |
750 | } | |
751 | ||
ff8f59b5 SM |
752 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
753 | hif_dev->tx.flags |= HIF_USB_TX_FLUSH; | |
754 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | |
755 | ||
fb9987d0 S |
756 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, |
757 | &hif_dev->tx.tx_pending, list) { | |
758 | usb_kill_urb(tx_buf->urb); | |
759 | list_del(&tx_buf->list); | |
760 | usb_free_urb(tx_buf->urb); | |
761 | kfree(tx_buf->buf); | |
762 | kfree(tx_buf); | |
763 | } | |
2f80194c SM |
764 | |
765 | usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); | |
fb9987d0 S |
766 | } |
767 | ||
768 | static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) | |
769 | { | |
770 | struct tx_buf *tx_buf; | |
771 | int i; | |
772 | ||
773 | INIT_LIST_HEAD(&hif_dev->tx.tx_buf); | |
774 | INIT_LIST_HEAD(&hif_dev->tx.tx_pending); | |
775 | spin_lock_init(&hif_dev->tx.tx_lock); | |
776 | __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); | |
2f80194c | 777 | init_usb_anchor(&hif_dev->mgmt_submitted); |
fb9987d0 S |
778 | |
779 | for (i = 0; i < MAX_TX_URB_NUM; i++) { | |
780 | tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); | |
781 | if (!tx_buf) | |
782 | goto err; | |
783 | ||
784 | tx_buf->buf = kzalloc(MAX_TX_BUF_SIZE, GFP_KERNEL); | |
785 | if (!tx_buf->buf) | |
786 | goto err; | |
787 | ||
788 | tx_buf->urb = usb_alloc_urb(0, GFP_KERNEL); | |
789 | if (!tx_buf->urb) | |
790 | goto err; | |
791 | ||
792 | tx_buf->hif_dev = hif_dev; | |
793 | __skb_queue_head_init(&tx_buf->skb_queue); | |
794 | ||
795 | list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | |
796 | } | |
797 | ||
798 | hif_dev->tx.tx_buf_cnt = MAX_TX_URB_NUM; | |
799 | ||
800 | return 0; | |
801 | err: | |
7606688a DC |
802 | if (tx_buf) { |
803 | kfree(tx_buf->buf); | |
804 | kfree(tx_buf); | |
805 | } | |
fb9987d0 S |
806 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); |
807 | return -ENOMEM; | |
808 | } | |
809 | ||
fb9987d0 S |
810 | static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) |
811 | { | |
6335ed0f | 812 | usb_kill_anchored_urbs(&hif_dev->rx_submitted); |
fb9987d0 S |
813 | } |
814 | ||
815 | static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) | |
816 | { | |
6335ed0f S |
817 | struct urb *urb = NULL; |
818 | struct sk_buff *skb = NULL; | |
fb9987d0 S |
819 | int i, ret; |
820 | ||
6335ed0f | 821 | init_usb_anchor(&hif_dev->rx_submitted); |
46baa1a2 | 822 | spin_lock_init(&hif_dev->rx_lock); |
6335ed0f | 823 | |
fb9987d0 S |
824 | for (i = 0; i < MAX_RX_URB_NUM; i++) { |
825 | ||
826 | /* Allocate URB */ | |
6335ed0f S |
827 | urb = usb_alloc_urb(0, GFP_KERNEL); |
828 | if (urb == NULL) { | |
fb9987d0 | 829 | ret = -ENOMEM; |
6335ed0f | 830 | goto err_urb; |
fb9987d0 S |
831 | } |
832 | ||
833 | /* Allocate buffer */ | |
f28a7b30 | 834 | skb = alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); |
6335ed0f S |
835 | if (!skb) { |
836 | ret = -ENOMEM; | |
837 | goto err_skb; | |
838 | } | |
fb9987d0 | 839 | |
6335ed0f S |
840 | usb_fill_bulk_urb(urb, hif_dev->udev, |
841 | usb_rcvbulkpipe(hif_dev->udev, | |
842 | USB_WLAN_RX_PIPE), | |
843 | skb->data, MAX_RX_BUF_SIZE, | |
844 | ath9k_hif_usb_rx_cb, skb); | |
845 | ||
846 | /* Anchor URB */ | |
847 | usb_anchor_urb(urb, &hif_dev->rx_submitted); | |
fb9987d0 | 848 | |
6335ed0f S |
849 | /* Submit URB */ |
850 | ret = usb_submit_urb(urb, GFP_KERNEL); | |
851 | if (ret) { | |
852 | usb_unanchor_urb(urb); | |
853 | goto err_submit; | |
854 | } | |
66b10e33 S |
855 | |
856 | /* | |
857 | * Drop reference count. | |
858 | * This ensures that the URB is freed when killing them. | |
859 | */ | |
860 | usb_free_urb(urb); | |
fb9987d0 S |
861 | } |
862 | ||
863 | return 0; | |
864 | ||
6335ed0f | 865 | err_submit: |
f28a7b30 | 866 | kfree_skb(skb); |
6335ed0f S |
867 | err_skb: |
868 | usb_free_urb(urb); | |
869 | err_urb: | |
fb9987d0 S |
870 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); |
871 | return ret; | |
872 | } | |
873 | ||
3deff760 | 874 | static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev) |
fb9987d0 | 875 | { |
3deff760 | 876 | usb_kill_anchored_urbs(&hif_dev->reg_in_submitted); |
fb9987d0 S |
877 | } |
878 | ||
3deff760 | 879 | static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev) |
fb9987d0 | 880 | { |
3deff760 SM |
881 | struct urb *urb = NULL; |
882 | struct sk_buff *skb = NULL; | |
883 | int i, ret; | |
fb9987d0 | 884 | |
3deff760 | 885 | init_usb_anchor(&hif_dev->reg_in_submitted); |
fb9987d0 | 886 | |
3deff760 | 887 | for (i = 0; i < MAX_REG_IN_URB_NUM; i++) { |
fb9987d0 | 888 | |
3deff760 SM |
889 | /* Allocate URB */ |
890 | urb = usb_alloc_urb(0, GFP_KERNEL); | |
891 | if (urb == NULL) { | |
892 | ret = -ENOMEM; | |
893 | goto err_urb; | |
894 | } | |
fb9987d0 | 895 | |
3deff760 SM |
896 | /* Allocate buffer */ |
897 | skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); | |
898 | if (!skb) { | |
899 | ret = -ENOMEM; | |
900 | goto err_skb; | |
901 | } | |
902 | ||
903 | usb_fill_bulk_urb(urb, hif_dev->udev, | |
904 | usb_rcvbulkpipe(hif_dev->udev, | |
905 | USB_REG_IN_PIPE), | |
906 | skb->data, MAX_REG_IN_BUF_SIZE, | |
907 | ath9k_hif_usb_reg_in_cb, skb); | |
908 | ||
909 | /* Anchor URB */ | |
910 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); | |
911 | ||
912 | /* Submit URB */ | |
913 | ret = usb_submit_urb(urb, GFP_KERNEL); | |
914 | if (ret) { | |
915 | usb_unanchor_urb(urb); | |
916 | goto err_submit; | |
917 | } | |
918 | ||
919 | /* | |
920 | * Drop reference count. | |
921 | * This ensures that the URB is freed when killing them. | |
922 | */ | |
923 | usb_free_urb(urb); | |
924 | } | |
fb9987d0 S |
925 | |
926 | return 0; | |
927 | ||
3deff760 SM |
928 | err_submit: |
929 | kfree_skb(skb); | |
930 | err_skb: | |
931 | usb_free_urb(urb); | |
932 | err_urb: | |
933 | ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); | |
934 | return ret; | |
fb9987d0 S |
935 | } |
936 | ||
937 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | |
938 | { | |
6f0f2669 S |
939 | /* Register Write */ |
940 | init_usb_anchor(&hif_dev->regout_submitted); | |
941 | ||
fb9987d0 S |
942 | /* TX */ |
943 | if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0) | |
944 | goto err; | |
945 | ||
946 | /* RX */ | |
947 | if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) | |
f8036965 | 948 | goto err_rx; |
fb9987d0 | 949 | |
6f0f2669 | 950 | /* Register Read */ |
3deff760 | 951 | if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0) |
f8036965 | 952 | goto err_reg; |
fb9987d0 S |
953 | |
954 | return 0; | |
f8036965 RM |
955 | err_reg: |
956 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | |
957 | err_rx: | |
958 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); | |
fb9987d0 S |
959 | err: |
960 | return -ENOMEM; | |
961 | } | |
962 | ||
1d8af8ca SM |
963 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) |
964 | { | |
965 | usb_kill_anchored_urbs(&hif_dev->regout_submitted); | |
3deff760 | 966 | ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); |
1d8af8ca SM |
967 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); |
968 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | |
969 | } | |
970 | ||
0ed7b93e | 971 | static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) |
fb9987d0 S |
972 | { |
973 | int transfer, err; | |
974 | const void *data = hif_dev->firmware->data; | |
975 | size_t len = hif_dev->firmware->size; | |
976 | u32 addr = AR9271_FIRMWARE; | |
977 | u8 *buf = kzalloc(4096, GFP_KERNEL); | |
b1762862 | 978 | u32 firm_offset; |
fb9987d0 S |
979 | |
980 | if (!buf) | |
981 | return -ENOMEM; | |
982 | ||
983 | while (len) { | |
291689fc | 984 | transfer = min_t(size_t, len, 4096); |
fb9987d0 S |
985 | memcpy(buf, data, transfer); |
986 | ||
987 | err = usb_control_msg(hif_dev->udev, | |
988 | usb_sndctrlpipe(hif_dev->udev, 0), | |
989 | FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT, | |
990 | addr >> 8, 0, buf, transfer, HZ); | |
991 | if (err < 0) { | |
992 | kfree(buf); | |
993 | return err; | |
994 | } | |
995 | ||
996 | len -= transfer; | |
997 | data += transfer; | |
998 | addr += transfer; | |
999 | } | |
1000 | kfree(buf); | |
1001 | ||
0ed7b93e | 1002 | if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info)) |
b1762862 | 1003 | firm_offset = AR7010_FIRMWARE_TEXT; |
fa6e15e0 | 1004 | else |
b1762862 S |
1005 | firm_offset = AR9271_FIRMWARE_TEXT; |
1006 | ||
fb9987d0 S |
1007 | /* |
1008 | * Issue FW download complete command to firmware. | |
1009 | */ | |
1010 | err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0), | |
1011 | FIRMWARE_DOWNLOAD_COMP, | |
1012 | 0x40 | USB_DIR_OUT, | |
b1762862 | 1013 | firm_offset >> 8, 0, NULL, 0, HZ); |
fb9987d0 S |
1014 | if (err) |
1015 | return -EIO; | |
1016 | ||
1017 | dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n", | |
ce43cee5 | 1018 | hif_dev->fw_name, (unsigned long) hif_dev->firmware->size); |
fb9987d0 S |
1019 | |
1020 | return 0; | |
1021 | } | |
1022 | ||
0ed7b93e | 1023 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) |
fb9987d0 | 1024 | { |
4a0e8ecc RM |
1025 | struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; |
1026 | struct usb_endpoint_descriptor *endp; | |
0ed7b93e | 1027 | int ret, idx; |
fb9987d0 | 1028 | |
0ed7b93e | 1029 | ret = ath9k_hif_usb_download_fw(hif_dev); |
1d8af8ca SM |
1030 | if (ret) { |
1031 | dev_err(&hif_dev->udev->dev, | |
ce43cee5 S |
1032 | "ath9k_htc: Firmware - %s download failed\n", |
1033 | hif_dev->fw_name); | |
0ed7b93e | 1034 | return ret; |
1d8af8ca SM |
1035 | } |
1036 | ||
4a0e8ecc RM |
1037 | /* On downloading the firmware to the target, the USB descriptor of EP4 |
1038 | * is 'patched' to change the type of the endpoint to Bulk. This will | |
1039 | * bring down CPU usage during the scan period. | |
1040 | */ | |
1041 | for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) { | |
1042 | endp = &alt->endpoint[idx].desc; | |
490b3f4e RM |
1043 | if ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) |
1044 | == USB_ENDPOINT_XFER_INT) { | |
4a0e8ecc RM |
1045 | endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK; |
1046 | endp->bmAttributes |= USB_ENDPOINT_XFER_BULK; | |
1047 | endp->bInterval = 0; | |
1048 | } | |
1049 | } | |
1050 | ||
490b3f4e RM |
1051 | /* Alloc URBs */ |
1052 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | |
1053 | if (ret) { | |
1054 | dev_err(&hif_dev->udev->dev, | |
1055 | "ath9k_htc: Unable to allocate URBs\n"); | |
0ed7b93e | 1056 | return ret; |
490b3f4e RM |
1057 | } |
1058 | ||
fb9987d0 | 1059 | return 0; |
fb9987d0 S |
1060 | } |
1061 | ||
fb9987d0 S |
1062 | static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) |
1063 | { | |
1064 | ath9k_hif_usb_dealloc_urbs(hif_dev); | |
0ed7b93e SM |
1065 | } |
1066 | ||
1067 | /* | |
1068 | * If initialization fails or the FW cannot be retrieved, | |
1069 | * detach the device. | |
1070 | */ | |
1071 | static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) | |
1072 | { | |
1073 | struct device *parent = hif_dev->udev->dev.parent; | |
1074 | ||
1075 | complete(&hif_dev->fw_done); | |
1076 | ||
1077 | if (parent) | |
1078 | device_lock(parent); | |
1079 | ||
1080 | device_release_driver(&hif_dev->udev->dev); | |
1081 | ||
1082 | if (parent) | |
1083 | device_unlock(parent); | |
1084 | } | |
1085 | ||
1086 | static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context) | |
1087 | { | |
1088 | struct hif_device_usb *hif_dev = context; | |
1089 | int ret; | |
1090 | ||
1091 | if (!fw) { | |
1092 | dev_err(&hif_dev->udev->dev, | |
1093 | "ath9k_htc: Failed to get firmware %s\n", | |
1094 | hif_dev->fw_name); | |
1095 | goto err_fw; | |
1096 | } | |
1097 | ||
1098 | hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb, | |
1099 | &hif_dev->udev->dev); | |
1100 | if (hif_dev->htc_handle == NULL) { | |
1101 | goto err_fw; | |
1102 | } | |
1103 | ||
1104 | hif_dev->firmware = fw; | |
1105 | ||
1106 | /* Proceed with initialization */ | |
1107 | ||
1108 | ret = ath9k_hif_usb_dev_init(hif_dev); | |
1109 | if (ret) | |
1110 | goto err_dev_init; | |
1111 | ||
1112 | ret = ath9k_htc_hw_init(hif_dev->htc_handle, | |
1113 | &hif_dev->interface->dev, | |
1114 | hif_dev->usb_device_id->idProduct, | |
1115 | hif_dev->udev->product, | |
1116 | hif_dev->usb_device_id->driver_info); | |
1117 | if (ret) { | |
1118 | ret = -EINVAL; | |
1119 | goto err_htc_hw_init; | |
1120 | } | |
1121 | ||
1122 | complete(&hif_dev->fw_done); | |
1123 | ||
1124 | return; | |
1125 | ||
1126 | err_htc_hw_init: | |
1127 | ath9k_hif_usb_dev_deinit(hif_dev); | |
1128 | err_dev_init: | |
1129 | ath9k_htc_hw_free(hif_dev->htc_handle); | |
1130 | release_firmware(fw); | |
1131 | hif_dev->firmware = NULL; | |
1132 | err_fw: | |
1133 | ath9k_hif_usb_firmware_fail(hif_dev); | |
fb9987d0 S |
1134 | } |
1135 | ||
36bcce43 SM |
1136 | /* |
1137 | * An exact copy of the function from zd1211rw. | |
1138 | */ | |
1139 | static int send_eject_command(struct usb_interface *interface) | |
1140 | { | |
1141 | struct usb_device *udev = interface_to_usbdev(interface); | |
1142 | struct usb_host_interface *iface_desc = &interface->altsetting[0]; | |
1143 | struct usb_endpoint_descriptor *endpoint; | |
1144 | unsigned char *cmd; | |
1145 | u8 bulk_out_ep; | |
1146 | int r; | |
1147 | ||
1148 | /* Find bulk out endpoint */ | |
1149 | for (r = 1; r >= 0; r--) { | |
1150 | endpoint = &iface_desc->endpoint[r].desc; | |
1151 | if (usb_endpoint_dir_out(endpoint) && | |
1152 | usb_endpoint_xfer_bulk(endpoint)) { | |
1153 | bulk_out_ep = endpoint->bEndpointAddress; | |
1154 | break; | |
1155 | } | |
1156 | } | |
1157 | if (r == -1) { | |
1158 | dev_err(&udev->dev, | |
1159 | "ath9k_htc: Could not find bulk out endpoint\n"); | |
1160 | return -ENODEV; | |
1161 | } | |
1162 | ||
1163 | cmd = kzalloc(31, GFP_KERNEL); | |
1164 | if (cmd == NULL) | |
1165 | return -ENODEV; | |
1166 | ||
1167 | /* USB bulk command block */ | |
1168 | cmd[0] = 0x55; /* bulk command signature */ | |
1169 | cmd[1] = 0x53; /* bulk command signature */ | |
1170 | cmd[2] = 0x42; /* bulk command signature */ | |
1171 | cmd[3] = 0x43; /* bulk command signature */ | |
1172 | cmd[14] = 6; /* command length */ | |
1173 | ||
1174 | cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */ | |
1175 | cmd[19] = 0x2; /* eject disc */ | |
1176 | ||
1177 | dev_info(&udev->dev, "Ejecting storage device...\n"); | |
1178 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), | |
1179 | cmd, 31, NULL, 2000); | |
1180 | kfree(cmd); | |
1181 | if (r) | |
1182 | return r; | |
1183 | ||
1184 | /* At this point, the device disconnects and reconnects with the real | |
1185 | * ID numbers. */ | |
1186 | ||
1187 | usb_set_intfdata(interface, NULL); | |
1188 | return 0; | |
1189 | } | |
1190 | ||
fb9987d0 S |
1191 | static int ath9k_hif_usb_probe(struct usb_interface *interface, |
1192 | const struct usb_device_id *id) | |
1193 | { | |
1194 | struct usb_device *udev = interface_to_usbdev(interface); | |
1195 | struct hif_device_usb *hif_dev; | |
fb9987d0 S |
1196 | int ret = 0; |
1197 | ||
36bcce43 SM |
1198 | if (id->driver_info == STORAGE_DEVICE) |
1199 | return send_eject_command(interface); | |
1200 | ||
fb9987d0 S |
1201 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); |
1202 | if (!hif_dev) { | |
1203 | ret = -ENOMEM; | |
1204 | goto err_alloc; | |
1205 | } | |
1206 | ||
1207 | usb_get_dev(udev); | |
0ed7b93e | 1208 | |
fb9987d0 S |
1209 | hif_dev->udev = udev; |
1210 | hif_dev->interface = interface; | |
0ed7b93e | 1211 | hif_dev->usb_device_id = id; |
fb9987d0 S |
1212 | #ifdef CONFIG_PM |
1213 | udev->reset_resume = 1; | |
1214 | #endif | |
1215 | usb_set_intfdata(interface, hif_dev); | |
1216 | ||
0ed7b93e | 1217 | init_completion(&hif_dev->fw_done); |
47fce026 | 1218 | |
ce43cee5 S |
1219 | /* Find out which firmware to load */ |
1220 | ||
0b5ead91 | 1221 | if (IS_AR7010_DEVICE(id->driver_info)) |
9efabad2 | 1222 | hif_dev->fw_name = FIRMWARE_AR7010_1_1; |
fa6e15e0 | 1223 | else |
d0ee0ebe | 1224 | hif_dev->fw_name = FIRMWARE_AR9271; |
ce43cee5 | 1225 | |
0ed7b93e SM |
1226 | ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, |
1227 | &hif_dev->udev->dev, GFP_KERNEL, | |
1228 | hif_dev, ath9k_hif_usb_firmware_cb); | |
fb9987d0 | 1229 | if (ret) { |
0ed7b93e SM |
1230 | dev_err(&hif_dev->udev->dev, |
1231 | "ath9k_htc: Async request for firmware %s failed\n", | |
1232 | hif_dev->fw_name); | |
1233 | goto err_fw_req; | |
fb9987d0 S |
1234 | } |
1235 | ||
0ed7b93e SM |
1236 | dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", |
1237 | hif_dev->fw_name); | |
fb9987d0 S |
1238 | |
1239 | return 0; | |
1240 | ||
0ed7b93e | 1241 | err_fw_req: |
fb9987d0 S |
1242 | usb_set_intfdata(interface, NULL); |
1243 | kfree(hif_dev); | |
1244 | usb_put_dev(udev); | |
1245 | err_alloc: | |
1246 | return ret; | |
1247 | } | |
1248 | ||
62e4716a S |
1249 | static void ath9k_hif_usb_reboot(struct usb_device *udev) |
1250 | { | |
1251 | u32 reboot_cmd = 0xffffffff; | |
1252 | void *buf; | |
1253 | int ret; | |
1254 | ||
a465a2cc | 1255 | buf = kmemdup(&reboot_cmd, 4, GFP_KERNEL); |
62e4716a S |
1256 | if (!buf) |
1257 | return; | |
1258 | ||
62e4716a S |
1259 | ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE), |
1260 | buf, 4, NULL, HZ); | |
1261 | if (ret) | |
1262 | dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n"); | |
1263 | ||
1264 | kfree(buf); | |
1265 | } | |
1266 | ||
fb9987d0 S |
1267 | static void ath9k_hif_usb_disconnect(struct usb_interface *interface) |
1268 | { | |
1269 | struct usb_device *udev = interface_to_usbdev(interface); | |
b2767363 | 1270 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
97dcec57 | 1271 | bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false; |
fb9987d0 | 1272 | |
36bcce43 SM |
1273 | if (!hif_dev) |
1274 | return; | |
1275 | ||
0ed7b93e SM |
1276 | wait_for_completion(&hif_dev->fw_done); |
1277 | ||
1278 | if (hif_dev->firmware) { | |
1279 | ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); | |
1280 | ath9k_htc_hw_free(hif_dev->htc_handle); | |
1281 | ath9k_hif_usb_dev_deinit(hif_dev); | |
1282 | release_firmware(hif_dev->firmware); | |
1283 | } | |
1284 | ||
36bcce43 | 1285 | usb_set_intfdata(interface, NULL); |
fb9987d0 | 1286 | |
97dcec57 | 1287 | if (!unplugged && (hif_dev->flags & HIF_USB_START)) |
62e4716a | 1288 | ath9k_hif_usb_reboot(udev); |
fb9987d0 S |
1289 | |
1290 | kfree(hif_dev); | |
1291 | dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n"); | |
1292 | usb_put_dev(udev); | |
1293 | } | |
1294 | ||
1295 | #ifdef CONFIG_PM | |
1296 | static int ath9k_hif_usb_suspend(struct usb_interface *interface, | |
1297 | pm_message_t message) | |
1298 | { | |
b2767363 | 1299 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
fb9987d0 | 1300 | |
f933ebed SM |
1301 | /* |
1302 | * The device has to be set to FULLSLEEP mode in case no | |
1303 | * interface is up. | |
1304 | */ | |
1305 | if (!(hif_dev->flags & HIF_USB_START)) | |
1306 | ath9k_htc_suspend(hif_dev->htc_handle); | |
1307 | ||
fb9987d0 S |
1308 | ath9k_hif_usb_dealloc_urbs(hif_dev); |
1309 | ||
1310 | return 0; | |
1311 | } | |
1312 | ||
1313 | static int ath9k_hif_usb_resume(struct usb_interface *interface) | |
1314 | { | |
b2767363 | 1315 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
fa6e15e0 | 1316 | struct htc_target *htc_handle = hif_dev->htc_handle; |
fb9987d0 S |
1317 | int ret; |
1318 | ||
1319 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | |
1320 | if (ret) | |
1321 | return ret; | |
1322 | ||
1323 | if (hif_dev->firmware) { | |
0ed7b93e | 1324 | ret = ath9k_hif_usb_download_fw(hif_dev); |
fb9987d0 S |
1325 | if (ret) |
1326 | goto fail_resume; | |
1327 | } else { | |
1328 | ath9k_hif_usb_dealloc_urbs(hif_dev); | |
1329 | return -EIO; | |
1330 | } | |
1331 | ||
1332 | mdelay(100); | |
1333 | ||
fa6e15e0 | 1334 | ret = ath9k_htc_resume(htc_handle); |
fb9987d0 S |
1335 | |
1336 | if (ret) | |
1337 | goto fail_resume; | |
1338 | ||
1339 | return 0; | |
1340 | ||
1341 | fail_resume: | |
1342 | ath9k_hif_usb_dealloc_urbs(hif_dev); | |
1343 | ||
1344 | return ret; | |
1345 | } | |
1346 | #endif | |
1347 | ||
1348 | static struct usb_driver ath9k_hif_usb_driver = { | |
50f68712 | 1349 | .name = KBUILD_MODNAME, |
fb9987d0 S |
1350 | .probe = ath9k_hif_usb_probe, |
1351 | .disconnect = ath9k_hif_usb_disconnect, | |
1352 | #ifdef CONFIG_PM | |
1353 | .suspend = ath9k_hif_usb_suspend, | |
1354 | .resume = ath9k_hif_usb_resume, | |
1355 | .reset_resume = ath9k_hif_usb_resume, | |
1356 | #endif | |
1357 | .id_table = ath9k_hif_usb_ids, | |
1358 | .soft_unbind = 1, | |
1359 | }; | |
1360 | ||
1361 | int ath9k_hif_usb_init(void) | |
1362 | { | |
1363 | return usb_register(&ath9k_hif_usb_driver); | |
1364 | } | |
1365 | ||
1366 | void ath9k_hif_usb_exit(void) | |
1367 | { | |
1368 | usb_deregister(&ath9k_hif_usb_driver); | |
1369 | } |