blob: db07e7b932046caa3eca774396d97416ac72e5d6 [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
John W. Linvilled0ee0eb2010-06-23 14:20:45 -040019/* identify firmware images */
Sujith Manoharance18f392011-04-13 11:22:42 +053020#define FIRMWARE_AR7010_1_1 "htc_7010.fw"
21#define FIRMWARE_AR9271 "htc_9271.fw"
John W. Linvilled0ee0eb2010-06-23 14:20:45 -040022
John W. Linvilled0ee0eb2010-06-23 14:20:45 -040023MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
24MODULE_FIRMWARE(FIRMWARE_AR9271);
25
Sujithfb9987d2010-03-17 14:25:25 +053026static struct usb_device_id ath9k_hif_usb_ids[] = {
Sujith4e63f762010-06-17 10:29:01 +053027 { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
28 { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */
Sujith4e63f762010-06-17 10:29:01 +053029 { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */
Sujith4e63f762010-06-17 10:29:01 +053030 { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
31 { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
32 { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
Haitao Zhangac618d72010-11-07 12:50:24 +080033 { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */
Rajkumar Manoharan32b08952010-11-10 17:51:24 +053034 { USB_DEVICE(0x13D3, 0x3348) }, /* Azurewave */
35 { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */
36 { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */
Sujith4e63f762010-06-17 10:29:01 +053037 { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
Rajkumar Manoharan32b08952010-11-10 17:51:24 +053038 { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
Sujith Manoharan452d7dd2010-12-13 07:39:32 +053039 { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
Sujith Manoharan0b5ead92010-12-07 16:31:38 +053040
41 { USB_DEVICE(0x0cf3, 0x7015),
42 .driver_info = AR9287_USB }, /* Atheros */
Rajkumar Manoharan64f12172010-11-19 16:53:20 +053043 { USB_DEVICE(0x1668, 0x1200),
Sujith Manoharan0b5ead92010-12-07 16:31:38 +053044 .driver_info = AR9287_USB }, /* Verizon */
45
46 { USB_DEVICE(0x0cf3, 0x7010),
47 .driver_info = AR9280_USB }, /* Atheros */
48 { USB_DEVICE(0x0846, 0x9018),
49 .driver_info = AR9280_USB }, /* Netgear WNDA3200 */
50 { USB_DEVICE(0x083A, 0xA704),
51 .driver_info = AR9280_USB }, /* SMC Networks */
52
Sujith Manoharan36bcce42011-02-21 07:47:52 +053053 { USB_DEVICE(0x0cf3, 0x20ff),
54 .driver_info = STORAGE_DEVICE },
55
Sujithfb9987d2010-03-17 14:25:25 +053056 { },
57};
58
59MODULE_DEVICE_TABLE(usb, ath9k_hif_usb_ids);
60
61static int __hif_usb_tx(struct hif_device_usb *hif_dev);
62
63static void hif_usb_regout_cb(struct urb *urb)
64{
65 struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
Sujithfb9987d2010-03-17 14:25:25 +053066
67 switch (urb->status) {
68 case 0:
69 break;
70 case -ENOENT:
71 case -ECONNRESET:
Sujithfb9987d2010-03-17 14:25:25 +053072 case -ENODEV:
73 case -ESHUTDOWN:
Sujith6f0f2662010-04-06 15:28:17 +053074 goto free;
Sujithfb9987d2010-03-17 14:25:25 +053075 default:
76 break;
77 }
78
79 if (cmd) {
80 ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle,
81 cmd->skb, 1);
82 kfree(cmd);
Sujithfb9987d2010-03-17 14:25:25 +053083 }
Sujith6f0f2662010-04-06 15:28:17 +053084
85 return;
86free:
Ming Lei0fa35a52010-04-13 00:29:15 +080087 kfree_skb(cmd->skb);
Sujith6f0f2662010-04-06 15:28:17 +053088 kfree(cmd);
Sujithfb9987d2010-03-17 14:25:25 +053089}
90
91static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
92 struct sk_buff *skb)
93{
94 struct urb *urb;
95 struct cmd_buf *cmd;
96 int ret = 0;
97
98 urb = usb_alloc_urb(0, GFP_KERNEL);
99 if (urb == NULL)
100 return -ENOMEM;
101
102 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
103 if (cmd == NULL) {
104 usb_free_urb(urb);
105 return -ENOMEM;
106 }
107
108 cmd->skb = skb;
109 cmd->hif_dev = hif_dev;
110
Rajkumar Manoharan4a0e8ecc2010-09-14 14:35:55 +0530111 usb_fill_bulk_urb(urb, hif_dev->udev,
112 usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE),
Sujithfb9987d2010-03-17 14:25:25 +0530113 skb->data, skb->len,
Rajkumar Manoharan4a0e8ecc2010-09-14 14:35:55 +0530114 hif_usb_regout_cb, cmd);
Sujithfb9987d2010-03-17 14:25:25 +0530115
Sujith6f0f2662010-04-06 15:28:17 +0530116 usb_anchor_urb(urb, &hif_dev->regout_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530117 ret = usb_submit_urb(urb, GFP_KERNEL);
118 if (ret) {
Sujith6f0f2662010-04-06 15:28:17 +0530119 usb_unanchor_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530120 kfree(cmd);
121 }
Sujith6f0f2662010-04-06 15:28:17 +0530122 usb_free_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530123
124 return ret;
125}
126
Sujitheac8e382010-04-16 11:54:00 +0530127static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
128 struct sk_buff_head *list)
Ming Leif8e1d082010-04-13 00:29:27 +0800129{
130 struct sk_buff *skb;
Sujitheac8e382010-04-16 11:54:00 +0530131
132 while ((skb = __skb_dequeue(list)) != NULL) {
Ming Leif8e1d082010-04-13 00:29:27 +0800133 dev_kfree_skb_any(skb);
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530134 }
135}
136
137static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev,
138 struct sk_buff_head *queue,
139 bool txok)
140{
141 struct sk_buff *skb;
142
143 while ((skb = __skb_dequeue(queue)) != NULL) {
144 ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
145 skb, txok);
146 (txok) ? TX_STAT_INC(skb_success) : TX_STAT_INC(skb_failed);
Sujitheac8e382010-04-16 11:54:00 +0530147 }
Ming Leif8e1d082010-04-13 00:29:27 +0800148}
149
Sujithc11d8f82010-04-23 10:28:09 +0530150static void hif_usb_tx_cb(struct urb *urb)
151{
152 struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
Dan Carpenter690e7812010-05-14 16:50:56 +0200153 struct hif_device_usb *hif_dev;
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530154 bool txok = true;
Sujithc11d8f82010-04-23 10:28:09 +0530155
Dan Carpenter690e7812010-05-14 16:50:56 +0200156 if (!tx_buf || !tx_buf->hif_dev)
Sujithc11d8f82010-04-23 10:28:09 +0530157 return;
158
Dan Carpenter690e7812010-05-14 16:50:56 +0200159 hif_dev = tx_buf->hif_dev;
160
Sujithc11d8f82010-04-23 10:28:09 +0530161 switch (urb->status) {
162 case 0:
163 break;
164 case -ENOENT:
165 case -ECONNRESET:
166 case -ENODEV:
167 case -ESHUTDOWN:
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530168 txok = false;
Sujith Manoharanff8f59b2010-12-28 14:28:05 +0530169
170 /*
171 * If the URBs are being flushed, no need to add this
172 * URB to the free list.
173 */
174 spin_lock(&hif_dev->tx.tx_lock);
175 if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
176 spin_unlock(&hif_dev->tx.tx_lock);
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530177 ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
Sujith Manoharanff8f59b2010-12-28 14:28:05 +0530178 return;
179 }
180 spin_unlock(&hif_dev->tx.tx_lock);
181
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530182 break;
Sujithc11d8f82010-04-23 10:28:09 +0530183 default:
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530184 txok = false;
Sujithc11d8f82010-04-23 10:28:09 +0530185 break;
186 }
187
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530188 ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok);
Sujithc11d8f82010-04-23 10:28:09 +0530189
Sujithc11d8f82010-04-23 10:28:09 +0530190 /* Re-initialize the SKB queue */
191 tx_buf->len = tx_buf->offset = 0;
192 __skb_queue_head_init(&tx_buf->skb_queue);
193
194 /* Add this TX buffer to the free list */
195 spin_lock(&hif_dev->tx.tx_lock);
196 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
197 hif_dev->tx.tx_buf_cnt++;
198 if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
199 __hif_usb_tx(hif_dev); /* Check for pending SKBs */
200 TX_STAT_INC(buf_completed);
201 spin_unlock(&hif_dev->tx.tx_lock);
202}
203
Sujithfb9987d2010-03-17 14:25:25 +0530204/* TX lock has to be taken */
205static int __hif_usb_tx(struct hif_device_usb *hif_dev)
206{
207 struct tx_buf *tx_buf = NULL;
208 struct sk_buff *nskb = NULL;
209 int ret = 0, i;
Sujith Manoharan2c273922011-02-27 09:23:52 +0530210 u16 tx_skb_cnt = 0;
Sujithfb9987d2010-03-17 14:25:25 +0530211 u8 *buf;
Sujith Manoharan2c273922011-02-27 09:23:52 +0530212 __le16 *hdr;
Sujithfb9987d2010-03-17 14:25:25 +0530213
214 if (hif_dev->tx.tx_skb_cnt == 0)
215 return 0;
216
217 /* Check if a free TX buffer is available */
218 if (list_empty(&hif_dev->tx.tx_buf))
219 return 0;
220
221 tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list);
Sujithc11d8f82010-04-23 10:28:09 +0530222 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending);
Sujithfb9987d2010-03-17 14:25:25 +0530223 hif_dev->tx.tx_buf_cnt--;
224
225 tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM);
226
227 for (i = 0; i < tx_skb_cnt; i++) {
228 nskb = __skb_dequeue(&hif_dev->tx.tx_skb_queue);
229
230 /* Should never be NULL */
231 BUG_ON(!nskb);
232
233 hif_dev->tx.tx_skb_cnt--;
234
235 buf = tx_buf->buf;
236 buf += tx_buf->offset;
Sujith Manoharan2c273922011-02-27 09:23:52 +0530237 hdr = (__le16 *)buf;
238 *hdr++ = cpu_to_le16(nskb->len);
239 *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG);
Sujithfb9987d2010-03-17 14:25:25 +0530240 buf += 4;
241 memcpy(buf, nskb->data, nskb->len);
242 tx_buf->len = nskb->len + 4;
243
244 if (i < (tx_skb_cnt - 1))
245 tx_buf->offset += (((tx_buf->len - 1) / 4) + 1) * 4;
246
247 if (i == (tx_skb_cnt - 1))
248 tx_buf->len += tx_buf->offset;
249
250 __skb_queue_tail(&tx_buf->skb_queue, nskb);
251 TX_STAT_INC(skb_queued);
252 }
253
254 usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev,
255 usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE),
256 tx_buf->buf, tx_buf->len,
257 hif_usb_tx_cb, tx_buf);
258
259 ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
260 if (ret) {
261 tx_buf->len = tx_buf->offset = 0;
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530262 ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false);
Sujithfb9987d2010-03-17 14:25:25 +0530263 __skb_queue_head_init(&tx_buf->skb_queue);
264 list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
265 hif_dev->tx.tx_buf_cnt++;
266 }
267
268 if (!ret)
269 TX_STAT_INC(buf_queued);
270
271 return ret;
272}
273
Sujith Manoharan40dc9e42011-04-13 11:24:31 +0530274static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb)
Sujithfb9987d2010-03-17 14:25:25 +0530275{
Sujith Manoharan40dc9e42011-04-13 11:24:31 +0530276 struct ath9k_htc_tx_ctl *tx_ctl;
Sujithfb9987d2010-03-17 14:25:25 +0530277 unsigned long flags;
278
279 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
280
281 if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
282 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
283 return -ENODEV;
284 }
285
286 /* Check if the max queue count has been reached */
287 if (hif_dev->tx.tx_skb_cnt > MAX_TX_BUF_NUM) {
288 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
289 return -ENOMEM;
290 }
291
292 __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb);
293 hif_dev->tx.tx_skb_cnt++;
294
Sujith Manoharan40dc9e42011-04-13 11:24:31 +0530295 tx_ctl = HTC_SKB_CB(skb);
296
297 /* Send normal/mgmt/beacon frames immediately */
298 if (tx_ctl->type != ATH9K_HTC_AMPDU)
Sujithfb9987d2010-03-17 14:25:25 +0530299 __hif_usb_tx(hif_dev);
300
301 /* Check if AMPDUs have to be sent immediately */
Sujith Manoharan40dc9e42011-04-13 11:24:31 +0530302 if ((tx_ctl->type == ATH9K_HTC_AMPDU) &&
Sujithfb9987d2010-03-17 14:25:25 +0530303 (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) &&
304 (hif_dev->tx.tx_skb_cnt < 2)) {
305 __hif_usb_tx(hif_dev);
306 }
307
308 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
309
310 return 0;
311}
312
313static void hif_usb_start(void *hif_handle, u8 pipe_id)
314{
315 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
316 unsigned long flags;
317
318 hif_dev->flags |= HIF_USB_START;
319
320 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
321 hif_dev->tx.flags &= ~HIF_USB_TX_STOP;
322 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
323}
324
325static void hif_usb_stop(void *hif_handle, u8 pipe_id)
326{
327 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
Sujith Manoharanff8f59b2010-12-28 14:28:05 +0530328 struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530329 unsigned long flags;
330
331 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
Sujith Manoharanb587fc82011-04-13 11:25:59 +0530332 ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false);
Sujithfb9987d2010-03-17 14:25:25 +0530333 hif_dev->tx.tx_skb_cnt = 0;
334 hif_dev->tx.flags |= HIF_USB_TX_STOP;
335 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
Sujith Manoharanff8f59b2010-12-28 14:28:05 +0530336
337 /* The pending URBs have to be canceled. */
338 list_for_each_entry_safe(tx_buf, tx_buf_tmp,
339 &hif_dev->tx.tx_pending, list) {
340 usb_kill_urb(tx_buf->urb);
341 }
Sujithfb9987d2010-03-17 14:25:25 +0530342}
343
Sujith Manoharan40dc9e42011-04-13 11:24:31 +0530344static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb)
Sujithfb9987d2010-03-17 14:25:25 +0530345{
346 struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle;
347 int ret = 0;
348
349 switch (pipe_id) {
350 case USB_WLAN_TX_PIPE:
Sujith Manoharan40dc9e42011-04-13 11:24:31 +0530351 ret = hif_usb_send_tx(hif_dev, skb);
Sujithfb9987d2010-03-17 14:25:25 +0530352 break;
353 case USB_REG_OUT_PIPE:
354 ret = hif_usb_send_regout(hif_dev, skb);
355 break;
356 default:
Sujith6335ed02010-03-29 16:07:15 +0530357 dev_err(&hif_dev->udev->dev,
358 "ath9k_htc: Invalid TX pipe: %d\n", pipe_id);
Sujithfb9987d2010-03-17 14:25:25 +0530359 ret = -EINVAL;
360 break;
361 }
362
363 return ret;
364}
365
366static struct ath9k_htc_hif hif_usb = {
367 .transport = ATH9K_HIF_USB,
368 .name = "ath9k_hif_usb",
369
370 .control_ul_pipe = USB_REG_OUT_PIPE,
371 .control_dl_pipe = USB_REG_IN_PIPE,
372
373 .start = hif_usb_start,
374 .stop = hif_usb_stop,
375 .send = hif_usb_send,
376};
377
378static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
379 struct sk_buff *skb)
380{
Sujithc5032692010-04-06 15:28:15 +0530381 struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER];
Joe Perches44b23b42010-11-30 12:19:11 -0800382 int index = 0, i = 0, len = skb->len;
383 int rx_remain_len, rx_pkt_len;
384 u16 pool_index = 0;
Sujithfb9987d2010-03-17 14:25:25 +0530385 u8 *ptr;
386
Sujith46baa1a2010-04-06 15:28:11 +0530387 spin_lock(&hif_dev->rx_lock);
388
Sujithfb9987d2010-03-17 14:25:25 +0530389 rx_remain_len = hif_dev->rx_remain_len;
390 rx_pkt_len = hif_dev->rx_transfer_len;
391
392 if (rx_remain_len != 0) {
393 struct sk_buff *remain_skb = hif_dev->remain_skb;
394
395 if (remain_skb) {
396 ptr = (u8 *) remain_skb->data;
397
398 index = rx_remain_len;
399 rx_remain_len -= hif_dev->rx_pad_len;
400 ptr += rx_pkt_len;
401
402 memcpy(ptr, skb->data, rx_remain_len);
403
404 rx_pkt_len += rx_remain_len;
405 hif_dev->rx_remain_len = 0;
406 skb_put(remain_skb, rx_pkt_len);
407
408 skb_pool[pool_index++] = remain_skb;
409
410 } else {
411 index = rx_remain_len;
412 }
413 }
414
Sujith46baa1a2010-04-06 15:28:11 +0530415 spin_unlock(&hif_dev->rx_lock);
416
Sujithfb9987d2010-03-17 14:25:25 +0530417 while (index < len) {
Joe Perches44b23b42010-11-30 12:19:11 -0800418 u16 pkt_len;
419 u16 pkt_tag;
420 u16 pad_len;
421 int chk_idx;
422
Sujithfb9987d2010-03-17 14:25:25 +0530423 ptr = (u8 *) skb->data;
424
425 pkt_len = ptr[index] + (ptr[index+1] << 8);
426 pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
427
Joe Perches44b23b42010-11-30 12:19:11 -0800428 if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
Sujithfb9987d2010-03-17 14:25:25 +0530429 RX_STAT_INC(skb_dropped);
Sujithfb9987d2010-03-17 14:25:25 +0530430 return;
431 }
Joe Perches44b23b42010-11-30 12:19:11 -0800432
433 pad_len = 4 - (pkt_len & 0x3);
434 if (pad_len == 4)
435 pad_len = 0;
436
437 chk_idx = index;
438 index = index + 4 + pkt_len + pad_len;
439
440 if (index > MAX_RX_BUF_SIZE) {
441 spin_lock(&hif_dev->rx_lock);
442 hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
443 hif_dev->rx_transfer_len =
444 MAX_RX_BUF_SIZE - chk_idx - 4;
445 hif_dev->rx_pad_len = pad_len;
446
447 nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
448 if (!nskb) {
449 dev_err(&hif_dev->udev->dev,
450 "ath9k_htc: RX memory allocation error\n");
451 spin_unlock(&hif_dev->rx_lock);
452 goto err;
453 }
454 skb_reserve(nskb, 32);
455 RX_STAT_INC(skb_allocated);
456
457 memcpy(nskb->data, &(skb->data[chk_idx+4]),
458 hif_dev->rx_transfer_len);
459
460 /* Record the buffer pointer */
461 hif_dev->remain_skb = nskb;
462 spin_unlock(&hif_dev->rx_lock);
463 } else {
464 nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
465 if (!nskb) {
466 dev_err(&hif_dev->udev->dev,
467 "ath9k_htc: RX memory allocation error\n");
468 goto err;
469 }
470 skb_reserve(nskb, 32);
471 RX_STAT_INC(skb_allocated);
472
473 memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
474 skb_put(nskb, pkt_len);
475 skb_pool[pool_index++] = nskb;
476 }
Sujithfb9987d2010-03-17 14:25:25 +0530477 }
478
479err:
Sujithfb9987d2010-03-17 14:25:25 +0530480 for (i = 0; i < pool_index; i++) {
481 ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
482 skb_pool[i]->len, USB_WLAN_RX_PIPE);
483 RX_STAT_INC(skb_completed);
484 }
485}
486
487static void ath9k_hif_usb_rx_cb(struct urb *urb)
488{
489 struct sk_buff *skb = (struct sk_buff *) urb->context;
Joe Perchesb2767362010-11-30 13:42:08 -0800490 struct hif_device_usb *hif_dev =
Sujithfb9987d2010-03-17 14:25:25 +0530491 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);
Sujithfb9987d2010-03-17 14:25:25 +0530514 ath9k_hif_usb_rx_stream(hif_dev, skb);
Sujithfb9987d2010-03-17 14:25:25 +0530515 }
516
517resubmit:
518 skb_reset_tail_pointer(skb);
519 skb_trim(skb, 0);
520
Sujith6335ed02010-03-29 16:07:15 +0530521 usb_anchor_urb(urb, &hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530522 ret = usb_submit_urb(urb, GFP_ATOMIC);
Sujith6335ed02010-03-29 16:07:15 +0530523 if (ret) {
524 usb_unanchor_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530525 goto free;
Sujith6335ed02010-03-29 16:07:15 +0530526 }
Sujithfb9987d2010-03-17 14:25:25 +0530527
528 return;
529free:
Ming Leif28a7b32010-04-13 00:28:53 +0800530 kfree_skb(skb);
Sujithfb9987d2010-03-17 14:25:25 +0530531}
532
533static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
534{
535 struct sk_buff *skb = (struct sk_buff *) urb->context;
536 struct sk_buff *nskb;
Joe Perchesb2767362010-11-30 13:42:08 -0800537 struct hif_device_usb *hif_dev =
Sujithfb9987d2010-03-17 14:25:25 +0530538 usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
539 int ret;
540
Sujith6335ed02010-03-29 16:07:15 +0530541 if (!skb)
542 return;
543
Sujithfb9987d2010-03-17 14:25:25 +0530544 if (!hif_dev)
545 goto free;
546
547 switch (urb->status) {
548 case 0:
549 break;
550 case -ENOENT:
551 case -ECONNRESET:
552 case -ENODEV:
553 case -ESHUTDOWN:
554 goto free;
555 default:
Sujith Manoharan3deff762011-04-13 11:25:23 +0530556 skb_reset_tail_pointer(skb);
557 skb_trim(skb, 0);
558
Sujithfb9987d2010-03-17 14:25:25 +0530559 goto resubmit;
560 }
561
562 if (likely(urb->actual_length != 0)) {
563 skb_put(skb, urb->actual_length);
564
Sujith5ab0af32010-04-23 10:28:17 +0530565 /* Process the command first */
566 ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
567 skb->len, USB_REG_IN_PIPE);
568
569
Ming Leie6c6d332010-04-13 00:29:05 +0800570 nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
Sujith5ab0af32010-04-23 10:28:17 +0530571 if (!nskb) {
572 dev_err(&hif_dev->udev->dev,
573 "ath9k_htc: REG_IN memory allocation failure\n");
574 urb->context = NULL;
575 return;
576 }
Sujithfb9987d2010-03-17 14:25:25 +0530577
Rajkumar Manoharan490b3f42010-11-08 12:49:12 +0530578 usb_fill_bulk_urb(urb, hif_dev->udev,
Rajkumar Manoharan0f529e92010-09-16 19:56:55 +0530579 usb_rcvbulkpipe(hif_dev->udev,
580 USB_REG_IN_PIPE),
Sujithfb9987d2010-03-17 14:25:25 +0530581 nskb->data, MAX_REG_IN_BUF_SIZE,
Rajkumar Manoharan490b3f42010-11-08 12:49:12 +0530582 ath9k_hif_usb_reg_in_cb, nskb);
Sujithfb9987d2010-03-17 14:25:25 +0530583 }
584
585resubmit:
Sujith Manoharan3deff762011-04-13 11:25:23 +0530586 usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530587 ret = usb_submit_urb(urb, GFP_ATOMIC);
Sujith Manoharan3deff762011-04-13 11:25:23 +0530588 if (ret) {
589 usb_unanchor_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530590 goto free;
Sujith Manoharan3deff762011-04-13 11:25:23 +0530591 }
Sujithfb9987d2010-03-17 14:25:25 +0530592
593 return;
594free:
Ming Leie6c6d332010-04-13 00:29:05 +0800595 kfree_skb(skb);
Sujith6335ed02010-03-29 16:07:15 +0530596 urb->context = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530597}
598
599static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
600{
Sujithfb9987d2010-03-17 14:25:25 +0530601 struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
Sujith Manoharanff8f59b2010-12-28 14:28:05 +0530602 unsigned long flags;
Sujithfb9987d2010-03-17 14:25:25 +0530603
Sujithc11d8f82010-04-23 10:28:09 +0530604 list_for_each_entry_safe(tx_buf, tx_buf_tmp,
605 &hif_dev->tx.tx_buf, list) {
606 usb_kill_urb(tx_buf->urb);
Sujithfb9987d2010-03-17 14:25:25 +0530607 list_del(&tx_buf->list);
608 usb_free_urb(tx_buf->urb);
609 kfree(tx_buf->buf);
610 kfree(tx_buf);
611 }
612
Sujith Manoharanff8f59b2010-12-28 14:28:05 +0530613 spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
614 hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
615 spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
616
Sujithfb9987d2010-03-17 14:25:25 +0530617 list_for_each_entry_safe(tx_buf, tx_buf_tmp,
618 &hif_dev->tx.tx_pending, list) {
619 usb_kill_urb(tx_buf->urb);
620 list_del(&tx_buf->list);
621 usb_free_urb(tx_buf->urb);
622 kfree(tx_buf->buf);
623 kfree(tx_buf);
624 }
Sujithfb9987d2010-03-17 14:25:25 +0530625}
626
627static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
628{
629 struct tx_buf *tx_buf;
630 int i;
631
632 INIT_LIST_HEAD(&hif_dev->tx.tx_buf);
633 INIT_LIST_HEAD(&hif_dev->tx.tx_pending);
634 spin_lock_init(&hif_dev->tx.tx_lock);
635 __skb_queue_head_init(&hif_dev->tx.tx_skb_queue);
636
637 for (i = 0; i < MAX_TX_URB_NUM; i++) {
638 tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
639 if (!tx_buf)
640 goto err;
641
642 tx_buf->buf = kzalloc(MAX_TX_BUF_SIZE, GFP_KERNEL);
643 if (!tx_buf->buf)
644 goto err;
645
646 tx_buf->urb = usb_alloc_urb(0, GFP_KERNEL);
647 if (!tx_buf->urb)
648 goto err;
649
650 tx_buf->hif_dev = hif_dev;
651 __skb_queue_head_init(&tx_buf->skb_queue);
652
653 list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
654 }
655
656 hif_dev->tx.tx_buf_cnt = MAX_TX_URB_NUM;
657
658 return 0;
659err:
Dan Carpenter76066882010-05-14 16:52:37 +0200660 if (tx_buf) {
661 kfree(tx_buf->buf);
662 kfree(tx_buf);
663 }
Sujithfb9987d2010-03-17 14:25:25 +0530664 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
665 return -ENOMEM;
666}
667
Sujithfb9987d2010-03-17 14:25:25 +0530668static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
669{
Sujith6335ed02010-03-29 16:07:15 +0530670 usb_kill_anchored_urbs(&hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530671}
672
673static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
674{
Sujith6335ed02010-03-29 16:07:15 +0530675 struct urb *urb = NULL;
676 struct sk_buff *skb = NULL;
Sujithfb9987d2010-03-17 14:25:25 +0530677 int i, ret;
678
Sujith6335ed02010-03-29 16:07:15 +0530679 init_usb_anchor(&hif_dev->rx_submitted);
Sujith46baa1a2010-04-06 15:28:11 +0530680 spin_lock_init(&hif_dev->rx_lock);
Sujith6335ed02010-03-29 16:07:15 +0530681
Sujithfb9987d2010-03-17 14:25:25 +0530682 for (i = 0; i < MAX_RX_URB_NUM; i++) {
683
684 /* Allocate URB */
Sujith6335ed02010-03-29 16:07:15 +0530685 urb = usb_alloc_urb(0, GFP_KERNEL);
686 if (urb == NULL) {
Sujithfb9987d2010-03-17 14:25:25 +0530687 ret = -ENOMEM;
Sujith6335ed02010-03-29 16:07:15 +0530688 goto err_urb;
Sujithfb9987d2010-03-17 14:25:25 +0530689 }
690
691 /* Allocate buffer */
Ming Leif28a7b32010-04-13 00:28:53 +0800692 skb = alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL);
Sujith6335ed02010-03-29 16:07:15 +0530693 if (!skb) {
694 ret = -ENOMEM;
695 goto err_skb;
696 }
697
698 usb_fill_bulk_urb(urb, hif_dev->udev,
699 usb_rcvbulkpipe(hif_dev->udev,
700 USB_WLAN_RX_PIPE),
701 skb->data, MAX_RX_BUF_SIZE,
702 ath9k_hif_usb_rx_cb, skb);
703
704 /* Anchor URB */
705 usb_anchor_urb(urb, &hif_dev->rx_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530706
707 /* Submit URB */
Sujith6335ed02010-03-29 16:07:15 +0530708 ret = usb_submit_urb(urb, GFP_KERNEL);
709 if (ret) {
710 usb_unanchor_urb(urb);
711 goto err_submit;
712 }
Sujith66b10e32010-04-06 15:28:13 +0530713
714 /*
715 * Drop reference count.
716 * This ensures that the URB is freed when killing them.
717 */
718 usb_free_urb(urb);
Sujithfb9987d2010-03-17 14:25:25 +0530719 }
720
721 return 0;
722
Sujith6335ed02010-03-29 16:07:15 +0530723err_submit:
Ming Leif28a7b32010-04-13 00:28:53 +0800724 kfree_skb(skb);
Sujith6335ed02010-03-29 16:07:15 +0530725err_skb:
726 usb_free_urb(urb);
727err_urb:
Sujithfb9987d2010-03-17 14:25:25 +0530728 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
729 return ret;
730}
731
Sujith Manoharan3deff762011-04-13 11:25:23 +0530732static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev)
Sujithfb9987d2010-03-17 14:25:25 +0530733{
Sujith Manoharan3deff762011-04-13 11:25:23 +0530734 usb_kill_anchored_urbs(&hif_dev->reg_in_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530735}
736
Sujith Manoharan3deff762011-04-13 11:25:23 +0530737static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
Sujithfb9987d2010-03-17 14:25:25 +0530738{
Sujith Manoharan3deff762011-04-13 11:25:23 +0530739 struct urb *urb = NULL;
740 struct sk_buff *skb = NULL;
741 int i, ret;
Sujithfb9987d2010-03-17 14:25:25 +0530742
Sujith Manoharan3deff762011-04-13 11:25:23 +0530743 init_usb_anchor(&hif_dev->reg_in_submitted);
Sujithfb9987d2010-03-17 14:25:25 +0530744
Sujith Manoharan3deff762011-04-13 11:25:23 +0530745 for (i = 0; i < MAX_REG_IN_URB_NUM; i++) {
Sujithfb9987d2010-03-17 14:25:25 +0530746
Sujith Manoharan3deff762011-04-13 11:25:23 +0530747 /* Allocate URB */
748 urb = usb_alloc_urb(0, GFP_KERNEL);
749 if (urb == NULL) {
750 ret = -ENOMEM;
751 goto err_urb;
752 }
Sujithfb9987d2010-03-17 14:25:25 +0530753
Sujith Manoharan3deff762011-04-13 11:25:23 +0530754 /* Allocate buffer */
755 skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL);
756 if (!skb) {
757 ret = -ENOMEM;
758 goto err_skb;
759 }
760
761 usb_fill_bulk_urb(urb, hif_dev->udev,
762 usb_rcvbulkpipe(hif_dev->udev,
763 USB_REG_IN_PIPE),
764 skb->data, MAX_REG_IN_BUF_SIZE,
765 ath9k_hif_usb_reg_in_cb, skb);
766
767 /* Anchor URB */
768 usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
769
770 /* Submit URB */
771 ret = usb_submit_urb(urb, GFP_KERNEL);
772 if (ret) {
773 usb_unanchor_urb(urb);
774 goto err_submit;
775 }
776
777 /*
778 * Drop reference count.
779 * This ensures that the URB is freed when killing them.
780 */
781 usb_free_urb(urb);
782 }
Sujithfb9987d2010-03-17 14:25:25 +0530783
784 return 0;
785
Sujith Manoharan3deff762011-04-13 11:25:23 +0530786err_submit:
787 kfree_skb(skb);
788err_skb:
789 usb_free_urb(urb);
790err_urb:
791 ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
792 return ret;
Sujithfb9987d2010-03-17 14:25:25 +0530793}
794
795static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev)
796{
Sujith6f0f2662010-04-06 15:28:17 +0530797 /* Register Write */
798 init_usb_anchor(&hif_dev->regout_submitted);
799
Sujithfb9987d2010-03-17 14:25:25 +0530800 /* TX */
801 if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0)
802 goto err;
803
804 /* RX */
805 if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0)
Rajkumar Manoharanf8036962010-07-07 15:19:18 +0530806 goto err_rx;
Sujithfb9987d2010-03-17 14:25:25 +0530807
Sujith6f0f2662010-04-06 15:28:17 +0530808 /* Register Read */
Sujith Manoharan3deff762011-04-13 11:25:23 +0530809 if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0)
Rajkumar Manoharanf8036962010-07-07 15:19:18 +0530810 goto err_reg;
Sujithfb9987d2010-03-17 14:25:25 +0530811
812 return 0;
Rajkumar Manoharanf8036962010-07-07 15:19:18 +0530813err_reg:
814 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
815err_rx:
816 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
Sujithfb9987d2010-03-17 14:25:25 +0530817err:
818 return -ENOMEM;
819}
820
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530821static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
822{
823 usb_kill_anchored_urbs(&hif_dev->regout_submitted);
Sujith Manoharan3deff762011-04-13 11:25:23 +0530824 ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530825 ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
826 ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
827}
828
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530829static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
830 u32 drv_info)
Sujithfb9987d2010-03-17 14:25:25 +0530831{
832 int transfer, err;
833 const void *data = hif_dev->firmware->data;
834 size_t len = hif_dev->firmware->size;
835 u32 addr = AR9271_FIRMWARE;
836 u8 *buf = kzalloc(4096, GFP_KERNEL);
Sujithb1762862010-06-02 15:53:34 +0530837 u32 firm_offset;
Sujithfb9987d2010-03-17 14:25:25 +0530838
839 if (!buf)
840 return -ENOMEM;
841
842 while (len) {
843 transfer = min_t(int, len, 4096);
844 memcpy(buf, data, transfer);
845
846 err = usb_control_msg(hif_dev->udev,
847 usb_sndctrlpipe(hif_dev->udev, 0),
848 FIRMWARE_DOWNLOAD, 0x40 | USB_DIR_OUT,
849 addr >> 8, 0, buf, transfer, HZ);
850 if (err < 0) {
851 kfree(buf);
852 return err;
853 }
854
855 len -= transfer;
856 data += transfer;
857 addr += transfer;
858 }
859 kfree(buf);
860
Sujith Manoharan0b5ead92010-12-07 16:31:38 +0530861 if (IS_AR7010_DEVICE(drv_info))
Sujithb1762862010-06-02 15:53:34 +0530862 firm_offset = AR7010_FIRMWARE_TEXT;
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530863 else
Sujithb1762862010-06-02 15:53:34 +0530864 firm_offset = AR9271_FIRMWARE_TEXT;
865
Sujithfb9987d2010-03-17 14:25:25 +0530866 /*
867 * Issue FW download complete command to firmware.
868 */
869 err = usb_control_msg(hif_dev->udev, usb_sndctrlpipe(hif_dev->udev, 0),
870 FIRMWARE_DOWNLOAD_COMP,
871 0x40 | USB_DIR_OUT,
Sujithb1762862010-06-02 15:53:34 +0530872 firm_offset >> 8, 0, NULL, 0, HZ);
Sujithfb9987d2010-03-17 14:25:25 +0530873 if (err)
874 return -EIO;
875
876 dev_info(&hif_dev->udev->dev, "ath9k_htc: Transferred FW: %s, size: %ld\n",
Sujithce43cee2010-06-02 15:53:30 +0530877 hif_dev->fw_name, (unsigned long) hif_dev->firmware->size);
Sujithfb9987d2010-03-17 14:25:25 +0530878
879 return 0;
880}
881
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530882static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info)
Sujithfb9987d2010-03-17 14:25:25 +0530883{
Rajkumar Manoharan4a0e8ecc2010-09-14 14:35:55 +0530884 int ret, idx;
885 struct usb_host_interface *alt = &hif_dev->interface->altsetting[0];
886 struct usb_endpoint_descriptor *endp;
Sujithfb9987d2010-03-17 14:25:25 +0530887
888 /* Request firmware */
Sujithce43cee2010-06-02 15:53:30 +0530889 ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name,
890 &hif_dev->udev->dev);
Sujithfb9987d2010-03-17 14:25:25 +0530891 if (ret) {
892 dev_err(&hif_dev->udev->dev,
Sujithce43cee2010-06-02 15:53:30 +0530893 "ath9k_htc: Firmware - %s not found\n", hif_dev->fw_name);
Sujithfb9987d2010-03-17 14:25:25 +0530894 goto err_fw_req;
895 }
896
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530897 /* Download firmware */
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +0530898 ret = ath9k_hif_usb_download_fw(hif_dev, drv_info);
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530899 if (ret) {
900 dev_err(&hif_dev->udev->dev,
Sujithce43cee2010-06-02 15:53:30 +0530901 "ath9k_htc: Firmware - %s download failed\n",
902 hif_dev->fw_name);
Sujith.Manoharan@atheros.com1d8af8c2010-05-11 16:24:40 +0530903 goto err_fw_download;
904 }
905
Rajkumar Manoharan4a0e8ecc2010-09-14 14:35:55 +0530906 /* On downloading the firmware to the target, the USB descriptor of EP4
907 * is 'patched' to change the type of the endpoint to Bulk. This will
908 * bring down CPU usage during the scan period.
909 */
910 for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) {
911 endp = &alt->endpoint[idx].desc;
Rajkumar Manoharan490b3f42010-11-08 12:49:12 +0530912 if ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
913 == USB_ENDPOINT_XFER_INT) {
Rajkumar Manoharan4a0e8ecc2010-09-14 14:35:55 +0530914 endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK;
915 endp->bmAttributes |= USB_ENDPOINT_XFER_BULK;
916 endp->bInterval = 0;
917 }
918 }
919
Rajkumar Manoharan490b3f42010-11-08 12:49:12 +0530920 /* Alloc URBs */
921 ret = ath9k_hif_usb_alloc_urbs(hif_dev);
922 if (ret) {
923 dev_err(&hif_dev->udev->dev,
924 "ath9k_htc: Unable to allocate URBs\n");
Sujith Manoharan512c0442011-02-21 07:50:38 +0530925 goto err_fw_download;
Rajkumar Manoharan490b3f42010-11-08 12:49:12 +0530926 }
927
Sujithfb9987d2010-03-17 14:25:25 +0530928 return 0;
929
Sujith Manoharancaa0a992010-12-07 16:32:02 +0530930err_fw_download:
Sujithfb9987d2010-03-17 14:25:25 +0530931 release_firmware(hif_dev->firmware);
932err_fw_req:
933 hif_dev->firmware = NULL;
934 return ret;
935}
936
Sujithfb9987d2010-03-17 14:25:25 +0530937static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
938{
939 ath9k_hif_usb_dealloc_urbs(hif_dev);
940 if (hif_dev->firmware)
941 release_firmware(hif_dev->firmware);
942}
943
Sujith Manoharan36bcce42011-02-21 07:47:52 +0530944/*
945 * An exact copy of the function from zd1211rw.
946 */
947static int send_eject_command(struct usb_interface *interface)
948{
949 struct usb_device *udev = interface_to_usbdev(interface);
950 struct usb_host_interface *iface_desc = &interface->altsetting[0];
951 struct usb_endpoint_descriptor *endpoint;
952 unsigned char *cmd;
953 u8 bulk_out_ep;
954 int r;
955
956 /* Find bulk out endpoint */
957 for (r = 1; r >= 0; r--) {
958 endpoint = &iface_desc->endpoint[r].desc;
959 if (usb_endpoint_dir_out(endpoint) &&
960 usb_endpoint_xfer_bulk(endpoint)) {
961 bulk_out_ep = endpoint->bEndpointAddress;
962 break;
963 }
964 }
965 if (r == -1) {
966 dev_err(&udev->dev,
967 "ath9k_htc: Could not find bulk out endpoint\n");
968 return -ENODEV;
969 }
970
971 cmd = kzalloc(31, GFP_KERNEL);
972 if (cmd == NULL)
973 return -ENODEV;
974
975 /* USB bulk command block */
976 cmd[0] = 0x55; /* bulk command signature */
977 cmd[1] = 0x53; /* bulk command signature */
978 cmd[2] = 0x42; /* bulk command signature */
979 cmd[3] = 0x43; /* bulk command signature */
980 cmd[14] = 6; /* command length */
981
982 cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */
983 cmd[19] = 0x2; /* eject disc */
984
985 dev_info(&udev->dev, "Ejecting storage device...\n");
986 r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
987 cmd, 31, NULL, 2000);
988 kfree(cmd);
989 if (r)
990 return r;
991
992 /* At this point, the device disconnects and reconnects with the real
993 * ID numbers. */
994
995 usb_set_intfdata(interface, NULL);
996 return 0;
997}
998
Sujithfb9987d2010-03-17 14:25:25 +0530999static int ath9k_hif_usb_probe(struct usb_interface *interface,
1000 const struct usb_device_id *id)
1001{
1002 struct usb_device *udev = interface_to_usbdev(interface);
1003 struct hif_device_usb *hif_dev;
Sujithfb9987d2010-03-17 14:25:25 +05301004 int ret = 0;
1005
Sujith Manoharan36bcce42011-02-21 07:47:52 +05301006 if (id->driver_info == STORAGE_DEVICE)
1007 return send_eject_command(interface);
1008
Sujithfb9987d2010-03-17 14:25:25 +05301009 hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL);
1010 if (!hif_dev) {
1011 ret = -ENOMEM;
1012 goto err_alloc;
1013 }
1014
1015 usb_get_dev(udev);
1016 hif_dev->udev = udev;
1017 hif_dev->interface = interface;
1018 hif_dev->device_id = id->idProduct;
1019#ifdef CONFIG_PM
1020 udev->reset_resume = 1;
1021#endif
1022 usb_set_intfdata(interface, hif_dev);
1023
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +05301024 hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
1025 &hif_dev->udev->dev);
1026 if (hif_dev->htc_handle == NULL) {
1027 ret = -ENOMEM;
1028 goto err_htc_hw_alloc;
1029 }
1030
Sujithce43cee2010-06-02 15:53:30 +05301031 /* Find out which firmware to load */
1032
Sujith Manoharan0b5ead92010-12-07 16:31:38 +05301033 if (IS_AR7010_DEVICE(id->driver_info))
Sujith Manoharan9efabad2011-04-13 11:22:33 +05301034 hif_dev->fw_name = FIRMWARE_AR7010_1_1;
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301035 else
John W. Linvilled0ee0eb2010-06-23 14:20:45 -04001036 hif_dev->fw_name = FIRMWARE_AR9271;
Sujithce43cee2010-06-02 15:53:30 +05301037
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301038 ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info);
Sujithfb9987d2010-03-17 14:25:25 +05301039 if (ret) {
1040 ret = -EINVAL;
1041 goto err_hif_init_usb;
1042 }
1043
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +05301044 ret = ath9k_htc_hw_init(hif_dev->htc_handle,
Vivek Natarajan21cb9872010-08-18 19:57:49 +05301045 &hif_dev->udev->dev, hif_dev->device_id,
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301046 hif_dev->udev->product, id->driver_info);
Sujithfb9987d2010-03-17 14:25:25 +05301047 if (ret) {
1048 ret = -EINVAL;
1049 goto err_htc_hw_init;
1050 }
1051
1052 dev_info(&hif_dev->udev->dev, "ath9k_htc: USB layer initialized\n");
1053
1054 return 0;
1055
1056err_htc_hw_init:
Sujithfb9987d2010-03-17 14:25:25 +05301057 ath9k_hif_usb_dev_deinit(hif_dev);
1058err_hif_init_usb:
Sujith.Manoharan@atheros.com47fce022010-05-11 16:24:41 +05301059 ath9k_htc_hw_free(hif_dev->htc_handle);
1060err_htc_hw_alloc:
Sujithfb9987d2010-03-17 14:25:25 +05301061 usb_set_intfdata(interface, NULL);
1062 kfree(hif_dev);
1063 usb_put_dev(udev);
1064err_alloc:
1065 return ret;
1066}
1067
Sujith62e47162010-04-23 10:28:16 +05301068static void ath9k_hif_usb_reboot(struct usb_device *udev)
1069{
1070 u32 reboot_cmd = 0xffffffff;
1071 void *buf;
1072 int ret;
1073
Julia Lawalla465a2c2010-05-15 23:17:19 +02001074 buf = kmemdup(&reboot_cmd, 4, GFP_KERNEL);
Sujith62e47162010-04-23 10:28:16 +05301075 if (!buf)
1076 return;
1077
Sujith62e47162010-04-23 10:28:16 +05301078 ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE),
1079 buf, 4, NULL, HZ);
1080 if (ret)
1081 dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n");
1082
1083 kfree(buf);
1084}
1085
Sujithfb9987d2010-03-17 14:25:25 +05301086static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
1087{
1088 struct usb_device *udev = interface_to_usbdev(interface);
Joe Perchesb2767362010-11-30 13:42:08 -08001089 struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
Sujith Manoharan97dcec52010-12-20 08:02:42 +05301090 bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false;
Sujithfb9987d2010-03-17 14:25:25 +05301091
Sujith Manoharan36bcce42011-02-21 07:47:52 +05301092 if (!hif_dev)
1093 return;
1094
1095 ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
1096 ath9k_htc_hw_free(hif_dev->htc_handle);
1097 ath9k_hif_usb_dev_deinit(hif_dev);
1098 usb_set_intfdata(interface, NULL);
Sujithfb9987d2010-03-17 14:25:25 +05301099
Sujith Manoharan97dcec52010-12-20 08:02:42 +05301100 if (!unplugged && (hif_dev->flags & HIF_USB_START))
Sujith62e47162010-04-23 10:28:16 +05301101 ath9k_hif_usb_reboot(udev);
Sujithfb9987d2010-03-17 14:25:25 +05301102
1103 kfree(hif_dev);
1104 dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
1105 usb_put_dev(udev);
1106}
1107
1108#ifdef CONFIG_PM
1109static int ath9k_hif_usb_suspend(struct usb_interface *interface,
1110 pm_message_t message)
1111{
Joe Perchesb2767362010-11-30 13:42:08 -08001112 struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
Sujithfb9987d2010-03-17 14:25:25 +05301113
Sujith Manoharanf933ebe2010-12-01 12:30:27 +05301114 /*
1115 * The device has to be set to FULLSLEEP mode in case no
1116 * interface is up.
1117 */
1118 if (!(hif_dev->flags & HIF_USB_START))
1119 ath9k_htc_suspend(hif_dev->htc_handle);
1120
Sujithfb9987d2010-03-17 14:25:25 +05301121 ath9k_hif_usb_dealloc_urbs(hif_dev);
1122
1123 return 0;
1124}
1125
1126static int ath9k_hif_usb_resume(struct usb_interface *interface)
1127{
Joe Perchesb2767362010-11-30 13:42:08 -08001128 struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301129 struct htc_target *htc_handle = hif_dev->htc_handle;
Sujithfb9987d2010-03-17 14:25:25 +05301130 int ret;
1131
1132 ret = ath9k_hif_usb_alloc_urbs(hif_dev);
1133 if (ret)
1134 return ret;
1135
1136 if (hif_dev->firmware) {
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301137 ret = ath9k_hif_usb_download_fw(hif_dev,
Sujith Manoharan0b5ead92010-12-07 16:31:38 +05301138 htc_handle->drv_priv->ah->hw_version.usbdev);
Sujithfb9987d2010-03-17 14:25:25 +05301139 if (ret)
1140 goto fail_resume;
1141 } else {
1142 ath9k_hif_usb_dealloc_urbs(hif_dev);
1143 return -EIO;
1144 }
1145
1146 mdelay(100);
1147
Rajkumar Manoharanfa6e15e2010-11-19 16:53:22 +05301148 ret = ath9k_htc_resume(htc_handle);
Sujithfb9987d2010-03-17 14:25:25 +05301149
1150 if (ret)
1151 goto fail_resume;
1152
1153 return 0;
1154
1155fail_resume:
1156 ath9k_hif_usb_dealloc_urbs(hif_dev);
1157
1158 return ret;
1159}
1160#endif
1161
1162static struct usb_driver ath9k_hif_usb_driver = {
1163 .name = "ath9k_hif_usb",
1164 .probe = ath9k_hif_usb_probe,
1165 .disconnect = ath9k_hif_usb_disconnect,
1166#ifdef CONFIG_PM
1167 .suspend = ath9k_hif_usb_suspend,
1168 .resume = ath9k_hif_usb_resume,
1169 .reset_resume = ath9k_hif_usb_resume,
1170#endif
1171 .id_table = ath9k_hif_usb_ids,
1172 .soft_unbind = 1,
1173};
1174
1175int ath9k_hif_usb_init(void)
1176{
1177 return usb_register(&ath9k_hif_usb_driver);
1178}
1179
1180void ath9k_hif_usb_exit(void)
1181{
1182 usb_deregister(&ath9k_hif_usb_driver);
1183}