blob: 142405ccd6c1160d9240778e3ad03ea30cbead79 [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
Sujithfb9987d2010-03-17 14:25:25 +053019static struct usb_device_id ath9k_hif_usb_ids[] = {
Sujithce43cee2010-06-02 15:53:30 +053020 { USB_DEVICE(0x0cf3, 0x9271) },
21 { USB_DEVICE(0x0cf3, 0x1006) },
Sujithfb9987d2010-03-17 14:25:25 +053022 { },
23};
24
25MODULE_DEVICE_TABLE(usb, ath9k_hif_usb_ids);
26
27static int __hif_usb_tx(struct hif_device_usb *hif_dev);
28
29static void hif_usb_regout_cb(struct urb *urb)
30{
31 struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
Sujithfb9987d2010-03-17 14:25:25 +053032
33 switch (urb->status) {
34 case 0:
35 break;
36 case -ENOENT:
37 case -ECONNRESET:
Sujithfb9987d2010-03-17 14:25:25 +053038 case -ENODEV:
39 case -ESHUTDOWN:
Sujith6f0f2662010-04-06 15:28:17 +053040 goto free;
Sujithfb9987d2010-03-17 14:25:25 +053041 default:
42 break;
43 }
44
45 if (cmd) {
46 ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
47 cmd->skb, 1);
48 kfree(cmd);
Sujithfb9987d2010-03-17 14:25:25 +053049 }
Sujith6f0f2662010-04-06 15:28:17 +053050
51 return;
52free:
Ming Lei0fa35a52010-04-13 00:29:15 +080053 kfree_skb(cmd->skb);
Sujith6f0f2662010-04-06 15:28:17 +053054 kfree(cmd);
Sujithfb9987d2010-03-17 14:25:25 +053055}
56
57static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
58 struct sk_buff *skb)
59{
60 struct urb *urb;
61 struct cmd_buf *cmd;
62 int ret = 0;
63
64 urb = usb_alloc_urb(0, GFP_KERNEL);
65 if (urb == NULL)
66 return -ENOMEM;
67
68 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
69 if (cmd == NULL) {
70 usb_free_urb(urb);
71 return -ENOMEM;
72 }
73
74 cmd->skb = skb;
75 cmd->hif_dev = hif_dev;
76
77 usb_fill_int_urb(urb, hif_dev->udev,
78 usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE),
79 skb->data, skb->len,
80 hif_usb_regout_cb, cmd, 1);
81
Sujith6f0f2662010-04-06 15:28:17 +053082 usb_anchor_urb(urb, &hif_dev->regout_submitted);
Sujithfb9987d2010-03-17 14:25:25 +053083 ret = usb_submit_urb(urb, GFP_KERNEL);
84 if (ret) {
Sujith6f0f2662010-04-06 15:28:17 +053085 usb_unanchor_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +053086 kfree(cmd);
87 }
Sujith6f0f2662010-04-06 15:28:17 +053088 usb_free_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +053089
90 return ret;
91}
92
Sujitheac8e382010-04-16 11:54:00 +053093static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
94 struct sk_buff_head *list)
Ming Leif8e1d082010-04-13 00:29:27 +080095{
96 struct sk_buff *skb;
Sujitheac8e382010-04-16 11:54:00 +053097
98 while ((skb = __skb_dequeue(list)) != NULL) {
Ming Leif8e1d082010-04-13 00:29:27 +080099 dev_kfree_skb_any(skb);
Sujitheac8e382010-04-16 11:54:00 +0530100 TX_STAT_INC(skb_dropped);
101 }
Ming Leif8e1d082010-04-13 00:29:27 +0800102}
103
Sujithc11d8f82010-04-23 10:28:09 +0530104static void hif_usb_tx_cb(struct urb *urb)
105{
106 struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
Dan Carpenter690e7812010-05-14 16:50:56 +0200107 struct hif_device_usb *hif_dev;
Sujithc11d8f82010-04-23 10:28:09 +0530108 struct sk_buff *skb;
109
Dan Carpenter690e7812010-05-14 16:50:56 +0200110 if (!tx_buf || !tx_buf->hif_dev)
Sujithc11d8f82010-04-23 10:28:09 +0530111 return;
112
Dan Carpenter690e7812010-05-14 16:50:56 +0200113 hif_dev = tx_buf->hif_dev;
114
Sujithc11d8f82010-04-23 10:28:09 +0530115 switch (urb->status) {
116 case 0:
117 break;
118 case -ENOENT:
119 case -ECONNRESET:
120 case -ENODEV:
121 case -ESHUTDOWN:
122 /*
123 * The URB has been killed, free the SKBs
124 * and return.
125 */
126 ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
127 return;
128 default:
129 break;
130 }
131
132 /* Check if TX has been stopped */
133 spin_lock(&hif_dev->tx.tx_lock);
134 if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
135 spin_unlock(&hif_dev->tx.tx_lock);
136 ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
137 goto add_free;
138 }
139 spin_unlock(&hif_dev->tx.tx_lock);
140
141 /* Complete the queued SKBs. */
142 while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) {
143 ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
144 skb, 1);
145 TX_STAT_INC(skb_completed);
146 }
147
148add_free:
149 /* Re-initialize the SKB queue */
150 tx_buf->len = tx_buf->offset = 0;
151 __skb_queue_head_init(&tx_buf->skb_queue);
152
153 /* Add this TX buffer to the free list */
154 spin_lock(&hif_dev->tx.tx_lock);
155 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
156 hif_dev->tx.tx_buf_cnt++;
157 if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
158 __hif_usb_tx(hif_dev); /* Check for pending SKBs */
159 TX_STAT_INC(buf_completed);
160 spin_unlock(&hif_dev->tx.tx_lock);
161}
162
Sujithfb9987d2010-03-17 14:25:25 +0530163/* TX lock has to be taken */
164static int __hif_usb_tx(struct hif_device_usb *hif_dev)
165{
166 struct tx_buf *tx_buf = NULL;
167 struct sk_buff *nskb = NULL;
168 int ret = 0, i;
169 u16 *hdr, tx_skb_cnt = 0;
170 u8 *buf;
171
172 if (hif_dev->tx.tx_skb_cnt == 0)
173 return 0;
174
175 /* Check if a free TX buffer is available */
176 if (list_empty(&hif_dev->tx.tx_buf))
177 return 0;
178
179 tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list);
Sujithc11d8f82010-04-23 10:28:09 +0530180 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending);
Sujithfb9987d2010-03-17 14:25:25 +0530181 hif_dev->tx.tx_buf_cnt--;
182
183 tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM);
184
185 for (i = 0; i < tx_skb_cnt; i++) {
186 nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue);
187
188 /* Should never be NULL */
189 BUG_ON(!nskb);
190
191 hif_dev->tx.tx_skb_cnt--;
192
193 buf = tx_buf->buf;
194 buf += tx_buf->offset;
195 hdr = (u16 *)buf;
196 *hdr++ = nskb->len;
197 *hdr++ = ATH_USB_TX_STREAM_MODE_TAG;
198 buf += 4;
199 memcpy(buf, nskb->data, nskb->len);
200 tx_buf->len = nskb->len + 4;
201
202 if (i < (tx_skb_cnt - 1))
203 tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4;
204
205 if (i == (tx_skb_cnt - 1))
206 tx_buf->len += tx_buf->offset;
207
208 __skb_queue_tail(&tx_buf->skb_queue, nskb);
209 TX_STAT_INC(skb_queued);
210 }
211
212 usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev,
213 usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE),
214 tx_buf->buf, tx_buf->len,
215 hif_usb_tx_cb, tx_buf);
216
217 ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
218 if (ret) {
219 tx_buf->len = tx_buf->offset = 0;
Sujitheac8e382010-04-16 11:54:00 +0530220 ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
Sujithfb9987d2010-03-17 14:25:25 +0530221 __skb_queue_head_init(&tx_buf->skb_queue);
222 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
223 hif_dev->tx.tx_buf_cnt++;
224 }
225
226 if (!ret)
227 TX_STAT_INC(buf_queued);
228
229 return ret;
230}
231
232static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb,
233 struct ath9k_htc_tx_ctl *tx_ctl)
234{
235 unsigned long flags;
236
237 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
238
239 if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
240 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
241 return -ENODEV;
242 }
243
244 /* Check if the max queue count has been reached */
245 if (hif_dev->tx.tx_skb_cnt > MAX_TX_BUF_NUM) {
246 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
247 return -ENOMEM;
248 }
249
250 __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
251 hif_dev->tx.tx_skb_cnt++;
252
253 /* Send normal frames immediately */
254 if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL)))
255 __hif_usb_tx(hif_dev);
256
257 /* Check if AMPDUs have to be sent immediately */
258 if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) &&
259 (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
260 (hif_dev->tx.tx_skb_cnt < 2)) {
261 __hif_usb_tx(hif_dev);
262 }
263
264 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
265
266 return 0;
267}
268
269static void hif_usb_start(void *hif_handle, u8 pipe_id)
270{
271 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
272 unsigned long flags;
273
274 hif_dev->flags |= HIF_USB_START;
275
276 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
277 hif_dev->tx.flags &= ~HIF_USB_TX_STOP;
278 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
279}
280
281static void hif_usb_stop(void *hif_handle, u8 pipe_id)
282{
283 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
284 unsigned long flags;
285
286 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
Sujitheac8e382010-04-16 11:54:00 +0530287 ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue);
Sujithfb9987d2010-03-17 14:25:25 +0530288 hif_dev->tx.tx_skb_cnt = 0;
289 hif_dev->tx.flags |= HIF_USB_TX_STOP;
290 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
291}
292
293static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb,
294 struct ath9k_htc_tx_ctl *tx_ctl)
295{
296 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
297 int ret = 0;
298
299 switch (pipe_id) {
300 case USB_WLAN_TX_PIPE:
301 ret = hif_usb_send_tx(hif_dev, skb, tx_ctl);
302 break;
303 case USB_REG_OUT_PIPE:
304 ret = hif_usb_send_regout(hif_dev, skb);
305 break;
306 default:
Sujith6335ed02010-03-29 16:07:15 +0530307 dev_err(&hif_dev->udev->dev,
308 "ath9k_htc: Invalid TX pipe: %d\n", pipe_id);
Sujithfb9987d2010-03-17 14:25:25 +0530309 ret = -EINVAL;
310 break;
311 }
312
313 return ret;
314}
315
316static struct ath9k_htc_hif hif_usb = {
317 .transport = ATH9K_HIF_USB,
318 .name = "ath9k_hif_usb",
319
320 .control_ul_pipe = USB_REG_OUT_PIPE,
321 .control_dl_pipe = USB_REG_IN_PIPE,
322
323 .start = hif_usb_start,
324 .stop = hif_usb_stop,
325 .send = hif_usb_send,
326};
327
328static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
329 struct sk_buff *skb)
330{
Sujithc5032692010-04-06 15:28:15 +0530331 struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER];
Sujithfb9987d2010-03-17 14:25:25 +0530332 int index = 0, i = 0, chk_idx, len = skb->len;
333 int rx_remain_len = 0, rx_pkt_len = 0;
334 u16 pkt_len, pkt_tag, pool_index = 0;
335 u8 *ptr;
336
Sujith46baa1a2010-04-06 15:28:11 +0530337 spin_lock(&hif_dev->rx_lock);
338
Sujithfb9987d2010-03-17 14:25:25 +0530339 rx_remain_len = hif_dev->rx_remain_len;
340 rx_pkt_len = hif_dev->rx_transfer_len;
341
342 if (rx_remain_len != 0) {
343 struct sk_buff *remain_skb = hif_dev->remain_skb;
344
345 if (remain_skb) {
346 ptr = (u8 *) remain_skb->data;
347
348 index = rx_remain_len;
349 rx_remain_len -= hif_dev->rx_pad_len;
350 ptr += rx_pkt_len;
351
352 memcpy(ptr, skb->data, rx_remain_len);
353
354 rx_pkt_len += rx_remain_len;
355 hif_dev->rx_remain_len = 0;
356 skb_put(remain_skb, rx_pkt_len);
357
358 skb_pool[pool_index++] = remain_skb;
359
360 } else {
361 index = rx_remain_len;
362 }
363 }
364
Sujith46baa1a2010-04-06 15:28:11 +0530365 spin_unlock(&hif_dev->rx_lock);
366
Sujithfb9987d2010-03-17 14:25:25 +0530367 while (index < len) {
368 ptr = (u8 *) skb->data;
369
370 pkt_len = ptr[index] + (ptr[index+1] << 8);
371 pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
372
373 if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) {
374 u16 pad_len;
375
376 pad_len = 4 - (pkt_len & 0x3);
377 if (pad_len == 4)
378 pad_len = 0;
379
380 chk_idx = index;
381 index = index + 4 + pkt_len + pad_len;
382
383 if (index > MAX_RX_BUF_SIZE) {
Sujith46baa1a2010-04-06 15:28:11 +0530384 spin_lock(&hif_dev->rx_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530385 hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
386 hif_dev->rx_transfer_len =
387 MAX_RX_BUF_SIZE - chk_idx - 4;
388 hif_dev->rx_pad_len = pad_len;
389
390 nskb = __dev_alloc_skb(pkt_len + 32,
391 GFP_ATOMIC);
392 if (!nskb) {
393 dev_err(&hif_dev->udev->dev,
394 "ath9k_htc: RX memory allocation"
395 " error\n");
Sujith46baa1a2010-04-06 15:28:11 +0530396 spin_unlock(&hif_dev->rx_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530397 goto err;
398 }
399 skb_reserve(nskb, 32);
400 RX_STAT_INC(skb_allocated);
401
402 memcpy(nskb->data, &(skb->data[chk_idx+4]),
403 hif_dev->rx_transfer_len);
404
405 /* Record the buffer pointer */
406 hif_dev->remain_skb = nskb;
Sujith46baa1a2010-04-06 15:28:11 +0530407 spin_unlock(&hif_dev->rx_lock);
Sujithfb9987d2010-03-17 14:25:25 +0530408 } else {
409 nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
410 if (!nskb) {
411 dev_err(&hif_dev->udev->dev,
412 "ath9k_htc: RX memory allocation"
413 " error\n");
414 goto err;
415 }
416 skb_reserve(nskb, 32);
417 RX_STAT_INC(skb_allocated);
418
419 memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
420 skb_put(nskb, pkt_len);
421 skb_pool[pool_index++] = nskb;
422 }
423 } else {
424 RX_STAT_INC(skb_dropped);
Sujithfb9987d2010-03-17 14:25:25 +0530425 return;
426 }
427 }
428
429err:
Sujithfb9987d2010-03-17 14:25:25 +0530430 for (i = 0; i < pool_index; i++) {
431 ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
432 skb_pool[i]->len, USB_WLAN_RX_PIPE);
433 RX_STAT_INC(skb_completed);
434 }
435}
436
437static void ath9k_hif_usb_rx_cb(struct urb *urb)
438{
439 struct sk_buff *skb = (struct sk_buff *) urb->context;
Sujithfb9987d2010-03-17 14:25:25 +0530440 struct hif_device_usb *hif_dev = (struct hif_device_usb *)
441 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
442 int ret;
443
Sujith6335ed02010-03-29 16:07:15 +0530444 if (!skb)
445 return;
446
Sujithfb9987d2010-03-17 14:25:25 +0530447 if (!hif_dev)
448 goto free;
449
450 switch (urb->status) {
451 case 0:
452 break;
453 case -ENOENT:
454 case -ECONNRESET:
455 case -ENODEV:
456 case -ESHUTDOWN:
457 goto free;
458 default:
459 goto resubmit;
460 }
461
462 if (likely(urb->actual_length != 0)) {
463 skb_put(skb, urb->actual_length);
Sujithfb9987d2010-03-17 14:25:25 +0530464 ath9k_hif_usb_rx_stream(hif_dev, skb);
Sujithfb9987d2010-03-17 14:25:25 +0530465 }
466
467resubmit:
468 skb_reset_tail_pointer(skb);
469 skb_trim(skb, 0);
470
Sujith6335ed02010-03-29 16:07:15 +0530471 usb_anchor_urb(urb, &hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530472 ret = usb_submit_urb(urb, GFP_ATOMIC);
Sujith6335ed02010-03-29 16:07:15 +0530473 if (ret) {
474 usb_unanchor_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530475 goto free;
Sujith6335ed02010-03-29 16:07:15 +0530476 }
Sujithfb9987d2010-03-17 14:25:25 +0530477
478 return;
479free:
Ming Leif28a7b32010-04-13 00:28:53 +0800480 kfree_skb(skb);
Sujithfb9987d2010-03-17 14:25:25 +0530481}
482
483static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
484{
485 struct sk_buff *skb = (struct sk_buff *) urb->context;
486 struct sk_buff *nskb;
487 struct hif_device_usb *hif_dev = (struct hif_device_usb *)
488 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
489 int ret;
490
Sujith6335ed02010-03-29 16:07:15 +0530491 if (!skb)
492 return;
493
Sujithfb9987d2010-03-17 14:25:25 +0530494 if (!hif_dev)
495 goto free;
496
497 switch (urb->status) {
498 case 0:
499 break;
500 case -ENOENT:
501 case -ECONNRESET:
502 case -ENODEV:
503 case -ESHUTDOWN:
504 goto free;
505 default:
506 goto resubmit;
507 }
508
509 if (likely(urb->actual_length != 0)) {
510 skb_put(skb, urb->actual_length);
511
Sujith5ab0af32010-04-23 10:28:17 +0530512 /* Process the command first */
513 ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
514 skb->len, USB_REG_IN_PIPE);
515
516
Ming Leie6c6d332010-04-13 00:29:05 +0800517 nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
Sujith5ab0af32010-04-23 10:28:17 +0530518 if (!nskb) {
519 dev_err(&hif_dev->udev->dev,
520 "ath9k_htc: REG_IN memory allocation failure\n");
521 urb->context = NULL;
522 return;
523 }
Sujithfb9987d2010-03-17 14:25:25 +0530524
525 usb_fill_int_urb(urb, hif_dev->udev,
526 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
527 nskb->data, MAX_REG_IN_BUF_SIZE,
528 ath9k_hif_usb_reg_in_cb, nskb, 1);
529
530 ret = usb_submit_urb(urb, GFP_ATOMIC);
531 if (ret) {
Ming Leie6c6d332010-04-13 00:29:05 +0800532 kfree_skb(nskb);
Sujith5ab0af32010-04-23 10:28:17 +0530533 urb->context = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530534 }
535
Sujithfb9987d2010-03-17 14:25:25 +0530536 return;
537 }
538
539resubmit:
540 skb_reset_tail_pointer(skb);
541 skb_trim(skb, 0);
542
543 ret = usb_submit_urb(urb, GFP_ATOMIC);
544 if (ret)
545 goto free;
546
547 return;
548free:
Ming Leie6c6d332010-04-13 00:29:05 +0800549 kfree_skb(skb);
Sujith6335ed02010-03-29 16:07:15 +0530550 urb->context = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530551}
552
553static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
554{
Sujithfb9987d2010-03-17 14:25:25 +0530555 struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
556
Sujithc11d8f82010-04-23 10:28:09 +0530557 list_for_each_entry_safe(tx_buf, tx_buf_tmp,
558 &hif_dev->tx.tx_buf, list) {
559 usb_kill_urb(tx_buf->urb);
Sujithfb9987d2010-03-17 14:25:25 +0530560 list_del(&tx_buf->list);
561 usb_free_urb(tx_buf->urb);
562 kfree(tx_buf->buf);
563 kfree(tx_buf);
564 }
565
Sujithfb9987d2010-03-17 14:25:25 +0530566 list_for_each_entry_safe(tx_buf, tx_buf_tmp,
567 &hif_dev->tx.tx_pending, list) {
568 usb_kill_urb(tx_buf->urb);
569 list_del(&tx_buf->list);
570 usb_free_urb(tx_buf->urb);
571 kfree(tx_buf->buf);
572 kfree(tx_buf);
573 }
Sujithfb9987d2010-03-17 14:25:25 +0530574}
575
576static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
577{
578 struct tx_buf *tx_buf;
579 int i;
580
581 INIT_LIST_HEAD(&hif_dev->tx.tx_buf);
582 INIT_LIST_HEAD(&hif_dev->tx.tx_pending);
583 spin_lock_init(&hif_dev->tx.tx_lock);
584 __skb_queue_head_init(&hif_dev->tx.tx_skb_queue);
585
586 for (i = 0; i < MAX_TX_URB_NUM; i++) {
587 tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
588 if (!tx_buf)
589 goto err;
590
591 tx_buf->buf = kzalloc(MAX_TX_BUF_SIZE, GFP_KERNEL);
592 if (!tx_buf->buf)
593 goto err;
594
595 tx_buf->urb = usb_alloc_urb(0, GFP_KERNEL);
596 if (!tx_buf->urb)
597 goto err;
598
599 tx_buf->hif_dev = hif_dev;
600 __skb_queue_head_init(&tx_buf->skb_queue);
601
602 list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
603 }
604
605 hif_dev->tx.tx_buf_cnt = MAX_TX_URB_NUM;
606
607 return 0;
608err:
Dan Carpenter76066882010-05-14 16:52:37 +0200609 if (tx_buf) {
610 kfree(tx_buf->buf);
611 kfree(tx_buf);
612 }
Sujithfb9987d2010-03-17 14:25:25 +0530613 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
614 return -ENOMEM;
615}
616
Sujithfb9987d2010-03-17 14:25:25 +0530617static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
618{
Sujith6335ed02010-03-29 16:07:15 +0530619 usb_kill_anchored_urbs(&hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530620}
621
622static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
623{
Sujith6335ed02010-03-29 16:07:15 +0530624 struct urb *urb = NULL;
625 struct sk_buff *skb = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530626 int i, ret;
627
Sujith6335ed02010-03-29 16:07:15 +0530628 init_usb_anchor(&hif_dev->rx_submitted);
Sujith46baa1a2010-04-06 15:28:11 +0530629 spin_lock_init(&hif_dev->rx_lock);
Sujith6335ed02010-03-29 16:07:15 +0530630
Sujithfb9987d2010-03-17 14:25:25 +0530631 for (i = 0; i < MAX_RX_URB_NUM; i++) {
632
633 /* Allocate URB */
Sujith6335ed02010-03-29 16:07:15 +0530634 urb = usb_alloc_urb(0, GFP_KERNEL);
635 if (urb == NULL) {
Sujithfb9987d2010-03-17 14:25:25 +0530636 ret = -ENOMEM;
Sujith6335ed02010-03-29 16:07:15 +0530637 goto err_urb;
Sujithfb9987d2010-03-17 14:25:25 +0530638 }
639
640 /* Allocate buffer */
Ming Leif28a7b32010-04-13 00:28:53 +0800641 skb = alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL);
Sujith6335ed02010-03-29 16:07:15 +0530642 if (!skb) {
643 ret = -ENOMEM;
644 goto err_skb;
645 }
646
647 usb_fill_bulk_urb(urb, hif_dev->udev,
648 usb_rcvbulkpipe(hif_dev->udev,
649 USB_WLAN_RX_PIPE),
650 skb->data, MAX_RX_BUF_SIZE,
651 ath9k_hif_usb_rx_cb, skb);
652
653 /* Anchor URB */
654 usb_anchor_urb(urb, &hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530655
656 /* Submit URB */
Sujith6335ed02010-03-29 16:07:15 +0530657 ret = usb_submit_urb(urb, GFP_KERNEL);
658 if (ret) {
659 usb_unanchor_urb(urb);
660 goto err_submit;
661 }
Sujith66b10e32010-04-06 15:28:13 +0530662
663 /*
664 * Drop reference count.
665 * This ensures that the URB is freed when killing them.
666 */
667 usb_free_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530668 }
669
670 return 0;
671
Sujith6335ed02010-03-29 16:07:15 +0530672err_submit:
Ming Leif28a7b32010-04-13 00:28:53 +0800673 kfree_skb(skb);
Sujith6335ed02010-03-29 16:07:15 +0530674err_skb:
675 usb_free_urb(urb);
676err_urb:
Sujithfb9987d2010-03-17 14:25:25 +0530677 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
678 return ret;
679}
680
681static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev)
682{
683 if (hif_dev->reg_in_urb) {
684 usb_kill_urb(hif_dev->reg_in_urb);
Sujith6335ed02010-03-29 16:07:15 +0530685 if (hif_dev->reg_in_urb->context)
Ming Leie6c6d332010-04-13 00:29:05 +0800686 kfree_skb((void *)hif_dev->reg_in_urb->context);
Sujithfb9987d2010-03-17 14:25:25 +0530687 usb_free_urb(hif_dev->reg_in_urb);
688 hif_dev->reg_in_urb = NULL;
689 }
690}
691
692static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev)
693{
694 struct sk_buff *skb;
695
696 hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL);
697 if (hif_dev->reg_in_urb == NULL)
698 return -ENOMEM;
699
Ming Leie6c6d332010-04-13 00:29:05 +0800700 skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
Sujithfb9987d2010-03-17 14:25:25 +0530701 if (!skb)
702 goto err;
703
704 usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev,
705 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
706 skb->data, MAX_REG_IN_BUF_SIZE,
707 ath9k_hif_usb_reg_in_cb, skb, 1);
708
709 if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0)
Sujith6335ed02010-03-29 16:07:15 +0530710 goto err;
Sujithfb9987d2010-03-17 14:25:25 +0530711
712 return 0;
713
Sujithfb9987d2010-03-17 14:25:25 +0530714err:
715 ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
716 return -ENOMEM;
717}
718
719static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
720{
Sujith6f0f2662010-04-06 15:28:17 +0530721 /* Register Write */
722 init_usb_anchor(&hif_dev->regout_submitted);
723
Sujithfb9987d2010-03-17 14:25:25 +0530724 /* TX */
725 if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0)
726 goto err;
727
728 /* RX */
729 if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0)
730 goto err;
731
Sujith6f0f2662010-04-06 15:28:17 +0530732 /* Register Read */
Sujithfb9987d2010-03-17 14:25:25 +0530733 if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0)
734 goto err;
735
736 return 0;
737err:
738 return -ENOMEM;
739}
740
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530741static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
742{
743 usb_kill_anchored_urbs(&hif_dev->regout_submitted);
744 ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
745 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
746 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
747}
748
Sujithfb9987d2010-03-17 14:25:25 +0530749static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
750{
751 int transfer, err;
752 const void *data = hif_dev->firmware->data;
753 size_t len = hif_dev->firmware->size;
754 u32 addr = AR9271_FIRMWARE;
755 u8 *buf = kzalloc(4096, GFP_KERNEL);
756
757 if (!buf)
758 return -ENOMEM;
759
760 while (len) {
761 transfer = min_t(int, len, 4096);
762 memcpy(buf, data, transfer);
763
764 err = usb_control_msg(hif_dev->udev,
765 usb_sndctrlpipe(hif_dev->udev, 0),
766 FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT,
767 addr >> 8, 0, buf, transfer, HZ);
768 if (err < 0) {
769 kfree(buf);
770 return err;
771 }
772
773 len -= transfer;
774 data += transfer;
775 addr += transfer;
776 }
777 kfree(buf);
778
779 /*
780 * Issue FW download complete command to firmware.
781 */
782 err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0),
783 FIRMWARE_DOWNLOAD_COMP,
784 0x40 | USB_DIR_OUT,
785 AR9271_FIRMWARE_TEXT >> 8, 0, NULL, 0, HZ);
786 if (err)
787 return -EIO;
788
789 dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n",
Sujithce43cee2010-06-02 15:53:30 +0530790 hif_dev->fw_name, (unsigned long) hif_dev->firmware->size);
Sujithfb9987d2010-03-17 14:25:25 +0530791
792 return 0;
793}
794
Sujithce43cee2010-06-02 15:53:30 +0530795static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
Sujithfb9987d2010-03-17 14:25:25 +0530796{
797 int ret;
798
799 /* Request firmware */
Sujithce43cee2010-06-02 15:53:30 +0530800 ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name,
801 &hif_dev->udev->dev);
Sujithfb9987d2010-03-17 14:25:25 +0530802 if (ret) {
803 dev_err(&hif_dev->udev->dev,
Sujithce43cee2010-06-02 15:53:30 +0530804 "ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name);
Sujithfb9987d2010-03-17 14:25:25 +0530805 goto err_fw_req;
806 }
807
Sujithfb9987d2010-03-17 14:25:25 +0530808 /* Alloc URBs */
809 ret = ath9k_hif_usb_alloc_urbs(hif_dev);
810 if (ret) {
811 dev_err(&hif_dev->udev->dev,
812 "ath9k_htc: Unable to allocate URBs\n");
813 goto err_urb;
814 }
815
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530816 /* Download firmware */
817 ret = ath9k_hif_usb_download_fw(hif_dev);
818 if (ret) {
819 dev_err(&hif_dev->udev->dev,
Sujithce43cee2010-06-02 15:53:30 +0530820 "ath9k_htc: Firmware - %s download failed\n",
821 hif_dev->fw_name);
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530822 goto err_fw_download;
823 }
824
Sujithfb9987d2010-03-17 14:25:25 +0530825 return 0;
826
Sujithfb9987d2010-03-17 14:25:25 +0530827err_fw_download:
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530828 ath9k_hif_usb_dealloc_urbs(hif_dev);
829err_urb:
Sujithfb9987d2010-03-17 14:25:25 +0530830 release_firmware(hif_dev->firmware);
831err_fw_req:
832 hif_dev->firmware = NULL;
833 return ret;
834}
835
Sujithfb9987d2010-03-17 14:25:25 +0530836static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
837{
838 ath9k_hif_usb_dealloc_urbs(hif_dev);
839 if (hif_dev->firmware)
840 release_firmware(hif_dev->firmware);
841}
842
843static int ath9k_hif_usb_probe(struct usb_interface *interface,
844 const struct usb_device_id *id)
845{
846 struct usb_device *udev = interface_to_usbdev(interface);
847 struct hif_device_usb *hif_dev;
Sujithfb9987d2010-03-17 14:25:25 +0530848 int ret = 0;
849
850 hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL);
851 if (!hif_dev) {
852 ret = -ENOMEM;
853 goto err_alloc;
854 }
855
856 usb_get_dev(udev);
857 hif_dev->udev = udev;
858 hif_dev->interface = interface;
859 hif_dev->device_id = id->idProduct;
860#ifdef CONFIG_PM
861 udev->reset_resume = 1;
862#endif
863 usb_set_intfdata(interface, hif_dev);
864
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +0530865 hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
866 &hif_dev->udev->dev);
867 if (hif_dev->htc_handle == NULL) {
868 ret = -ENOMEM;
869 goto err_htc_hw_alloc;
870 }
871
Sujithce43cee2010-06-02 15:53:30 +0530872 /* Find out which firmware to load */
873
874 switch(hif_dev->device_id) {
875 case 0x9271:
876 case 0x1006:
877 hif_dev->fw_name = "ar9271.fw";
878 break;
879 default:
880 break;
881 }
882
883 if (!hif_dev->fw_name) {
884 dev_err(&udev->dev, "Can't determine firmware !\n");
885 goto err_htc_hw_alloc;
886 }
887
888 ret = ath9k_hif_usb_dev_init(hif_dev);
Sujithfb9987d2010-03-17 14:25:25 +0530889 if (ret) {
890 ret = -EINVAL;
891 goto err_hif_init_usb;
892 }
893
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +0530894 ret = ath9k_htc_hw_init(hif_dev->htc_handle,
895 &hif_dev->udev->dev, hif_dev->device_id);
Sujithfb9987d2010-03-17 14:25:25 +0530896 if (ret) {
897 ret = -EINVAL;
898 goto err_htc_hw_init;
899 }
900
901 dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n");
902
903 return 0;
904
905err_htc_hw_init:
Sujithfb9987d2010-03-17 14:25:25 +0530906 ath9k_hif_usb_dev_deinit(hif_dev);
907err_hif_init_usb:
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +0530908 ath9k_htc_hw_free(hif_dev->htc_handle);
909err_htc_hw_alloc:
Sujithfb9987d2010-03-17 14:25:25 +0530910 usb_set_intfdata(interface, NULL);
911 kfree(hif_dev);
912 usb_put_dev(udev);
913err_alloc:
914 return ret;
915}
916
Sujith62e47162010-04-23 10:28:16 +0530917static void ath9k_hif_usb_reboot(struct usb_device *udev)
918{
919 u32 reboot_cmd = 0xffffffff;
920 void *buf;
921 int ret;
922
Julia Lawalla465a2c2010-05-15 23:17:19 +0200923 buf = kmemdup(&reboot_cmd, 4, GFP_KERNEL);
Sujith62e47162010-04-23 10:28:16 +0530924 if (!buf)
925 return;
926
Sujith62e47162010-04-23 10:28:16 +0530927 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE),
928 buf, 4, NULL, HZ);
929 if (ret)
930 dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n");
931
932 kfree(buf);
933}
934
Sujithfb9987d2010-03-17 14:25:25 +0530935static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
936{
937 struct usb_device *udev = interface_to_usbdev(interface);
938 struct hif_device_usb *hif_dev =
939 (struct hif_device_usb *) usb_get_intfdata(interface);
940
941 if (hif_dev) {
Sujithd8f996f2010-04-23 10:28:20 +0530942 ath9k_htc_hw_deinit(hif_dev->htc_handle,
943 (udev->state == USB_STATE_NOTATTACHED) ? true : false);
Sujithfb9987d2010-03-17 14:25:25 +0530944 ath9k_htc_hw_free(hif_dev->htc_handle);
945 ath9k_hif_usb_dev_deinit(hif_dev);
946 usb_set_intfdata(interface, NULL);
947 }
948
949 if (hif_dev->flags & HIF_USB_START)
Sujith62e47162010-04-23 10:28:16 +0530950 ath9k_hif_usb_reboot(udev);
Sujithfb9987d2010-03-17 14:25:25 +0530951
952 kfree(hif_dev);
953 dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
954 usb_put_dev(udev);
955}
956
957#ifdef CONFIG_PM
958static int ath9k_hif_usb_suspend(struct usb_interface *interface,
959 pm_message_t message)
960{
961 struct hif_device_usb *hif_dev =
962 (struct hif_device_usb *) usb_get_intfdata(interface);
963
964 ath9k_hif_usb_dealloc_urbs(hif_dev);
965
966 return 0;
967}
968
969static int ath9k_hif_usb_resume(struct usb_interface *interface)
970{
971 struct hif_device_usb *hif_dev =
972 (struct hif_device_usb *) usb_get_intfdata(interface);
973 int ret;
974
975 ret = ath9k_hif_usb_alloc_urbs(hif_dev);
976 if (ret)
977 return ret;
978
979 if (hif_dev->firmware) {
980 ret = ath9k_hif_usb_download_fw(hif_dev);
981 if (ret)
982 goto fail_resume;
983 } else {
984 ath9k_hif_usb_dealloc_urbs(hif_dev);
985 return -EIO;
986 }
987
988 mdelay(100);
989
990 ret = ath9k_htc_resume(hif_dev->htc_handle);
991
992 if (ret)
993 goto fail_resume;
994
995 return 0;
996
997fail_resume:
998 ath9k_hif_usb_dealloc_urbs(hif_dev);
999
1000 return ret;
1001}
1002#endif
1003
1004static struct usb_driver ath9k_hif_usb_driver = {
1005 .name = "ath9k_hif_usb",
1006 .probe = ath9k_hif_usb_probe,
1007 .disconnect = ath9k_hif_usb_disconnect,
1008#ifdef CONFIG_PM
1009 .suspend = ath9k_hif_usb_suspend,
1010 .resume = ath9k_hif_usb_resume,
1011 .reset_resume = ath9k_hif_usb_resume,
1012#endif
1013 .id_table = ath9k_hif_usb_ids,
1014 .soft_unbind = 1,
1015};
1016
1017int ath9k_hif_usb_init(void)
1018{
1019 return usb_register(&ath9k_hif_usb_driver);
1020}
1021
1022void ath9k_hif_usb_exit(void)
1023{
1024 usb_deregister(&ath9k_hif_usb_driver);
1025}