blob: 23c15aa9fbd5167c51e80601eb5213c0dd144283 [file] [log] [blame]
Sujithfb9987d2010-03-17 14:25:25 +05301/*
2 * Copyright (c) 2010 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 "htc.h"
18
19#define ATH9K_FW_USB_DEV(devid, fw) \
20 { USB_DEVICE(0x0cf3, devid), .driver_info = (unsigned long) fw }
21
22static struct usb_device_id ath9k_hif_usb_ids[] = {
23 ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"),
Sujithe92119c2010-04-01 10:28:24 +053024 ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"),
Sujithfb9987d2010-03-17 14:25:25 +053025 { },
26};
27
28MODULE_DEVICE_TABLE(usb, ath9k_hif_usb_ids);
29
30static int __hif_usb_tx(struct hif_device_usb *hif_dev);
31
32static void hif_usb_regout_cb(struct urb *urb)
33{
34 struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
Sujithfb9987d2010-03-17 14:25:25 +053035
36 switch (urb->status) {
37 case 0:
38 break;
39 case -ENOENT:
40 case -ECONNRESET:
Sujithfb9987d2010-03-17 14:25:25 +053041 case -ENODEV:
42 case -ESHUTDOWN:
Sujith6f0f2662010-04-06 15:28:17 +053043 goto free;
Sujithfb9987d2010-03-17 14:25:25 +053044 default:
45 break;
46 }
47
48 if (cmd) {
49 ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
50 cmd->skb, 1);
51 kfree(cmd);
Sujithfb9987d2010-03-17 14:25:25 +053052 }
Sujith6f0f2662010-04-06 15:28:17 +053053
54 return;
55free:
Ming Lei0fa35a52010-04-13 00:29:15 +080056 kfree_skb(cmd->skb);
Sujith6f0f2662010-04-06 15:28:17 +053057 kfree(cmd);
Sujithfb9987d2010-03-17 14:25:25 +053058}
59
60static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
61 struct sk_buff *skb)
62{
63 struct urb *urb;
64 struct cmd_buf *cmd;
65 int ret = 0;
66
67 urb = usb_alloc_urb(0, GFP_KERNEL);
68 if (urb == NULL)
69 return -ENOMEM;
70
71 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
72 if (cmd == NULL) {
73 usb_free_urb(urb);
74 return -ENOMEM;
75 }
76
77 cmd->skb = skb;
78 cmd->hif_dev = hif_dev;
79
80 usb_fill_int_urb(urb, hif_dev->udev,
81 usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE),
82 skb->data, skb->len,
83 hif_usb_regout_cb, cmd, 1);
84
Sujith6f0f2662010-04-06 15:28:17 +053085 usb_anchor_urb(urb, &hif_dev->regout_submitted);
Sujithfb9987d2010-03-17 14:25:25 +053086 ret = usb_submit_urb(urb, GFP_KERNEL);
87 if (ret) {
Sujith6f0f2662010-04-06 15:28:17 +053088 usb_unanchor_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +053089 kfree(cmd);
90 }
Sujith6f0f2662010-04-06 15:28:17 +053091 usb_free_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +053092
93 return ret;
94}
95
Sujitheac8e382010-04-16 11:54:00 +053096static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
97 struct sk_buff_head *list)
Ming Leif8e1d082010-04-13 00:29:27 +080098{
99 struct sk_buff *skb;
Sujitheac8e382010-04-16 11:54:00 +0530100
101 while ((skb = __skb_dequeue(list)) != NULL) {
Ming Leif8e1d082010-04-13 00:29:27 +0800102 dev_kfree_skb_any(skb);
Sujitheac8e382010-04-16 11:54:00 +0530103 TX_STAT_INC(skb_dropped);
104 }
Ming Leif8e1d082010-04-13 00:29:27 +0800105}
106
Sujithc11d8f82010-04-23 10:28:09 +0530107static void hif_usb_tx_cb(struct urb *urb)
108{
109 struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
Dan Carpenter690e7812010-05-14 16:50:56 +0200110 struct hif_device_usb *hif_dev;
Sujithc11d8f82010-04-23 10:28:09 +0530111 struct sk_buff *skb;
112
Dan Carpenter690e7812010-05-14 16:50:56 +0200113 if (!tx_buf || !tx_buf->hif_dev)
Sujithc11d8f82010-04-23 10:28:09 +0530114 return;
115
Dan Carpenter690e7812010-05-14 16:50:56 +0200116 hif_dev = tx_buf->hif_dev;
117
Sujithc11d8f82010-04-23 10:28:09 +0530118 switch (urb->status) {
119 case 0:
120 break;
121 case -ENOENT:
122 case -ECONNRESET:
123 case -ENODEV:
124 case -ESHUTDOWN:
125 /*
126 * The URB has been killed, free the SKBs
127 * and return.
128 */
129 ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
130 return;
131 default:
132 break;
133 }
134
135 /* Check if TX has been stopped */
136 spin_lock(&hif_dev->tx.tx_lock);
137 if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
138 spin_unlock(&hif_dev->tx.tx_lock);
139 ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
140 goto add_free;
141 }
142 spin_unlock(&hif_dev->tx.tx_lock);
143
144 /* Complete the queued SKBs. */
145 while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) {
146 ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
147 skb, 1);
148 TX_STAT_INC(skb_completed);
149 }
150
151add_free:
152 /* Re-initialize the SKB queue */
153 tx_buf->len = tx_buf->offset = 0;
154 __skb_queue_head_init(&tx_buf->skb_queue);
155
156 /* Add this TX buffer to the free list */
157 spin_lock(&hif_dev->tx.tx_lock);
158 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
159 hif_dev->tx.tx_buf_cnt++;
160 if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
161 __hif_usb_tx(hif_dev); /* Check for pending SKBs */
162 TX_STAT_INC(buf_completed);
163 spin_unlock(&hif_dev->tx.tx_lock);
164}
165
Sujithfb9987d2010-03-17 14:25:25 +0530166/* TX lock has to be taken */
167static int __hif_usb_tx(struct hif_device_usb *hif_dev)
168{
169 struct tx_buf *tx_buf = NULL;
170 struct sk_buff *nskb = NULL;
171 int ret = 0, i;
172 u16 *hdr, tx_skb_cnt = 0;
173 u8 *buf;
174
175 if (hif_dev->tx.tx_skb_cnt == 0)
176 return 0;
177
178 /* Check if a free TX buffer is available */
179 if (list_empty(&hif_dev->tx.tx_buf))
180 return 0;
181
182 tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list);
Sujithc11d8f82010-04-23 10:28:09 +0530183 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending);
Sujithfb9987d2010-03-17 14:25:25 +0530184 hif_dev->tx.tx_buf_cnt--;
185
186 tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM);
187
188 for (i = 0; i < tx_skb_cnt; i++) {
189 nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue);
190
191 /* Should never be NULL */
192 BUG_ON(!nskb);
193
194 hif_dev->tx.tx_skb_cnt--;
195
196 buf = tx_buf->buf;
197 buf += tx_buf->offset;
198 hdr = (u16 *)buf;
199 *hdr++ = nskb->len;
200 *hdr++ = ATH_USB_TX_STREAM_MODE_TAG;
201 buf += 4;
202 memcpy(buf, nskb->data, nskb->len);
203 tx_buf->len = nskb->len + 4;
204
205 if (i < (tx_skb_cnt - 1))
206 tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4;
207
208 if (i == (tx_skb_cnt - 1))
209 tx_buf->len += tx_buf->offset;
210
211 __skb_queue_tail(&tx_buf->skb_queue, nskb);
212 TX_STAT_INC(skb_queued);
213 }
214
215 usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev,
216 usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE),
217 tx_buf->buf, tx_buf->len,
218 hif_usb_tx_cb, tx_buf);
219
220 ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
221 if (ret) {
222 tx_buf->len = tx_buf->offset = 0;
Sujitheac8e382010-04-16 11:54:00 +0530223 ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
Sujithfb9987d2010-03-17 14:25:25 +0530224 __skb_queue_head_init(&tx_buf->skb_queue);
225 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
226 hif_dev->tx.tx_buf_cnt++;
227 }
228
229 if (!ret)
230 TX_STAT_INC(buf_queued);
231
232 return ret;
233}
234
235static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
236 struct ath9k_htc_tx_ctl *tx_ctl)
237{
238 unsigned long flags;
239
240 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
241
242 if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
243 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
244 return -ENODEV;
245 }
246
247 /* Check if the max queue count has been reached */
248 if (hif_dev->tx.tx_skb_cnt > MAX_TX_BUF_NUM) {
249 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
250 return -ENOMEM;
251 }
252
253 __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
254 hif_dev->tx.tx_skb_cnt++;
255
256 /* Send normal frames immediately */
257 if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL)))
258 __hif_usb_tx(hif_dev);
259
260 /* Check if AMPDUs have to be sent immediately */
261 if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) &&
262 (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
263 (hif_dev->tx.tx_skb_cnt < 2)) {
264 __hif_usb_tx(hif_dev);
265 }
266
267 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
268
269 return 0;
270}
271
272static void hif_usb_start(void *hif_handle, u8 pipe_id)
273{
274 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
275 unsigned long flags;
276
277 hif_dev->flags |= HIF_USB_START;
278
279 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
280 hif_dev->tx.flags &= ~HIF_USB_TX_STOP;
281 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
282}
283
284static void hif_usb_stop(void *hif_handle, u8 pipe_id)
285{
286 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
287 unsigned long flags;
288
289 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
Sujitheac8e382010-04-16 11:54:00 +0530290 ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue);
Sujithfb9987d2010-03-17 14:25:25 +0530291 hif_dev->tx.tx_skb_cnt = 0;
292 hif_dev->tx.flags |= HIF_USB_TX_STOP;
293 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
294}
295
296static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
297 struct ath9k_htc_tx_ctl *tx_ctl)
298{
299 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
300 int ret = 0;
301
302 switch (pipe_id) {
303 case USB_WLAN_TX_PIPE:
304 ret = hif_usb_send_tx(hif_dev, skb, tx_ctl);
305 break;
306 case USB_REG_OUT_PIPE:
307 ret = hif_usb_send_regout(hif_dev, skb);
308 break;
309 default:
Sujith6335ed02010-03-29 16:07:15 +0530310 dev_err(&hif_dev->udev->dev,
311 "ath9k_htc: Invalid TX pipe: %d\n", pipe_id);
Sujithfb9987d2010-03-17 14:25:25 +0530312 ret = -EINVAL;
313 break;
314 }
315
316 return ret;
317}
318
319static struct ath9k_htc_hif hif_usb = {
320 .transport = ATH9K_HIF_USB,
321 .name = "ath9k_hif_usb",
322
323 .control_ul_pipe = USB_REG_OUT_PIPE,
324 .control_dl_pipe = USB_REG_IN_PIPE,
325
326 .start = hif_usb_start,
327 .stop = hif_usb_stop,
328 .send = hif_usb_send,
329};
330
331static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
332 struct sk_buff *skb)
333{
Sujithc5032692010-04-06 15:28:15 +0530334 struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER];
Sujithfb9987d2010-03-17 14:25:25 +0530335 int index = 0, i = 0, chk_idx, len = skb->len;
336 int rx_remain_len = 0, rx_pkt_len = 0;
337 u16 pkt_len, pkt_tag, pool_index = 0;
338 u8 *ptr;
339
Sujith46baa1a2010-04-06 15:28:11 +0530340 spin_lock(&hif_dev->rx_lock);
341
Sujithfb9987d2010-03-17 14:25:25 +0530342 rx_remain_len = hif_dev->rx_remain_len;
343 rx_pkt_len = hif_dev->rx_transfer_len;
344
345 if (rx_remain_len != 0) {
346 struct sk_buff *remain_skb = hif_dev->remain_skb;
347
348 if (remain_skb) {
349 ptr = (u8 *) remain_skb->data;
350
351 index = rx_remain_len;
352 rx_remain_len -= hif_dev->rx_pad_len;
353 ptr += rx_pkt_len;
354
355 memcpy(ptr, skb->data, rx_remain_len);
356
357 rx_pkt_len += rx_remain_len;
358 hif_dev->rx_remain_len = 0;
359 skb_put(remain_skb, rx_pkt_len);
360
361 skb_pool[pool_index++] = remain_skb;
362
363 } else {
364 index = rx_remain_len;
365 }
366 }
367
Sujith46baa1a2010-04-06 15:28:11 +0530368 spin_unlock(&hif_dev->rx_lock);
369
Sujithfb9987d2010-03-17 14:25:25 +0530370 while (index < len) {
371 ptr = (u8 *) skb->data;
372
373 pkt_len = ptr[index] + (ptr[index+1] << 8);
374 pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
375
376 if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) {
377 u16 pad_len;
378
379 pad_len = 4 - (pkt_len & 0x3);
380 if (pad_len == 4)
381 pad_len = 0;
382
383 chk_idx = index;
384 index = index + 4 + pkt_len + pad_len;
385
386 if (index > MAX_RX_BUF_SIZE) {
Sujith46baa1a2010-04-06 15:28:11 +0530387 spin_lock(&hif_dev->rx_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530388 hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
389 hif_dev->rx_transfer_len =
390 MAX_RX_BUF_SIZE - chk_idx - 4;
391 hif_dev->rx_pad_len = pad_len;
392
393 nskb = __dev_alloc_skb(pkt_len + 32,
394 GFP_ATOMIC);
395 if (!nskb) {
396 dev_err(&hif_dev->udev->dev,
397 "ath9k_htc: RX memory allocation"
398 " error\n");
Sujith46baa1a2010-04-06 15:28:11 +0530399 spin_unlock(&hif_dev->rx_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530400 goto err;
401 }
402 skb_reserve(nskb, 32);
403 RX_STAT_INC(skb_allocated);
404
405 memcpy(nskb->data, &(skb->data[chk_idx+4]),
406 hif_dev->rx_transfer_len);
407
408 /* Record the buffer pointer */
409 hif_dev->remain_skb = nskb;
Sujith46baa1a2010-04-06 15:28:11 +0530410 spin_unlock(&hif_dev->rx_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530411 } else {
412 nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
413 if (!nskb) {
414 dev_err(&hif_dev->udev->dev,
415 "ath9k_htc: RX memory allocation"
416 " error\n");
417 goto err;
418 }
419 skb_reserve(nskb, 32);
420 RX_STAT_INC(skb_allocated);
421
422 memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
423 skb_put(nskb, pkt_len);
424 skb_pool[pool_index++] = nskb;
425 }
426 } else {
427 RX_STAT_INC(skb_dropped);
Sujithfb9987d2010-03-17 14:25:25 +0530428 return;
429 }
430 }
431
432err:
Sujithfb9987d2010-03-17 14:25:25 +0530433 for (i = 0; i < pool_index; i++) {
434 ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
435 skb_pool[i]->len, USB_WLAN_RX_PIPE);
436 RX_STAT_INC(skb_completed);
437 }
438}
439
440static void ath9k_hif_usb_rx_cb(struct urb *urb)
441{
442 struct sk_buff *skb = (struct sk_buff *) urb->context;
Sujithfb9987d2010-03-17 14:25:25 +0530443 struct hif_device_usb *hif_dev = (struct hif_device_usb *)
444 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
445 int ret;
446
Sujith6335ed02010-03-29 16:07:15 +0530447 if (!skb)
448 return;
449
Sujithfb9987d2010-03-17 14:25:25 +0530450 if (!hif_dev)
451 goto free;
452
453 switch (urb->status) {
454 case 0:
455 break;
456 case -ENOENT:
457 case -ECONNRESET:
458 case -ENODEV:
459 case -ESHUTDOWN:
460 goto free;
461 default:
462 goto resubmit;
463 }
464
465 if (likely(urb->actual_length != 0)) {
466 skb_put(skb, urb->actual_length);
Sujithfb9987d2010-03-17 14:25:25 +0530467 ath9k_hif_usb_rx_stream(hif_dev, skb);
Sujithfb9987d2010-03-17 14:25:25 +0530468 }
469
470resubmit:
471 skb_reset_tail_pointer(skb);
472 skb_trim(skb, 0);
473
Sujith6335ed02010-03-29 16:07:15 +0530474 usb_anchor_urb(urb, &hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530475 ret = usb_submit_urb(urb, GFP_ATOMIC);
Sujith6335ed02010-03-29 16:07:15 +0530476 if (ret) {
477 usb_unanchor_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530478 goto free;
Sujith6335ed02010-03-29 16:07:15 +0530479 }
Sujithfb9987d2010-03-17 14:25:25 +0530480
481 return;
482free:
Ming Leif28a7b32010-04-13 00:28:53 +0800483 kfree_skb(skb);
Sujithfb9987d2010-03-17 14:25:25 +0530484}
485
486static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
487{
488 struct sk_buff *skb = (struct sk_buff *) urb->context;
489 struct sk_buff *nskb;
490 struct hif_device_usb *hif_dev = (struct hif_device_usb *)
491 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
492 int ret;
493
Sujith6335ed02010-03-29 16:07:15 +0530494 if (!skb)
495 return;
496
Sujithfb9987d2010-03-17 14:25:25 +0530497 if (!hif_dev)
498 goto free;
499
500 switch (urb->status) {
501 case 0:
502 break;
503 case -ENOENT:
504 case -ECONNRESET:
505 case -ENODEV:
506 case -ESHUTDOWN:
507 goto free;
508 default:
509 goto resubmit;
510 }
511
512 if (likely(urb->actual_length != 0)) {
513 skb_put(skb, urb->actual_length);
514
Sujith5ab0af32010-04-23 10:28:17 +0530515 /* Process the command first */
516 ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
517 skb->len, USB_REG_IN_PIPE);
518
519
Ming Leie6c6d332010-04-13 00:29:05 +0800520 nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
Sujith5ab0af32010-04-23 10:28:17 +0530521 if (!nskb) {
522 dev_err(&hif_dev->udev->dev,
523 "ath9k_htc: REG_IN memory allocation failure\n");
524 urb->context = NULL;
525 return;
526 }
Sujithfb9987d2010-03-17 14:25:25 +0530527
528 usb_fill_int_urb(urb, hif_dev->udev,
529 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
530 nskb->data, MAX_REG_IN_BUF_SIZE,
531 ath9k_hif_usb_reg_in_cb, nskb, 1);
532
533 ret = usb_submit_urb(urb, GFP_ATOMIC);
534 if (ret) {
Ming Leie6c6d332010-04-13 00:29:05 +0800535 kfree_skb(nskb);
Sujith5ab0af32010-04-23 10:28:17 +0530536 urb->context = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530537 }
538
Sujithfb9987d2010-03-17 14:25:25 +0530539 return;
540 }
541
542resubmit:
543 skb_reset_tail_pointer(skb);
544 skb_trim(skb, 0);
545
546 ret = usb_submit_urb(urb, GFP_ATOMIC);
547 if (ret)
548 goto free;
549
550 return;
551free:
Ming Leie6c6d332010-04-13 00:29:05 +0800552 kfree_skb(skb);
Sujith6335ed02010-03-29 16:07:15 +0530553 urb->context = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530554}
555
556static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
557{
Sujithfb9987d2010-03-17 14:25:25 +0530558 struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
559
Sujithc11d8f82010-04-23 10:28:09 +0530560 list_for_each_entry_safe(tx_buf, tx_buf_tmp,
561 &hif_dev->tx.tx_buf, list) {
562 usb_kill_urb(tx_buf->urb);
Sujithfb9987d2010-03-17 14:25:25 +0530563 list_del(&tx_buf->list);
564 usb_free_urb(tx_buf->urb);
565 kfree(tx_buf->buf);
566 kfree(tx_buf);
567 }
568
Sujithfb9987d2010-03-17 14:25:25 +0530569 list_for_each_entry_safe(tx_buf, tx_buf_tmp,
570 &hif_dev->tx.tx_pending, list) {
571 usb_kill_urb(tx_buf->urb);
572 list_del(&tx_buf->list);
573 usb_free_urb(tx_buf->urb);
574 kfree(tx_buf->buf);
575 kfree(tx_buf);
576 }
Sujithfb9987d2010-03-17 14:25:25 +0530577}
578
579static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
580{
581 struct tx_buf *tx_buf;
582 int i;
583
584 INIT_LIST_HEAD(&hif_dev->tx.tx_buf);
585 INIT_LIST_HEAD(&hif_dev->tx.tx_pending);
586 spin_lock_init(&hif_dev->tx.tx_lock);
587 __skb_queue_head_init(&hif_dev->tx.tx_skb_queue);
588
589 for (i = 0; i < MAX_TX_URB_NUM; i++) {
590 tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
591 if (!tx_buf)
592 goto err;
593
594 tx_buf->buf = kzalloc(MAX_TX_BUF_SIZE, GFP_KERNEL);
595 if (!tx_buf->buf)
596 goto err;
597
598 tx_buf->urb = usb_alloc_urb(0, GFP_KERNEL);
599 if (!tx_buf->urb)
600 goto err;
601
602 tx_buf->hif_dev = hif_dev;
603 __skb_queue_head_init(&tx_buf->skb_queue);
604
605 list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
606 }
607
608 hif_dev->tx.tx_buf_cnt = MAX_TX_URB_NUM;
609
610 return 0;
611err:
Dan Carpenter76066882010-05-14 16:52:37 +0200612 if (tx_buf) {
613 kfree(tx_buf->buf);
614 kfree(tx_buf);
615 }
Sujithfb9987d2010-03-17 14:25:25 +0530616 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
617 return -ENOMEM;
618}
619
Sujithfb9987d2010-03-17 14:25:25 +0530620static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
621{
Sujith6335ed02010-03-29 16:07:15 +0530622 usb_kill_anchored_urbs(&hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530623}
624
625static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
626{
Sujith6335ed02010-03-29 16:07:15 +0530627 struct urb *urb = NULL;
628 struct sk_buff *skb = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530629 int i, ret;
630
Sujith6335ed02010-03-29 16:07:15 +0530631 init_usb_anchor(&hif_dev->rx_submitted);
Sujith46baa1a2010-04-06 15:28:11 +0530632 spin_lock_init(&hif_dev->rx_lock);
Sujith6335ed02010-03-29 16:07:15 +0530633
Sujithfb9987d2010-03-17 14:25:25 +0530634 for (i = 0; i < MAX_RX_URB_NUM; i++) {
635
636 /* Allocate URB */
Sujith6335ed02010-03-29 16:07:15 +0530637 urb = usb_alloc_urb(0, GFP_KERNEL);
638 if (urb == NULL) {
Sujithfb9987d2010-03-17 14:25:25 +0530639 ret = -ENOMEM;
Sujith6335ed02010-03-29 16:07:15 +0530640 goto err_urb;
Sujithfb9987d2010-03-17 14:25:25 +0530641 }
642
643 /* Allocate buffer */
Ming Leif28a7b32010-04-13 00:28:53 +0800644 skb = alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL);
Sujith6335ed02010-03-29 16:07:15 +0530645 if (!skb) {
646 ret = -ENOMEM;
647 goto err_skb;
648 }
649
650 usb_fill_bulk_urb(urb, hif_dev->udev,
651 usb_rcvbulkpipe(hif_dev->udev,
652 USB_WLAN_RX_PIPE),
653 skb->data, MAX_RX_BUF_SIZE,
654 ath9k_hif_usb_rx_cb, skb);
655
656 /* Anchor URB */
657 usb_anchor_urb(urb, &hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530658
659 /* Submit URB */
Sujith6335ed02010-03-29 16:07:15 +0530660 ret = usb_submit_urb(urb, GFP_KERNEL);
661 if (ret) {
662 usb_unanchor_urb(urb);
663 goto err_submit;
664 }
Sujith66b10e32010-04-06 15:28:13 +0530665
666 /*
667 * Drop reference count.
668 * This ensures that the URB is freed when killing them.
669 */
670 usb_free_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530671 }
672
673 return 0;
674
Sujith6335ed02010-03-29 16:07:15 +0530675err_submit:
Ming Leif28a7b32010-04-13 00:28:53 +0800676 kfree_skb(skb);
Sujith6335ed02010-03-29 16:07:15 +0530677err_skb:
678 usb_free_urb(urb);
679err_urb:
Sujithfb9987d2010-03-17 14:25:25 +0530680 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
681 return ret;
682}
683
684static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev)
685{
686 if (hif_dev->reg_in_urb) {
687 usb_kill_urb(hif_dev->reg_in_urb);
Sujith6335ed02010-03-29 16:07:15 +0530688 if (hif_dev->reg_in_urb->context)
Ming Leie6c6d332010-04-13 00:29:05 +0800689 kfree_skb((void *)hif_dev->reg_in_urb->context);
Sujithfb9987d2010-03-17 14:25:25 +0530690 usb_free_urb(hif_dev->reg_in_urb);
691 hif_dev->reg_in_urb = NULL;
692 }
693}
694
695static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
696{
697 struct sk_buff *skb;
698
699 hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL);
700 if (hif_dev->reg_in_urb == NULL)
701 return -ENOMEM;
702
Ming Leie6c6d332010-04-13 00:29:05 +0800703 skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
Sujithfb9987d2010-03-17 14:25:25 +0530704 if (!skb)
705 goto err;
706
707 usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev,
708 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
709 skb->data, MAX_REG_IN_BUF_SIZE,
710 ath9k_hif_usb_reg_in_cb, skb, 1);
711
712 if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0)
Sujith6335ed02010-03-29 16:07:15 +0530713 goto err;
Sujithfb9987d2010-03-17 14:25:25 +0530714
715 return 0;
716
Sujithfb9987d2010-03-17 14:25:25 +0530717err:
718 ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
719 return -ENOMEM;
720}
721
722static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
723{
Sujith6f0f2662010-04-06 15:28:17 +0530724 /* Register Write */
725 init_usb_anchor(&hif_dev->regout_submitted);
726
Sujithfb9987d2010-03-17 14:25:25 +0530727 /* TX */
728 if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0)
729 goto err;
730
731 /* RX */
732 if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0)
Rajkumar Manoharanf8036962010-07-07 15:19:18 +0530733 goto err_rx;
Sujithfb9987d2010-03-17 14:25:25 +0530734
Sujith6f0f2662010-04-06 15:28:17 +0530735 /* Register Read */
Sujithfb9987d2010-03-17 14:25:25 +0530736 if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0)
Rajkumar Manoharanf8036962010-07-07 15:19:18 +0530737 goto err_reg;
Sujithfb9987d2010-03-17 14:25:25 +0530738
739 return 0;
Rajkumar Manoharanf8036962010-07-07 15:19:18 +0530740err_reg:
741 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
742err_rx:
743 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
Sujithfb9987d2010-03-17 14:25:25 +0530744err:
745 return -ENOMEM;
746}
747
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530748static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
749{
750 usb_kill_anchored_urbs(&hif_dev->regout_submitted);
751 ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
752 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
753 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
754}
755
Sujithfb9987d2010-03-17 14:25:25 +0530756static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
757{
758 int transfer, err;
759 const void *data = hif_dev->firmware->data;
760 size_t len = hif_dev->firmware->size;
761 u32 addr = AR9271_FIRMWARE;
762 u8 *buf = kzalloc(4096, GFP_KERNEL);
763
764 if (!buf)
765 return -ENOMEM;
766
767 while (len) {
768 transfer = min_t(int, len, 4096);
769 memcpy(buf, data, transfer);
770
771 err = usb_control_msg(hif_dev->udev,
772 usb_sndctrlpipe(hif_dev->udev, 0),
773 FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT,
774 addr >> 8, 0, buf, transfer, HZ);
775 if (err < 0) {
776 kfree(buf);
777 return err;
778 }
779
780 len -= transfer;
781 data += transfer;
782 addr += transfer;
783 }
784 kfree(buf);
785
786 /*
787 * Issue FW download complete command to firmware.
788 */
789 err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0),
790 FIRMWARE_DOWNLOAD_COMP,
791 0x40 | USB_DIR_OUT,
792 AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ);
793 if (err)
794 return -EIO;
795
796 dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n",
797 "ar9271.fw", (unsigned long) hif_dev->firmware->size);
798
799 return 0;
800}
801
802static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev,
803 const char *fw_name)
804{
805 int ret;
806
807 /* Request firmware */
808 ret = request_firmware(&hif_dev->firmware, fw_name, &hif_dev->udev->dev);
809 if (ret) {
810 dev_err(&hif_dev->udev->dev,
811 "ath9k_htc: Firmware - %s not found\n", fw_name);
812 goto err_fw_req;
813 }
814
Sujithfb9987d2010-03-17 14:25:25 +0530815 /* Alloc URBs */
816 ret = ath9k_hif_usb_alloc_urbs(hif_dev);
817 if (ret) {
818 dev_err(&hif_dev->udev->dev,
819 "ath9k_htc: Unable to allocate URBs\n");
820 goto err_urb;
821 }
822
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530823 /* Download firmware */
824 ret = ath9k_hif_usb_download_fw(hif_dev);
825 if (ret) {
826 dev_err(&hif_dev->udev->dev,
827 "ath9k_htc: Firmware - %s download failed\n", fw_name);
828 goto err_fw_download;
829 }
830
Sujithfb9987d2010-03-17 14:25:25 +0530831 return 0;
832
Sujithfb9987d2010-03-17 14:25:25 +0530833err_fw_download:
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530834 ath9k_hif_usb_dealloc_urbs(hif_dev);
835err_urb:
Sujithfb9987d2010-03-17 14:25:25 +0530836 release_firmware(hif_dev->firmware);
837err_fw_req:
838 hif_dev->firmware = NULL;
839 return ret;
840}
841
Sujithfb9987d2010-03-17 14:25:25 +0530842static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
843{
844 ath9k_hif_usb_dealloc_urbs(hif_dev);
845 if (hif_dev->firmware)
846 release_firmware(hif_dev->firmware);
847}
848
849static int ath9k_hif_usb_probe(struct usb_interface *interface,
850 const struct usb_device_id *id)
851{
852 struct usb_device *udev = interface_to_usbdev(interface);
853 struct hif_device_usb *hif_dev;
854 const char *fw_name = (const char *) id->driver_info;
855 int ret = 0;
856
857 hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL);
858 if (!hif_dev) {
859 ret = -ENOMEM;
860 goto err_alloc;
861 }
862
863 usb_get_dev(udev);
864 hif_dev->udev = udev;
865 hif_dev->interface = interface;
866 hif_dev->device_id = id->idProduct;
867#ifdef CONFIG_PM
868 udev->reset_resume = 1;
869#endif
870 usb_set_intfdata(interface, hif_dev);
871
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +0530872 hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
873 &hif_dev->udev->dev);
874 if (hif_dev->htc_handle == NULL) {
875 ret = -ENOMEM;
876 goto err_htc_hw_alloc;
877 }
878
Sujithfb9987d2010-03-17 14:25:25 +0530879 ret = ath9k_hif_usb_dev_init(hif_dev, fw_name);
880 if (ret) {
881 ret = -EINVAL;
882 goto err_hif_init_usb;
883 }
884
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +0530885 ret = ath9k_htc_hw_init(hif_dev->htc_handle,
886 &hif_dev->udev->dev, hif_dev->device_id);
Sujithfb9987d2010-03-17 14:25:25 +0530887 if (ret) {
888 ret = -EINVAL;
889 goto err_htc_hw_init;
890 }
891
892 dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n");
893
894 return 0;
895
896err_htc_hw_init:
Sujithfb9987d2010-03-17 14:25:25 +0530897 ath9k_hif_usb_dev_deinit(hif_dev);
898err_hif_init_usb:
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +0530899 ath9k_htc_hw_free(hif_dev->htc_handle);
900err_htc_hw_alloc:
Sujithfb9987d2010-03-17 14:25:25 +0530901 usb_set_intfdata(interface, NULL);
902 kfree(hif_dev);
903 usb_put_dev(udev);
904err_alloc:
905 return ret;
906}
907
Sujith62e47162010-04-23 10:28:16 +0530908static void ath9k_hif_usb_reboot(struct usb_device *udev)
909{
910 u32 reboot_cmd = 0xffffffff;
911 void *buf;
912 int ret;
913
914 buf = kmalloc(4, GFP_KERNEL);
915 if (!buf)
916 return;
917
918 memcpy(buf, &reboot_cmd, 4);
919
920 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE),
921 buf, 4, NULL, HZ);
922 if (ret)
923 dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n");
924
925 kfree(buf);
926}
927
Sujithfb9987d2010-03-17 14:25:25 +0530928static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
929{
930 struct usb_device *udev = interface_to_usbdev(interface);
931 struct hif_device_usb *hif_dev =
932 (struct hif_device_usb *) usb_get_intfdata(interface);
933
934 if (hif_dev) {
Sujithd8f996f2010-04-23 10:28:20 +0530935 ath9k_htc_hw_deinit(hif_dev->htc_handle,
936 (udev->state == USB_STATE_NOTATTACHED) ? true : false);
Sujithfb9987d2010-03-17 14:25:25 +0530937 ath9k_htc_hw_free(hif_dev->htc_handle);
938 ath9k_hif_usb_dev_deinit(hif_dev);
939 usb_set_intfdata(interface, NULL);
940 }
941
942 if (hif_dev->flags & HIF_USB_START)
Sujith62e47162010-04-23 10:28:16 +0530943 ath9k_hif_usb_reboot(udev);
Sujithfb9987d2010-03-17 14:25:25 +0530944
945 kfree(hif_dev);
946 dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
947 usb_put_dev(udev);
948}
949
950#ifdef CONFIG_PM
951static int ath9k_hif_usb_suspend(struct usb_interface *interface,
952 pm_message_t message)
953{
954 struct hif_device_usb *hif_dev =
955 (struct hif_device_usb *) usb_get_intfdata(interface);
956
957 ath9k_hif_usb_dealloc_urbs(hif_dev);
958
959 return 0;
960}
961
962static int ath9k_hif_usb_resume(struct usb_interface *interface)
963{
964 struct hif_device_usb *hif_dev =
965 (struct hif_device_usb *) usb_get_intfdata(interface);
966 int ret;
967
968 ret = ath9k_hif_usb_alloc_urbs(hif_dev);
969 if (ret)
970 return ret;
971
972 if (hif_dev->firmware) {
973 ret = ath9k_hif_usb_download_fw(hif_dev);
974 if (ret)
975 goto fail_resume;
976 } else {
977 ath9k_hif_usb_dealloc_urbs(hif_dev);
978 return -EIO;
979 }
980
981 mdelay(100);
982
983 ret = ath9k_htc_resume(hif_dev->htc_handle);
984
985 if (ret)
986 goto fail_resume;
987
988 return 0;
989
990fail_resume:
991 ath9k_hif_usb_dealloc_urbs(hif_dev);
992
993 return ret;
994}
995#endif
996
997static struct usb_driver ath9k_hif_usb_driver = {
998 .name = "ath9k_hif_usb",
999 .probe = ath9k_hif_usb_probe,
1000 .disconnect = ath9k_hif_usb_disconnect,
1001#ifdef CONFIG_PM
1002 .suspend = ath9k_hif_usb_suspend,
1003 .resume = ath9k_hif_usb_resume,
1004 .reset_resume = ath9k_hif_usb_resume,
1005#endif
1006 .id_table = ath9k_hif_usb_ids,
1007 .soft_unbind = 1,
1008};
1009
1010int ath9k_hif_usb_init(void)
1011{
1012 return usb_register(&ath9k_hif_usb_driver);
1013}
1014
1015void ath9k_hif_usb_exit(void)
1016{
1017 usb_deregister(&ath9k_hif_usb_driver);
1018}