aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2012-02-09 15:09:08 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-02-22 14:48:53 -0500
commit71bb244ba2fd5390eefe4ee9054abdb3f8b05922 (patch)
tree40908e8c5eb0676f503f95a9234a2265e97723f2 /drivers/net/wireless/brcm80211
parentcf44066a3836847a74f6a0817c680726b796239f (diff)
brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
This patch extends the use of the brcmfmac driver with support for chipsets with a USB host interface. The first chipsets supported are the bcm43235, bcm43236, and bcm43238 for which firmware has been submitted. This driver change has been successfully built for x86, x86_64, ppc64, arm_le, and mips_be. It has been tested successfully on x86 and x86_64. Cc: M. Lambert <lambertm@westman.wave.ca> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Kan Yan <kanyan@broadcom.com> Reviewed-by: Alwin Beukers <alwin@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211')
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig17
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile6
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h6
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c8
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c1623
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.h84
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h75
7 files changed, 1812 insertions, 7 deletions
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index cd6375de2a60..c5104533e24e 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -26,16 +26,25 @@ config BRCMFMAC
26 it'll be called brcmfmac.ko. 26 it'll be called brcmfmac.ko.
27 27
28config BRCMFMAC_SDIO 28config BRCMFMAC_SDIO
29 bool "SDIO bus interface support for FullMAC" 29 bool "SDIO bus interface support for FullMAC driver"
30 depends on MMC 30 depends on MMC
31 depends on BRCMFMAC 31 depends on BRCMFMAC
32 select FW_LOADER 32 select FW_LOADER
33 default y 33 default y
34 ---help--- 34 ---help---
35 This option enables the SDIO bus interface support for Broadcom 35 This option enables the SDIO bus interface support for Broadcom
36 FullMAC WLAN driver. 36 IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
37 Say Y if you want to use brcmfmac for a compatible SDIO interface 37 use the driver for a SDIO wireless card.
38 wireless card. 38
39config BRCMFMAC_USB
40 bool "USB bus interface support for FullMAC driver"
41 depends on USB
42 depends on BRCMFMAC
43 select FW_LOADER
44 ---help---
45 This option enables the USB bus interface support for Broadcom
46 IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
47 use the driver for an USB wireless card.
39 48
40config BRCMDBG 49config BRCMDBG
41 bool "Broadcom driver debug functions" 50 bool "Broadcom driver debug functions"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 9ca9ea1135ea..abb48032753b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -19,6 +19,8 @@ ccflags-y += \
19 -Idrivers/net/wireless/brcm80211/brcmfmac \ 19 -Idrivers/net/wireless/brcm80211/brcmfmac \
20 -Idrivers/net/wireless/brcm80211/include 20 -Idrivers/net/wireless/brcm80211/include
21 21
22ccflags-y += -D__CHECK_ENDIAN__
23
22obj-$(CONFIG_BRCMFMAC) += brcmfmac.o 24obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
23brcmfmac-objs += \ 25brcmfmac-objs += \
24 wl_cfg80211.o \ 26 wl_cfg80211.o \
@@ -30,5 +32,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
30 bcmsdh.o \ 32 bcmsdh.o \
31 bcmsdh_sdmmc.o \ 33 bcmsdh_sdmmc.o \
32 sdio_chip.o 34 sdio_chip.o
33 35brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
34ccflags-y += -D__CHECK_ENDIAN__ 36 usb.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index bc575b4f158e..b7671b30692f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -40,8 +40,8 @@ struct dngl_stats {
40struct brcmf_bus { 40struct brcmf_bus {
41 u8 type; /* bus type */ 41 u8 type; /* bus type */
42 union { 42 union {
43 /* pointer to sdio private structure */
44 struct brcmf_sdio_dev *sdio; 43 struct brcmf_sdio_dev *sdio;
44 struct brcmf_usbdev *usb;
45 } bus_priv; 45 } bus_priv;
46 struct brcmf_pub *drvr; /* pointer to driver pub structure brcmf_pub */ 46 struct brcmf_pub *drvr; /* pointer to driver pub structure brcmf_pub */
47 enum brcmf_bus_state state; 47 enum brcmf_bus_state state;
@@ -110,5 +110,9 @@ extern int brcmf_add_if(struct device *dev, int ifidx,
110extern void brcmf_sdio_exit(void); 110extern void brcmf_sdio_exit(void);
111extern int brcmf_sdio_init(void); 111extern int brcmf_sdio_init(void);
112#endif 112#endif
113#ifdef CONFIG_BRCMFMAC_USB
114extern void brcmf_usb_exit(void);
115extern int brcmf_usb_init(void);
116#endif
113 117
114#endif /* _BRCMF_BUS_H_ */ 118#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 68da7568ad10..c4da05817443 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1190,6 +1190,11 @@ static int __init brcmfmac_init(void)
1190 if (ret) 1190 if (ret)
1191 goto fail; 1191 goto fail;
1192#endif 1192#endif
1193#ifdef CONFIG_BRCMFMAC_USB
1194 ret = brcmf_usb_init();
1195 if (ret)
1196 goto fail;
1197#endif
1193 1198
1194fail: 1199fail:
1195 return ret; 1200 return ret;
@@ -1200,6 +1205,9 @@ static void __exit brcmfmac_exit(void)
1200#ifdef CONFIG_BRCMFMAC_SDIO 1205#ifdef CONFIG_BRCMFMAC_SDIO
1201 brcmf_sdio_exit(); 1206 brcmf_sdio_exit();
1202#endif 1207#endif
1208#ifdef CONFIG_BRCMFMAC_USB
1209 brcmf_usb_exit();
1210#endif
1203} 1211}
1204 1212
1205module_init(brcmfmac_init); 1213module_init(brcmfmac_init);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
new file mode 100644
index 000000000000..934ed782620c
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -0,0 +1,1623 @@
1/*
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>
31#include <net/cfg80211.h>
32
33#include <defs.h>
34#include <brcmu_utils.h>
35#include <brcmu_wifi.h>
36#include <dhd_bus.h>
37#include <dhd_dbg.h>
38
39#include "usb_rdl.h"
40#include "usb.h"
41
42#define IOCTL_RESP_TIMEOUT 2000
43
44#define BRCMF_USB_SYNC_TIMEOUT 300 /* ms */
45#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
68#define BRCMF_USB_FW_NAME "brcm/brcmfmac-usb.bin"
69
70enum usbdev_suspend_state {
71 USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
72 suspend */
73 USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be
74 * suspended. Wating PM to
75 * suspend the device
76 */
77 USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */
78};
79
80struct brcmf_usb_probe_info {
81 void *usbdev_info;
82 struct usb_device *usb; /* USB device pointer from OS */
83 uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
84 int intr_size; /* Size of interrupt message */
85 int interval; /* Interrupt polling interval */
86 int vid;
87 int pid;
88 enum usb_device_speed device_speed;
89 enum usbdev_suspend_state suspend_state;
90 struct usb_interface *intf;
91};
92static struct brcmf_usb_probe_info usbdev_probe_info;
93
94struct brcmf_usb_image {
95 void *data;
96 u32 len;
97};
98static struct brcmf_usb_image g_image = { NULL, 0 };
99
100struct intr_transfer_buf {
101 u32 notification;
102 u32 reserved;
103};
104
105struct brcmf_usbdev_info {
106 struct brcmf_usbdev bus_pub; /* MUST BE FIRST */
107 spinlock_t qlock;
108 struct list_head rx_freeq;
109 struct list_head rx_postq;
110 struct list_head tx_freeq;
111 struct list_head tx_postq;
112 enum usbdev_suspend_state suspend_state;
113 uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
114
115 bool activity;
116 int rx_low_watermark;
117 int tx_low_watermark;
118 int tx_high_watermark;
119 bool txoff;
120 bool rxoff;
121 bool txoverride;
122
123 struct brcmf_usbreq *tx_reqs;
124 struct brcmf_usbreq *rx_reqs;
125
126 u8 *image; /* buffer for combine fw and nvram */
127 int image_len;
128
129 wait_queue_head_t wait;
130 bool waitdone;
131 int sync_urb_status;
132
133 struct usb_device *usbdev;
134 struct device *dev;
135 enum usb_device_speed device_speed;
136
137 int ctl_in_pipe, ctl_out_pipe;
138 struct urb *ctl_urb; /* URB for control endpoint */
139 struct usb_ctrlrequest ctl_write;
140 struct usb_ctrlrequest ctl_read;
141 u32 ctl_urb_actual_length;
142 int ctl_urb_status;
143 int ctl_completed;
144 wait_queue_head_t ioctl_resp_wait;
145 wait_queue_head_t ctrl_wait;
146 ulong ctl_op;
147
148 bool rxctl_deferrespok;
149
150 struct urb *bulk_urb; /* used for FW download */
151 struct urb *intr_urb; /* URB for interrupt endpoint */
152 int intr_size; /* Size of interrupt message */
153 int interval; /* Interrupt polling interval */
154 struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */
155
156 struct brcmf_usb_probe_info probe_info;
157
158};
159
160static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
161 struct brcmf_usbreq *req);
162
163MODULE_AUTHOR("Broadcom Corporation");
164MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver.");
165MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards");
166MODULE_LICENSE("Dual BSD/GPL");
167
168static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev)
169{
170 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
171 return bus_if->bus_priv.usb;
172}
173
174static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
175{
176 return brcmf_usb_get_buspub(dev)->devinfo;
177}
178
179#if 0
180static void
181brcmf_usb_txflowcontrol(struct brcmf_usbdev_info *devinfo, bool onoff)
182{
183 dhd_txflowcontrol(devinfo->bus_pub.netdev, 0, onoff);
184}
185#endif
186
187static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo,
188 uint *condition, bool *pending)
189{
190 DECLARE_WAITQUEUE(wait, current);
191 int timeout = IOCTL_RESP_TIMEOUT;
192
193 /* Convert timeout in millsecond to jiffies */
194 timeout = msecs_to_jiffies(timeout);
195 /* Wait until control frame is available */
196 add_wait_queue(&devinfo->ioctl_resp_wait, &wait);
197 set_current_state(TASK_INTERRUPTIBLE);
198
199 smp_mb();
200 while (!(*condition) && (!signal_pending(current) && timeout)) {
201 timeout = schedule_timeout(timeout);
202 /* Wait until control frame is available */
203 smp_mb();
204 }
205
206 if (signal_pending(current))
207 *pending = true;
208
209 set_current_state(TASK_RUNNING);
210 remove_wait_queue(&devinfo->ioctl_resp_wait, &wait);
211
212 return timeout;
213}
214
215static int brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
216{
217 if (waitqueue_active(&devinfo->ioctl_resp_wait))
218 wake_up_interruptible(&devinfo->ioctl_resp_wait);
219
220 return 0;
221}
222
223static void
224brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status)
225{
226
227 if (unlikely(devinfo == NULL))
228 return;
229
230 if (type == BRCMF_USB_CBCTL_READ) {
231 if (status == 0)
232 devinfo->bus_pub.stats.rx_ctlpkts++;
233 else
234 devinfo->bus_pub.stats.rx_ctlerrs++;
235 } else if (type == BRCMF_USB_CBCTL_WRITE) {
236 if (status == 0)
237 devinfo->bus_pub.stats.tx_ctlpkts++;
238 else
239 devinfo->bus_pub.stats.tx_ctlerrs++;
240 }
241
242 devinfo->ctl_urb_status = status;
243 devinfo->ctl_completed = true;
244 brcmf_usb_ioctl_resp_wake(devinfo);
245}
246
247static void
248brcmf_usb_ctlread_complete(struct urb *urb)
249{
250 struct brcmf_usbdev_info *devinfo =
251 (struct brcmf_usbdev_info *)urb->context;
252
253 devinfo->ctl_urb_actual_length = urb->actual_length;
254 brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ,
255 urb->status);
256}
257
258static void
259brcmf_usb_ctlwrite_complete(struct urb *urb)
260{
261 struct brcmf_usbdev_info *devinfo =
262 (struct brcmf_usbdev_info *)urb->context;
263
264 brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE,
265 urb->status);
266}
267
268static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state)
269{
270 return 0;
271}
272
273static int
274brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
275{
276 int ret;
277 u16 size;
278
279 if (devinfo == NULL || buf == NULL ||
280 len == 0 || devinfo->ctl_urb == NULL)
281 return -EINVAL;
282
283 /* If the USB/HSIC bus in sleep state, wake it up */
284 if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED)
285 if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
286 brcmf_dbg(ERROR, "Could not Resume the bus!\n");
287 return -EIO;
288 }
289
290 devinfo->activity = true;
291 size = len;
292 devinfo->ctl_write.wLength = cpu_to_le16p(&size);
293 devinfo->ctl_urb->transfer_buffer_length = size;
294 devinfo->ctl_urb_status = 0;
295 devinfo->ctl_urb_actual_length = 0;
296
297 usb_fill_control_urb(devinfo->ctl_urb,
298 devinfo->usbdev,
299 devinfo->ctl_out_pipe,
300 (unsigned char *) &devinfo->ctl_write,
301 buf, size,
302 (usb_complete_t)brcmf_usb_ctlwrite_complete,
303 devinfo);
304
305 ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
306 if (ret < 0)
307 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
308
309 return ret;
310}
311
312static int
313brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
314{
315 int ret;
316 u16 size;
317
318 if ((devinfo == NULL) || (buf == NULL) || (len == 0)
319 || (devinfo->ctl_urb == NULL))
320 return -EINVAL;
321
322 size = len;
323 devinfo->ctl_read.wLength = cpu_to_le16p(&size);
324 devinfo->ctl_urb->transfer_buffer_length = size;
325
326 if (devinfo->rxctl_deferrespok) {
327 /* BMAC model */
328 devinfo->ctl_read.bRequestType = USB_DIR_IN
329 | USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
330 devinfo->ctl_read.bRequest = DL_DEFER_RESP_OK;
331 } else {
332 /* full dongle model */
333 devinfo->ctl_read.bRequestType = USB_DIR_IN
334 | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
335 devinfo->ctl_read.bRequest = 1;
336 }
337
338 usb_fill_control_urb(devinfo->ctl_urb,
339 devinfo->usbdev,
340 devinfo->ctl_in_pipe,
341 (unsigned char *) &devinfo->ctl_read,
342 buf, size,
343 (usb_complete_t)brcmf_usb_ctlread_complete,
344 devinfo);
345
346 ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
347 if (ret < 0)
348 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
349
350 return ret;
351}
352
353static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
354{
355 int err = 0;
356 int timeout = 0;
357 bool pending;
358 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
359
360 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
361 /* TODO: handle suspend/resume */
362 return -EIO;
363 }
364
365 if (test_and_set_bit(0, &devinfo->ctl_op))
366 return -EIO;
367
368 err = brcmf_usb_send_ctl(devinfo, buf, len);
369 if (err) {
370 brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
371 return err;
372 }
373
374 devinfo->ctl_completed = false;
375 timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
376 &pending);
377 clear_bit(0, &devinfo->ctl_op);
378 if (!timeout) {
379 brcmf_dbg(ERROR, "Txctl wait timed out\n");
380 err = -EIO;
381 }
382 return err;
383}
384
385static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
386{
387 int err = 0;
388 int timeout = 0;
389 bool pending;
390 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
391
392 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
393 /* TODO: handle suspend/resume */
394 return -EIO;
395 }
396 if (test_and_set_bit(0, &devinfo->ctl_op))
397 return -EIO;
398
399 err = brcmf_usb_recv_ctl(devinfo, buf, len);
400 if (err) {
401 brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
402 return err;
403 }
404 devinfo->ctl_completed = false;
405 timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
406 &pending);
407 err = devinfo->ctl_urb_status;
408 clear_bit(0, &devinfo->ctl_op);
409 if (!timeout) {
410 brcmf_dbg(ERROR, "rxctl wait timed out\n");
411 err = -EIO;
412 }
413 if (!err)
414 return devinfo->ctl_urb_actual_length;
415 else
416 return err;
417}
418
419static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
420 struct list_head *q)
421{
422 unsigned long flags;
423 struct brcmf_usbreq *req;
424 spin_lock_irqsave(&devinfo->qlock, flags);
425 if (list_empty(q)) {
426 spin_unlock_irqrestore(&devinfo->qlock, flags);
427 return NULL;
428 }
429 req = list_entry(q->next, struct brcmf_usbreq, list);
430 list_del_init(q->next);
431 spin_unlock_irqrestore(&devinfo->qlock, flags);
432 return req;
433
434}
435
436static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo,
437 struct list_head *q, struct brcmf_usbreq *req)
438{
439 unsigned long flags;
440 spin_lock_irqsave(&devinfo->qlock, flags);
441 list_add_tail(&req->list, q);
442 spin_unlock_irqrestore(&devinfo->qlock, flags);
443}
444
445static struct brcmf_usbreq *
446brcmf_usbdev_qinit(struct list_head *q, int qsize)
447{
448 int i;
449 struct brcmf_usbreq *req, *reqs;
450
451 reqs = kzalloc(sizeof(struct brcmf_usbreq) * qsize, GFP_ATOMIC);
452 if (reqs == NULL) {
453 brcmf_dbg(ERROR, "fail to allocate memory!\n");
454 return NULL;
455 }
456 req = reqs;
457
458 for (i = 0; i < qsize; i++) {
459 req->urb = usb_alloc_urb(0, GFP_ATOMIC);
460 if (!req->urb)
461 goto fail;
462
463 INIT_LIST_HEAD(&req->list);
464 list_add_tail(&req->list, q);
465 req++;
466 }
467 return reqs;
468fail:
469 brcmf_dbg(ERROR, "fail!\n");
470 while (!list_empty(q)) {
471 req = list_entry(q->next, struct brcmf_usbreq, list);
472 if (req && req->urb)
473 usb_free_urb(req->urb);
474 list_del(q->next);
475 }
476 return NULL;
477
478}
479
480static void brcmf_usb_free_q(struct list_head *q, bool pending)
481{
482 struct brcmf_usbreq *req, *next;
483 int i = 0;
484 list_for_each_entry_safe(req, next, q, list) {
485 if (!req || !req->urb) {
486 brcmf_dbg(ERROR, "bad req\n");
487 break;
488 }
489 i++;
490 if (pending) {
491 usb_kill_urb(req->urb);
492 } else {
493 usb_free_urb(req->urb);
494 list_del_init(&req->list);
495 }
496 }
497}
498
499static void brcmf_usb_del_fromq(struct brcmf_usbdev_info *devinfo,
500 struct brcmf_usbreq *req)
501{
502 unsigned long flags;
503
504 spin_lock_irqsave(&devinfo->qlock, flags);
505 list_del_init(&req->list);
506 spin_unlock_irqrestore(&devinfo->qlock, flags);
507}
508
509
510static void brcmf_usb_tx_complete(struct urb *urb)
511{
512 struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
513 struct brcmf_usbdev_info *devinfo = req->devinfo;
514
515 brcmf_usb_del_fromq(devinfo, req);
516 if (urb->status == 0)
517 devinfo->bus_pub.stats.tx_packets++;
518 else
519 devinfo->bus_pub.stats.tx_errors++;
520
521 dev_kfree_skb(req->skb);
522 req->skb = NULL;
523 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
524
525}
526
527static void brcmf_usb_rx_complete(struct urb *urb)
528{
529 struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
530 struct brcmf_usbdev_info *devinfo = req->devinfo;
531 struct sk_buff *skb;
532 int ifidx = 0;
533
534 brcmf_usb_del_fromq(devinfo, req);
535 skb = req->skb;
536 req->skb = NULL;
537
538 if (urb->status == 0) {
539 devinfo->bus_pub.stats.rx_packets++;
540 } else {
541 devinfo->bus_pub.stats.rx_errors++;
542 dev_kfree_skb(skb);
543 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
544 return;
545 }
546
547 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
548 skb_put(skb, urb->actual_length);
549 if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
550 brcmf_dbg(ERROR, "rx protocol error\n");
551 brcmu_pkt_buf_free_skb(skb);
552 devinfo->bus_pub.bus->dstats.rx_errors++;
553 } else {
554 brcmf_rx_packet(devinfo->dev, ifidx, skb);
555 brcmf_usb_rx_refill(devinfo, req);
556 }
557 } else {
558 dev_kfree_skb(skb);
559 }
560 return;
561
562}
563
564static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
565 struct brcmf_usbreq *req)
566{
567 struct sk_buff *skb;
568 int ret;
569
570 if (!req || !devinfo)
571 return;
572
573 skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
574 if (!skb) {
575 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
576 return;
577 }
578 req->skb = skb;
579
580 usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
581 skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
582 req);
583 req->urb->transfer_flags |= URB_ZERO_PACKET;
584 req->devinfo = devinfo;
585
586 ret = usb_submit_urb(req->urb, GFP_ATOMIC);
587 if (ret == 0) {
588 brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
589 } else {
590 dev_kfree_skb(req->skb);
591 req->skb = NULL;
592 brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
593 }
594 return;
595}
596
597static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
598{
599 struct brcmf_usbreq *req;
600
601 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
602 brcmf_dbg(ERROR, "bus is not up\n");
603 return;
604 }
605 while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq)) != NULL)
606 brcmf_usb_rx_refill(devinfo, req);
607}
608
609static void
610brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
611{
612 struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
613 int old_state;
614
615
616 if (devinfo->bus_pub.state == state)
617 return;
618
619 old_state = devinfo->bus_pub.state;
620 brcmf_dbg(TRACE, "dbus state change from %d to to %d\n",
621 old_state, state);
622
623 /* Don't update state if it's PnP firmware re-download */
624 if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */
625 devinfo->bus_pub.state = state;
626
627 if ((old_state == BCMFMAC_USB_STATE_SLEEP)
628 && (state == BCMFMAC_USB_STATE_UP)) {
629 brcmf_usb_rx_fill_all(devinfo);
630 }
631
632 /* update state of upper layer */
633 if (state == BCMFMAC_USB_STATE_DOWN) {
634 brcmf_dbg(INFO, "DBUS is down\n");
635 bcmf_bus->state = BRCMF_BUS_DOWN;
636 } else {
637 brcmf_dbg(INFO, "DBUS current state=%d\n", state);
638 }
639}
640
641static void
642brcmf_usb_intr_complete(struct urb *urb)
643{
644 struct brcmf_usbdev_info *devinfo =
645 (struct brcmf_usbdev_info *)urb->context;
646 bool killed;
647
648 if (devinfo == NULL)
649 return;
650
651 if (unlikely(urb->status)) {
652 if (devinfo->suspend_state ==
653 USBOS_SUSPEND_STATE_SUSPEND_PENDING)
654 killed = true;
655
656 if ((urb->status == -ENOENT && (!killed))
657 || urb->status == -ESHUTDOWN ||
658 urb->status == -ENODEV) {
659 brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
660 }
661 }
662
663 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) {
664 brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n");
665 return;
666 }
667
668 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
669 usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
670}
671
672static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
673{
674 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
675 struct brcmf_usbreq *req;
676 int ret;
677
678 if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
679 /* TODO: handle suspend/resume */
680 return -EIO;
681 }
682
683 req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);
684 if (!req) {
685 brcmf_dbg(ERROR, "no req to send\n");
686 return -ENOMEM;
687 }
688 if (!req->urb) {
689 brcmf_dbg(ERROR, "no urb for req %p\n", req);
690 return -ENOBUFS;
691 }
692
693 req->skb = skb;
694 req->devinfo = devinfo;
695 usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
696 skb->data, skb->len, brcmf_usb_tx_complete, req);
697 req->urb->transfer_flags |= URB_ZERO_PACKET;
698 ret = usb_submit_urb(req->urb, GFP_ATOMIC);
699 if (!ret) {
700 brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
701 } else {
702 req->skb = NULL;
703 brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
704 }
705
706 return ret;
707}
708
709
710static int brcmf_usb_up(struct device *dev)
711{
712 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
713 u16 ifnum;
714
715 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
716 return 0;
717
718 if (devinfo == NULL)
719 return -EINVAL;
720
721 /* If the USB/HSIC bus in sleep state, wake it up */
722 if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) {
723 if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
724 brcmf_dbg(ERROR, "Could not Resume the bus!\n");
725 return -EIO;
726 }
727 }
728 devinfo->activity = true;
729
730 /* Success, indicate devinfo is fully up */
731 brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP);
732
733 if (devinfo->intr_urb) {
734 int ret;
735
736 usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
737 devinfo->intr_pipe,
738 &devinfo->intr,
739 devinfo->intr_size,
740 (usb_complete_t)brcmf_usb_intr_complete,
741 devinfo,
742 devinfo->interval);
743
744 ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
745 if (ret) {
746 brcmf_dbg(ERROR, "USB_SUBMIT_URB failed with status %d\n",
747 ret);
748 return -EINVAL;
749 }
750 }
751
752 if (devinfo->ctl_urb) {
753 devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
754 devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
755
756 ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber;
757
758 /* CTL Write */
759 devinfo->ctl_write.bRequestType =
760 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
761 devinfo->ctl_write.bRequest = 0;
762 devinfo->ctl_write.wValue = cpu_to_le16(0);
763 devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum);
764
765 /* CTL Read */
766 devinfo->ctl_read.bRequestType =
767 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
768 devinfo->ctl_read.bRequest = 1;
769 devinfo->ctl_read.wValue = cpu_to_le16(0);
770 devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum);
771 }
772 brcmf_usb_rx_fill_all(devinfo);
773 return 0;
774}
775
776static void brcmf_usb_down(struct device *dev)
777{
778 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
779
780 if (devinfo == NULL)
781 return;
782
783 brcmf_dbg(TRACE, "enter\n");
784 if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN)
785 return;
786
787 brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
788 if (devinfo->intr_urb)
789 usb_kill_urb(devinfo->intr_urb);
790
791 if (devinfo->ctl_urb)
792 usb_kill_urb(devinfo->ctl_urb);
793
794 if (devinfo->bulk_urb)
795 usb_kill_urb(devinfo->bulk_urb);
796 brcmf_usb_free_q(&devinfo->tx_postq, true);
797
798 brcmf_usb_free_q(&devinfo->rx_postq, true);
799}
800
801static int
802brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time)
803{
804 int ret;
805 int err = 0;
806 int ms = time;
807
808 ret = wait_event_interruptible_timeout(devinfo->wait,
809 devinfo->waitdone == true, (ms * HZ / 1000));
810
811 if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) {
812 brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n",
813 ret, devinfo->sync_urb_status);
814 err = -EINVAL;
815 }
816 devinfo->waitdone = false;
817 return err;
818}
819
820static void
821brcmf_usb_sync_complete(struct urb *urb)
822{
823 struct brcmf_usbdev_info *devinfo =
824 (struct brcmf_usbdev_info *)urb->context;
825
826 devinfo->waitdone = true;
827 wake_up_interruptible(&devinfo->wait);
828 devinfo->sync_urb_status = urb->status;
829}
830
831static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
832 void *buffer, int buflen)
833{
834 int ret = 0;
835 char *tmpbuf;
836 u16 size;
837
838 if ((!devinfo) || (devinfo->ctl_urb == NULL))
839 return false;
840
841 tmpbuf = kmalloc(buflen, GFP_ATOMIC);
842 if (!tmpbuf)
843 return false;
844
845 size = buflen;
846 devinfo->ctl_urb->transfer_buffer_length = size;
847
848 devinfo->ctl_read.wLength = cpu_to_le16p(&size);
849 devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR |
850 USB_RECIP_INTERFACE;
851 devinfo->ctl_read.bRequest = cmd;
852
853 usb_fill_control_urb(devinfo->ctl_urb,
854 devinfo->usbdev,
855 usb_rcvctrlpipe(devinfo->usbdev, 0),
856 (unsigned char *) &devinfo->ctl_read,
857 (void *) tmpbuf, size,
858 (usb_complete_t)brcmf_usb_sync_complete, devinfo);
859
860 ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
861 if (ret < 0) {
862 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
863 kfree(tmpbuf);
864 return false;
865 }
866
867 ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
868 memcpy(buffer, tmpbuf, buflen);
869 kfree(tmpbuf);
870
871 return (ret == 0);
872}
873
874static bool
875brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
876{
877 struct bootrom_id_le id;
878 u32 chipid, chiprev;
879
880 brcmf_dbg(TRACE, "enter\n");
881
882 if (devinfo == NULL)
883 return false;
884
885 /* Check if firmware downloaded already by querying runtime ID */
886 id.chip = cpu_to_le32(0xDEAD);
887 brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
888 sizeof(struct bootrom_id_le));
889
890 chipid = le32_to_cpu(id.chip);
891 chiprev = le32_to_cpu(id.chiprev);
892
893 if ((chipid & 0x4300) == 0x4300)
894 brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev);
895 else
896 brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev);
897 if (chipid == BRCMF_POSTBOOT_ID) {
898 brcmf_dbg(INFO, "firmware already downloaded\n");
899 brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
900 sizeof(struct bootrom_id_le));
901 return false;
902 } else {
903 devinfo->bus_pub.attrib.devid = chipid;
904 devinfo->bus_pub.attrib.chiprev = chiprev;
905 }
906 return true;
907}
908
909static int
910brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
911{
912 struct bootrom_id_le id;
913 u16 wait = 0, wait_time;
914
915 brcmf_dbg(TRACE, "enter\n");
916
917 if (devinfo == NULL)
918 return -EINVAL;
919
920 /* Give dongle chance to boot */
921 wait_time = BRCMF_USB_DLIMAGE_SPINWAIT;
922 while (wait < BRCMF_USB_DLIMAGE_LIMIT) {
923 mdelay(wait_time);
924 wait += wait_time;
925 id.chip = cpu_to_le32(0xDEAD); /* Get the ID */
926 brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
927 sizeof(struct bootrom_id_le));
928 if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
929 break;
930 }
931
932 if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) {
933 brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n",
934 wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
935
936 brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
937 sizeof(struct bootrom_id_le));
938
939 /* XXX this wait may not be necessary */
940 mdelay(BRCMF_USB_RESETCFG_SPINWAIT);
941 return 0;
942 } else {
943 brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n",
944 wait);
945 return -EINVAL;
946 }
947}
948
949
950static int
951brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len)
952{
953 int ret;
954
955 if ((devinfo == NULL) || (devinfo->bulk_urb == NULL))
956 return -EINVAL;
957
958 /* Prepare the URB */
959 usb_fill_bulk_urb(devinfo->bulk_urb, devinfo->usbdev,
960 devinfo->tx_pipe, buffer, len,
961 (usb_complete_t)brcmf_usb_sync_complete, devinfo);
962
963 devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
964
965 ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
966 if (ret) {
967 brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
968 return ret;
969 }
970 ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
971 return ret;
972}
973
974static int
975brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
976{
977 unsigned int sendlen, sent, dllen;
978 char *bulkchunk = NULL, *dlpos;
979 struct rdl_state_le state;
980 u32 rdlstate, rdlbytes;
981 int err = 0;
982 brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen);
983
984 bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
985 if (bulkchunk == NULL) {
986 err = -ENOMEM;
987 goto fail;
988 }
989
990 /* 1) Prepare USB boot loader for runtime image */
991 brcmf_usb_dl_cmd(devinfo, DL_START, &state,
992 sizeof(struct rdl_state_le));
993
994 rdlstate = le32_to_cpu(state.state);
995 rdlbytes = le32_to_cpu(state.bytes);
996
997 /* 2) Check we are in the Waiting state */
998 if (rdlstate != DL_WAITING) {
999 brcmf_dbg(ERROR, "Failed to DL_START\n");
1000 err = -EINVAL;
1001 goto fail;
1002 }
1003 sent = 0;
1004 dlpos = fw;
1005 dllen = fwlen;
1006
1007 /* Get chip id and rev */
1008 while (rdlbytes != dllen) {
1009 /* Wait until the usb device reports it received all
1010 * the bytes we sent */
1011 if ((rdlbytes == sent) && (rdlbytes != dllen)) {
1012 if ((dllen-sent) < RDL_CHUNK)
1013 sendlen = dllen-sent;
1014 else
1015 sendlen = RDL_CHUNK;
1016
1017 /* simply avoid having to send a ZLP by ensuring we
1018 * never have an even
1019 * multiple of 64
1020 */
1021 if (!(sendlen % 64))
1022 sendlen -= 4;
1023
1024 /* send data */
1025 memcpy(bulkchunk, dlpos, sendlen);
1026 if (brcmf_usb_dl_send_bulk(devinfo, bulkchunk,
1027 sendlen)) {
1028 brcmf_dbg(ERROR, "send_bulk failed\n");
1029 err = -EINVAL;
1030 goto fail;
1031 }
1032
1033 dlpos += sendlen;
1034 sent += sendlen;
1035 }
1036 if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
1037 sizeof(struct rdl_state_le))) {
1038 brcmf_dbg(ERROR, "DL_GETSTATE Failed xxxx\n");
1039 err = -EINVAL;
1040 goto fail;
1041 }
1042
1043 rdlstate = le32_to_cpu(state.state);
1044 rdlbytes = le32_to_cpu(state.bytes);
1045
1046 /* restart if an error is reported */
1047 if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) {
1048 brcmf_dbg(ERROR, "Bad Hdr or Bad CRC state %d\n",
1049 rdlstate);
1050 err = -EINVAL;
1051 goto fail;
1052 }
1053 }
1054
1055fail:
1056 kfree(bulkchunk);
1057 brcmf_dbg(TRACE, "err=%d\n", err);
1058 return err;
1059}
1060
1061static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
1062{
1063 int err;
1064
1065 brcmf_dbg(TRACE, "enter\n");
1066
1067 if (devinfo == NULL)
1068 return -EINVAL;
1069
1070 if (devinfo->bus_pub.attrib.devid == 0xDEAD)
1071 return -EINVAL;
1072
1073 err = brcmf_usb_dl_writeimage(devinfo, fw, len);
1074 if (err == 0)
1075 devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE;
1076 else
1077 devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING;
1078 brcmf_dbg(TRACE, "exit: err=%d\n", err);
1079
1080 return err;
1081}
1082
1083static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
1084{
1085 struct rdl_state_le state;
1086
1087 brcmf_dbg(TRACE, "enter\n");
1088 if (!devinfo)
1089 return -EINVAL;
1090
1091 if (devinfo->bus_pub.attrib.devid == 0xDEAD)
1092 return -EINVAL;
1093
1094 /* Check we are runnable */
1095 brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
1096 sizeof(struct rdl_state_le));
1097
1098 /* Start the image */
1099 if (state.state == cpu_to_le32(DL_RUNNABLE)) {
1100 if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state,
1101 sizeof(struct rdl_state_le)))
1102 return -ENODEV;
1103 if (brcmf_usb_resetcfg(devinfo))
1104 return -ENODEV;
1105 /* The Dongle may go for re-enumeration. */
1106 } else {
1107 brcmf_dbg(ERROR, "Dongle not runnable\n");
1108 return -EINVAL;
1109 }
1110 brcmf_dbg(TRACE, "exit\n");
1111 return 0;
1112}
1113
1114static bool brcmf_usb_chip_support(int chipid, int chiprev)
1115{
1116 switch(chipid) {
1117 case 43235:
1118 case 43236:
1119 case 43238:
1120 return (chiprev == 3);
1121 default:
1122 break;
1123 }
1124 return false;
1125}
1126
1127static int
1128brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
1129{
1130 struct brcmf_usb_attrib *attr;
1131 int err;
1132
1133 brcmf_dbg(TRACE, "enter\n");
1134 if (devinfo == NULL)
1135 return -ENODEV;
1136
1137 attr = &devinfo->bus_pub.attrib;
1138
1139 if (!brcmf_usb_chip_support(attr->devid, attr->chiprev)) {
1140 brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
1141 attr->devid, attr->chiprev);
1142 return -EINVAL;
1143 }
1144
1145 if (!devinfo->image) {
1146 brcmf_dbg(ERROR, "No firmware!\n");
1147 return -ENOENT;
1148 }
1149
1150 err = brcmf_usb_dlstart(devinfo,
1151 devinfo->image, devinfo->image_len);
1152 if (err == 0)
1153 err = brcmf_usb_dlrun(devinfo);
1154 return err;
1155}
1156
1157
1158static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub)
1159{
1160 struct brcmf_usbdev_info *devinfo =
1161 (struct brcmf_usbdev_info *)bus_pub;
1162
1163 brcmf_dbg(TRACE, "devinfo %p\n", devinfo);
1164
1165 /* store the image globally */
1166 g_image.data = devinfo->image;
1167 g_image.len = devinfo->image_len;
1168
1169 /* free the URBS */
1170 brcmf_usb_free_q(&devinfo->rx_freeq, false);
1171 brcmf_usb_free_q(&devinfo->tx_freeq, false);
1172
1173 usb_free_urb(devinfo->intr_urb);
1174 usb_free_urb(devinfo->ctl_urb);
1175 usb_free_urb(devinfo->bulk_urb);
1176
1177 kfree(devinfo->tx_reqs);
1178 kfree(devinfo->rx_reqs);
1179 kfree(devinfo);
1180}
1181
1182#define TRX_MAGIC 0x30524448 /* "HDR0" */
1183#define TRX_VERSION 1 /* Version 1 */
1184#define TRX_MAX_LEN 0x3B0000 /* Max length */
1185#define TRX_NO_HEADER 1 /* Do not write TRX header */
1186#define TRX_MAX_OFFSET 3 /* Max number of individual files */
1187#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */
1188
1189struct trx_header_le {
1190 __le32 magic; /* "HDR0" */
1191 __le32 len; /* Length of file including header */
1192 __le32 crc32; /* CRC from flag_version to end of file */
1193 __le32 flag_version; /* 0:15 flags, 16:31 version */
1194 __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of
1195 * header */
1196};
1197
1198static int check_file(const u8 *headers)
1199{
1200 struct trx_header_le *trx;
1201 int actual_len = -1;
1202
1203 /* Extract trx header */
1204 trx = (struct trx_header_le *) headers;
1205 if (trx->magic != cpu_to_le32(TRX_MAGIC))
1206 return -1;
1207
1208 headers += sizeof(struct trx_header_le);
1209
1210 if (le32_to_cpu(trx->flag_version) & TRX_UNCOMP_IMAGE) {
1211 actual_len = le32_to_cpu(trx->offsets[TRX_OFFSETS_DLFWLEN_IDX]);
1212 return actual_len + sizeof(struct trx_header_le);
1213 }
1214 return -1;
1215}
1216
1217static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
1218{
1219 s8 *fwname;
1220 const struct firmware *fw;
1221 int err;
1222
1223 devinfo->image = g_image.data;
1224 devinfo->image_len = g_image.len;
1225
1226 /*
1227 * if we have an image we can leave here.
1228 */
1229 if (devinfo->image)
1230 return 0;
1231
1232 fwname = BRCMF_USB_FW_NAME;
1233
1234 err = request_firmware(&fw, fwname, devinfo->dev);
1235 if (!fw) {
1236 brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname);
1237 return err;
1238 }
1239 if (check_file(fw->data) < 0) {
1240 brcmf_dbg(ERROR, "invalid firmware %s\n", fwname);
1241 return -EINVAL;
1242 }
1243
1244 devinfo->image = kmalloc(fw->size, GFP_ATOMIC); /* plus nvram */
1245 if (!devinfo->image)
1246 return -ENOMEM;
1247
1248 memcpy(devinfo->image, fw->data, fw->size);
1249 devinfo->image_len = fw->size;
1250
1251 release_firmware(fw);
1252 return 0;
1253}
1254
1255
1256static
1257struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
1258{
1259 struct brcmf_usbdev_info *devinfo;
1260
1261 devinfo = kzalloc(sizeof(struct brcmf_usbdev_info), GFP_ATOMIC);
1262 if (devinfo == NULL)
1263 return NULL;
1264
1265 devinfo->bus_pub.nrxq = nrxq;
1266 devinfo->rx_low_watermark = nrxq / 2;
1267 devinfo->bus_pub.devinfo = devinfo;
1268 devinfo->bus_pub.ntxq = ntxq;
1269
1270 /* flow control when too many tx urbs posted */
1271 devinfo->tx_low_watermark = ntxq / 4;
1272 devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3;
1273 devinfo->dev = dev;
1274 devinfo->usbdev = usbdev_probe_info.usb;
1275 devinfo->tx_pipe = usbdev_probe_info.tx_pipe;
1276 devinfo->rx_pipe = usbdev_probe_info.rx_pipe;
1277 devinfo->rx_pipe2 = usbdev_probe_info.rx_pipe2;
1278 devinfo->intr_pipe = usbdev_probe_info.intr_pipe;
1279
1280 devinfo->interval = usbdev_probe_info.interval;
1281 devinfo->intr_size = usbdev_probe_info.intr_size;
1282
1283 memcpy(&devinfo->probe_info, &usbdev_probe_info,
1284 sizeof(struct brcmf_usb_probe_info));
1285 devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE;
1286
1287 /* Initialize other structure content */
1288 init_waitqueue_head(&devinfo->ioctl_resp_wait);
1289
1290 /* Initialize the spinlocks */
1291 spin_lock_init(&devinfo->qlock);
1292
1293 INIT_LIST_HEAD(&devinfo->rx_freeq);
1294 INIT_LIST_HEAD(&devinfo->rx_postq);
1295
1296 INIT_LIST_HEAD(&devinfo->tx_freeq);
1297 INIT_LIST_HEAD(&devinfo->tx_postq);
1298
1299 devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq);
1300 if (!devinfo->rx_reqs)
1301 goto error;
1302
1303 devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq);
1304 if (!devinfo->tx_reqs)
1305 goto error;
1306
1307 devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
1308 if (!devinfo->intr_urb) {
1309 brcmf_dbg(ERROR, "usb_alloc_urb (intr) failed\n");
1310 goto error;
1311 }
1312 devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
1313 if (!devinfo->ctl_urb) {
1314 brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n");
1315 goto error;
1316 }
1317 devinfo->rxctl_deferrespok = 0;
1318
1319 devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC);
1320 if (!devinfo->bulk_urb) {
1321 brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n");
1322 goto error;
1323 }
1324
1325 init_waitqueue_head(&devinfo->wait);
1326 if (!brcmf_usb_dlneeded(devinfo))
1327 return &devinfo->bus_pub;
1328
1329 brcmf_dbg(TRACE, "start fw downloading\n");
1330 if (brcmf_usb_get_fw(devinfo))
1331 goto error;
1332
1333 if (brcmf_usb_fw_download(devinfo))
1334 goto error;
1335
1336 return &devinfo->bus_pub;
1337
1338error:
1339 brcmf_dbg(ERROR, "failed!\n");
1340 brcmf_usb_detach(&devinfo->bus_pub);
1341 return NULL;
1342}
1343
1344static int brcmf_usb_probe_cb(struct device *dev, const char *desc,
1345 u32 bustype, u32 hdrlen)
1346{
1347 struct brcmf_bus *bus = NULL;
1348 struct brcmf_usbdev *bus_pub = NULL;
1349 int ret;
1350
1351
1352 bus_pub = brcmf_usb_attach(BRCMF_USB_NRXQ, BRCMF_USB_NTXQ, dev);
1353 if (!bus_pub) {
1354 ret = -ENODEV;
1355 goto fail;
1356 }
1357
1358 bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
1359 if (!bus) {
1360 ret = -ENOMEM;
1361 goto fail;
1362 }
1363
1364 bus_pub->bus = bus;
1365 bus->brcmf_bus_txdata = brcmf_usb_tx;
1366 bus->brcmf_bus_init = brcmf_usb_up;
1367 bus->brcmf_bus_stop = brcmf_usb_down;
1368 bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt;
1369 bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt;
1370 bus->type = bustype;
1371 bus->bus_priv.usb = bus_pub;
1372 dev_set_drvdata(dev, bus);
1373
1374 /* Attach to the common driver interface */
1375 ret = brcmf_attach(hdrlen, dev);
1376 if (ret) {
1377 brcmf_dbg(ERROR, "dhd_attach failed\n");
1378 goto fail;
1379 }
1380
1381 ret = brcmf_bus_start(dev);
1382 if (ret == -ENOLINK) {
1383 brcmf_dbg(ERROR, "dongle is not responding\n");
1384 brcmf_detach(dev);
1385 goto fail;
1386 }
1387
1388 /* add interface and open for business */
1389 ret = brcmf_add_if(dev, 0, "wlan%d", NULL);
1390 if (ret) {
1391 brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
1392 brcmf_detach(dev);
1393 goto fail;
1394 }
1395
1396 return 0;
1397fail:
1398 /* Release resources in reverse order */
1399 if (bus_pub)
1400 brcmf_usb_detach(bus_pub);
1401 kfree(bus);
1402 return ret;
1403}
1404
1405static void
1406brcmf_usb_disconnect_cb(struct brcmf_usbdev *bus_pub)
1407{
1408 if (!bus_pub)
1409 return;
1410 brcmf_dbg(TRACE, "enter: bus_pub %p\n", bus_pub);
1411
1412 brcmf_detach(bus_pub->devinfo->dev);
1413 kfree(bus_pub->bus);
1414 brcmf_usb_detach(bus_pub);
1415
1416}
1417
1418static int
1419brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
1420{
1421 int ep;
1422 struct usb_endpoint_descriptor *endpoint;
1423 int ret = 0;
1424 struct usb_device *usb = interface_to_usbdev(intf);
1425 int num_of_eps;
1426 u8 endpoint_num;
1427
1428 brcmf_dbg(TRACE, "enter\n");
1429
1430 usbdev_probe_info.usb = usb;
1431 usbdev_probe_info.intf = intf;
1432
1433 if (id != NULL) {
1434 usbdev_probe_info.vid = id->idVendor;
1435 usbdev_probe_info.pid = id->idProduct;
1436 }
1437
1438 usb_set_intfdata(intf, &usbdev_probe_info);
1439
1440 /* Check that the device supports only one configuration */
1441 if (usb->descriptor.bNumConfigurations != 1) {
1442 ret = -1;
1443 goto fail;
1444 }
1445
1446 if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
1447 ret = -1;
1448 goto fail;
1449 }
1450
1451 /*
1452 * Only the BDC interface configuration is supported:
1453 * Device class: USB_CLASS_VENDOR_SPEC
1454 * if0 class: USB_CLASS_VENDOR_SPEC
1455 * if0/ep0: control
1456 * if0/ep1: bulk in
1457 * if0/ep2: bulk out (ok if swapped with bulk in)
1458 */
1459 if (CONFIGDESC(usb)->bNumInterfaces != 1) {
1460 ret = -1;
1461 goto fail;
1462 }
1463
1464 /* Check interface */
1465 if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
1466 IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 ||
1467 IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) {
1468 brcmf_dbg(ERROR, "invalid control interface: class %d, subclass %d, proto %d\n",
1469 IFDESC(usb, CONTROL_IF).bInterfaceClass,
1470 IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
1471 IFDESC(usb, CONTROL_IF).bInterfaceProtocol);
1472 ret = -1;
1473 goto fail;
1474 }
1475
1476 /* Check control endpoint */
1477 endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
1478 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
1479 != USB_ENDPOINT_XFER_INT) {
1480 brcmf_dbg(ERROR, "invalid control endpoint %d\n",
1481 endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
1482 ret = -1;
1483 goto fail;
1484 }
1485
1486 endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
1487 usbdev_probe_info.intr_pipe = usb_rcvintpipe(usb, endpoint_num);
1488
1489 usbdev_probe_info.rx_pipe = 0;
1490 usbdev_probe_info.rx_pipe2 = 0;
1491 usbdev_probe_info.tx_pipe = 0;
1492 num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
1493
1494 /* Check data endpoints and get pipes */
1495 for (ep = 1; ep <= num_of_eps; ep++) {
1496 endpoint = &IFEPDESC(usb, BULK_IF, ep);
1497 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1498 USB_ENDPOINT_XFER_BULK) {
1499 brcmf_dbg(ERROR, "invalid data endpoint %d\n", ep);
1500 ret = -1;
1501 goto fail;
1502 }
1503
1504 endpoint_num = endpoint->bEndpointAddress &
1505 USB_ENDPOINT_NUMBER_MASK;
1506 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
1507 == USB_DIR_IN) {
1508 if (!usbdev_probe_info.rx_pipe) {
1509 usbdev_probe_info.rx_pipe =
1510 usb_rcvbulkpipe(usb, endpoint_num);
1511 } else {
1512 usbdev_probe_info.rx_pipe2 =
1513 usb_rcvbulkpipe(usb, endpoint_num);
1514 }
1515 } else {
1516 usbdev_probe_info.tx_pipe =
1517 usb_sndbulkpipe(usb, endpoint_num);
1518 }
1519 }
1520
1521 /* Allocate interrupt URB and data buffer */
1522 /* RNDIS says 8-byte intr, our old drivers used 4-byte */
1523 if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
1524 usbdev_probe_info.intr_size = 8;
1525 else
1526 usbdev_probe_info.intr_size = 4;
1527
1528 usbdev_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
1529
1530 usbdev_probe_info.device_speed = usb->speed;
1531 if (usb->speed == USB_SPEED_HIGH)
1532 brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
1533 else
1534 brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n");
1535
1536 ret = brcmf_usb_probe_cb(&usb->dev, "", USB_BUS, 0);
1537 if (ret)
1538 goto fail;
1539
1540 /* Success */
1541 return 0;
1542
1543fail:
1544 brcmf_dbg(ERROR, "failed with errno %d\n", ret);
1545 usb_set_intfdata(intf, NULL);
1546 return ret;
1547
1548}
1549
1550static void
1551brcmf_usb_disconnect(struct usb_interface *intf)
1552{
1553 struct usb_device *usb = interface_to_usbdev(intf);
1554
1555 brcmf_dbg(TRACE, "enter\n");
1556 brcmf_usb_disconnect_cb(brcmf_usb_get_buspub(&usb->dev));
1557 usb_set_intfdata(intf, NULL);
1558}
1559
1560/*
1561 * only need to signal the bus being down and update the suspend state.
1562 */
1563static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
1564{
1565 struct usb_device *usb = interface_to_usbdev(intf);
1566 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
1567
1568 brcmf_dbg(TRACE, "enter\n");
1569 devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN;
1570 devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
1571 return 0;
1572}
1573
1574/*
1575 * mark suspend state active and crank up the bus.
1576 */
1577static int brcmf_usb_resume(struct usb_interface *intf)
1578{
1579 struct usb_device *usb = interface_to_usbdev(intf);
1580 struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
1581
1582 brcmf_dbg(TRACE, "enter\n");
1583 devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
1584 brcmf_bus_start(&usb->dev);
1585 return 0;
1586}
1587
1588#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
1589#define BRCMF_USB_DEVICE_ID_43236 0xbd17
1590#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc
1591
1592static struct usb_device_id brcmf_usb_devid_table[] = {
1593 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) },
1594 /* special entry for device with firmware loaded and running */
1595 { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
1596 { }
1597};
1598MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
1599MODULE_FIRMWARE(BRCMF_USB_FW_NAME);
1600
1601/* TODO: suspend and resume entries */
1602static struct usb_driver brcmf_usbdrvr = {
1603 .name = KBUILD_MODNAME,
1604 .probe = brcmf_usb_probe,
1605 .disconnect = brcmf_usb_disconnect,
1606 .id_table = brcmf_usb_devid_table,
1607 .suspend = brcmf_usb_suspend,
1608 .resume = brcmf_usb_resume,
1609 .supports_autosuspend = 1
1610};
1611
1612void brcmf_usb_exit(void)
1613{
1614 usb_deregister(&brcmf_usbdrvr);
1615 kfree(g_image.data);
1616 g_image.data = NULL;
1617 g_image.len = 0;
1618}
1619
1620int brcmf_usb_init(void)
1621{
1622 return usb_register(&brcmf_usbdrvr);
1623}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
new file mode 100644
index 000000000000..b31da7b83ff7
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
@@ -0,0 +1,84 @@
1/*
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#ifndef BRCMFMAC_USB_H
17#define BRCMFMAC_USB_H
18
19enum brcmf_usb_state {
20 BCMFMAC_USB_STATE_DL_PENDING,
21 BCMFMAC_USB_STATE_DL_DONE,
22 BCMFMAC_USB_STATE_UP,
23 BCMFMAC_USB_STATE_DOWN,
24 BCMFMAC_USB_STATE_PNP_FWDL,
25 BCMFMAC_USB_STATE_DISCONNECT,
26 BCMFMAC_USB_STATE_SLEEP
27};
28
29enum brcmf_usb_pnp_state {
30 BCMFMAC_USB_PNP_DISCONNECT,
31 BCMFMAC_USB_PNP_SLEEP,
32 BCMFMAC_USB_PNP_RESUME,
33};
34
35struct brcmf_stats {
36 u32 tx_errors;
37 u32 tx_packets;
38 u32 tx_multicast;
39 u32 tx_ctlpkts;
40 u32 tx_ctlerrs;
41 u32 tx_dropped;
42 u32 tx_flushed;
43 u32 rx_errors;
44 u32 rx_packets;
45 u32 rx_multicast;
46 u32 rx_ctlpkts;
47 u32 rx_ctlerrs;
48 u32 rx_dropped;
49 u32 rx_flushed;
50
51};
52
53struct brcmf_usb_attrib {
54 int bustype;
55 int vid;
56 int pid;
57 int devid;
58 int chiprev; /* chip revsion number */
59 int mtu;
60 int nchan; /* Data Channels */
61 int has_2nd_bulk_in_ep;
62};
63
64struct brcmf_usbdev_info;
65
66struct brcmf_usbdev {
67 struct brcmf_bus *bus;
68 struct brcmf_usbdev_info *devinfo;
69 enum brcmf_usb_state state;
70 struct brcmf_stats stats;
71 int ntxq, nrxq, rxsize;
72 u32 bus_mtu;
73 struct brcmf_usb_attrib attrib;
74};
75
76/* IO Request Block (IRB) */
77struct brcmf_usbreq {
78 struct list_head list;
79 struct brcmf_usbdev_info *devinfo;
80 struct urb *urb;
81 struct sk_buff *skb;
82};
83
84#endif /* BRCMFMAC_USB_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
new file mode 100644
index 000000000000..0a35c51c3da2
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
@@ -0,0 +1,75 @@
1/*
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#ifndef _USB_RDL_H
18#define _USB_RDL_H
19
20/* Control messages: bRequest values */
21#define DL_GETSTATE 0 /* returns the rdl_state_t struct */
22#define DL_CHECK_CRC 1 /* currently unused */
23#define DL_GO 2 /* execute downloaded image */
24#define DL_START 3 /* initialize dl state */
25#define DL_REBOOT 4 /* reboot the device in 2 seconds */
26#define DL_GETVER 5 /* returns the bootrom_id_t struct */
27#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset
28 * event to occur in 2 seconds. It is the
29 * responsibility of the downloaded code to
30 * clear this event
31 */
32#define DL_EXEC 7 /* jump to a supplied address */
33#define DL_RESETCFG 8 /* To support single enum on dongle
34 * - Not used by bootloader
35 */
36#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup
37 * if resp unavailable
38 */
39
40/* states */
41#define DL_WAITING 0 /* waiting to rx first pkt */
42#define DL_READY 1 /* hdr was good, waiting for more of the
43 * compressed image */
44#define DL_BAD_HDR 2 /* hdr was corrupted */
45#define DL_BAD_CRC 3 /* compressed image was corrupted */
46#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */
47#define DL_START_FAIL 5 /* failed to initialize correctly */
48#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM
49 * value */
50#define DL_IMAGE_TOOBIG 7 /* download image too big (exceeds DATA_START
51 * for rdl) */
52
53struct rdl_state_le {
54 __le32 state;
55 __le32 bytes;
56};
57
58struct bootrom_id_le {
59 __le32 chip; /* Chip id */
60 __le32 chiprev; /* Chip rev */
61 __le32 ramsize; /* Size of RAM */
62 __le32 remapbase; /* Current remap base address */
63 __le32 boardtype; /* Type of board */
64 __le32 boardrev; /* Board revision */
65};
66
67#define RDL_CHUNK 1500 /* size of each dl transfer */
68
69#define TRX_OFFSETS_DLFWLEN_IDX 0
70#define TRX_OFFSETS_JUMPTO_IDX 1
71#define TRX_OFFSETS_NVM_LEN_IDX 2
72
73#define TRX_OFFSETS_DLBASE_IDX 0
74
75#endif /* _USB_RDL_H */