blob: 484a6e4f23a206dc6e341bd7ffde1c7d4cd45656 [file] [log] [blame]
Arend van Spriel71bb2442012-02-09 21:09:08 +01001/*
2 * Copyright (c) 2011 Broadcom Corporation
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 ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/kthread.h>
21#include <linux/slab.h>
22#include <linux/skbuff.h>
23#include <linux/netdevice.h>
24#include <linux/spinlock.h>
25#include <linux/ethtool.h>
26#include <linux/fcntl.h>
27#include <linux/fs.h>
28#include <linux/uaccess.h>
29#include <linux/firmware.h>
30#include <linux/usb.h>
Hauke Mehrtensedb9bc92012-05-18 20:22:53 +020031#include <linux/vmalloc.h>
Arend van Spriel71bb2442012-02-09 21:09:08 +010032#include <net/cfg80211.h>
33
34#include <defs.h>
35#include <brcmu_utils.h>
36#include <brcmu_wifi.h>
37#include <dhd_bus.h>
38#include <dhd_dbg.h>
39
40#include "usb_rdl.h"
41#include "usb.h"
42
43#define IOCTL_RESP_TIMEOUT 2000
44
Arend van Spriel71bb2442012-02-09 21:09:08 +010045#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */
46#define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */
47
48#define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle
49 has boot up */
50#define BRCMF_USB_RESETCFG_SPINWAIT 1 /* wait after resetcfg (ms) */
51
52#define BRCMF_USB_NRXQ 50
53#define BRCMF_USB_NTXQ 50
54
55#define CONFIGDESC(usb) (&((usb)->actconfig)->desc)
56#define IFPTR(usb, idx) ((usb)->actconfig->interface[(idx)])
57#define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0])
58#define IFDESC(usb, idx) IFALTS((usb), (idx)).desc
59#define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[(ep)]).desc
60
61#define CONTROL_IF 0
62#define BULK_IF 0
63
64#define BRCMF_USB_CBCTL_WRITE 0
65#define BRCMF_USB_CBCTL_READ 1
66#define BRCMF_USB_MAX_PKT_SIZE 1600
67
Hante Meuleman70f08222012-08-30 19:43:01 +020068#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin"
Rafał Miłeckifda82412012-02-24 07:22:51 +010069#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
Hante Meuleman1212d372012-08-30 19:43:00 +020070#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
Arend van Spriel71bb2442012-02-09 21:09:08 +010071
72enum usbdev_suspend_state {
73 USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
74 suspend */
75 USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be
76 * suspended. Wating PM to
77 * suspend the device
78 */
79 USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */
80};
81
Arend van Spriel71bb2442012-02-09 21:09:08 +010082struct brcmf_usb_image {
Hante Meuleman803599d2012-09-19 22:21:10 +020083 struct list_head list;
84 s8 *fwname;
85 u8 *image;
86 int image_len;
Arend van Spriel71bb2442012-02-09 21:09:08 +010087};
Hante Meuleman803599d2012-09-19 22:21:10 +020088static struct list_head fw_image_list;
Arend van Spriel71bb2442012-02-09 21:09:08 +010089
90struct intr_transfer_buf {
91 u32 notification;
92 u32 reserved;
93};
94
95struct brcmf_usbdev_info {
96 struct brcmf_usbdev bus_pub; /* MUST BE FIRST */
97 spinlock_t qlock;
98 struct list_head rx_freeq;
99 struct list_head rx_postq;
100 struct list_head tx_freeq;
101 struct list_head tx_postq;
102 enum usbdev_suspend_state suspend_state;
103 uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
104
105 bool activity;
106 int rx_low_watermark;
107 int tx_low_watermark;
108 int tx_high_watermark;
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200109 int tx_freecount;
110 bool tx_flowblock;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100111
112 struct brcmf_usbreq *tx_reqs;
113 struct brcmf_usbreq *rx_reqs;
114
115 u8 *image; /* buffer for combine fw and nvram */
116 int image_len;
117
Arend van Spriel71bb2442012-02-09 21:09:08 +0100118 struct usb_device *usbdev;
119 struct device *dev;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100120
121 int ctl_in_pipe, ctl_out_pipe;
122 struct urb *ctl_urb; /* URB for control endpoint */
123 struct usb_ctrlrequest ctl_write;
124 struct usb_ctrlrequest ctl_read;
125 u32 ctl_urb_actual_length;
126 int ctl_urb_status;
127 int ctl_completed;
128 wait_queue_head_t ioctl_resp_wait;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100129 ulong ctl_op;
130
Arend van Spriel71bb2442012-02-09 21:09:08 +0100131 struct urb *bulk_urb; /* used for FW download */
132 struct urb *intr_urb; /* URB for interrupt endpoint */
133 int intr_size; /* Size of interrupt message */
134 int interval; /* Interrupt polling interval */
135 struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */
Arend van Spriel71bb2442012-02-09 21:09:08 +0100136};
137
138static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
139 struct brcmf_usbreq *req);
140
141MODULE_AUTHOR("Broadcom Corporation");
142MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver.");
143MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards");
144MODULE_LICENSE("Dual BSD/GPL");
145
146static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev)
147{
148 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
149 return bus_if->bus_priv.usb;
150}
151
152static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
153{
154 return brcmf_usb_get_buspub(dev)->devinfo;
155}
156
Hante Meuleman70398a52012-09-27 14:17:47 +0200157static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo)
Arend van Spriel71bb2442012-02-09 21:09:08 +0100158{
Hante Meuleman70398a52012-09-27 14:17:47 +0200159 return wait_event_timeout(devinfo->ioctl_resp_wait,
160 devinfo->ctl_completed,
161 msecs_to_jiffies(IOCTL_RESP_TIMEOUT));
Arend van Spriel71bb2442012-02-09 21:09:08 +0100162}
163
Hante Meuleman70398a52012-09-27 14:17:47 +0200164static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
Arend van Spriel71bb2442012-02-09 21:09:08 +0100165{
166 if (waitqueue_active(&devinfo->ioctl_resp_wait))
Hante Meuleman70398a52012-09-27 14:17:47 +0200167 wake_up(&devinfo->ioctl_resp_wait);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100168}
169
170static void
171brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status)
172{
173
174 if (unlikely(devinfo == NULL))
175 return;
176
177 if (type == BRCMF_USB_CBCTL_READ) {
178 if (status == 0)
179 devinfo->bus_pub.stats.rx_ctlpkts++;
180 else
181 devinfo->bus_pub.stats.rx_ctlerrs++;
182 } else if (type == BRCMF_USB_CBCTL_WRITE) {
183 if (status == 0)
184 devinfo->bus_pub.stats.tx_ctlpkts++;
185 else
186 devinfo->bus_pub.stats.tx_ctlerrs++;
187 }
188
189 devinfo->ctl_urb_status = status;
190 devinfo->ctl_completed = true;
191 brcmf_usb_ioctl_resp_wake(devinfo);
192}
193
194static void
195brcmf_usb_ctlread_complete(struct urb *urb)
196{
197 struct brcmf_usbdev_info *devinfo =
198 (struct brcmf_usbdev_info *)urb->context;
199
200 devinfo->ctl_urb_actual_length = urb->actual_length;
201 brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ,
202 urb->status);
203}
204
205static void
206brcmf_usb_ctlwrite_complete(struct urb *urb)
207{
208 struct brcmf_usbdev_info *devinfo =
209 (struct brcmf_usbdev_info *)urb->context;
210
211 brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE,
212 urb->status);
213}
214
215static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state)
216{
217 return 0;
218}
219
220static int
221brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
222{
223 int ret;
224 u16 size;
225
226 if (devinfo == NULL || buf == NULL ||
227 len == 0 || devinfo->ctl_urb == NULL)
228 return -EINVAL;
229
230 /* If the USB/HSIC bus in sleep state, wake it up */
231 if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED)
232 if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
233 brcmf_dbg(ERROR, "Could not Resume the bus!\n");
234 return -EIO;
235 }
236
237 devinfo->activity = true;
238 size = len;
239 devinfo->ctl_write.wLength = cpu_to_le16p(&size);
240 devinfo->ctl_urb->transfer_buffer_length = size;
241 devinfo->ctl_urb_status = 0;
242 devinfo->ctl_urb_actual_length = 0;
243
244 usb_fill_control_urb(devinfo->ctl_urb,
245 devinfo->usbdev,
246 devinfo->ctl_out_pipe,
247 (unsigned char *) &devinfo->ctl_write,
248 buf, size,
249 (usb_complete_t)brcmf_usb_ctlwrite_complete,
250 devinfo);
251
252 ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
253 if (ret < 0)
254 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
255
256 return ret;
257}
258
259static int
260brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
261{
262 int ret;
263 u16 size;
264
265 if ((devinfo == NULL) || (buf == NULL) || (len == 0)
266 || (devinfo->ctl_urb == NULL))
267 return -EINVAL;
268
269 size = len;
270 devinfo->ctl_read.wLength = cpu_to_le16p(&size);
271 devinfo->ctl_urb->transfer_buffer_length = size;
272
Hante Meuleman81643292012-09-19 22:21:14 +0200273 devinfo->ctl_read.bRequestType = USB_DIR_IN
274 | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
275 devinfo->ctl_read.bRequest = 1;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100276
277 usb_fill_control_urb(devinfo->ctl_urb,
278 devinfo->usbdev,
279 devinfo->ctl_in_pipe,
280 (unsigned char *) &devinfo->ctl_read,
281 buf, size,
282 (usb_complete_t)brcmf_usb_ctlread_complete,
283 devinfo);
284
285 ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
286 if (ret < 0)
287 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
288
289 return ret;
290}
291
292static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
293{
294 int err = 0;
295 int timeout = 0;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100296 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
297
298 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
299 /* TODO: handle suspend/resume */
300 return -EIO;
301 }
302
303 if (test_and_set_bit(0, &devinfo->ctl_op))
304 return -EIO;
305
Hante Meulemana77f5742012-08-30 19:42:58 +0200306 devinfo->ctl_completed = false;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100307 err = brcmf_usb_send_ctl(devinfo, buf, len);
308 if (err) {
309 brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
Hante Meuleman6385df22012-09-19 22:21:16 +0200310 clear_bit(0, &devinfo->ctl_op);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100311 return err;
312 }
Hante Meuleman70398a52012-09-27 14:17:47 +0200313 timeout = brcmf_usb_ioctl_resp_wait(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100314 clear_bit(0, &devinfo->ctl_op);
315 if (!timeout) {
316 brcmf_dbg(ERROR, "Txctl wait timed out\n");
317 err = -EIO;
318 }
319 return err;
320}
321
322static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
323{
324 int err = 0;
325 int timeout = 0;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100326 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
327
328 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
329 /* TODO: handle suspend/resume */
330 return -EIO;
331 }
332 if (test_and_set_bit(0, &devinfo->ctl_op))
333 return -EIO;
334
Hante Meuleman70398a52012-09-27 14:17:47 +0200335 devinfo->ctl_completed = false;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100336 err = brcmf_usb_recv_ctl(devinfo, buf, len);
337 if (err) {
338 brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
Hante Meuleman6385df22012-09-19 22:21:16 +0200339 clear_bit(0, &devinfo->ctl_op);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100340 return err;
341 }
Hante Meuleman70398a52012-09-27 14:17:47 +0200342 timeout = brcmf_usb_ioctl_resp_wait(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100343 err = devinfo->ctl_urb_status;
344 clear_bit(0, &devinfo->ctl_op);
345 if (!timeout) {
346 brcmf_dbg(ERROR, "rxctl wait timed out\n");
347 err = -EIO;
348 }
349 if (!err)
350 return devinfo->ctl_urb_actual_length;
351 else
352 return err;
353}
354
355static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200356 struct list_head *q, int *counter)
Arend van Spriel71bb2442012-02-09 21:09:08 +0100357{
358 unsigned long flags;
359 struct brcmf_usbreq *req;
360 spin_lock_irqsave(&devinfo->qlock, flags);
361 if (list_empty(q)) {
362 spin_unlock_irqrestore(&devinfo->qlock, flags);
363 return NULL;
364 }
365 req = list_entry(q->next, struct brcmf_usbreq, list);
366 list_del_init(q->next);
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200367 if (counter)
368 (*counter)--;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100369 spin_unlock_irqrestore(&devinfo->qlock, flags);
370 return req;
371
372}
373
374static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo,
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200375 struct list_head *q, struct brcmf_usbreq *req,
376 int *counter)
Arend van Spriel71bb2442012-02-09 21:09:08 +0100377{
378 unsigned long flags;
379 spin_lock_irqsave(&devinfo->qlock, flags);
380 list_add_tail(&req->list, q);
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200381 if (counter)
382 (*counter)++;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100383 spin_unlock_irqrestore(&devinfo->qlock, flags);
384}
385
386static struct brcmf_usbreq *
387brcmf_usbdev_qinit(struct list_head *q, int qsize)
388{
389 int i;
390 struct brcmf_usbreq *req, *reqs;
391
392 reqs = kzalloc(sizeof(struct brcmf_usbreq) * qsize, GFP_ATOMIC);
393 if (reqs == NULL) {
394 brcmf_dbg(ERROR, "fail to allocate memory!\n");
395 return NULL;
396 }
397 req = reqs;
398
399 for (i = 0; i < qsize; i++) {
400 req->urb = usb_alloc_urb(0, GFP_ATOMIC);
401 if (!req->urb)
402 goto fail;
403
404 INIT_LIST_HEAD(&req->list);
405 list_add_tail(&req->list, q);
406 req++;
407 }
408 return reqs;
409fail:
410 brcmf_dbg(ERROR, "fail!\n");
411 while (!list_empty(q)) {
412 req = list_entry(q->next, struct brcmf_usbreq, list);
413 if (req && req->urb)
414 usb_free_urb(req->urb);
415 list_del(q->next);
416 }
417 return NULL;
418
419}
420
421static void brcmf_usb_free_q(struct list_head *q, bool pending)
422{
423 struct brcmf_usbreq *req, *next;
424 int i = 0;
425 list_for_each_entry_safe(req, next, q, list) {
Dan Carpenterd4ca0092012-02-24 09:22:27 +0300426 if (!req->urb) {
Arend van Spriel71bb2442012-02-09 21:09:08 +0100427 brcmf_dbg(ERROR, "bad req\n");
428 break;
429 }
430 i++;
431 if (pending) {
432 usb_kill_urb(req->urb);
433 } else {
434 usb_free_urb(req->urb);
435 list_del_init(&req->list);
436 }
437 }
438}
439
440static void brcmf_usb_del_fromq(struct brcmf_usbdev_info *devinfo,
441 struct brcmf_usbreq *req)
442{
443 unsigned long flags;
444
445 spin_lock_irqsave(&devinfo->qlock, flags);
446 list_del_init(&req->list);
447 spin_unlock_irqrestore(&devinfo->qlock, flags);
448}
449
450
451static void brcmf_usb_tx_complete(struct urb *urb)
452{
453 struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
454 struct brcmf_usbdev_info *devinfo = req->devinfo;
455
456 brcmf_usb_del_fromq(devinfo, req);
457 if (urb->status == 0)
Arend van Spriel1d9c1792012-03-02 22:55:47 +0100458 devinfo->bus_pub.bus->dstats.tx_packets++;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100459 else
Arend van Spriel1d9c1792012-03-02 22:55:47 +0100460 devinfo->bus_pub.bus->dstats.tx_errors++;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100461
Hante Meuleman1e2d9582012-09-27 14:17:50 +0200462 brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
463
Arend van Spriel01e33312012-08-30 10:05:34 +0200464 brcmu_pkt_buf_free_skb(req->skb);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100465 req->skb = NULL;
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200466 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
467 if (devinfo->tx_freecount > devinfo->tx_high_watermark &&
468 devinfo->tx_flowblock) {
469 brcmf_txflowblock(devinfo->dev, false);
470 devinfo->tx_flowblock = false;
471 }
Arend van Spriel71bb2442012-02-09 21:09:08 +0100472}
473
474static void brcmf_usb_rx_complete(struct urb *urb)
475{
476 struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
477 struct brcmf_usbdev_info *devinfo = req->devinfo;
478 struct sk_buff *skb;
479 int ifidx = 0;
480
481 brcmf_usb_del_fromq(devinfo, req);
482 skb = req->skb;
483 req->skb = NULL;
484
485 if (urb->status == 0) {
Arend van Spriel1d9c1792012-03-02 22:55:47 +0100486 devinfo->bus_pub.bus->dstats.rx_packets++;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100487 } else {
Arend van Spriel1d9c1792012-03-02 22:55:47 +0100488 devinfo->bus_pub.bus->dstats.rx_errors++;
Arend van Spriel01e33312012-08-30 10:05:34 +0200489 brcmu_pkt_buf_free_skb(skb);
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200490 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100491 return;
492 }
493
494 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
495 skb_put(skb, urb->actual_length);
496 if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
497 brcmf_dbg(ERROR, "rx protocol error\n");
498 brcmu_pkt_buf_free_skb(skb);
499 devinfo->bus_pub.bus->dstats.rx_errors++;
Hante Meuleman64477eb2012-09-11 21:18:50 +0200500 } else
Arend van Spriel71bb2442012-02-09 21:09:08 +0100501 brcmf_rx_packet(devinfo->dev, ifidx, skb);
Hante Meuleman64477eb2012-09-11 21:18:50 +0200502 brcmf_usb_rx_refill(devinfo, req);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100503 } else {
Arend van Spriel01e33312012-08-30 10:05:34 +0200504 brcmu_pkt_buf_free_skb(skb);
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200505 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100506 }
507 return;
508
509}
510
511static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
512 struct brcmf_usbreq *req)
513{
514 struct sk_buff *skb;
515 int ret;
516
517 if (!req || !devinfo)
518 return;
519
520 skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
521 if (!skb) {
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200522 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100523 return;
524 }
525 req->skb = skb;
526
527 usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
528 skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
529 req);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100530 req->devinfo = devinfo;
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200531 brcmf_usb_enq(devinfo, &devinfo->rx_postq, req, NULL);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100532
533 ret = usb_submit_urb(req->urb, GFP_ATOMIC);
Hante Meuleman2e875ac2012-08-30 10:05:36 +0200534 if (ret) {
535 brcmf_usb_del_fromq(devinfo, req);
Arend van Spriel01e33312012-08-30 10:05:34 +0200536 brcmu_pkt_buf_free_skb(req->skb);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100537 req->skb = NULL;
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200538 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100539 }
540 return;
541}
542
543static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
544{
545 struct brcmf_usbreq *req;
546
547 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
548 brcmf_dbg(ERROR, "bus is not up\n");
549 return;
550 }
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200551 while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
Arend van Spriel71bb2442012-02-09 21:09:08 +0100552 brcmf_usb_rx_refill(devinfo, req);
553}
554
555static void
556brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
557{
558 struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
559 int old_state;
560
561
562 if (devinfo->bus_pub.state == state)
563 return;
564
565 old_state = devinfo->bus_pub.state;
566 brcmf_dbg(TRACE, "dbus state change from %d to to %d\n",
567 old_state, state);
568
569 /* Don't update state if it's PnP firmware re-download */
570 if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */
571 devinfo->bus_pub.state = state;
572
573 if ((old_state == BCMFMAC_USB_STATE_SLEEP)
574 && (state == BCMFMAC_USB_STATE_UP)) {
575 brcmf_usb_rx_fill_all(devinfo);
576 }
577
578 /* update state of upper layer */
579 if (state == BCMFMAC_USB_STATE_DOWN) {
580 brcmf_dbg(INFO, "DBUS is down\n");
581 bcmf_bus->state = BRCMF_BUS_DOWN;
582 } else {
583 brcmf_dbg(INFO, "DBUS current state=%d\n", state);
584 }
585}
586
587static void
588brcmf_usb_intr_complete(struct urb *urb)
589{
590 struct brcmf_usbdev_info *devinfo =
591 (struct brcmf_usbdev_info *)urb->context;
592 bool killed;
593
594 if (devinfo == NULL)
595 return;
596
597 if (unlikely(urb->status)) {
598 if (devinfo->suspend_state ==
599 USBOS_SUSPEND_STATE_SUSPEND_PENDING)
600 killed = true;
601
602 if ((urb->status == -ENOENT && (!killed))
603 || urb->status == -ESHUTDOWN ||
604 urb->status == -ENODEV) {
605 brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
606 }
607 }
608
609 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) {
610 brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n");
611 return;
612 }
613
614 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
615 usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
616}
617
618static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
619{
620 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
621 struct brcmf_usbreq *req;
622 int ret;
623
624 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
625 /* TODO: handle suspend/resume */
626 return -EIO;
627 }
628
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200629 req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
630 &devinfo->tx_freecount);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100631 if (!req) {
Hante Meuleman2e875ac2012-08-30 10:05:36 +0200632 brcmu_pkt_buf_free_skb(skb);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100633 brcmf_dbg(ERROR, "no req to send\n");
634 return -ENOMEM;
635 }
Arend van Spriel71bb2442012-02-09 21:09:08 +0100636
637 req->skb = skb;
638 req->devinfo = devinfo;
639 usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
640 skb->data, skb->len, brcmf_usb_tx_complete, req);
641 req->urb->transfer_flags |= URB_ZERO_PACKET;
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200642 brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100643 ret = usb_submit_urb(req->urb, GFP_ATOMIC);
Hante Meuleman2e875ac2012-08-30 10:05:36 +0200644 if (ret) {
645 brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
646 brcmf_usb_del_fromq(devinfo, req);
647 brcmu_pkt_buf_free_skb(req->skb);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100648 req->skb = NULL;
Hante Meulemanc6ab4292012-09-11 21:18:48 +0200649 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
650 &devinfo->tx_freecount);
651 } else {
652 if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
653 !devinfo->tx_flowblock) {
654 brcmf_txflowblock(dev, true);
655 devinfo->tx_flowblock = true;
656 }
Arend van Spriel71bb2442012-02-09 21:09:08 +0100657 }
658
659 return ret;
660}
661
662
663static int brcmf_usb_up(struct device *dev)
664{
665 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
666 u16 ifnum;
667
Dan Carpenterd4ca0092012-02-24 09:22:27 +0300668 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
669 return 0;
670
Arend van Spriel71bb2442012-02-09 21:09:08 +0100671 /* If the USB/HSIC bus in sleep state, wake it up */
672 if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) {
673 if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
674 brcmf_dbg(ERROR, "Could not Resume the bus!\n");
675 return -EIO;
676 }
677 }
678 devinfo->activity = true;
679
680 /* Success, indicate devinfo is fully up */
681 brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP);
682
683 if (devinfo->intr_urb) {
684 int ret;
685
686 usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
687 devinfo->intr_pipe,
688 &devinfo->intr,
689 devinfo->intr_size,
690 (usb_complete_t)brcmf_usb_intr_complete,
691 devinfo,
692 devinfo->interval);
693
694 ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
695 if (ret) {
696 brcmf_dbg(ERROR, "USB_SUBMIT_URB failed with status %d\n",
697 ret);
698 return -EINVAL;
699 }
700 }
701
702 if (devinfo->ctl_urb) {
703 devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
704 devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
705
706 ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber;
707
708 /* CTL Write */
709 devinfo->ctl_write.bRequestType =
710 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
711 devinfo->ctl_write.bRequest = 0;
712 devinfo->ctl_write.wValue = cpu_to_le16(0);
713 devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum);
714
715 /* CTL Read */
716 devinfo->ctl_read.bRequestType =
717 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
718 devinfo->ctl_read.bRequest = 1;
719 devinfo->ctl_read.wValue = cpu_to_le16(0);
720 devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum);
721 }
722 brcmf_usb_rx_fill_all(devinfo);
723 return 0;
724}
725
726static void brcmf_usb_down(struct device *dev)
727{
728 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
729
730 if (devinfo == NULL)
731 return;
732
733 brcmf_dbg(TRACE, "enter\n");
734 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN)
735 return;
736
737 brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
738 if (devinfo->intr_urb)
739 usb_kill_urb(devinfo->intr_urb);
740
741 if (devinfo->ctl_urb)
742 usb_kill_urb(devinfo->ctl_urb);
743
744 if (devinfo->bulk_urb)
745 usb_kill_urb(devinfo->bulk_urb);
746 brcmf_usb_free_q(&devinfo->tx_postq, true);
747
748 brcmf_usb_free_q(&devinfo->rx_postq, true);
749}
750
Arend van Spriel71bb2442012-02-09 21:09:08 +0100751static void
752brcmf_usb_sync_complete(struct urb *urb)
753{
754 struct brcmf_usbdev_info *devinfo =
755 (struct brcmf_usbdev_info *)urb->context;
756
Hante Meuleman1e271c92012-10-22 10:36:18 -0700757 devinfo->ctl_completed = true;
758 brcmf_usb_ioctl_resp_wake(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100759}
760
761static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
762 void *buffer, int buflen)
763{
764 int ret = 0;
765 char *tmpbuf;
766 u16 size;
767
768 if ((!devinfo) || (devinfo->ctl_urb == NULL))
769 return false;
770
771 tmpbuf = kmalloc(buflen, GFP_ATOMIC);
772 if (!tmpbuf)
773 return false;
774
775 size = buflen;
776 devinfo->ctl_urb->transfer_buffer_length = size;
777
778 devinfo->ctl_read.wLength = cpu_to_le16p(&size);
779 devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR |
780 USB_RECIP_INTERFACE;
781 devinfo->ctl_read.bRequest = cmd;
782
783 usb_fill_control_urb(devinfo->ctl_urb,
784 devinfo->usbdev,
785 usb_rcvctrlpipe(devinfo->usbdev, 0),
786 (unsigned char *) &devinfo->ctl_read,
787 (void *) tmpbuf, size,
788 (usb_complete_t)brcmf_usb_sync_complete, devinfo);
789
Hante Meuleman1e271c92012-10-22 10:36:18 -0700790 devinfo->ctl_completed = false;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100791 ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
792 if (ret < 0) {
793 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
794 kfree(tmpbuf);
795 return false;
796 }
797
Hante Meuleman1e271c92012-10-22 10:36:18 -0700798 ret = brcmf_usb_ioctl_resp_wait(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100799 memcpy(buffer, tmpbuf, buflen);
800 kfree(tmpbuf);
801
Hante Meuleman1e271c92012-10-22 10:36:18 -0700802 return ret;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100803}
804
805static bool
806brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
807{
808 struct bootrom_id_le id;
809 u32 chipid, chiprev;
810
811 brcmf_dbg(TRACE, "enter\n");
812
813 if (devinfo == NULL)
814 return false;
815
816 /* Check if firmware downloaded already by querying runtime ID */
817 id.chip = cpu_to_le32(0xDEAD);
818 brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
819 sizeof(struct bootrom_id_le));
820
821 chipid = le32_to_cpu(id.chip);
822 chiprev = le32_to_cpu(id.chiprev);
823
824 if ((chipid & 0x4300) == 0x4300)
825 brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev);
826 else
827 brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev);
828 if (chipid == BRCMF_POSTBOOT_ID) {
829 brcmf_dbg(INFO, "firmware already downloaded\n");
830 brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
831 sizeof(struct bootrom_id_le));
832 return false;
833 } else {
Arend van Sprielac94f192012-03-02 22:55:46 +0100834 devinfo->bus_pub.devid = chipid;
835 devinfo->bus_pub.chiprev = chiprev;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100836 }
837 return true;
838}
839
840static int
841brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
842{
843 struct bootrom_id_le id;
844 u16 wait = 0, wait_time;
845
846 brcmf_dbg(TRACE, "enter\n");
847
848 if (devinfo == NULL)
849 return -EINVAL;
850
851 /* Give dongle chance to boot */
852 wait_time = BRCMF_USB_DLIMAGE_SPINWAIT;
853 while (wait < BRCMF_USB_DLIMAGE_LIMIT) {
854 mdelay(wait_time);
855 wait += wait_time;
856 id.chip = cpu_to_le32(0xDEAD); /* Get the ID */
857 brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
858 sizeof(struct bootrom_id_le));
859 if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
860 break;
861 }
862
863 if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) {
864 brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n",
865 wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
866
867 brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
868 sizeof(struct bootrom_id_le));
869
870 /* XXX this wait may not be necessary */
871 mdelay(BRCMF_USB_RESETCFG_SPINWAIT);
872 return 0;
873 } else {
874 brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n",
875 wait);
876 return -EINVAL;
877 }
878}
879
880
881static int
882brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len)
883{
884 int ret;
885
886 if ((devinfo == NULL) || (devinfo->bulk_urb == NULL))
887 return -EINVAL;
888
889 /* Prepare the URB */
890 usb_fill_bulk_urb(devinfo->bulk_urb, devinfo->usbdev,
891 devinfo->tx_pipe, buffer, len,
892 (usb_complete_t)brcmf_usb_sync_complete, devinfo);
893
894 devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
895
Hante Meuleman1e271c92012-10-22 10:36:18 -0700896 devinfo->ctl_completed = false;
Arend van Spriel71bb2442012-02-09 21:09:08 +0100897 ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
898 if (ret) {
899 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
900 return ret;
901 }
Hante Meuleman1e271c92012-10-22 10:36:18 -0700902 ret = brcmf_usb_ioctl_resp_wait(devinfo);
903 return (ret == 0);
Arend van Spriel71bb2442012-02-09 21:09:08 +0100904}
905
906static int
907brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
908{
909 unsigned int sendlen, sent, dllen;
910 char *bulkchunk = NULL, *dlpos;
911 struct rdl_state_le state;
912 u32 rdlstate, rdlbytes;
913 int err = 0;
914 brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen);
915
916 bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
917 if (bulkchunk == NULL) {
918 err = -ENOMEM;
919 goto fail;
920 }
921
922 /* 1) Prepare USB boot loader for runtime image */
923 brcmf_usb_dl_cmd(devinfo, DL_START, &state,
924 sizeof(struct rdl_state_le));
925
926 rdlstate = le32_to_cpu(state.state);
927 rdlbytes = le32_to_cpu(state.bytes);
928
929 /* 2) Check we are in the Waiting state */
930 if (rdlstate != DL_WAITING) {
931 brcmf_dbg(ERROR, "Failed to DL_START\n");
932 err = -EINVAL;
933 goto fail;
934 }
935 sent = 0;
936 dlpos = fw;
937 dllen = fwlen;
938
939 /* Get chip id and rev */
940 while (rdlbytes != dllen) {
941 /* Wait until the usb device reports it received all
942 * the bytes we sent */
943 if ((rdlbytes == sent) && (rdlbytes != dllen)) {
944 if ((dllen-sent) < RDL_CHUNK)
945 sendlen = dllen-sent;
946 else
947 sendlen = RDL_CHUNK;
948
949 /* simply avoid having to send a ZLP by ensuring we
950 * never have an even
951 * multiple of 64
952 */
953 if (!(sendlen % 64))
954 sendlen -= 4;
955
956 /* send data */
957 memcpy(bulkchunk, dlpos, sendlen);
958 if (brcmf_usb_dl_send_bulk(devinfo, bulkchunk,
959 sendlen)) {
960 brcmf_dbg(ERROR, "send_bulk failed\n");
961 err = -EINVAL;
962 goto fail;
963 }
964
965 dlpos += sendlen;
966 sent += sendlen;
967 }
968 if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
969 sizeof(struct rdl_state_le))) {
970 brcmf_dbg(ERROR, "DL_GETSTATE Failed xxxx\n");
971 err = -EINVAL;
972 goto fail;
973 }
974
975 rdlstate = le32_to_cpu(state.state);
976 rdlbytes = le32_to_cpu(state.bytes);
977
978 /* restart if an error is reported */
979 if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) {
980 brcmf_dbg(ERROR, "Bad Hdr or Bad CRC state %d\n",
981 rdlstate);
982 err = -EINVAL;
983 goto fail;
984 }
985 }
986
987fail:
988 kfree(bulkchunk);
989 brcmf_dbg(TRACE, "err=%d\n", err);
990 return err;
991}
992
993static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
994{
995 int err;
996
997 brcmf_dbg(TRACE, "enter\n");
998
999 if (devinfo == NULL)
1000 return -EINVAL;
1001
Arend van Sprielac94f192012-03-02 22:55:46 +01001002 if (devinfo->bus_pub.devid == 0xDEAD)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001003 return -EINVAL;
1004
1005 err = brcmf_usb_dl_writeimage(devinfo, fw, len);
1006 if (err == 0)
1007 devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE;
1008 else
1009 devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING;
1010 brcmf_dbg(TRACE, "exit: err=%d\n", err);
1011
1012 return err;
1013}
1014
1015static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
1016{
1017 struct rdl_state_le state;
1018
1019 brcmf_dbg(TRACE, "enter\n");
1020 if (!devinfo)
1021 return -EINVAL;
1022
Arend van Sprielac94f192012-03-02 22:55:46 +01001023 if (devinfo->bus_pub.devid == 0xDEAD)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001024 return -EINVAL;
1025
1026 /* Check we are runnable */
1027 brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
1028 sizeof(struct rdl_state_le));
1029
1030 /* Start the image */
1031 if (state.state == cpu_to_le32(DL_RUNNABLE)) {
1032 if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state,
1033 sizeof(struct rdl_state_le)))
1034 return -ENODEV;
1035 if (brcmf_usb_resetcfg(devinfo))
1036 return -ENODEV;
1037 /* The Dongle may go for re-enumeration. */
1038 } else {
1039 brcmf_dbg(ERROR, "Dongle not runnable\n");
1040 return -EINVAL;
1041 }
1042 brcmf_dbg(TRACE, "exit\n");
1043 return 0;
1044}
1045
1046static bool brcmf_usb_chip_support(int chipid, int chiprev)
1047{
1048 switch(chipid) {
Hante Meuleman70f08222012-08-30 19:43:01 +02001049 case 43143:
1050 return true;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001051 case 43235:
1052 case 43236:
1053 case 43238:
1054 return (chiprev == 3);
Hante Meuleman1212d372012-08-30 19:43:00 +02001055 case 43242:
1056 return true;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001057 default:
1058 break;
1059 }
1060 return false;
1061}
1062
1063static int
1064brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
1065{
Arend van Sprielac94f192012-03-02 22:55:46 +01001066 int devid, chiprev;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001067 int err;
1068
1069 brcmf_dbg(TRACE, "enter\n");
1070 if (devinfo == NULL)
1071 return -ENODEV;
1072
Arend van Sprielac94f192012-03-02 22:55:46 +01001073 devid = devinfo->bus_pub.devid;
1074 chiprev = devinfo->bus_pub.chiprev;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001075
Arend van Sprielac94f192012-03-02 22:55:46 +01001076 if (!brcmf_usb_chip_support(devid, chiprev)) {
Arend van Spriel71bb2442012-02-09 21:09:08 +01001077 brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
Arend van Sprielac94f192012-03-02 22:55:46 +01001078 devid, chiprev);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001079 return -EINVAL;
1080 }
1081
1082 if (!devinfo->image) {
1083 brcmf_dbg(ERROR, "No firmware!\n");
1084 return -ENOENT;
1085 }
1086
1087 err = brcmf_usb_dlstart(devinfo,
1088 devinfo->image, devinfo->image_len);
1089 if (err == 0)
1090 err = brcmf_usb_dlrun(devinfo);
1091 return err;
1092}
1093
1094
Hante Meulemand74a0b52012-09-11 21:18:51 +02001095static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001096{
Arend van Spriel71bb2442012-02-09 21:09:08 +01001097 brcmf_dbg(TRACE, "devinfo %p\n", devinfo);
1098
Arend van Spriel71bb2442012-02-09 21:09:08 +01001099 /* free the URBS */
1100 brcmf_usb_free_q(&devinfo->rx_freeq, false);
1101 brcmf_usb_free_q(&devinfo->tx_freeq, false);
1102
1103 usb_free_urb(devinfo->intr_urb);
1104 usb_free_urb(devinfo->ctl_urb);
1105 usb_free_urb(devinfo->bulk_urb);
1106
1107 kfree(devinfo->tx_reqs);
1108 kfree(devinfo->rx_reqs);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001109}
1110
1111#define TRX_MAGIC 0x30524448 /* "HDR0" */
1112#define TRX_VERSION 1 /* Version 1 */
1113#define TRX_MAX_LEN 0x3B0000 /* Max length */
1114#define TRX_NO_HEADER 1 /* Do not write TRX header */
1115#define TRX_MAX_OFFSET 3 /* Max number of individual files */
1116#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */
1117
1118struct trx_header_le {
1119 __le32 magic; /* "HDR0" */
1120 __le32 len; /* Length of file including header */
1121 __le32 crc32; /* CRC from flag_version to end of file */
1122 __le32 flag_version; /* 0:15 flags, 16:31 version */
1123 __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of
1124 * header */
1125};
1126
1127static int check_file(const u8 *headers)
1128{
1129 struct trx_header_le *trx;
1130 int actual_len = -1;
1131
1132 /* Extract trx header */
1133 trx = (struct trx_header_le *) headers;
1134 if (trx->magic != cpu_to_le32(TRX_MAGIC))
1135 return -1;
1136
1137 headers += sizeof(struct trx_header_le);
1138
1139 if (le32_to_cpu(trx->flag_version) & TRX_UNCOMP_IMAGE) {
1140 actual_len = le32_to_cpu(trx->offsets[TRX_OFFSETS_DLFWLEN_IDX]);
1141 return actual_len + sizeof(struct trx_header_le);
1142 }
1143 return -1;
1144}
1145
1146static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
1147{
1148 s8 *fwname;
1149 const struct firmware *fw;
Hante Meuleman803599d2012-09-19 22:21:10 +02001150 struct brcmf_usb_image *fw_image;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001151 int err;
1152
Hante Meuleman1212d372012-08-30 19:43:00 +02001153 switch (devinfo->bus_pub.devid) {
Hante Meuleman70f08222012-08-30 19:43:01 +02001154 case 43143:
1155 fwname = BRCMF_USB_43143_FW_NAME;
1156 break;
Hante Meuleman1212d372012-08-30 19:43:00 +02001157 case 43235:
1158 case 43236:
1159 case 43238:
1160 fwname = BRCMF_USB_43236_FW_NAME;
1161 break;
1162 case 43242:
1163 fwname = BRCMF_USB_43242_FW_NAME;
1164 break;
1165 default:
1166 return -EINVAL;
1167 break;
1168 }
Arend van Spriel71bb2442012-02-09 21:09:08 +01001169
Hante Meuleman803599d2012-09-19 22:21:10 +02001170 list_for_each_entry(fw_image, &fw_image_list, list) {
1171 if (fw_image->fwname == fwname) {
1172 devinfo->image = fw_image->image;
1173 devinfo->image_len = fw_image->image_len;
1174 return 0;
1175 }
1176 }
1177 /* fw image not yet loaded. Load it now and add to list */
Arend van Spriel71bb2442012-02-09 21:09:08 +01001178 err = request_firmware(&fw, fwname, devinfo->dev);
1179 if (!fw) {
1180 brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname);
1181 return err;
1182 }
1183 if (check_file(fw->data) < 0) {
1184 brcmf_dbg(ERROR, "invalid firmware %s\n", fwname);
1185 return -EINVAL;
1186 }
1187
Hante Meuleman803599d2012-09-19 22:21:10 +02001188 fw_image = kzalloc(sizeof(*fw_image), GFP_ATOMIC);
1189 if (!fw_image)
1190 return -ENOMEM;
1191 INIT_LIST_HEAD(&fw_image->list);
1192 list_add_tail(&fw_image->list, &fw_image_list);
1193 fw_image->fwname = fwname;
1194 fw_image->image = vmalloc(fw->size);
1195 if (!fw_image->image)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001196 return -ENOMEM;
1197
Hante Meuleman803599d2012-09-19 22:21:10 +02001198 memcpy(fw_image->image, fw->data, fw->size);
1199 fw_image->image_len = fw->size;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001200
1201 release_firmware(fw);
Hante Meuleman803599d2012-09-19 22:21:10 +02001202
1203 devinfo->image = fw_image->image;
1204 devinfo->image_len = fw_image->image_len;
1205
Arend van Spriel71bb2442012-02-09 21:09:08 +01001206 return 0;
1207}
1208
1209
1210static
Hante Meulemand74a0b52012-09-11 21:18:51 +02001211struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
1212 int nrxq, int ntxq)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001213{
Arend van Spriel71bb2442012-02-09 21:09:08 +01001214 devinfo->bus_pub.nrxq = nrxq;
1215 devinfo->rx_low_watermark = nrxq / 2;
1216 devinfo->bus_pub.devinfo = devinfo;
1217 devinfo->bus_pub.ntxq = ntxq;
1218
1219 /* flow control when too many tx urbs posted */
1220 devinfo->tx_low_watermark = ntxq / 4;
1221 devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001222 devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE;
1223
1224 /* Initialize other structure content */
1225 init_waitqueue_head(&devinfo->ioctl_resp_wait);
1226
1227 /* Initialize the spinlocks */
1228 spin_lock_init(&devinfo->qlock);
1229
1230 INIT_LIST_HEAD(&devinfo->rx_freeq);
1231 INIT_LIST_HEAD(&devinfo->rx_postq);
1232
1233 INIT_LIST_HEAD(&devinfo->tx_freeq);
1234 INIT_LIST_HEAD(&devinfo->tx_postq);
1235
Hante Meulemanc6ab4292012-09-11 21:18:48 +02001236 devinfo->tx_flowblock = false;
1237
Arend van Spriel71bb2442012-02-09 21:09:08 +01001238 devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq);
1239 if (!devinfo->rx_reqs)
1240 goto error;
1241
1242 devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq);
1243 if (!devinfo->tx_reqs)
1244 goto error;
Hante Meulemanc6ab4292012-09-11 21:18:48 +02001245 devinfo->tx_freecount = ntxq;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001246
1247 devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
1248 if (!devinfo->intr_urb) {
1249 brcmf_dbg(ERROR, "usb_alloc_urb (intr) failed\n");
1250 goto error;
1251 }
1252 devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
1253 if (!devinfo->ctl_urb) {
1254 brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n");
1255 goto error;
1256 }
Arend van Spriel71bb2442012-02-09 21:09:08 +01001257 devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC);
1258 if (!devinfo->bulk_urb) {
1259 brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n");
1260 goto error;
1261 }
1262
Arend van Spriel71bb2442012-02-09 21:09:08 +01001263 if (!brcmf_usb_dlneeded(devinfo))
1264 return &devinfo->bus_pub;
1265
1266 brcmf_dbg(TRACE, "start fw downloading\n");
1267 if (brcmf_usb_get_fw(devinfo))
1268 goto error;
1269
1270 if (brcmf_usb_fw_download(devinfo))
1271 goto error;
1272
1273 return &devinfo->bus_pub;
1274
1275error:
1276 brcmf_dbg(ERROR, "failed!\n");
Hante Meulemand74a0b52012-09-11 21:18:51 +02001277 brcmf_usb_detach(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001278 return NULL;
1279}
1280
Hante Meulemand74a0b52012-09-11 21:18:51 +02001281static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
1282 const char *desc, u32 bustype, u32 hdrlen)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001283{
1284 struct brcmf_bus *bus = NULL;
1285 struct brcmf_usbdev *bus_pub = NULL;
1286 int ret;
Hante Meulemand74a0b52012-09-11 21:18:51 +02001287 struct device *dev = devinfo->dev;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001288
Hante Meulemand74a0b52012-09-11 21:18:51 +02001289 bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
Hante Meuleman9cd23a72012-09-13 21:12:04 +02001290 if (!bus_pub)
1291 return -ENODEV;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001292
1293 bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
1294 if (!bus) {
1295 ret = -ENOMEM;
1296 goto fail;
1297 }
1298
1299 bus_pub->bus = bus;
1300 bus->brcmf_bus_txdata = brcmf_usb_tx;
1301 bus->brcmf_bus_init = brcmf_usb_up;
1302 bus->brcmf_bus_stop = brcmf_usb_down;
1303 bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt;
1304 bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt;
1305 bus->type = bustype;
1306 bus->bus_priv.usb = bus_pub;
1307 dev_set_drvdata(dev, bus);
1308
1309 /* Attach to the common driver interface */
1310 ret = brcmf_attach(hdrlen, dev);
1311 if (ret) {
1312 brcmf_dbg(ERROR, "dhd_attach failed\n");
1313 goto fail;
1314 }
1315
1316 ret = brcmf_bus_start(dev);
Hante Meulemane270b302012-10-10 11:13:06 -07001317 if (ret) {
Arend van Spriel71bb2442012-02-09 21:09:08 +01001318 brcmf_dbg(ERROR, "dongle is not responding\n");
1319 brcmf_detach(dev);
1320 goto fail;
1321 }
1322
Arend van Spriel71bb2442012-02-09 21:09:08 +01001323 return 0;
1324fail:
1325 /* Release resources in reverse order */
Arend van Spriel71bb2442012-02-09 21:09:08 +01001326 kfree(bus);
Hante Meulemand74a0b52012-09-11 21:18:51 +02001327 brcmf_usb_detach(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001328 return ret;
1329}
1330
1331static void
Hante Meulemand74a0b52012-09-11 21:18:51 +02001332brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001333{
Hante Meulemand74a0b52012-09-11 21:18:51 +02001334 if (!devinfo)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001335 return;
Hante Meulemand74a0b52012-09-11 21:18:51 +02001336 brcmf_dbg(TRACE, "enter: bus_pub %p\n", devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001337
Hante Meulemand74a0b52012-09-11 21:18:51 +02001338 brcmf_detach(devinfo->dev);
1339 kfree(devinfo->bus_pub.bus);
1340 brcmf_usb_detach(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001341}
1342
1343static int
1344brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
1345{
1346 int ep;
1347 struct usb_endpoint_descriptor *endpoint;
1348 int ret = 0;
1349 struct usb_device *usb = interface_to_usbdev(intf);
1350 int num_of_eps;
1351 u8 endpoint_num;
Hante Meulemand74a0b52012-09-11 21:18:51 +02001352 struct brcmf_usbdev_info *devinfo;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001353
1354 brcmf_dbg(TRACE, "enter\n");
1355
Hante Meulemand74a0b52012-09-11 21:18:51 +02001356 devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
1357 if (devinfo == NULL)
1358 return -ENOMEM;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001359
Hante Meulemand74a0b52012-09-11 21:18:51 +02001360 devinfo->usbdev = usb;
1361 devinfo->dev = &usb->dev;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001362
Hante Meulemand74a0b52012-09-11 21:18:51 +02001363 usb_set_intfdata(intf, devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001364
1365 /* Check that the device supports only one configuration */
1366 if (usb->descriptor.bNumConfigurations != 1) {
1367 ret = -1;
1368 goto fail;
1369 }
1370
1371 if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
1372 ret = -1;
1373 goto fail;
1374 }
1375
1376 /*
1377 * Only the BDC interface configuration is supported:
1378 * Device class: USB_CLASS_VENDOR_SPEC
1379 * if0 class: USB_CLASS_VENDOR_SPEC
1380 * if0/ep0: control
1381 * if0/ep1: bulk in
1382 * if0/ep2: bulk out (ok if swapped with bulk in)
1383 */
1384 if (CONFIGDESC(usb)->bNumInterfaces != 1) {
1385 ret = -1;
1386 goto fail;
1387 }
1388
1389 /* Check interface */
1390 if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
1391 IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 ||
1392 IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) {
1393 brcmf_dbg(ERROR, "invalid control interface: class %d, subclass %d, proto %d\n",
1394 IFDESC(usb, CONTROL_IF).bInterfaceClass,
1395 IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
1396 IFDESC(usb, CONTROL_IF).bInterfaceProtocol);
1397 ret = -1;
1398 goto fail;
1399 }
1400
1401 /* Check control endpoint */
1402 endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
1403 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1404 != USB_ENDPOINT_XFER_INT) {
1405 brcmf_dbg(ERROR, "invalid control endpoint %d\n",
1406 endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
1407 ret = -1;
1408 goto fail;
1409 }
1410
1411 endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
Hante Meulemand74a0b52012-09-11 21:18:51 +02001412 devinfo->intr_pipe = usb_rcvintpipe(usb, endpoint_num);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001413
Hante Meulemand74a0b52012-09-11 21:18:51 +02001414 devinfo->rx_pipe = 0;
1415 devinfo->rx_pipe2 = 0;
1416 devinfo->tx_pipe = 0;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001417 num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
1418
1419 /* Check data endpoints and get pipes */
1420 for (ep = 1; ep <= num_of_eps; ep++) {
1421 endpoint = &IFEPDESC(usb, BULK_IF, ep);
1422 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1423 USB_ENDPOINT_XFER_BULK) {
1424 brcmf_dbg(ERROR, "invalid data endpoint %d\n", ep);
1425 ret = -1;
1426 goto fail;
1427 }
1428
1429 endpoint_num = endpoint->bEndpointAddress &
1430 USB_ENDPOINT_NUMBER_MASK;
1431 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1432 == USB_DIR_IN) {
Hante Meulemand74a0b52012-09-11 21:18:51 +02001433 if (!devinfo->rx_pipe) {
1434 devinfo->rx_pipe =
Arend van Spriel71bb2442012-02-09 21:09:08 +01001435 usb_rcvbulkpipe(usb, endpoint_num);
1436 } else {
Hante Meulemand74a0b52012-09-11 21:18:51 +02001437 devinfo->rx_pipe2 =
Arend van Spriel71bb2442012-02-09 21:09:08 +01001438 usb_rcvbulkpipe(usb, endpoint_num);
1439 }
1440 } else {
Hante Meulemand74a0b52012-09-11 21:18:51 +02001441 devinfo->tx_pipe = usb_sndbulkpipe(usb, endpoint_num);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001442 }
1443 }
1444
1445 /* Allocate interrupt URB and data buffer */
1446 /* RNDIS says 8-byte intr, our old drivers used 4-byte */
1447 if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
Hante Meulemand74a0b52012-09-11 21:18:51 +02001448 devinfo->intr_size = 8;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001449 else
Hante Meulemand74a0b52012-09-11 21:18:51 +02001450 devinfo->intr_size = 4;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001451
Hante Meulemand74a0b52012-09-11 21:18:51 +02001452 devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001453
Arend van Spriel71bb2442012-02-09 21:09:08 +01001454 if (usb->speed == USB_SPEED_HIGH)
1455 brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
1456 else
1457 brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n");
1458
Hante Meulemand74a0b52012-09-11 21:18:51 +02001459 ret = brcmf_usb_probe_cb(devinfo, "", USB_BUS, 0);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001460 if (ret)
1461 goto fail;
1462
1463 /* Success */
1464 return 0;
1465
1466fail:
1467 brcmf_dbg(ERROR, "failed with errno %d\n", ret);
Hante Meulemand74a0b52012-09-11 21:18:51 +02001468 kfree(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001469 usb_set_intfdata(intf, NULL);
1470 return ret;
1471
1472}
1473
1474static void
1475brcmf_usb_disconnect(struct usb_interface *intf)
1476{
Hante Meulemand74a0b52012-09-11 21:18:51 +02001477 struct brcmf_usbdev_info *devinfo;
Arend van Spriel71bb2442012-02-09 21:09:08 +01001478
1479 brcmf_dbg(TRACE, "enter\n");
Hante Meulemand74a0b52012-09-11 21:18:51 +02001480 devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
1481 brcmf_usb_disconnect_cb(devinfo);
1482 kfree(devinfo);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001483}
1484
1485/*
1486 * only need to signal the bus being down and update the suspend state.
1487 */
1488static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
1489{
1490 struct usb_device *usb = interface_to_usbdev(intf);
1491 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
1492
1493 brcmf_dbg(TRACE, "enter\n");
1494 devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN;
1495 devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
1496 return 0;
1497}
1498
1499/*
1500 * mark suspend state active and crank up the bus.
1501 */
1502static int brcmf_usb_resume(struct usb_interface *intf)
1503{
1504 struct usb_device *usb = interface_to_usbdev(intf);
1505 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
1506
1507 brcmf_dbg(TRACE, "enter\n");
1508 devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
1509 brcmf_bus_start(&usb->dev);
1510 return 0;
1511}
1512
1513#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
Hante Meuleman70f08222012-08-30 19:43:01 +02001514#define BRCMF_USB_DEVICE_ID_43143 0xbd1e
Arend van Spriel71bb2442012-02-09 21:09:08 +01001515#define BRCMF_USB_DEVICE_ID_43236 0xbd17
Hante Meuleman1212d372012-08-30 19:43:00 +02001516#define BRCMF_USB_DEVICE_ID_43242 0xbd1f
Arend van Spriel71bb2442012-02-09 21:09:08 +01001517#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc
1518
1519static struct usb_device_id brcmf_usb_devid_table[] = {
Hante Meuleman70f08222012-08-30 19:43:01 +02001520 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) },
Arend van Spriel71bb2442012-02-09 21:09:08 +01001521 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) },
Hante Meuleman1212d372012-08-30 19:43:00 +02001522 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) },
Arend van Spriel71bb2442012-02-09 21:09:08 +01001523 /* special entry for device with firmware loaded and running */
1524 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
1525 { }
1526};
1527MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
Hante Meuleman70f08222012-08-30 19:43:01 +02001528MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
Rafał Miłeckifda82412012-02-24 07:22:51 +01001529MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
Hante Meuleman1212d372012-08-30 19:43:00 +02001530MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001531
1532/* TODO: suspend and resume entries */
1533static struct usb_driver brcmf_usbdrvr = {
1534 .name = KBUILD_MODNAME,
1535 .probe = brcmf_usb_probe,
1536 .disconnect = brcmf_usb_disconnect,
1537 .id_table = brcmf_usb_devid_table,
1538 .suspend = brcmf_usb_suspend,
1539 .resume = brcmf_usb_resume,
Sarah Sharpc51fa662012-05-21 05:34:24 -07001540 .supports_autosuspend = 1,
Sarah Sharpe1f12eb2012-04-23 10:08:51 -07001541 .disable_hub_initiated_lpm = 1,
Arend van Spriel71bb2442012-02-09 21:09:08 +01001542};
1543
Hante Meuleman803599d2012-09-19 22:21:10 +02001544static void brcmf_release_fw(struct list_head *q)
1545{
1546 struct brcmf_usb_image *fw_image, *next;
1547
1548 list_for_each_entry_safe(fw_image, next, q, list) {
1549 vfree(fw_image->image);
1550 list_del_init(&fw_image->list);
1551 }
1552}
1553
1554
Arend van Spriel71bb2442012-02-09 21:09:08 +01001555void brcmf_usb_exit(void)
1556{
1557 usb_deregister(&brcmf_usbdrvr);
Hante Meuleman803599d2012-09-19 22:21:10 +02001558 brcmf_release_fw(&fw_image_list);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001559}
1560
Arend van Spriel549040a2012-03-02 22:55:48 +01001561void brcmf_usb_init(void)
Arend van Spriel71bb2442012-02-09 21:09:08 +01001562{
Hante Meuleman803599d2012-09-19 22:21:10 +02001563 INIT_LIST_HEAD(&fw_image_list);
Arend van Spriel549040a2012-03-02 22:55:48 +01001564 usb_register(&brcmf_usbdrvr);
Arend van Spriel71bb2442012-02-09 21:09:08 +01001565}