3 * USB Linux Implementation
5 * Copyright (C) 1999-2015, Broadcom Corporation
7 * Unless you and Broadcom execute a separate written software license
8 * agreement governing use of this software, this software is licensed to you
9 * under the terms of the GNU General Public License version 2 (the "GPL"),
10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11 * following added to such license:
13 * As a special exception, the copyright holders of this software give you
14 * permission to link this software with independent modules, and to copy and
15 * distribute the resulting executable under terms of your choice, provided that
16 * you also meet, for each linked independent module, the terms and conditions of
17 * the license of that module. An independent module is a module which is not
18 * derived from this software. The special exception does not apply to any
19 * modifications of the software.
21 * Notwithstanding the above, under no circumstances may you combine this
22 * software in any way with any other Broadcom software provided under a license
23 * other than the GPL, without Broadcom's express prior written consent.
25 * $Id: dbus_usb_linux.c 571551 2015-07-15 13:32:46Z $
32 * DBUS_LINUX_RXDPC is created for router platform performance tuning. A separate thread is created
33 * to handle USB RX and avoid the call chain getting too long and enhance cache hit rate.
35 * DBUS_LINUX_RXDPC setting is in wlconfig file.
39 * If DBUS_LINUX_RXDPC is off, spin_lock_bh() for CTFPOOL in
40 * linux_osl.c has to be changed to spin_lock_irqsave() because
41 * PKTGET/PKTFREE are no longer in bottom half.
43 * Right now we have another queue rpcq in wl_linux.c. Maybe we
44 * can eliminate that one to reduce the overhead.
46 * Enabling 2nd EP and DBUS_LINUX_RXDPC causing traffic from
47 * both EP's to be queued in the same rx queue. If we want
48 * RXDPC to work with 2nd EP. The EP for RPC call return
49 * should bypass the dpc and go directly up.
52 /* #define DBUS_LINUX_RXDPC */
54 /* Dbus histogram for ntxq, nrxq, dpc parameter tuning */
55 /* #define DBUS_LINUX_HIST */
58 #include <bcmendian.h>
59 #include <linux/init.h>
60 #include <linux/kernel.h>
61 #include <linux/slab.h>
62 #include <linux/usb.h>
63 #include <linux/skbuff.h>
64 #include <linux/netdevice.h>
65 #include <linux/random.h>
66 #include <linux/spinlock.h>
67 #include <linux/list.h>
68 #include <asm/uaccess.h>
69 #include <asm/unaligned.h>
73 #include <linux/usb.h>
75 #include <linux/firmware.h>
76 #include <linux/kmod.h>
77 #ifdef DBUS_LINUX_RXDPC
78 #include <linux/sched.h>
81 #if defined(BCM_REQUEST_FW)
82 #if !defined(__FreeBSD__)
83 #include <linux/vmalloc.h>
84 #endif /* !defined(__FreeBSD__) */
85 #endif /* defined(BCM_REQUEST_FW) */
87 #if defined(USBOS_THREAD) || defined(USBOS_TX_THREAD)
89 * The usb-thread is designed to provide currency on multiprocessors and SMP linux kernels. On the
90 * dual cores platform, the WLAN driver, without threads, executed only on CPU0. The driver consumed
91 * almost of 100% on CPU0, while CPU1 remained idle. The behavior was observed on Broadcom's STB.
93 * The WLAN driver consumed most of CPU0 and not CPU1 because tasklets/queues, software irq, and
94 * hardware irq are executing from CPU0, only. CPU0 became the system's bottle-neck. TPUT is lower
95 * and system's responsiveness is slower.
97 * To improve system responsiveness and TPUT usb-thread was implemented. The system's threads could
98 * be scheduled to run on any core. One core could be processing data in the usb-layer and the other
99 * core could be processing data in the wl-layer.
101 * For further info see [WlThreadAndUsbThread] Twiki.
104 #include <linux/kthread.h>
105 #include <linux/interrupt.h>
106 #include <linux/irq.h>
107 #include <asm/hardirq.h>
108 #include <linux/list.h>
109 #include <linux_osl.h>
110 #endif /* USBOS_THREAD || USBOS_TX_THREAD */
112 #ifdef DBUS_LINUX_RXDPC
113 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
114 #define RESCHED() _cond_resched()
115 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
116 #define RESCHED() cond_resched()
118 #define RESCHED() __cond_resched()
119 #endif /* LINUX_VERSION_CODE */
120 #endif /* DBUS_LINUX_RXDPC */
122 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
126 #define MOD_PARAM_PATHLEN 2048
127 extern char firmware_path
[MOD_PARAM_PATHLEN
];
128 extern char nvram_path
[MOD_PARAM_PATHLEN
];
130 /* Starting with the 3.10 kernel release, dynamic PM support for USB is present whenever
131 * the kernel was built with CONFIG_PM_RUNTIME enabled. The CONFIG_USB_SUSPEND option has
134 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)) && defined(CONFIG_USB_SUSPEND)) \
135 || ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) && defined(CONFIG_PM_RUNTIME))
136 /* For USB power management support, see Linux kernel: Documentation/usb/power-management.txt */
137 #define USB_SUSPEND_AVAILABLE
140 static inline int usb_submit_urb_linux(struct urb
*urb
)
143 #ifdef BCM_MAX_URB_LEN
144 if (urb
&& (urb
->transfer_buffer_length
> BCM_MAX_URB_LEN
)) {
145 DBUSERR(("URB transfer length=%d exceeded %d ra=%p\n", urb
->transfer_buffer_length
,
146 BCM_MAX_URB_LEN
, __builtin_return_address(0)));
152 return usb_submit_urb(urb
, GFP_ATOMIC
);
154 return usb_submit_urb(urb
);
159 #define USB_SUBMIT_URB(urb) usb_submit_urb_linux(urb)
163 #define USB_ALLOC_URB() usb_alloc_urb(0, GFP_ATOMIC)
164 #define USB_UNLINK_URB(urb) (usb_kill_urb(urb))
165 #define USB_FREE_URB(urb) (usb_free_urb(urb))
166 #define USB_REGISTER() usb_register(&dbus_usbdev)
167 #define USB_DEREGISTER() usb_deregister(&dbus_usbdev)
169 #ifdef USB_SUSPEND_AVAILABLE
171 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
172 #define USB_AUTOPM_SET_INTERFACE(intf) usb_autopm_set_interface(intf)
174 #define USB_ENABLE_AUTOSUSPEND(udev) usb_enable_autosuspend(udev)
175 #define USB_DISABLE_AUTOSUSPEND(udev) usb_disable_autosuspend(udev)
176 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */
178 #define USB_AUTOPM_GET_INTERFACE(intf) usb_autopm_get_interface(intf)
179 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf) usb_autopm_get_interface_async(intf)
180 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf) usb_autopm_put_interface_async(intf)
181 #define USB_MARK_LAST_BUSY(dev) usb_mark_last_busy(dev)
183 #else /* USB_SUSPEND_AVAILABLE */
185 #define USB_AUTOPM_GET_INTERFACE(intf) do {} while (0)
186 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf) do {} while (0)
187 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf) do {} while (0)
188 #define USB_MARK_LAST_BUSY(dev) do {} while (0)
189 #endif /* USB_SUSPEND_AVAILABLE */
191 #define USB_CONTROL_MSG(dev, pipe, request, requesttype, value, index, data, size, timeout) \
192 usb_control_msg((dev), (pipe), (request), (requesttype), (value), (index), \
193 (data), (size), (timeout))
194 #define USB_BUFFER_ALLOC(dev, size, mem, dma) usb_buffer_alloc(dev, size, mem, dma)
195 #define USB_BUFFER_FREE(dev, size, data, dma) usb_buffer_free(dev, size, data, dma)
198 #define URB_QUEUE_BULK URB_ZERO_PACKET
200 #define URB_QUEUE_BULK 0
201 #endif /* WL_URB_ZPKT */
203 #define CALLBACK_ARGS struct urb *urb, struct pt_regs *regs
204 #define CALLBACK_ARGS_DATA urb, regs
205 #define CONFIGDESC(usb) (&((usb)->actconfig)->desc)
206 #define IFPTR(usb, idx) ((usb)->actconfig->interface[idx])
207 #define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0])
208 #define IFDESC(usb, idx) IFALTS((usb), (idx)).desc
209 #define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[ep]).desc
210 #ifdef DBUS_LINUX_RXDPC
211 #define DAEMONIZE(a) daemonize(a); allow_signal(SIGKILL); allow_signal(SIGTERM);
212 #define SET_NICE(n) set_user_nice(current, n)
217 #define USB_ALLOC_URB() usb_alloc_urb(0)
218 #define USB_UNLINK_URB(urb) usb_unlink_urb(urb)
219 #define USB_FREE_URB(urb) (usb_free_urb(urb))
220 #define USB_REGISTER() usb_register(&dbus_usbdev)
221 #define USB_DEREGISTER() usb_deregister(&dbus_usbdev)
222 #define USB_AUTOPM_GET_INTERFACE(intf) do {} while (0)
223 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf) do {} while (0)
224 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf) do {} while (0)
225 #define USB_MARK_LAST_BUSY(dev) do {} while (0)
227 #define USB_CONTROL_MSG(dev, pipe, request, requesttype, value, index, data, size, timeout) \
228 usb_control_msg((dev), (pipe), (request), (requesttype), (value), (index), \
229 (data), (size), (timeout))
230 #define USB_BUFFER_ALLOC(dev, size, mem, dma) kmalloc(size, mem)
231 #define USB_BUFFER_FREE(dev, size, data, dma) kfree(data)
234 #define URB_QUEUE_BULK USB_QUEUE_BULK|URB_ZERO_PACKET
236 #define URB_QUEUE_BULK 0
237 #endif /* WL_URB_ZPKT */
239 #define CALLBACK_ARGS struct urb *urb
240 #define CALLBACK_ARGS_DATA urb
241 #define CONFIGDESC(usb) ((usb)->actconfig)
242 #define IFPTR(usb, idx) (&(usb)->actconfig->interface[idx])
243 #define IFALTS(usb, idx) ((usb)->actconfig->interface[idx].altsetting[0])
244 #define IFDESC(usb, idx) IFALTS((usb), (idx))
245 #define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[ep])
247 #ifdef DBUS_LINUX_RXDPC
248 #define DAEMONIZE(a) daemonize();
249 #define SET_NICE(n) do {current->nice = (n);} while (0)
250 #endif /* DBUS_LINUX_RXDPC */
252 #endif /* KERNEL26 */
254 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
255 #define USB_SPEED_SUPER 5
256 #endif /* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) */
261 #ifdef BCMUSBDEV_COMPOSITE
262 #define USB_COMPIF_MAX 4
264 #define USB_CLASS_WIRELESS 0xe0
265 #define USB_CLASS_MISC 0xef
266 #define USB_SUBCLASS_COMMON 0x02
267 #define USB_PROTO_IAD 0x01
268 #define USB_PROTO_VENDOR 0xff
270 #define USB_QUIRK_NO_SET_INTF 0x04 /* device does not support set_interface */
271 #endif /* BCMUSBDEV_COMPOSITE */
273 #define USB_SYNC_WAIT_TIMEOUT 300 /* ms */
275 #define FW_NAME_PREFIX_LEN 8 /* FW_NAME prefix length */
277 /* Private data kept in skb */
278 #define SKB_PRIV(skb, idx) (&((void **)skb->cb)[idx])
279 #define SKB_PRIV_URB(skb) (*(struct urb **)SKB_PRIV(skb, 0))
281 #ifndef DBUS_USB_RXQUEUE_BATCH_ADD
282 /* items to add each time within limit */
283 #define DBUS_USB_RXQUEUE_BATCH_ADD 8
285 #ifndef DBUS_USB_RXQUEUE_LOWER_WATERMARK
286 /* add a new batch req to rx queue when waiting item count reduce to this number */
287 #define DBUS_USB_RXQUEUE_LOWER_WATERMARK 4
289 enum usbos_suspend_state
{
290 USBOS_SUSPEND_STATE_DEVICE_ACTIVE
= 0, /* Device is busy, won't allow suspend */
291 USBOS_SUSPEND_STATE_SUSPEND_PENDING
, /* Device is idle, can be suspended */
292 /* Wating PM to suspend */
293 USBOS_SUSPEND_STATE_SUSPENDED
/* Device suspended */
296 enum usbos_request_state
{
297 USBOS_REQUEST_STATE_UNSCHEDULED
= 0, /* USB TX request not scheduled */
298 USBOS_REQUEST_STATE_SCHEDULED
, /* USB TX request given to TX thread */
299 USBOS_REQUEST_STATE_SUBMITTED
/* USB TX request submitted */
311 dbus_intf_callbacks_t
*cbs
;
314 struct usb_device
*usb
; /* USB device pointer from OS */
315 struct urb
*intr_urb
; /* URB for interrupt endpoint */
316 struct list_head req_rxfreeq
;
317 struct list_head req_txfreeq
;
318 struct list_head req_rxpostedq
; /* Posted down to USB driver for RX */
319 struct list_head req_txpostedq
; /* Posted down to USB driver for TX */
320 spinlock_t rxfree_lock
; /* Lock for rx free list */
321 spinlock_t txfree_lock
; /* Lock for tx free list */
322 spinlock_t rxposted_lock
; /* Lock for rx posted list */
323 spinlock_t txposted_lock
; /* Lock for tx posted list */
324 uint rx_pipe
, tx_pipe
, intr_pipe
, rx_pipe2
; /* Pipe numbers for USB I/O */
327 struct list_head req_rxpendingq
; /* RXDPC: Pending for dpc to send up */
328 spinlock_t rxpending_lock
; /* RXDPC: Lock for rx pending list */
330 struct semaphore dpc_sem
;
331 struct completion dpc_exited
;
333 #if defined(DBUS_LINUX_HIST)
334 int dpc_cnt
, dpc_pktcnt
, dpc_maxpktcnt
;
338 struct urb
*ctl_tx_urb
;
339 int ctl_in_pipe
, ctl_out_pipe
;
340 struct usb_ctrlrequest ctl_write
;
341 struct usb_ctrlrequest ctl_read
;
342 #ifdef USBOS_TX_THREAD
343 enum usbos_request_state ctl_state
;
344 #endif /* USBOS_TX_THREAD */
346 spinlock_t rxlock
; /* Lock for rxq management */
347 spinlock_t txlock
; /* Lock for txq management */
349 int intr_size
; /* Size of interrupt message */
350 int interval
; /* Interrupt polling interval */
351 intr_t intr
; /* Data buffer for interrupt endpoint */
356 atomic_t txallocated
;
357 atomic_t rxallocated
;
358 bool rxctl_deferrespok
; /* Get a response for setup from dongle */
360 wait_queue_head_t wait
;
364 struct urb
*blk_urb
; /* Used for downloading embedded image */
366 #if defined(DBUS_LINUX_HIST)
371 spinlock_t ctrl_lock
;
372 spinlock_t usbos_list_lock
;
373 struct list_head usbos_list
;
374 struct list_head usbos_free_list
;
375 atomic_t usbos_list_cnt
;
376 wait_queue_head_t usbos_queue_head
;
377 struct task_struct
*usbos_kt
;
378 #endif /* USBOS_THREAD */
380 #ifdef USBOS_TX_THREAD
381 spinlock_t usbos_tx_list_lock
;
382 struct list_head usbos_tx_list
;
383 wait_queue_head_t usbos_tx_queue_head
;
384 struct task_struct
*usbos_tx_kt
;
385 #endif /* USBOS_TX_THREAD */
387 struct dma_pool
*qtd_pool
; /* QTD pool for USB optimization only */
388 int tx_ep
, rx_ep
, rx2_ep
; /* EPs for USB optimization */
389 struct usb_device
*usb_device
; /* USB device for optimization */
390 #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX) /** Linux USB AP related */
391 spinlock_t fastpath_lock
;
395 typedef struct urb_req
{
400 usbos_info_t
*usbinfo
;
401 struct list_head urb_list
;
405 typedef struct usbos_list_entry
{
406 struct list_head list
; /* must be first */
410 } usbos_list_entry_t
;
412 static void* dbus_usbos_thread_init(usbos_info_t
*usbos_info
);
413 static void dbus_usbos_thread_deinit(usbos_info_t
*usbos_info
);
414 static void dbus_usbos_dispatch_schedule(CALLBACK_ARGS
);
415 static int dbus_usbos_thread_func(void *data
);
416 #endif /* USBOS_THREAD */
418 #ifdef USBOS_TX_THREAD
419 void* dbus_usbos_tx_thread_init(usbos_info_t
*usbos_info
);
420 void dbus_usbos_tx_thread_deinit(usbos_info_t
*usbos_info
);
421 int dbus_usbos_tx_thread_func(void *data
);
422 #endif /* USBOS_TX_THREAD */
424 /* Shared Function prototypes */
425 bool dbus_usbos_dl_cmd(usbos_info_t
*usbinfo
, uint8 cmd
, void *buffer
, int buflen
);
426 int dbus_usbos_wait(usbos_info_t
*usbinfo
, uint16 ms
);
427 bool dbus_usbos_dl_send_bulk(usbos_info_t
*usbinfo
, void *buffer
, int len
);
428 int dbus_write_membytes(usbos_info_t
*usbinfo
, bool set
, uint32 address
, uint8
*data
, uint size
);
430 /* Local function prototypes */
431 static void dbus_usbos_send_complete(CALLBACK_ARGS
);
432 #ifdef DBUS_LINUX_RXDPC
433 static void dbus_usbos_recv_dpc(usbos_info_t
*usbos_info
);
434 static int dbus_usbos_dpc_thread(void *data
);
435 #endif /* DBUS_LINUX_RXDPC */
436 static void dbus_usbos_recv_complete(CALLBACK_ARGS
);
437 static int dbus_usbos_errhandler(void *bus
, int err
);
438 static int dbus_usbos_state_change(void *bus
, int state
);
439 static void dbusos_stop(usbos_info_t
*usbos_info
);
441 static int dbus_usbos_resume(struct usb_interface
*intf
);
442 static int dbus_usbos_suspend(struct usb_interface
*intf
, pm_message_t message
);
444 static int dbus_usbos_probe(struct usb_interface
*intf
, const struct usb_device_id
*id
);
445 static void dbus_usbos_disconnect(struct usb_interface
*intf
);
446 #if defined(USB_SUSPEND_AVAILABLE)
447 static int dbus_usbos_resume(struct usb_interface
*intf
);
448 static int dbus_usbos_suspend(struct usb_interface
*intf
, pm_message_t message
);
449 /* at the moment, used for full dongle host driver only */
450 static int dbus_usbos_reset_resume(struct usb_interface
*intf
);
451 #endif /* USB_SUSPEND_AVAILABLE */
453 static void *dbus_usbos_probe(struct usb_device
*usb
, unsigned int ifnum
,
454 const struct usb_device_id
*id
);
455 static void dbus_usbos_disconnect(struct usb_device
*usb
, void *ptr
);
456 #endif /* KERNEL26 */
457 #if defined(BCM_REQUEST_FW)
458 static int get_file_buf(char *file_path
, char **filebuf
, int *filelen
);
461 static uint32
time_diff(struct timeval
*now
, struct timeval
*then
);
463 #ifdef USB_TRIGGER_DEBUG
464 static bool dbus_usbos_ctl_send_debugtrig(usbos_info_t
*usbinfo
);
465 #endif /* USB_TRIGGER_DEBUG */
466 static struct usb_device_id devid_table
[] = {
467 { USB_DEVICE(BCM_DNGL_VID
, 0x0000) }, /* Configurable via register() */
468 #if defined(BCM_REQUEST_FW)
469 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_4328
) },
470 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_4322
) },
471 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_4319
) },
472 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_43236
) },
473 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_43143
) },
474 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_43242
) },
475 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_4360
) },
476 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_4350
) },
477 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BL_PID_43569
) },
479 #ifdef EXTENDED_VID_PID
481 #endif /* EXTENDED_VID_PID */
482 { USB_DEVICE(BCM_DNGL_VID
, BCM_DNGL_BDC_PID
) }, /* Default BDC */
486 MODULE_DEVICE_TABLE(usb
, devid_table
);
488 /** functions called by the Linux kernel USB subsystem */
489 static struct usb_driver dbus_usbdev
= {
491 probe
: dbus_usbos_probe
,
492 disconnect
: dbus_usbos_disconnect
,
493 id_table
: devid_table
,
494 suspend
: dbus_usbos_suspend
,
495 resume
: dbus_usbos_resume
,
496 #if defined(USB_SUSPEND_AVAILABLE)
497 suspend
: dbus_usbos_suspend
,
498 resume
: dbus_usbos_resume
,
499 reset_resume
: dbus_usbos_reset_resume
,
500 /* Linux USB core will allow autosuspend for devices bound to this driver */
501 supports_autosuspend
: 1
502 #endif /* USB_SUSPEND_AVAILABLE */
505 /** This stores USB info during Linux probe callback
506 * since attach() is not called yet at this point
510 struct usb_device
*usb
; /* USB device pointer from OS */
511 uint rx_pipe
; /* Pipe numbers for USB I/O */
512 uint tx_pipe
; /* Pipe numbers for USB I/O */
513 uint intr_pipe
; /* Pipe numbers for USB I/O */
514 uint rx_pipe2
; /* Pipe numbers for USB I/O */
515 int intr_size
; /* Size of interrupt message */
516 int interval
; /* Interrupt polling interval */
522 DEVICE_SPEED device_speed
;
523 enum usbos_suspend_state suspend_state
;
524 struct usb_interface
*intf
;
528 * USB Linux dbus_intf_t
530 static void *dbus_usbos_intf_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
);
531 static void dbus_usbos_intf_detach(dbus_pub_t
*pub
, void *info
);
532 static int dbus_usbos_intf_send_irb(void *bus
, dbus_irb_tx_t
*txirb
);
533 static int dbus_usbos_intf_recv_irb(void *bus
, dbus_irb_rx_t
*rxirb
);
534 static int dbus_usbos_intf_recv_irb_from_ep(void *bus
, dbus_irb_rx_t
*rxirb
, uint32 ep_idx
);
535 static int dbus_usbos_intf_cancel_irb(void *bus
, dbus_irb_tx_t
*txirb
);
536 static int dbus_usbos_intf_send_ctl(void *bus
, uint8
*buf
, int len
);
537 static int dbus_usbos_intf_recv_ctl(void *bus
, uint8
*buf
, int len
);
538 static int dbus_usbos_intf_get_attrib(void *bus
, dbus_attrib_t
*attrib
);
539 static int dbus_usbos_intf_up(void *bus
);
540 static int dbus_usbos_intf_down(void *bus
);
541 static int dbus_usbos_intf_stop(void *bus
);
542 static int dbus_usbos_readreg(void *bus
, uint32 regaddr
, int datalen
, uint32
*value
);
543 extern int dbus_usbos_loopback_tx(void *usbos_info_ptr
, int cnt
, int size
);
544 #ifndef LINUX_POSTMOGRIFY_REMOVAL
545 int dbus_usbos_writereg(void *bus
, uint32 regaddr
, int datalen
, uint32 data
);
546 #endif /* LINUX_POSTMOGRIFY_REMOVAL */
547 #if defined(DBUS_LINUX_HIST)
548 static void dbus_usbos_intf_dump(void *bus
, struct bcmstrbuf
*b
);
550 static int dbus_usbos_intf_set_config(void *bus
, dbus_config_t
*config
);
551 static bool dbus_usbos_intf_recv_needed(void *bus
);
552 static void *dbus_usbos_intf_exec_rxlock(void *bus
, exec_cb_t cb
, struct exec_parms
*args
);
553 static void *dbus_usbos_intf_exec_txlock(void *bus
, exec_cb_t cb
, struct exec_parms
*args
);
554 #ifdef BCMUSBDEV_COMPOSITE
555 static int dbus_usbos_intf_wlan(struct usb_device
*usb
);
556 #endif /* BCMUSBDEV_COMPOSITE */
558 /** functions called by dbus_usb.c */
559 static dbus_intf_t dbus_usbos_intf
= {
560 .attach
= dbus_usbos_intf_attach
,
561 .detach
= dbus_usbos_intf_detach
,
562 .up
= dbus_usbos_intf_up
,
563 .down
= dbus_usbos_intf_down
,
564 .send_irb
= dbus_usbos_intf_send_irb
,
565 .recv_irb
= dbus_usbos_intf_recv_irb
,
566 .cancel_irb
= dbus_usbos_intf_cancel_irb
,
567 .send_ctl
= dbus_usbos_intf_send_ctl
,
568 .recv_ctl
= dbus_usbos_intf_recv_ctl
,
570 .get_attrib
= dbus_usbos_intf_get_attrib
,
574 .stop
= dbus_usbos_intf_stop
,
579 #if defined(DBUS_LINUX_HIST)
580 .dump
= dbus_usbos_intf_dump
,
584 .set_config
= dbus_usbos_intf_set_config
,
586 .device_exists
= NULL
,
590 .recv_needed
= dbus_usbos_intf_recv_needed
,
591 .exec_rxlock
= dbus_usbos_intf_exec_rxlock
,
592 .exec_txlock
= dbus_usbos_intf_exec_txlock
,
594 .tx_timer_init
= NULL
,
595 .tx_timer_start
= NULL
,
596 .tx_timer_stop
= NULL
,
601 .sched_probe_cb
= NULL
,
608 .recv_irb_from_ep
= dbus_usbos_intf_recv_irb_from_ep
,
609 .readreg
= dbus_usbos_readreg
612 static probe_info_t g_probe_info
;
613 static probe_cb_t probe_cb
= NULL
;
614 static disconnect_cb_t disconnect_cb
= NULL
;
615 static void *probe_arg
= NULL
;
616 static void *disc_arg
= NULL
;
618 #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX)
619 #define EHCI_PAGE_SIZE 4096
621 /* Copies of structures located elsewhere. */
627 dbus_intf_callbacks_t
*cbs
;
628 dbus_intf_t
*drvintf
;
632 /** General info for all BUS */
633 typedef struct dbus_irbq
{
639 /** This private structure dbus_info_t is also declared in dbus.c.
640 * All the fields must be consistent in both declarations.
642 typedef struct dbus_info
{
643 dbus_pub_t pub
; /* MUST BE FIRST */
646 dbus_callbacks_t
*cbs
;
648 dbus_intf_t
*drvintf
;
652 int rx_low_watermark
;
653 int tx_low_watermark
;
657 bool tx_timer_ticking
;
661 #ifdef EHCI_FASTPATH_RX
662 atomic_t rx_outstanding
;
666 uint8
*image
; /* buffer for combine fw and nvram */
675 static atomic_t s_tx_pending
;
677 static int optimize_init(usbos_info_t
*usbos_info
, struct usb_device
*usb
, int out
,
679 static int optimize_deinit(usbos_info_t
*usbos_info
, struct usb_device
*usb
);
680 #endif /* #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX) */
683 static volatile int loopback_rx_cnt
, loopback_tx_cnt
;
685 bool is_loopback_pkt(void *buf
);
686 int matches_loopback_pkt(void *buf
);
688 * multiple code paths in this file dequeue a URB request, this function makes sure that it happens
689 * in a concurrency save manner. Don't call this from a sleepable process context.
691 static urb_req_t
* BCMFASTPATH
692 dbus_usbos_qdeq(struct list_head
*urbreq_q
, spinlock_t
*lock
)
697 ASSERT(urbreq_q
!= NULL
);
699 spin_lock_irqsave(lock
, flags
);
701 if (list_empty(urbreq_q
)) {
704 ASSERT(urbreq_q
->next
!= NULL
);
705 ASSERT(urbreq_q
->next
!= urbreq_q
);
707 req
= list_entry(urbreq_q
->next
, urb_req_t
, urb_list
);
708 list_del_init(&req
->urb_list
);
711 spin_unlock_irqrestore(lock
, flags
);
716 static void BCMFASTPATH
717 dbus_usbos_qenq(struct list_head
*urbreq_q
, urb_req_t
*req
, spinlock_t
*lock
)
721 spin_lock_irqsave(lock
, flags
);
723 list_add_tail(&req
->urb_list
, urbreq_q
);
725 spin_unlock_irqrestore(lock
, flags
);
730 * multiple code paths in this file remove a URB request from a list, this function makes sure that
731 * it happens in a concurrency save manner. Don't call this from a sleepable process context.
732 * Is quite similar to dbus_usbos_qdeq(), I wonder why this function is needed.
735 dbus_usbos_req_del(urb_req_t
*req
, spinlock_t
*lock
)
739 spin_lock_irqsave(lock
, flags
);
741 list_del_init(&req
->urb_list
);
743 spin_unlock_irqrestore(lock
, flags
);
748 * Driver requires a pool of URBs to operate. This function is called during
749 * initialization (attach phase), allocates a number of URBs, and puts them
750 * on the free (req_rxfreeq and req_txfreeq) queue
753 dbus_usbos_urbreqs_alloc(usbos_info_t
*usbos_info
, uint32 count
, bool is_rx
)
759 for (i
= 0; i
< count
; i
++) {
762 req
= MALLOC(usbos_info
->pub
->osh
, sizeof(urb_req_t
));
764 DBUSERR(("%s: MALLOC req failed\n", __FUNCTION__
));
765 err
= DBUS_ERR_NOMEM
;
768 bzero(req
, sizeof(urb_req_t
));
770 req
->urb
= USB_ALLOC_URB();
771 if (req
->urb
== NULL
) {
772 DBUSERR(("%s: USB_ALLOC_URB req->urb failed\n", __FUNCTION__
));
773 err
= DBUS_ERR_NOMEM
;
777 INIT_LIST_HEAD(&req
->urb_list
);
780 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
781 /* don't allocate now. Do it on demand */
784 /* pre-allocate buffers never to be released */
785 req
->pkt
= MALLOC(usbos_info
->pub
->osh
, usbos_info
->rxbuf_len
);
786 if (req
->pkt
== NULL
) {
787 DBUSERR(("%s: MALLOC req->pkt failed\n", __FUNCTION__
));
788 err
= DBUS_ERR_NOMEM
;
792 req
->buf_len
= usbos_info
->rxbuf_len
;
793 dbus_usbos_qenq(&usbos_info
->req_rxfreeq
, req
, &usbos_info
->rxfree_lock
);
796 dbus_usbos_qenq(&usbos_info
->req_txfreeq
, req
, &usbos_info
->txfree_lock
);
803 if (is_rx
&& req
->pkt
) {
804 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
805 /* req->pkt is NULL in "NOCOPY" mode */
807 MFREE(usbos_info
->pub
->osh
, req
->pkt
, req
->buf_len
);
811 USB_FREE_URB(req
->urb
);
813 MFREE(usbos_info
->pub
->osh
, req
, sizeof(urb_req_t
));
818 atomic_add(allocated
, is_rx
? &usbos_info
->rxallocated
: &usbos_info
->txallocated
);
821 DBUSTRACE(("%s: add %d (total %d) rx buf, each has %d bytes\n", __FUNCTION__
,
822 allocated
, atomic_read(&usbos_info
->rxallocated
), usbos_info
->rxbuf_len
));
824 DBUSTRACE(("%s: add %d (total %d) tx req\n", __FUNCTION__
,
825 allocated
, atomic_read(&usbos_info
->txallocated
)));
831 /** Typically called during detach or when attach failed. Don't call until all URBs unlinked */
833 dbus_usbos_urbreqs_free(usbos_info_t
*usbos_info
, bool is_rx
)
837 struct list_head
*req_q
;
841 req_q
= &usbos_info
->req_rxfreeq
;
842 lock
= &usbos_info
->rxfree_lock
;
844 req_q
= &usbos_info
->req_txfreeq
;
845 lock
= &usbos_info
->txfree_lock
;
847 while ((req
= dbus_usbos_qdeq(req_q
, lock
)) != NULL
) {
851 /* We do MFREE instead of PKTFREE because the pkt has been
852 * converted to native already
854 MFREE(usbos_info
->pub
->osh
, req
->pkt
, req
->buf_len
);
860 /* sending req should not be assigned pkt buffer */
861 ASSERT(req
->pkt
== NULL
);
865 USB_FREE_URB(req
->urb
);
868 MFREE(usbos_info
->pub
->osh
, req
, sizeof(urb_req_t
));
876 * called by Linux kernel on URB completion. Upper DBUS layer (dbus_usb.c) has to be notified of
880 dbus_usbos_send_complete(CALLBACK_ARGS
)
882 urb_req_t
*req
= urb
->context
;
883 dbus_irb_tx_t
*txirb
= req
->arg
;
884 usbos_info_t
*usbos_info
= req
->usbinfo
;
886 int status
= DBUS_OK
;
889 /* Enable USB autosuspend if no packets are being sent */
890 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info
.intf
);
892 spin_lock_irqsave(&usbos_info
->txlock
, flags
);
894 dbus_usbos_req_del(req
, &usbos_info
->txposted_lock
);
895 txposted
= atomic_dec_return(&usbos_info
->txposted
);
896 #if defined(DBUS_LINUX_HIST)
897 if (usbos_info
->txposted_hist
) {
898 usbos_info
->txposted_hist
[txposted
]++;
901 if (unlikely (txposted
< 0)) {
902 DBUSERR(("%s ERROR: txposted is negative (%d)!!\n", __FUNCTION__
, txposted
));
904 spin_unlock_irqrestore(&usbos_info
->txlock
, flags
);
906 if (unlikely (urb
->status
)) {
907 status
= DBUS_ERR_TXFAIL
;
908 DBUSTRACE(("txfail status %d\n", urb
->status
));
911 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
912 /* sending req should not be assigned pkt buffer */
913 ASSERT(req
->pkt
== NULL
);
915 /* txirb should always be set, except for ZLP. ZLP is reusing this callback function. */
917 if (txirb
->send_buf
!= NULL
) {
918 MFREE(usbos_info
->pub
->osh
, txirb
->send_buf
, req
->buf_len
);
919 txirb
->send_buf
= NULL
;
922 if (likely (usbos_info
->cbarg
&& usbos_info
->cbs
)) {
923 if (likely (usbos_info
->cbs
->send_irb_complete
!= NULL
))
924 usbos_info
->cbs
->send_irb_complete(usbos_info
->cbarg
, txirb
, status
);
928 dbus_usbos_qenq(&usbos_info
->req_txfreeq
, req
, &usbos_info
->txfree_lock
);
932 * In order to receive USB traffic from the dongle, we need to supply the Linux kernel with a free
933 * URB that is going to contain received data.
935 static int BCMFASTPATH
936 dbus_usbos_recv_urb_submit(usbos_info_t
*usbos_info
, dbus_irb_rx_t
*rxirb
, uint32 ep_idx
)
945 BCM_REFERENCE(rxposted
);
947 if (!(req
= dbus_usbos_qdeq(&usbos_info
->req_rxfreeq
, &usbos_info
->rxfree_lock
))) {
948 DBUSTRACE(("%s No free URB!\n", __FUNCTION__
));
949 return DBUS_ERR_RXDROP
;
952 spin_lock_irqsave(&usbos_info
->rxlock
, flags
);
954 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
955 req
->pkt
= rxirb
->pkt
= PKTGET(usbos_info
->pub
->osh
, req
->buf_len
, FALSE
);
957 DBUSERR(("%s: PKTGET failed\n", __FUNCTION__
));
958 dbus_usbos_qenq(&usbos_info
->req_rxfreeq
, req
, &usbos_info
->rxfree_lock
);
959 ret
= DBUS_ERR_RXDROP
;
962 /* consider the packet "native" so we don't count it as MALLOCED in the osl */
963 PKTTONATIVE(usbos_info
->pub
->osh
, req
->pkt
);
965 p
= PKTDATA(usbos_info
->pub
->osh
, req
->pkt
);
967 if (req
->buf_len
!= usbos_info
->rxbuf_len
) {
969 MFREE(usbos_info
->pub
->osh
, req
->pkt
, req
->buf_len
);
970 DBUSTRACE(("%s: replace rx buff: old len %d, new len %d\n", __FUNCTION__
,
971 req
->buf_len
, usbos_info
->rxbuf_len
));
973 req
->pkt
= MALLOC(usbos_info
->pub
->osh
, usbos_info
->rxbuf_len
);
974 if (req
->pkt
== NULL
) {
975 DBUSERR(("%s: MALLOC req->pkt failed\n", __FUNCTION__
));
976 ret
= DBUS_ERR_NOMEM
;
979 req
->buf_len
= usbos_info
->rxbuf_len
;
981 rxirb
->buf
= req
->pkt
;
983 #endif /* defined(BCM_RPC_NOCOPY) */
984 rxirb
->buf_len
= req
->buf_len
;
985 req
->usbinfo
= usbos_info
;
988 rx_pipe
= usbos_info
->rx_pipe
;
990 rx_pipe
= usbos_info
->rx_pipe2
;
991 ASSERT(usbos_info
->rx_pipe2
);
993 /* Prepare the URB */
994 usb_fill_bulk_urb(req
->urb
, usbos_info
->usb
, rx_pipe
,
997 (usb_complete_t
)dbus_usbos_recv_complete
, req
);
998 req
->urb
->transfer_flags
|= URB_QUEUE_BULK
;
1000 if ((ret
= USB_SUBMIT_URB(req
->urb
))) {
1001 DBUSERR(("%s USB_SUBMIT_URB failed. status %d\n", __FUNCTION__
, ret
));
1002 dbus_usbos_qenq(&usbos_info
->req_rxfreeq
, req
, &usbos_info
->rxfree_lock
);
1003 ret
= DBUS_ERR_RXFAIL
;
1006 rxposted
= atomic_inc_return(&usbos_info
->rxposted
);
1007 #if defined(DBUS_LINUX_HIST)
1008 if (usbos_info
->rxposted_hist
) {
1009 usbos_info
->rxposted_hist
[rxposted
]++;
1013 dbus_usbos_qenq(&usbos_info
->req_rxpostedq
, req
, &usbos_info
->rxposted_lock
);
1015 spin_unlock_irqrestore(&usbos_info
->rxlock
, flags
);
1019 #ifdef DBUS_LINUX_RXDPC
1020 static void BCMFASTPATH
1021 dbus_usbos_recv_dpc(usbos_info_t
*usbos_info
)
1023 urb_req_t
*req
= NULL
;
1024 dbus_irb_rx_t
*rxirb
= NULL
;
1025 int dbus_status
= DBUS_OK
;
1026 bool killed
= (g_probe_info
.suspend_state
== USBOS_SUSPEND_STATE_SUSPEND_PENDING
) ? 1 : 0;
1028 #if defined(DBUS_LINUX_HIST)
1031 usbos_info
->dpc_cnt
++;
1034 while ((req
= dbus_usbos_qdeq(&usbos_info
->req_rxpendingq
,
1035 &usbos_info
->rxpending_lock
)) != NULL
) {
1036 struct urb
*urb
= req
->urb
;
1042 * Linux 2.4 disconnect: -ENOENT or -EILSEQ for CRC error; rmmod: -ENOENT
1043 * Linux 2.6 disconnect: -EPROTO, rmmod: -ESHUTDOWN
1045 if ((urb
->status
== -ENOENT
&& (!killed
)) || urb
->status
== -ESHUTDOWN
) {
1046 /* NOTE: unlink() can not be called from URB callback().
1047 * Do not call dbusos_stop() here.
1049 dbus_usbos_state_change(usbos_info
, DBUS_STATE_DOWN
);
1050 } else if (urb
->status
== -EPROTO
) {
1052 DBUSERR(("%s rx error %d\n", __FUNCTION__
, urb
->status
));
1053 dbus_usbos_errhandler(usbos_info
, DBUS_ERR_RXFAIL
);
1056 /* On error, don't submit more URBs yet */
1057 DBUSERR(("%s %d rx error %d\n", __FUNCTION__
, __LINE__
, urb
->status
));
1059 rxirb
->actual_len
= 0;
1060 dbus_status
= DBUS_ERR_RXFAIL
;
1064 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
1065 /* detach the packet from the req */
1068 /* Make the skb represent the received urb */
1069 rxirb
->actual_len
= urb
->actual_length
;
1072 usbos_info
->rxpending
--;
1073 #if defined(DBUS_LINUX_HIST)
1076 if (usbos_info
->cbarg
&& usbos_info
->cbs
&&
1077 usbos_info
->cbs
->recv_irb_complete
) {
1078 usbos_info
->cbs
->recv_irb_complete(usbos_info
->cbarg
, rxirb
, dbus_status
);
1080 dbus_usbos_qenq(&usbos_info
->req_rxfreeq
, req
, &usbos_info
->rxfree_lock
);
1083 #if defined(DBUS_LINUX_HIST)
1084 usbos_info
->dpc_pktcnt
+= cnt
;
1085 usbos_info
->dpc_maxpktcnt
= MAX(cnt
, usbos_info
->dpc_maxpktcnt
);
1087 #ifdef DBUS_LINUX_HIST
1089 static unsigned long last_dump
= 0;
1091 /* dump every 20 sec */
1092 if (jiffies
> (last_dump
+ 20*HZ
)) {
1093 dbus_usbos_intf_dump(usbos_info
, NULL
);
1094 last_dump
= jiffies
;
1097 #endif /* DBUS_LINUX_HIST */
1100 static int BCMFASTPATH
1101 dbus_usbos_dpc_thread(void *data
)
1103 usbos_info_t
*usbos_info
= (usbos_info_t
*)data
;
1105 DAEMONIZE("dbus_rx_dpc");
1106 /* High priority for short response time. We will yield by ourselves. */
1107 /* SET_NICE(-10); */
1109 /* Run until signal received */
1111 if (down_interruptible(&usbos_info
->dpc_sem
) == 0) {
1112 dbus_usbos_recv_dpc(usbos_info
);
1118 complete_and_exit(&usbos_info
->dpc_exited
, 0);
1121 #endif /* DBUS_LINUX_RXDPC */
1123 /* called by worked thread when a 'receive URB' completed */
1124 /* or Linux kernel when it returns a URB to this driver */
1125 static void BCMFASTPATH
1126 dbus_usbos_recv_complete_handle(urb_req_t
*req
, int len
, int status
)
1128 #ifdef DBUS_LINUX_RXDPC
1129 usbos_info_t
*usbos_info
= req
->usbinfo
;
1130 unsigned long flags
;
1131 int rxallocated
, rxposted
;
1133 spin_lock_irqsave(&usbos_info
->rxlock
, flags
);
1134 /* detach the packet from the queue */
1135 dbus_usbos_req_del(req
, &usbos_info
->rxposted_lock
);
1136 rxposted
= atomic_dec_return(&usbos_info
->rxposted
);
1137 rxallocated
= atomic_read(&usbos_info
->rxallocated
);
1139 /* Enqueue to rxpending queue */
1140 usbos_info
->rxpending
++;
1141 dbus_usbos_qenq(&usbos_info
->req_rxpendingq
, req
, &usbos_info
->rxpending_lock
);
1142 spin_unlock_irqrestore(&usbos_info
->rxlock
, flags
);
1144 #error "RX req/buf appending-mode not verified for DBUS_LINUX_RXDPC because it was disabled"
1145 if ((rxallocated
< usbos_info
->pub
->nrxq
) && (!status
) &&
1146 (rxposted
== DBUS_USB_RXQUEUE_LOWER_WATERMARK
)) {
1147 DBUSTRACE(("%s: need more rx buf: rxallocated %d rxposted %d!\n",
1148 __FUNCTION__
, rxallocated
, rxposted
));
1149 dbus_usbos_urbreqs_alloc(usbos_info
,
1150 MIN(DBUS_USB_RXQUEUE_BATCH_ADD
,
1151 usbos_info
->pub
->nrxq
- rxallocated
), TRUE
);
1153 #error "Please verify above code works if you happened to enable DBUS_LINUX_RXDPC!!"
1155 /* Wake up dpc for further processing */
1156 ASSERT(usbos_info
->dpc_pid
>= 0);
1157 up(&usbos_info
->dpc_sem
);
1159 dbus_irb_rx_t
*rxirb
= req
->arg
;
1160 usbos_info_t
*usbos_info
= req
->usbinfo
;
1161 unsigned long flags
;
1162 int rxallocated
, rxposted
;
1163 int dbus_status
= DBUS_OK
;
1164 bool killed
= (g_probe_info
.suspend_state
== USBOS_SUSPEND_STATE_SUSPEND_PENDING
) ? 1 : 0;
1166 spin_lock_irqsave(&usbos_info
->rxlock
, flags
);
1167 dbus_usbos_req_del(req
, &usbos_info
->rxposted_lock
);
1168 rxposted
= atomic_dec_return(&usbos_info
->rxposted
);
1169 rxallocated
= atomic_read(&usbos_info
->rxallocated
);
1170 spin_unlock_irqrestore(&usbos_info
->rxlock
, flags
);
1172 if ((rxallocated
< usbos_info
->pub
->nrxq
) && (!status
) &&
1173 (rxposted
== DBUS_USB_RXQUEUE_LOWER_WATERMARK
)) {
1174 DBUSTRACE(("%s: need more rx buf: rxallocated %d rxposted %d!\n",
1175 __FUNCTION__
, rxallocated
, rxposted
));
1176 dbus_usbos_urbreqs_alloc(usbos_info
,
1177 MIN(DBUS_USB_RXQUEUE_BATCH_ADD
,
1178 usbos_info
->pub
->nrxq
- rxallocated
), TRUE
);
1184 * Linux 2.4 disconnect: -ENOENT or -EILSEQ for CRC error; rmmod: -ENOENT
1185 * Linux 2.6 disconnect: -EPROTO, rmmod: -ESHUTDOWN
1187 if ((status
== -ENOENT
&& (!killed
))|| status
== -ESHUTDOWN
) {
1188 /* NOTE: unlink() can not be called from URB callback().
1189 * Do not call dbusos_stop() here.
1191 dbus_usbos_state_change(usbos_info
, DBUS_STATE_DOWN
);
1192 } else if (status
== -EPROTO
) {
1194 DBUSTRACE(("%s rx error %d\n", __FUNCTION__
, status
));
1195 dbus_usbos_errhandler(usbos_info
, DBUS_ERR_RXFAIL
);
1197 printf("%s rx error %d\n", __FUNCTION__
, status
);
1199 /* On error, don't submit more URBs yet */
1201 rxirb
->actual_len
= 0;
1202 dbus_status
= DBUS_ERR_RXFAIL
;
1206 /* Make the skb represent the received urb */
1207 rxirb
->actual_len
= len
;
1209 if (rxirb
->actual_len
< sizeof(uint32
)) {
1210 DBUSTRACE(("small pkt len %d, process as ZLP\n", rxirb
->actual_len
));
1211 dbus_status
= DBUS_ERR_RXZLP
;
1215 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
1216 /* detach the packet from the queue */
1218 #endif /* BCM_RPC_NOCOPY || BCM_RPC_RXNOCOPY */
1220 if (usbos_info
->cbarg
&& usbos_info
->cbs
) {
1221 if (usbos_info
->cbs
->recv_irb_complete
) {
1222 usbos_info
->cbs
->recv_irb_complete(usbos_info
->cbarg
, rxirb
, dbus_status
);
1226 dbus_usbos_qenq(&usbos_info
->req_rxfreeq
, req
, &usbos_info
->rxfree_lock
);
1227 #endif /* DBUS_LINUX_RXDPC */
1229 /* Mark the interface as busy to reset USB autosuspend timer */
1230 USB_MARK_LAST_BUSY(usbos_info
->usb
);
1233 /** called by Linux kernel when it returns a URB to this driver */
1235 dbus_usbos_recv_complete(CALLBACK_ARGS
)
1238 dbus_usbos_dispatch_schedule(CALLBACK_ARGS_DATA
);
1239 #else /* !USBOS_THREAD */
1240 dbus_usbos_recv_complete_handle(urb
->context
, urb
->actual_length
, urb
->status
);
1241 #endif /* USBOS_THREAD */
1246 * If Linux notifies our driver that a control read or write URB has completed, we should notify
1247 * the DBUS layer above us (dbus_usb.c in this case).
1250 dbus_usbos_ctl_complete(usbos_info_t
*usbos_info
, int type
, int urbstatus
)
1252 int status
= DBUS_ERR
;
1254 if (usbos_info
== NULL
)
1257 switch (urbstatus
) {
1264 #ifdef INTR_EP_ENABLE
1265 DBUSERR(("%s:%d fail status %d bus:%d susp:%d intr:%d ctli:%d ctlo:%d\n",
1266 __FUNCTION__
, type
, urbstatus
,
1267 usbos_info
->pub
->busstate
, g_probe_info
.suspend_state
,
1268 usbos_info
->intr_urb_submitted
, usbos_info
->ctlin_urb_submitted
,
1269 usbos_info
->ctlout_urb_submitted
));
1271 DBUSERR(("%s: failed with status %d\n", __FUNCTION__
, urbstatus
));
1274 #endif /* INTR_EP_ENABLE */
1277 if (usbos_info
->cbarg
&& usbos_info
->cbs
) {
1278 if (usbos_info
->cbs
->ctl_complete
)
1279 usbos_info
->cbs
->ctl_complete(usbos_info
->cbarg
, type
, status
);
1283 #ifndef USB_SYNC_CTRL_URB
1284 /** called by Linux */
1286 dbus_usbos_ctlread_complete(CALLBACK_ARGS
)
1288 usbos_info_t
*usbos_info
= (usbos_info_t
*)urb
->context
;
1290 unsigned long flags
;
1292 spin_lock_irqsave(&usbos_info
->ctrl_lock
, flags
);
1293 #endif /* USBOS_THREAD */
1296 usbos_info
= (usbos_info_t
*)urb
->context
;
1298 dbus_usbos_ctl_complete(usbos_info
, DBUS_CBCTL_READ
, urb
->status
);
1301 if (usbos_info
->rxctl_deferrespok
) {
1302 usbos_info
->ctl_read
.bRequestType
= USB_DIR_IN
| USB_TYPE_CLASS
|
1303 USB_RECIP_INTERFACE
;
1304 usbos_info
->ctl_read
.bRequest
= 1;
1306 spin_unlock_irqrestore(&usbos_info
->ctrl_lock
, flags
);
1310 /** called by Linux */
1312 dbus_usbos_ctlwrite_complete(CALLBACK_ARGS
)
1314 usbos_info_t
*usbos_info
= (usbos_info_t
*)urb
->context
;
1316 unsigned long flags
;
1318 spin_lock_irqsave(&usbos_info
->ctrl_lock
, flags
);
1319 #endif /* USBOS_THREAD */
1322 usbos_info
= (usbos_info_t
*)urb
->context
;
1324 dbus_usbos_ctl_complete(usbos_info
, DBUS_CBCTL_WRITE
, urb
->status
);
1326 #ifdef USBOS_TX_THREAD
1327 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_UNSCHEDULED
;
1328 #endif /* USBOS_TX_THREAD */
1331 spin_unlock_irqrestore(&usbos_info
->ctrl_lock
, flags
);
1334 /* Enable USB autosuspend if no packets are being sent */
1335 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info
.intf
);
1337 #endif /* USB_SYNC_CTRL_URB */
1339 #ifdef INTR_EP_ENABLE
1340 /** called by Linux */
1342 dbus_usbos_intr_complete(CALLBACK_ARGS
)
1344 usbos_info_t
*usbos_info
= (usbos_info_t
*)urb
->context
;
1345 bool killed
= (g_probe_info
.suspend_state
== USBOS_SUSPEND_STATE_SUSPEND_PENDING
) ? 1 : 0;
1347 if (usbos_info
== NULL
|| usbos_info
->pub
== NULL
)
1349 if ((urb
->status
== -ENOENT
&& (!killed
)) || urb
->status
== -ESHUTDOWN
||
1350 urb
->status
== -ENODEV
) {
1351 dbus_usbos_state_change(usbos_info
, DBUS_STATE_DOWN
);
1354 if (usbos_info
->pub
->busstate
== DBUS_STATE_DOWN
) {
1355 DBUSERR(("%s: intr cb when DBUS down, ignoring\n", __FUNCTION__
));
1358 dbus_usbos_ctl_complete(usbos_info
, DBUS_CBINTR_POLL
, urb
->status
);
1360 #endif /* INTR_EP_ENABLE */
1363 * when the bus is going to sleep or halt, the Linux kernel requires us to take ownership of our
1364 * URBs again. Multiple code paths in this file require a list of URBs to be cancelled in a
1365 * concurrency save manner.
1368 dbus_usbos_unlink(struct list_head
*urbreq_q
, spinlock_t
*lock
)
1372 /* dbus_usbos_recv_complete() adds req back to req_freeq */
1373 while ((req
= dbus_usbos_qdeq(urbreq_q
, lock
)) != NULL
) {
1374 ASSERT(req
->urb
!= NULL
);
1375 USB_UNLINK_URB(req
->urb
);
1379 /** multiple code paths in this file require the bus to stop */
1381 dbus_usbos_cancel_all_urbs(usbos_info_t
*usbos_info
)
1383 int rxposted
, txposted
;
1385 DBUSTRACE(("%s: unlink all URBs\n", __FUNCTION__
));
1387 #ifdef USBOS_TX_THREAD
1388 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_UNSCHEDULED
;
1390 /* Yield the CPU to TX thread so all pending requests are submitted */
1391 while (!list_empty(&usbos_info
->usbos_tx_list
)) {
1392 wake_up_interruptible(&usbos_info
->usbos_tx_queue_head
);
1395 #endif /* USBOS_TX_THREAD */
1397 /* tell Linux kernel to cancel a single intr, ctl and blk URB */
1398 if (usbos_info
->intr_urb
)
1399 USB_UNLINK_URB(usbos_info
->intr_urb
);
1400 if (usbos_info
->ctl_urb
)
1401 USB_UNLINK_URB(usbos_info
->ctl_urb
);
1402 if (usbos_info
->ctl_tx_urb
)
1403 USB_UNLINK_URB(usbos_info
->ctl_tx_urb
);
1404 if (usbos_info
->blk_urb
)
1405 USB_UNLINK_URB(usbos_info
->blk_urb
);
1407 dbus_usbos_unlink(&usbos_info
->req_txpostedq
, &usbos_info
->txposted_lock
);
1408 dbus_usbos_unlink(&usbos_info
->req_rxpostedq
, &usbos_info
->rxposted_lock
);
1410 /* Wait until the callbacks for all submitted URBs have been called, because the
1411 * handler needs to know is an USB suspend is in progress.
1413 SPINWAIT((atomic_read(&usbos_info
->txposted
) != 0 ||
1414 atomic_read(&usbos_info
->rxposted
) != 0), 10000);
1416 txposted
= atomic_read(&usbos_info
->txposted
);
1417 rxposted
= atomic_read(&usbos_info
->rxposted
);
1418 if (txposted
!= 0 || rxposted
!= 0) {
1419 DBUSERR(("%s ERROR: REQs posted, rx=%d tx=%d!\n",
1420 __FUNCTION__
, rxposted
, txposted
));
1424 /** multiple code paths require the bus to stop */
1426 dbusos_stop(usbos_info_t
*usbos_info
)
1435 #ifdef USB_TRIGGER_DEBUG
1436 dbus_usbos_ctl_send_debugtrig(usbos_info
);
1437 #endif /* USB_TRIGGER_DEBUG */
1438 dbus_usbos_state_change(usbos_info
, DBUS_STATE_DOWN
);
1440 dbus_usbos_cancel_all_urbs(usbos_info
);
1443 /* yield the CPU to rx packet thread */
1445 if (atomic_read(&usbos_info
->usbos_list_cnt
) <= 0) break;
1446 wake_up_interruptible(&usbos_info
->usbos_queue_head
);
1449 #endif /* USBOS_THREAD */
1451 rxposted
= atomic_read(&usbos_info
->rxposted
);
1453 DBUSERR(("%s ERROR: rx REQs posted=%d in stop!\n", __FUNCTION__
,
1457 ASSERT(atomic_read(&usbos_info
->txposted
) == 0 && rxposted
== 0);
1459 #ifdef DBUS_LINUX_RXDPC
1460 /* Stop the dpc thread */
1461 if (usbos_info
->dpc_pid
>= 0) {
1462 KILL_PROC(usbos_info
->dpc_pid
, SIGTERM
);
1463 wait_for_completion(&usbos_info
->dpc_exited
);
1466 /* Move pending reqs to free queue so they can be freed */
1467 while ((req
= dbus_usbos_qdeq(&usbos_info
->req_rxpendingq
,
1468 &usbos_info
->rxpending_lock
)) != NULL
) {
1469 dbus_usbos_qenq(&usbos_info
->req_rxfreeq
, req
,
1470 &usbos_info
->rxfree_lock
);
1472 #endif /* DBUS_LINUX_RXDPC */
1476 dbus_usbos_suspend(struct usb_interface
*intf
,
1477 pm_message_t message
)
1479 printk("AP6269: dbus_usbos_suspend enter, calling disconnect\n");
1480 dbus_usbos_disconnect(intf
);
1485 * The resume method is called to tell the driver that the device has been resumed and the driver
1486 * can return to normal operation. URBs may once more be submitted.
1488 static int dbus_usbos_resume(struct usb_interface
*intf
)
1494 #if defined(USB_SUSPEND_AVAILABLE)
1497 * Linux kernel sports a 'USB auto suspend' feature. See: http://lwn.net/Articles/373550/
1498 * The suspend method is called by the Linux kernel to warn the driver that the device is going to
1499 * be suspended. If the driver returns a negative error code, the suspend will be aborted. If the
1500 * driver returns 0, it must cancel all outstanding URBs (usb_kill_urb()) and not submit any more.
1503 dbus_usbos_suspend(struct usb_interface
*intf
,
1504 pm_message_t message
)
1506 DBUSERR(("%s suspend state: %d\n", __FUNCTION__
, g_probe_info
.suspend_state
));
1507 /* DHD for full dongle model */
1508 g_probe_info
.suspend_state
= USBOS_SUSPEND_STATE_SUSPEND_PENDING
;
1509 dbus_usbos_state_change((usbos_info_t
*)g_probe_info
.usbos_info
, DBUS_STATE_SLEEP
);
1510 dbus_usbos_cancel_all_urbs((usbos_info_t
*)g_probe_info
.usbos_info
);
1511 g_probe_info
.suspend_state
= USBOS_SUSPEND_STATE_SUSPENDED
;
1517 * The resume method is called to tell the driver that the device has been resumed and the driver
1518 * can return to normal operation. URBs may once more be submitted.
1520 static int dbus_usbos_resume(struct usb_interface
*intf
)
1522 DBUSERR(("%s Device resumed\n", __FUNCTION__
));
1524 dbus_usbos_state_change((usbos_info_t
*)g_probe_info
.usbos_info
, DBUS_STATE_UP
);
1525 g_probe_info
.suspend_state
= USBOS_SUSPEND_STATE_DEVICE_ACTIVE
;
1530 * This function is directly called by the Linux kernel, when the suspended device has been reset
1531 * instead of being resumed
1533 static int dbus_usbos_reset_resume(struct usb_interface
*intf
)
1535 DBUSERR(("%s Device reset resumed\n", __FUNCTION__
));
1536 return dbus_usbos_resume(intf
);
1539 #endif /* USB_SUSPEND_AVAILABLE */
1542 * Called by Linux kernel at initialization time, kernel wants to know if our driver will accept the
1543 * caller supplied USB interface. Note that USB drivers are bound to interfaces, and not to USB
1548 dbus_usbos_probe(struct usb_interface
*intf
, const struct usb_device_id
*id
)
1551 dbus_usbos_probe(struct usb_device
*usb
, unsigned int ifnum
, const struct usb_device_id
*id
)
1552 #endif /* KERNEL26 */
1555 struct usb_endpoint_descriptor
*endpoint
;
1558 struct usb_device
*usb
= interface_to_usbdev(intf
);
1563 #ifdef BCMUSBDEV_COMPOSITE
1565 bool intr_ep
= FALSE
;
1566 #endif /* BCMUSBDEV_COMPOSITE */
1568 #ifdef BCMUSBDEV_COMPOSITE
1569 wlan_if
= dbus_usbos_intf_wlan(usb
);
1571 if ((wlan_if
>= 0) && (IFPTR(usb
, wlan_if
) == intf
)) {
1573 if (wlan_if
== ifnum
) {
1574 #endif /* KERNEL26 */
1575 #endif /* BCMUSBDEV_COMPOSITE */
1576 g_probe_info
.usb
= usb
;
1577 g_probe_info
.dldone
= TRUE
;
1578 #ifdef BCMUSBDEV_COMPOSITE
1580 DBUSTRACE(("dbus_usbos_probe: skip probe for non WLAN interface\n"));
1581 ret
= BCME_UNSUPPORTED
;
1584 #endif /* BCMUSBDEV_COMPOSITE */
1587 g_probe_info
.intf
= intf
;
1588 #endif /* KERNEL26 */
1590 #ifdef BCMUSBDEV_COMPOSITE
1591 if (IFDESC(usb
, wlan_if
).bInterfaceNumber
> USB_COMPIF_MAX
) {
1593 if (IFDESC(usb
, CONTROL_IF
).bInterfaceNumber
) {
1594 #endif /* BCMUSBDEV_COMPOSITE */
1599 g_probe_info
.vid
= id
->idVendor
;
1600 g_probe_info
.pid
= id
->idProduct
;
1604 usb_set_intfdata(intf
, &g_probe_info
);
1607 /* Check that the device supports only one configuration */
1608 if (usb
->descriptor
.bNumConfigurations
!= 1) {
1613 if (usb
->descriptor
.bDeviceClass
!= USB_CLASS_VENDOR_SPEC
) {
1614 #ifdef BCMUSBDEV_COMPOSITE
1615 if ((usb
->descriptor
.bDeviceClass
!= USB_CLASS_MISC
) &&
1616 (usb
->descriptor
.bDeviceClass
!= USB_CLASS_WIRELESS
)) {
1617 #endif /* BCMUSBDEV_COMPOSITE */
1620 #ifdef BCMUSBDEV_COMPOSITE
1622 #endif /* BCMUSBDEV_COMPOSITE */
1626 * Only the BDC interface configuration is supported:
1627 * Device class: USB_CLASS_VENDOR_SPEC
1628 * if0 class: USB_CLASS_VENDOR_SPEC
1631 * if0/ep2: bulk out (ok if swapped with bulk in)
1633 if (CONFIGDESC(usb
)->bNumInterfaces
!= 1) {
1634 #ifdef BCMUSBDEV_COMPOSITE
1635 if (CONFIGDESC(usb
)->bNumInterfaces
> USB_COMPIF_MAX
) {
1636 #endif /* BCMUSBDEV_COMPOSITE */
1639 #ifdef BCMUSBDEV_COMPOSITE
1641 #endif /* BCMUSBDEV_COMPOSITE */
1644 /* Check interface */
1646 #ifdef BCMUSBDEV_COMPOSITE
1647 if (usb_interface_claimed(IFPTR(usb
, wlan_if
))) {
1649 if (usb_interface_claimed(IFPTR(usb
, CONTROL_IF
))) {
1650 #endif /* BCMUSBDEV_COMPOSITE */
1654 #endif /* !KERNEL26 */
1656 #ifdef BCMUSBDEV_COMPOSITE
1657 if ((IFDESC(usb
, wlan_if
).bInterfaceClass
!= USB_CLASS_VENDOR_SPEC
||
1658 IFDESC(usb
, wlan_if
).bInterfaceSubClass
!= 2 ||
1659 IFDESC(usb
, wlan_if
).bInterfaceProtocol
!= 0xff) &&
1660 (IFDESC(usb
, wlan_if
).bInterfaceClass
!= USB_CLASS_MISC
||
1661 IFDESC(usb
, wlan_if
).bInterfaceSubClass
!= USB_SUBCLASS_COMMON
||
1662 IFDESC(usb
, wlan_if
).bInterfaceProtocol
!= USB_PROTO_IAD
)) {
1663 DBUSERR(("%s: invalid control interface: class %d, subclass %d, proto %d\n",
1665 IFDESC(usb
, wlan_if
).bInterfaceClass
,
1666 IFDESC(usb
, wlan_if
).bInterfaceSubClass
,
1667 IFDESC(usb
, wlan_if
).bInterfaceProtocol
));
1669 if (IFDESC(usb
, CONTROL_IF
).bInterfaceClass
!= USB_CLASS_VENDOR_SPEC
||
1670 IFDESC(usb
, CONTROL_IF
).bInterfaceSubClass
!= 2 ||
1671 IFDESC(usb
, CONTROL_IF
).bInterfaceProtocol
!= 0xff) {
1672 DBUSERR(("%s: invalid control interface: class %d, subclass %d, proto %d\n",
1674 IFDESC(usb
, CONTROL_IF
).bInterfaceClass
,
1675 IFDESC(usb
, CONTROL_IF
).bInterfaceSubClass
,
1676 IFDESC(usb
, CONTROL_IF
).bInterfaceProtocol
));
1677 #endif /* BCMUSBDEV_COMPOSITE */
1682 /* Check control endpoint */
1683 #ifdef BCMUSBDEV_COMPOSITE
1684 endpoint
= &IFEPDESC(usb
, wlan_if
, 0);
1686 endpoint
= &IFEPDESC(usb
, CONTROL_IF
, 0);
1687 #endif /* BCMUSBDEV_COMPOSITE */
1688 if ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) != USB_ENDPOINT_XFER_INT
) {
1689 #ifdef BCMUSBDEV_COMPOSITE
1690 if ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) !=
1691 USB_ENDPOINT_XFER_BULK
) {
1692 #endif /* BCMUSBDEV_COMPOSITE */
1693 DBUSERR(("%s: invalid control endpoint %d\n",
1694 __FUNCTION__
, endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
));
1697 #ifdef BCMUSBDEV_COMPOSITE
1699 #endif /* BCMUSBDEV_COMPOSITE */
1702 #ifdef BCMUSBDEV_COMPOSITE
1703 if ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) == USB_ENDPOINT_XFER_INT
) {
1704 #endif /* BCMUSBDEV_COMPOSITE */
1705 g_probe_info
.intr_pipe
=
1706 usb_rcvintpipe(usb
, endpoint
->bEndpointAddress
& USB_ENDPOINT_NUMBER_MASK
);
1707 #ifdef BCMUSBDEV_COMPOSITE
1710 #endif /* BCMUSBDEV_COMPOSITE */
1713 /* Claim interface */
1714 #ifdef BCMUSBDEV_COMPOSITE
1715 usb_driver_claim_interface(&dbus_usbdev
, IFPTR(usb
, wlan_if
), &g_probe_info
);
1717 usb_driver_claim_interface(&dbus_usbdev
, IFPTR(usb
, CONTROL_IF
), &g_probe_info
);
1718 #endif /* BCMUSBDEV_COMPOSITE */
1720 #endif /* !KERNEL26 */
1721 g_probe_info
.rx_pipe
= 0;
1722 g_probe_info
.rx_pipe2
= 0;
1723 g_probe_info
.tx_pipe
= 0;
1724 #ifdef BCMUSBDEV_COMPOSITE
1729 num_of_eps
= IFDESC(usb
, wlan_if
).bNumEndpoints
- 1;
1731 num_of_eps
= IFDESC(usb
, BULK_IF
).bNumEndpoints
- 1;
1732 #endif /* BCMUSBDEV_COMPOSITE */
1734 if ((num_of_eps
!= 2) && (num_of_eps
!= 3)) {
1735 #ifdef BCMUSBDEV_COMPOSITE
1737 #endif /* BCMUSBDEV_COMPOSITE */
1740 /* Check data endpoints and get pipes */
1741 #ifdef BCMUSBDEV_COMPOSITE
1742 for (; ep
<= num_of_eps
; ep
++) {
1743 endpoint
= &IFEPDESC(usb
, wlan_if
, ep
);
1745 for (ep
= 1; ep
<= num_of_eps
; ep
++) {
1746 endpoint
= &IFEPDESC(usb
, BULK_IF
, ep
);
1747 #endif /* BCMUSBDEV_COMPOSITE */
1748 if ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) !=
1749 USB_ENDPOINT_XFER_BULK
) {
1750 DBUSERR(("%s: invalid data endpoint %d\n",
1756 if ((endpoint
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
) {
1757 if (!g_probe_info
.rx_pipe
) {
1758 g_probe_info
.rx_pipe
= usb_rcvbulkpipe(usb
,
1759 (endpoint
->bEndpointAddress
& USB_ENDPOINT_NUMBER_MASK
));
1761 g_probe_info
.rx_pipe2
= usb_rcvbulkpipe(usb
,
1762 (endpoint
->bEndpointAddress
& USB_ENDPOINT_NUMBER_MASK
));
1766 g_probe_info
.tx_pipe
= usb_sndbulkpipe(usb
, (endpoint
->bEndpointAddress
&
1767 USB_ENDPOINT_NUMBER_MASK
));
1770 /* Allocate interrupt URB and data buffer */
1771 /* RNDIS says 8-byte intr, our old drivers used 4-byte */
1772 #ifdef BCMUSBDEV_COMPOSITE
1773 g_probe_info
.intr_size
= (IFEPDESC(usb
, wlan_if
, 0).wMaxPacketSize
== 16) ? 8 : 4;
1774 g_probe_info
.interval
= IFEPDESC(usb
, wlan_if
, 0).bInterval
;
1775 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21))
1776 usb
->quirks
|= USB_QUIRK_NO_SET_INTF
;
1779 g_probe_info
.intr_size
= (IFEPDESC(usb
, CONTROL_IF
, 0).wMaxPacketSize
== 16) ? 8 : 4;
1780 g_probe_info
.interval
= IFEPDESC(usb
, CONTROL_IF
, 0).bInterval
;
1781 #endif /* BCMUSBDEV_COMPOSITE */
1784 /* usb_fill_int_urb does the interval decoding in 2.6 */
1785 if (usb
->speed
== USB_SPEED_HIGH
)
1786 g_probe_info
.interval
= 1 << (g_probe_info
.interval
- 1);
1788 if (usb
->speed
== USB_SPEED_SUPER
) {
1789 g_probe_info
.device_speed
= SUPER_SPEED
;
1790 DBUSERR(("super speed device detected\n"));
1791 } else if (usb
->speed
== USB_SPEED_HIGH
) {
1792 g_probe_info
.device_speed
= HIGH_SPEED
;
1793 DBUSERR(("high speed device detected\n"));
1795 g_probe_info
.device_speed
= FULL_SPEED
;
1796 DBUSERR(("full speed device detected\n"));
1798 if (g_probe_info
.dereged
== FALSE
&& probe_cb
) {
1799 disc_arg
= probe_cb(probe_arg
, "", USB_BUS
, 0);
1802 g_probe_info
.disc_cb_done
= FALSE
;
1805 intf
->needs_remote_wakeup
= 1;
1806 #endif /* KERNEL26 */
1812 usb_inc_dev_use(usb
);
1813 return &g_probe_info
;
1817 #ifdef BCMUSBDEV_COMPOSITE
1818 if (ret
!= BCME_UNSUPPORTED
)
1819 #endif /* BCMUSBDEV_COMPOSITE */
1820 DBUSERR(("%s: failed with errno %d\n", __FUNCTION__
, ret
));
1823 #ifdef BCMUSBDEV_COMPOSITE
1824 usb_driver_release_interface(&dbus_usbdev
, IFPTR(usb
, wlan_if
));
1826 usb_driver_release_interface(&dbus_usbdev
, IFPTR(usb
, CONTROL_IF
));
1827 #endif /* BCMUSBDEV_COMPOSITE */
1828 #endif /* !KERNEL26 */
1831 usb_set_intfdata(intf
, NULL
);
1838 /** Called by Linux kernel, is the counter part of dbus_usbos_probe() */
1841 dbus_usbos_disconnect(struct usb_interface
*intf
)
1844 dbus_usbos_disconnect(struct usb_device
*usb
, void *ptr
)
1848 struct usb_device
*usb
= interface_to_usbdev(intf
);
1849 probe_info_t
*probe_usb_init_data
= usb_get_intfdata(intf
);
1851 probe_info_t
*probe_usb_init_data
= (probe_info_t
*) ptr
;
1853 usbos_info_t
*usbos_info
;
1855 if (probe_usb_init_data
) {
1856 usbos_info
= (usbos_info_t
*) probe_usb_init_data
->usbos_info
;
1858 if ((probe_usb_init_data
->dereged
== FALSE
) && disconnect_cb
&& disc_arg
) {
1859 disconnect_cb(disc_arg
);
1861 probe_usb_init_data
->disc_cb_done
= TRUE
;
1868 #ifdef BCMUSBDEV_COMPOSITE
1869 usb_driver_release_interface(&dbus_usbdev
, IFPTR(usb
, wlan_if
));
1871 usb_driver_release_interface(&dbus_usbdev
, IFPTR(usb
, CONTROL_IF
));
1872 #endif /* BCMUSBDEV_COMPOSITE */
1873 usb_dec_dev_use(usb
);
1874 #endif /* !KERNEL26 */
1878 #define LOOPBACK_PKT_START 0xBABE1234
1880 bool is_loopback_pkt(void *buf
)
1883 uint32
*buf_ptr
= (uint32
*) buf
;
1885 if (*buf_ptr
== LOOPBACK_PKT_START
)
1891 int matches_loopback_pkt(void *buf
)
1894 unsigned char *cbuf
= (unsigned char *) buf
;
1895 uint32
*x
= (uint32
*) buf
;
1897 for (i
= 8; i
< loopback_size
; i
++) {
1898 if (cbuf
[i
] != (i
% 256)) {
1899 printf("%s: mismatch at i=%d %d : ", __FUNCTION__
, i
, cbuf
[i
]);
1900 printf("%s: rx packet index %u\n", __FUNCTION__
, x
[1]);
1901 for (j
= i
; ((j
< i
+ 16) && (j
< loopback_size
)); j
++) {
1902 printf("%d ", cbuf
[j
]);
1912 uint32
time_diff(struct timeval
*now
, struct timeval
*then
)
1914 return (now
->tv_usec
>= then
->tv_usec
) ?
1915 now
->tv_usec
- then
->tv_usec
:
1916 1000000 - (then
->tv_usec
- now
->tv_usec
);
1919 int dbus_usbos_loopback_tx(void *usbos_info_ptr
, int cnt
, int size
)
1921 usbos_info_t
*usbos_info
= (usbos_info_t
*) usbos_info_ptr
;
1925 int rc
, last_rx_cnt
;
1928 int max_size
= 1650;
1929 int usb_packet_size
= 512;
1930 int min_packet_size
= 10;
1931 struct timeval su_time
;
1932 struct timeval du_time
;
1933 uint32 actual_bw
= 0;
1935 if (size
% usb_packet_size
== 0) {
1937 DBUSERR(("%s: overriding size=%d \n", __FUNCTION__
, size
));
1940 if (size
< min_packet_size
) {
1941 size
= min_packet_size
;
1942 DBUSERR(("%s: overriding size=%d\n", __FUNCTION__
, min_packet_size
));
1944 if (size
> max_size
) {
1946 DBUSERR(("%s: overriding size=%d\n", __FUNCTION__
, max_size
));
1949 loopback_tx_cnt
= 0;
1950 loopback_rx_cnt
= 0;
1953 loopback_size
= size
;
1955 do_gettimeofday(&su_time
);
1957 while (loopback_tx_cnt
< cnt
) {
1959 int pkt_size
= loopback_size
;
1961 p
= PKTGET(usbos_info
->pub
->osh
, pkt_size
, TRUE
);
1963 DBUSERR(("%s:%d Failed to allocate packet sz=%d\n",
1964 __FUNCTION__
, __LINE__
, pkt_size
));
1969 * Loopback packet data
1970 * ---------------------------------------------------------------------------
1971 * | | Loopback Indicator | PKT Index | Data... |
1972 * ---------------------------------------------------------------------------
1976 x
= (uint32
*) PKTDATA(usbos_info
->pub
->osh
, p
);
1977 *x
= LOOPBACK_PKT_START
;
1978 x
[1] = loopback_tx_cnt
;
1979 buf
= (unsigned char*) x
;
1980 for (j
= 8; j
< pkt_size
; j
++) {
1983 rc
= dbus_send_buf(usbos_info
->pub
, buf
, pkt_size
, p
);
1984 if (rc
!= BCME_OK
) {
1985 DBUSERR(("%s:%d Freeing packet \n", __FUNCTION__
, __LINE__
));
1986 PKTFREE(usbos_info
->pub
->osh
, p
, TRUE
);
1987 dbus_usbos_wait(usbos_info
, 1);
1993 if (tx_failed_cnt
== 5) {
1994 DBUSERR(("%s : Failed to send loopback packets cnt=%d loopback_tx_cnt=%d\n",
1995 __FUNCTION__
, cnt
, loopback_tx_cnt
));
1999 printf("Transmitted %d loopback packets of size %d\n", loopback_tx_cnt
, loopback_size
);
2001 last_rx_cnt
= loopback_rx_cnt
;
2002 while (loopback_rx_cnt
< loopback_tx_cnt
) {
2003 dbus_usbos_wait(usbos_info
, 1);
2004 if (loopback_rx_cnt
<= last_rx_cnt
) {
2006 if (rx_wait_cnt
> 5) {
2007 DBUSERR(("%s: Matched rx cnt stuck at %d \n",
2008 __FUNCTION__
, last_rx_cnt
));
2013 last_rx_cnt
= loopback_rx_cnt
;
2017 do_gettimeofday(&du_time
);
2019 actual_bw
= (loopback_tx_cnt
+ loopback_rx_cnt
) * loopback_size
* 8 /
2020 time_diff(&du_time
, &su_time
)*1000000;
2022 printf("Received %d loopback packets of size %d\n", loopback_tx_cnt
, loopback_size
);
2023 printf("BW : %u bps\n", actual_bw
);
2029 /** Higher layer (dbus_usb.c) wants to transmit an I/O Request Block */
2031 dbus_usbos_intf_send_irb(void *bus
, dbus_irb_tx_t
*txirb
)
2033 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2034 urb_req_t
*req
, *req_zlp
= NULL
;
2036 unsigned long flags
= 0;
2038 uint32 buffer_length
;
2040 bool reqs_obtained
= FALSE
;
2042 BCM_REFERENCE(flags
);
2044 if ((usbos_info
== NULL
) || !usbos_info
->tx_pipe
) {
2048 if (txirb
->pkt
!= NULL
) {
2049 buffer_length
= pkttotlen(usbos_info
->pub
->osh
, txirb
->pkt
);
2050 /* In case of multiple packets the values below may be overwritten */
2051 txirb
->send_buf
= NULL
;
2052 buf
= PKTDATA(usbos_info
->pub
->osh
, txirb
->pkt
);
2053 } else { /* txirb->buf != NULL */
2054 ASSERT(txirb
->buf
!= NULL
);
2055 ASSERT(txirb
->send_buf
== NULL
);
2056 buffer_length
= txirb
->len
;
2060 if (!(req
= dbus_usbos_qdeq(&usbos_info
->req_txfreeq
, &usbos_info
->txfree_lock
))) {
2061 DBUSERR(("%s No free URB!\n", __FUNCTION__
));
2062 return DBUS_ERR_TXDROP
;
2065 /* If not using standard Linux kernel functionality for handling Zero Length Packet(ZLP),
2066 * the dbus needs to generate ZLP when length is multiple of MaxPacketSize.
2069 if (!(buffer_length
% usbos_info
->maxps
)) {
2071 dbus_usbos_qdeq(&usbos_info
->req_txfreeq
, &usbos_info
->txfree_lock
))) {
2072 DBUSERR(("%s No free URB for ZLP!\n", __FUNCTION__
));
2073 ret
= DBUS_ERR_TXDROP
;
2077 /* No txirb, so that dbus_usbos_send_complete can differentiate between
2080 req_zlp
->arg
= NULL
;
2081 req_zlp
->usbinfo
= usbos_info
;
2082 req_zlp
->buf_len
= 0;
2084 usb_fill_bulk_urb(req_zlp
->urb
, usbos_info
->usb
, usbos_info
->tx_pipe
, NULL
,
2085 0, (usb_complete_t
)dbus_usbos_send_complete
, req_zlp
);
2087 req_zlp
->urb
->transfer_flags
|= URB_QUEUE_BULK
;
2089 #endif /* !WL_URB_ZPKT */
2091 /* In case of fail, this boolean is used to determine if the USB autosuspend needs to be
2092 * enabled and if spin_unlock_irqrestore() needs to be called.
2094 reqs_obtained
= TRUE
;
2096 #ifndef USBOS_TX_THREAD
2097 /* Disable USB autosuspend until this request completes, and request USB resume if needed.
2098 * Because this call runs asynchronously, there is no guarantee the bus is resumed before
2099 * the URB is submitted, and this request might be dropped. Use USB_SUSPEND_THREAD to avoid
2102 USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info
.intf
);
2103 #endif /* !USBOS_TX_THREAD */
2105 spin_lock_irqsave(&usbos_info
->txlock
, flags
);
2108 req
->usbinfo
= usbos_info
;
2111 /* Prepare the URB */
2112 if (txirb
->pkt
!= NULL
) {
2116 /* For multiple packets, allocate contiguous buffer and copy packet data to it */
2117 if (PKTNEXT(usbos_info
->pub
->osh
, txirb
->pkt
)) {
2118 transfer_buf
= MALLOC(usbos_info
->pub
->osh
, buffer_length
);
2119 if (!transfer_buf
) {
2120 ret
= DBUS_ERR_TXDROP
;
2121 DBUSERR(("fail to alloc to usb buffer\n"));
2126 txirb
->send_buf
= transfer_buf
;
2127 req
->buf_len
= buffer_length
;
2130 pktlen
= PKTLEN(usbos_info
->pub
->osh
, pkt
);
2131 bcopy(PKTDATA(usbos_info
->pub
->osh
, pkt
), transfer_buf
, pktlen
);
2132 transfer_buf
+= pktlen
;
2133 pkt
= PKTNEXT(usbos_info
->pub
->osh
, pkt
);
2136 ASSERT(((uint8
*) txirb
->send_buf
+ buffer_length
) == (transfer_buf
));
2138 /* Overwrite buf pointer with pointer to allocated contiguous transfer_buf
2140 buf
= txirb
->send_buf
;
2144 usb_fill_bulk_urb(req
->urb
, usbos_info
->usb
, usbos_info
->tx_pipe
, buf
,
2145 buffer_length
, (usb_complete_t
)dbus_usbos_send_complete
, req
);
2147 req
->urb
->transfer_flags
|= URB_QUEUE_BULK
;
2149 #ifdef USBOS_TX_THREAD
2150 /* Enqueue TX request, the TX thread will resume the bus if needed and submit
2153 dbus_usbos_qenq(&usbos_info
->usbos_tx_list
, req
, &usbos_info
->usbos_tx_list_lock
);
2154 if (req_zlp
!= NULL
) {
2155 dbus_usbos_qenq(&usbos_info
->usbos_tx_list
, req_zlp
,
2156 &usbos_info
->usbos_tx_list_lock
);
2158 spin_unlock_irqrestore(&usbos_info
->txlock
, flags
);
2160 wake_up_interruptible(&usbos_info
->usbos_tx_queue_head
);
2163 if ((ret
= USB_SUBMIT_URB(req
->urb
))) {
2164 ret
= DBUS_ERR_TXDROP
;
2168 dbus_usbos_qenq(&usbos_info
->req_txpostedq
, req
, &usbos_info
->txposted_lock
);
2169 atomic_inc(&usbos_info
->txposted
);
2171 if (req_zlp
!= NULL
) {
2172 if ((ret
= USB_SUBMIT_URB(req_zlp
->urb
))) {
2173 DBUSERR(("failed to submit ZLP URB!\n"));
2175 ret
= DBUS_ERR_TXDROP
;
2179 dbus_usbos_qenq(&usbos_info
->req_txpostedq
, req_zlp
, &usbos_info
->txposted_lock
);
2180 /* Also increment txposted for zlp packet, as it will be decremented in
2181 * dbus_usbos_send_complete()
2183 atomic_inc(&usbos_info
->txposted
);
2186 spin_unlock_irqrestore(&usbos_info
->txlock
, flags
);
2188 #endif /* USBOS_TX_THREAD */
2191 if (txirb
->send_buf
!= NULL
) {
2192 MFREE(usbos_info
->pub
->osh
, txirb
->send_buf
, req
->buf_len
);
2193 txirb
->send_buf
= NULL
;
2196 dbus_usbos_qenq(&usbos_info
->req_txfreeq
, req
, &usbos_info
->txfree_lock
);
2197 #ifndef USBOS_TX_THREAD
2200 if (req_zlp
!= NULL
) {
2201 dbus_usbos_qenq(&usbos_info
->req_txfreeq
, req_zlp
, &usbos_info
->txfree_lock
);
2204 if (reqs_obtained
) {
2205 spin_unlock_irqrestore(&usbos_info
->txlock
, flags
);
2207 #ifndef USBOS_TX_THREAD
2208 /* Enable USB autosuspend if no packets are being sent */
2209 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info
.intf
);
2210 #endif /* !USBOS_TX_THREAD */
2216 /** Higher layer (dbus_usb.c) recycles a received (and used) packet. */
2218 dbus_usbos_intf_recv_irb(void *bus
, dbus_irb_rx_t
*rxirb
)
2220 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2223 if (usbos_info
== NULL
)
2226 ret
= dbus_usbos_recv_urb_submit(usbos_info
, rxirb
, 0);
2231 dbus_usbos_intf_recv_irb_from_ep(void *bus
, dbus_irb_rx_t
*rxirb
, uint32 ep_idx
)
2233 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2236 if (usbos_info
== NULL
)
2239 #ifdef INTR_EP_ENABLE
2240 /* By specifying the ep_idx value of 0xff, the cdc layer is asking to
2241 * submit an interrupt URB
2243 if (rxirb
== NULL
&& ep_idx
== 0xff) {
2244 /* submit intr URB */
2245 if ((ret
= USB_SUBMIT_URB(usbos_info
->intr_urb
)) < 0) {
2246 DBUSERR(("%s intr USB_SUBMIT_URB failed, status %d\n",
2247 __FUNCTION__
, ret
));
2252 if (rxirb
== NULL
) {
2255 #endif /* INTR_EP_ENABLE */
2257 ret
= dbus_usbos_recv_urb_submit(usbos_info
, rxirb
, ep_idx
);
2261 /** Higher layer (dbus_usb.c) want to cancel an IRB */
2263 dbus_usbos_intf_cancel_irb(void *bus
, dbus_irb_tx_t
*txirb
)
2265 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2267 if (usbos_info
== NULL
)
2274 dbus_usbos_intf_send_ctl(void *bus
, uint8
*buf
, int len
)
2276 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2279 #ifdef USB_SYNC_CTRL_URB
2281 #endif /* USB_SYNC_CTRL_URB */
2283 if ((usbos_info
== NULL
) || (buf
== NULL
) || (len
== 0))
2286 if (usbos_info
->ctl_tx_urb
== NULL
)
2289 #ifdef USBOS_TX_THREAD
2290 if (usbos_info
->ctl_state
!= USBOS_REQUEST_STATE_UNSCHEDULED
) {
2291 return DBUS_ERR_TXCTLFAIL
;
2294 /* Disable USB autosuspend until this request completes, and request USB resume if needed.
2295 * Because this call runs asynchronously, there is no guarantee the bus is resumed before
2296 * the URB is submitted, and this request might be dropped. Use USB_SUSPEND_THREAD to avoid
2299 USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info
.intf
);
2300 #endif /* USBOS_TX_THREAD */
2303 usbos_info
->ctl_write
.wLength
= cpu_to_le16p(&size
);
2304 usbos_info
->ctl_tx_urb
->transfer_buffer_length
= size
;
2307 #ifdef USB_SYNC_CTRL_URB
2308 #ifdef USBOS_TX_THREAD
2309 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_SCHEDULED
;
2312 ret
= USB_CONTROL_MSG(usbos_info
->usb
, usbos_info
->ctl_out_pipe
,
2313 usbos_info
->ctl_write
.bRequest
, usbos_info
->ctl_write
.bRequestType
,
2314 usbos_info
->ctl_write
.wValue
, usbos_info
->ctl_write
.wIndex
,
2315 buf
, usbos_info
->ctl_write
.wLength
, USB_CTRL_EP_TIMEOUT
);
2317 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info
.intf
);
2320 DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__
, ret
));
2321 ret
= DBUS_ERR_TXCTLFAIL
;
2328 #ifdef USBOS_TX_THREAD
2329 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_UNSCHEDULED
;
2331 dbus_usbos_ctl_complete(usbos_info
, DBUS_CBCTL_WRITE
, status
);
2335 usb_fill_control_urb(usbos_info
->ctl_tx_urb
,
2337 usbos_info
->ctl_out_pipe
,
2338 (unsigned char *) &usbos_info
->ctl_write
,
2339 buf
, size
, (usb_complete_t
)dbus_usbos_ctlwrite_complete
, usbos_info
);
2341 #ifdef USBOS_TX_THREAD
2342 /* Enqueue CTRL request, the TX thread will resume the bus if needed and submit
2345 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_SCHEDULED
;
2346 wake_up_interruptible(&usbos_info
->usbos_tx_queue_head
);
2348 if ((ret
= USB_SUBMIT_URB(usbos_info
->ctl_tx_urb
))) {
2349 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__
, ret
));
2351 /* Enable USB autosuspend if no packets are being sent */
2352 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info
.intf
);
2354 return DBUS_ERR_TXCTLFAIL
;
2356 #endif /* USBOS_TX_THREAD */
2359 #endif /* USB_SYNC_CTRL_URB */
2364 /** This function does not seem to be called by anyone, including dbus_usb.c */
2366 dbus_usbos_intf_recv_ctl(void *bus
, uint8
*buf
, int len
)
2368 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2372 unsigned long flags
;
2373 #endif /* USBOS_THREAD */
2374 #ifdef USB_SYNC_CTRL_URB
2376 #endif /* USB_SYNC_CTRL_URB */
2378 if ((usbos_info
== NULL
) || (buf
== NULL
) || (len
== 0))
2381 if (usbos_info
->ctl_urb
== NULL
)
2384 #if defined(USBOS_THREAD) && !defined(USB_SYNC_CTRL_URB)
2385 spin_lock_irqsave(&usbos_info
->ctrl_lock
, flags
);
2388 usbos_info
->ctl_read
.wLength
= cpu_to_le16p(&size
);
2389 usbos_info
->ctl_urb
->transfer_buffer_length
= size
;
2391 if (usbos_info
->rxctl_deferrespok
) {
2393 usbos_info
->ctl_read
.bRequestType
= USB_DIR_IN
| USB_TYPE_VENDOR
|
2394 USB_RECIP_INTERFACE
;
2395 usbos_info
->ctl_read
.bRequest
= DL_DEFER_RESP_OK
;
2397 /* full dongle model */
2398 usbos_info
->ctl_read
.bRequestType
= USB_DIR_IN
| USB_TYPE_CLASS
|
2399 USB_RECIP_INTERFACE
;
2400 usbos_info
->ctl_read
.bRequest
= 1;
2403 #ifdef USB_SYNC_CTRL_URB
2405 ret
= USB_CONTROL_MSG(usbos_info
->usb
, usbos_info
->ctl_in_pipe
,
2406 usbos_info
->ctl_read
.bRequest
, usbos_info
->ctl_read
.bRequestType
,
2407 usbos_info
->ctl_read
.wValue
, usbos_info
->ctl_read
.wIndex
,
2408 buf
, usbos_info
->ctl_read
.wLength
, USB_CTRL_EP_TIMEOUT
);
2411 DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__
, ret
));
2412 ret
= DBUS_ERR_RXCTLFAIL
;
2419 dbus_usbos_ctl_complete(usbos_info
, DBUS_CBCTL_READ
, status
);
2422 usb_fill_control_urb(usbos_info
->ctl_urb
,
2424 usbos_info
->ctl_in_pipe
,
2425 (unsigned char *) &usbos_info
->ctl_read
,
2426 buf
, size
, (usb_complete_t
)dbus_usbos_ctlread_complete
, usbos_info
);
2428 ret
= USB_SUBMIT_URB(usbos_info
->ctl_urb
);
2430 spin_unlock_irqrestore(&usbos_info
->ctrl_lock
, flags
);
2433 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__
, ret
));
2434 return DBUS_ERR_RXCTLFAIL
;
2437 #endif /* USB_SYNC_CTRL_URB */
2442 dbus_usbos_intf_get_attrib(void *bus
, dbus_attrib_t
*attrib
)
2444 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2446 if ((usbos_info
== NULL
) || (attrib
== NULL
))
2449 attrib
->bustype
= DBUS_USB
;
2450 attrib
->vid
= g_probe_info
.vid
;
2451 attrib
->pid
= g_probe_info
.pid
;
2452 attrib
->devid
= 0x4322;
2456 /* MaxPacketSize for USB hi-speed bulk out is 512 bytes
2457 * and 64-bytes for full-speed.
2458 * When sending pkt > MaxPacketSize, Host SW breaks it
2459 * up into multiple packets.
2461 attrib
->mtu
= usbos_info
->maxps
;
2466 /** Called by higher layer (dbus_usb.c) when it wants to 'up' the USB interface to the dongle */
2468 dbus_usbos_intf_up(void *bus
)
2470 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2472 #ifdef BCMUSBDEV_COMPOSITE
2475 if (usbos_info
== NULL
)
2478 if (usbos_info
->usb
== NULL
)
2481 #if defined(INTR_EP_ENABLE)
2482 /* full dongle use intr EP, bmac doesn't use it */
2483 if (usbos_info
->intr_urb
) {
2486 usb_fill_int_urb(usbos_info
->intr_urb
, usbos_info
->usb
,
2487 usbos_info
->intr_pipe
, &usbos_info
->intr
,
2488 usbos_info
->intr_size
, (usb_complete_t
)dbus_usbos_intr_complete
,
2489 usbos_info
, usbos_info
->interval
);
2491 if ((ret
= USB_SUBMIT_URB(usbos_info
->intr_urb
))) {
2492 DBUSERR(("%s USB_SUBMIT_URB failed with status %d\n", __FUNCTION__
, ret
));
2498 if (usbos_info
->ctl_urb
&& usbos_info
->ctl_tx_urb
) {
2499 usbos_info
->ctl_in_pipe
= usb_rcvctrlpipe(usbos_info
->usb
, 0);
2500 usbos_info
->ctl_out_pipe
= usb_sndctrlpipe(usbos_info
->usb
, 0);
2502 #ifdef BCMUSBDEV_COMPOSITE
2503 wlan_if
= dbus_usbos_intf_wlan(usbos_info
->usb
);
2504 ifnum
= cpu_to_le16(IFDESC(usbos_info
->usb
, wlan_if
).bInterfaceNumber
);
2506 ifnum
= cpu_to_le16(IFDESC(usbos_info
->usb
, CONTROL_IF
).bInterfaceNumber
);
2507 #endif /* BCMUSBDEV_COMPOSITE */
2509 usbos_info
->ctl_write
.bRequestType
=
2510 USB_DIR_OUT
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
2511 usbos_info
->ctl_write
.bRequest
= 0;
2512 usbos_info
->ctl_write
.wValue
= cpu_to_le16(0);
2513 usbos_info
->ctl_write
.wIndex
= cpu_to_le16p(&ifnum
);
2516 usbos_info
->ctl_read
.bRequestType
=
2517 USB_DIR_IN
| USB_TYPE_CLASS
| USB_RECIP_INTERFACE
;
2518 usbos_info
->ctl_read
.bRequest
= 1;
2519 usbos_info
->ctl_read
.wValue
= cpu_to_le16(0);
2520 usbos_info
->ctl_read
.wIndex
= cpu_to_le16p(&ifnum
);
2523 /* Success, indicate usbos_info is fully up */
2524 dbus_usbos_state_change(usbos_info
, DBUS_STATE_UP
);
2530 dbus_usbos_intf_down(void *bus
)
2532 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2534 if (usbos_info
== NULL
)
2537 dbusos_stop(usbos_info
);
2542 dbus_usbos_intf_stop(void *bus
)
2544 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2546 if (usbos_info
== NULL
)
2549 dbusos_stop(usbos_info
);
2553 #if defined(DBUS_LINUX_HIST)
2555 dbus_usbos_intf_dump(void *bus
, struct bcmstrbuf
*b
)
2557 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
2558 int i
= 0, j
= 0, rxposted
, txposted
;
2560 rxposted
= atomic_read(&usbos_info
->rxposted
);
2561 txposted
= atomic_read(&usbos_info
->txposted
);
2563 bcm_bprintf(b
, "\ndbus linux dump\n");
2564 bcm_bprintf(b
, "txposted %d rxposted %d\n",
2565 txposted
, rxposted
);
2567 bcm_bprintf(b
, "RXDPC: dpc_cnt %d dpc_pktcnt %d dpc_maxpktcnt %d avg_dpc_pktcnt\n",
2568 usbos_info
->dpc_cnt
, usbos_info
->dpc_pktcnt
,
2569 usbos_info
->dpc_maxpktcnt
, usbos_info
->dpc_cnt
?
2570 (usbos_info
->dpc_pktcnt
/usbos_info
->dpc_cnt
):1);
2573 bcm_bprintf(b
, "txposted\n");
2575 printf("\ndbus linux dump\n");
2576 printf("txposted %d rxposted %d\n",
2577 txposted
, rxposted
);
2578 printf("RXDPC: dpc_cnt %d dpc_pktcnt %d dpc_maxpktcnt %d avg_dpc_pktcnt %d\n",
2579 usbos_info
->dpc_cnt
, usbos_info
->dpc_pktcnt
,
2580 usbos_info
->dpc_maxpktcnt
, usbos_info
->dpc_cnt
?
2581 (usbos_info
->dpc_pktcnt
/usbos_info
->dpc_cnt
):1);
2584 printf("txposted\n");
2587 for (i
= 0; i
< usbos_info
->pub
->ntxq
; i
++) {
2588 if (usbos_info
->txposted_hist
== NULL
) {
2591 if (usbos_info
->txposted_hist
[i
]) {
2593 bcm_bprintf(b
, "%d: %d ", i
, usbos_info
->txposted_hist
[i
]);
2595 printf("%d: %d ", i
, usbos_info
->txposted_hist
[i
]);
2599 bcm_bprintf(b
, "\n");
2608 bcm_bprintf(b
, "\nrxposted\n");
2610 printf("\nrxposted\n");
2611 for (i
= 0; i
< usbos_info
->pub
->nrxq
; i
++) {
2612 if (usbos_info
->rxposted_hist
== NULL
) {
2615 if (usbos_info
->rxposted_hist
[i
]) {
2617 bcm_bprintf(b
, "%d: %d ", i
, usbos_info
->rxposted_hist
[i
]);
2619 printf("%d: %d ", i
, usbos_info
->rxposted_hist
[i
]);
2623 bcm_bprintf(b
, "\n");
2630 bcm_bprintf(b
, "\n");
2638 /** Called by higher layer (dbus_usb.c) */
2640 dbus_usbos_intf_set_config(void *bus
, dbus_config_t
*config
)
2643 usbos_info_t
* usbos_info
= bus
;
2645 if (config
->config_id
== DBUS_CONFIG_ID_RXCTL_DEFERRES
) {
2646 usbos_info
->rxctl_deferrespok
= config
->rxctl_deferrespok
;
2648 } else if (config
->config_id
== DBUS_CONFIG_ID_AGGR_LIMIT
) {
2650 /* DBUS_CONFIG_ID_AGGR_LIMIT shouldn't be called after probe stage */
2651 ASSERT(disc_arg
== NULL
);
2652 #endif /* BCM_FD_AGGR */
2653 ASSERT(config
->aggr_param
.maxrxsf
> 0);
2654 ASSERT(config
->aggr_param
.maxrxsize
> 0);
2655 if (config
->aggr_param
.maxrxsize
> usbos_info
->rxbuf_len
) {
2656 int state
= usbos_info
->pub
->busstate
;
2657 dbus_usbos_unlink(&usbos_info
->req_rxpostedq
, &usbos_info
->rxposted_lock
);
2658 while (atomic_read(&usbos_info
->rxposted
)) {
2659 DBUSTRACE(("%s rxposted is %d, delay 1 ms\n", __FUNCTION__
,
2660 atomic_read(&usbos_info
->rxposted
)));
2661 dbus_usbos_wait(usbos_info
, 1);
2663 usbos_info
->rxbuf_len
= config
->aggr_param
.maxrxsize
;
2664 dbus_usbos_state_change(usbos_info
, state
);
2673 * In some cases, the code must submit an URB and wait for its completion.
2674 * Related: dbus_usbos_sync_complete()
2677 dbus_usbos_sync_wait(usbos_info_t
*usbinfo
, uint16 time
)
2683 ret
= wait_event_interruptible_timeout(usbinfo
->wait
,
2684 usbinfo
->waitdone
== TRUE
, (ms
* HZ
/ 1000));
2686 if ((usbinfo
->waitdone
== FALSE
) || (usbinfo
->sync_urb_status
)) {
2687 DBUSERR(("%s: timeout(%d) or urb err=0x%x\n",
2688 __FUNCTION__
, ret
, usbinfo
->sync_urb_status
));
2692 usbinfo
->waitdone
= FALSE
;
2697 * In some cases, the code must submit an URB and wait for its completion.
2698 * Related: dbus_usbos_sync_wait()
2701 dbus_usbos_sync_complete(CALLBACK_ARGS
)
2703 usbos_info_t
*usbos_info
= (usbos_info_t
*)urb
->context
;
2705 usbos_info
->waitdone
= TRUE
;
2706 wake_up_interruptible(&usbos_info
->wait
);
2708 usbos_info
->sync_urb_status
= urb
->status
;
2711 DBUSERR(("%s: sync urb error %d\n", __FUNCTION__
, urb
->status
));
2715 /** Called by dbus_usb.c when it wants to download firmware into the dongle */
2717 dbus_usbos_dl_cmd(usbos_info_t
*usbinfo
, uint8 cmd
, void *buffer
, int buflen
)
2723 if ((usbinfo
== NULL
) || (buffer
== NULL
) || (buflen
== 0))
2726 if (usbinfo
->ctl_urb
== NULL
)
2729 tmpbuf
= (char *) MALLOC(usbinfo
->pub
->osh
, buflen
);
2731 DBUSERR(("%s: Unable to allocate memory \n", __FUNCTION__
));
2736 usbinfo
->ctl_urb
->transfer_buffer_length
= size
;
2738 usbinfo
->ctl_read
.wLength
= cpu_to_le16p(&size
);
2739 usbinfo
->ctl_read
.bRequestType
= USB_DIR_IN
| USB_TYPE_VENDOR
|
2740 USB_RECIP_INTERFACE
;
2741 usbinfo
->ctl_read
.bRequest
= cmd
;
2743 #if defined(BCM_REQUEST_FW)
2745 usbinfo
->ctl_read
.wIndex
= 0x1;
2749 #ifdef USB_SYNC_CTRL_URB
2750 ret
= USB_CONTROL_MSG(usbinfo
->usb
, usb_rcvctrlpipe(usbinfo
->usb
, 0),
2751 usbinfo
->ctl_read
.bRequest
, usbinfo
->ctl_read
.bRequestType
,
2752 usbinfo
->ctl_read
.wValue
, usbinfo
->ctl_read
.wIndex
,
2753 (void *) tmpbuf
, usbinfo
->ctl_read
.wLength
, USB_CTRL_EP_TIMEOUT
);
2755 usb_fill_control_urb(usbinfo
->ctl_urb
,
2757 usb_rcvctrlpipe(usbinfo
->usb
, 0),
2758 (unsigned char *) &usbinfo
->ctl_read
,
2759 (void *) tmpbuf
, size
, (usb_complete_t
)dbus_usbos_sync_complete
, usbinfo
);
2761 ret
= USB_SUBMIT_URB(usbinfo
->ctl_urb
);
2765 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__
, ret
));
2766 MFREE(usbinfo
->pub
->osh
, tmpbuf
, buflen
);
2770 #ifndef USB_SYNC_CTRL_URB
2771 ret
= dbus_usbos_sync_wait(usbinfo
, USB_SYNC_WAIT_TIMEOUT
);
2773 memcpy(buffer
, tmpbuf
, buflen
);
2774 MFREE(usbinfo
->pub
->osh
, tmpbuf
, buflen
);
2775 #ifdef USB_SYNC_CTRL_URB
2778 return (ret
== DBUS_OK
);
2783 * Called by dbus_usb.c when it wants to download a buffer into the dongle (e.g. as part of the
2784 * download process, when writing nvram variables).
2787 dbus_write_membytes(usbos_info_t
* usbinfo
, bool set
, uint32 address
, uint8
*data
, uint size
)
2790 int write_bytes
= 4;
2794 DBUSTRACE(("Enter:%s\n", __FUNCTION__
));
2796 /* Read is not supported */
2798 DBUSERR(("Currently read is not supported!!\n"));
2802 hwacc
.cmd
= DL_CMD_WRHW
;
2803 hwacc
.addr
= address
;
2805 DBUSTRACE(("Address:%x size:%d", hwacc
.addr
, size
));
2809 } else if (size
>= 2) {
2815 hwacc
.len
= write_bytes
;
2817 while (size
>= write_bytes
) {
2818 hwacc
.data
= *((unsigned int*)data
);
2820 status
= USB_CONTROL_MSG(usbinfo
->usb
, usb_sndctrlpipe(usbinfo
->usb
, 0),
2821 DL_WRHW
, (USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
),
2822 1, 0, (char *)&hwacc
, sizeof(hwacc_t
), USB_CTRL_EP_TIMEOUT
);
2826 DBUSERR((" Ctrl write hwacc failed w/status %d @ address:%x \n",
2827 status
, hwacc
.addr
));
2831 hwacc
.addr
+= write_bytes
;
2832 data
+= write_bytes
;
2833 size
-= write_bytes
;
2842 dbus_usbos_readreg(void *bus
, uint32 regaddr
, int datalen
, uint32
*value
)
2844 usbos_info_t
*usbinfo
= (usbos_info_t
*) bus
;
2848 uint16 size
= sizeof(hwacc_t
);
2852 else if (datalen
== 2)
2857 if (usbinfo
== NULL
)
2860 if (usbinfo
->ctl_urb
== NULL
)
2863 usbinfo
->ctl_urb
->transfer_buffer_length
= size
;
2865 usbinfo
->ctl_read
.bRequestType
= USB_DIR_IN
| USB_TYPE_VENDOR
|
2866 USB_RECIP_INTERFACE
;
2867 usbinfo
->ctl_read
.bRequest
= cmd
;
2868 usbinfo
->ctl_read
.wLength
= htol16(size
);
2869 usbinfo
->ctl_read
.wValue
= htol16(regaddr
& 0xFFFF);
2870 usbinfo
->ctl_read
.wIndex
= htol16(regaddr
>> 16);
2872 #ifdef USB_SYNC_CTRL_URB
2873 ret
= USB_CONTROL_MSG(usbinfo
->usb
, usb_rcvctrlpipe(usbinfo
->usb
, 0),
2874 usbinfo
->ctl_read
.bRequest
, usbinfo
->ctl_read
.bRequestType
,
2875 usbinfo
->ctl_read
.wValue
, usbinfo
->ctl_read
.wIndex
,
2876 (void *) &hwacc
, usbinfo
->ctl_read
.wLength
, USB_CTRL_EP_TIMEOUT
);
2879 *value
= hwacc
.data
;
2883 usb_fill_control_urb(usbinfo
->ctl_urb
,
2885 usb_rcvctrlpipe(usbinfo
->usb
, 0),
2886 (unsigned char *) &usbinfo
->ctl_read
,
2887 (void *) &hwacc
, size
, (usb_complete_t
)dbus_usbos_sync_complete
, usbinfo
);
2889 ret
= USB_SUBMIT_URB(usbinfo
->ctl_urb
);
2891 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__
, ret
));
2895 ret
= dbus_usbos_sync_wait(usbinfo
, USB_SYNC_WAIT_TIMEOUT
);
2897 if (ret
== DBUS_OK
) {
2898 *value
= hwacc
.data
;
2901 #endif /* USB_SYNC_CTRL_URB */
2906 #ifndef LINUX_POSTMOGRIFY_REMOVAL
2908 dbus_usbos_writereg(void *bus
, uint32 regaddr
, int datalen
, uint32 data
)
2910 usbos_info_t
*usbinfo
= (usbos_info_t
*) bus
;
2912 uint32 cmd
= DL_WRHW
;
2914 uint16 size
= sizeof(hwacc_t
);
2916 if (usbinfo
== NULL
)
2919 if (usbinfo
->ctl_urb
== NULL
)
2922 hwacc
.cmd
= DL_WRHW
;
2923 hwacc
.addr
= regaddr
;
2925 hwacc
.len
= datalen
;
2927 usbinfo
->ctl_urb
->transfer_buffer_length
= size
;
2929 usbinfo
->ctl_write
.bRequestType
= USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
;
2930 usbinfo
->ctl_write
.bRequest
= cmd
;
2931 usbinfo
->ctl_write
.wLength
= htol16(size
);
2932 usbinfo
->ctl_write
.wValue
= htol16(1);
2933 usbinfo
->ctl_write
.wIndex
= htol16(0);
2935 #ifdef USB_SYNC_CTRL_URB
2936 ret
= USB_CONTROL_MSG(usbinfo
->usb
, usb_sndctrlpipe(usbinfo
->usb
, 0),
2937 usbinfo
->ctl_write
.bRequest
, usbinfo
->ctl_write
.bRequestType
,
2938 usbinfo
->ctl_write
.wValue
, usbinfo
->ctl_write
.wIndex
,
2939 (void *) &hwacc
, usbinfo
->ctl_write
.wLength
, USB_CTRL_EP_TIMEOUT
);
2942 DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__
, ret
));
2947 usb_fill_control_urb(usbinfo
->ctl_urb
,
2949 usb_sndctrlpipe(usbinfo
->usb
, 0),
2950 (unsigned char *) &usbinfo
->ctl_write
,
2951 (void *) &hwacc
, size
, (usb_complete_t
)dbus_usbos_sync_complete
, usbinfo
);
2953 ret
= USB_SUBMIT_URB(usbinfo
->ctl_urb
);
2955 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__
, ret
));
2959 ret
= dbus_usbos_sync_wait(usbinfo
, USB_SYNC_WAIT_TIMEOUT
);
2960 #endif /* USB_SYNC_CTRL_URB */
2965 #endif /* LINUX_POSTMOGRIFY_REMOVAL */
2968 dbus_usbos_wait(usbos_info_t
*usbinfo
, uint16 ms
)
2970 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
2974 msleep_interruptible(ms
);
2981 /** Called by dbus_usb.c as part of the firmware download process */
2983 dbus_usbos_dl_send_bulk(usbos_info_t
*usbinfo
, void *buffer
, int len
)
2987 #ifdef EHCI_FASTPATH_TX
2988 struct ehci_qtd
*qtd
= optimize_ehci_qtd_alloc(GFP_KERNEL
);
2989 int token
= EHCI_QTD_SET_CERR(3);
2994 optimize_qtd_fill_with_data(usbinfo
->pub
, 0, qtd
, buffer
, token
, len
);
2995 optimize_submit_async(qtd
, 0);
2997 if (usbinfo
== NULL
)
3000 if (usbinfo
->blk_urb
== NULL
)
3003 /* Prepare the URB */
3004 usb_fill_bulk_urb(usbinfo
->blk_urb
, usbinfo
->usb
, usbinfo
->tx_pipe
, buffer
,
3005 len
, (usb_complete_t
)dbus_usbos_sync_complete
, usbinfo
);
3007 usbinfo
->blk_urb
->transfer_flags
|= URB_QUEUE_BULK
;
3009 if ((ret
= USB_SUBMIT_URB(usbinfo
->blk_urb
))) {
3010 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__
, ret
));
3013 #endif /* EHCI_FASTPATH_TX */
3015 ret
= dbus_usbos_sync_wait(usbinfo
, USB_SYNC_WAIT_TIMEOUT
);
3017 return (ret
== DBUS_OK
);
3023 dbus_usbos_intf_recv_needed(void *bus
)
3029 * Higher layer (dbus_usb.c) wants to execute a function on the condition that the rx spin lock has
3033 dbus_usbos_intf_exec_rxlock(void *bus
, exec_cb_t cb
, struct exec_parms
*args
)
3035 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
3037 unsigned long flags
;
3039 if (usbos_info
== NULL
)
3042 spin_lock_irqsave(&usbos_info
->rxlock
, flags
);
3044 spin_unlock_irqrestore(&usbos_info
->rxlock
, flags
);
3050 dbus_usbos_intf_exec_txlock(void *bus
, exec_cb_t cb
, struct exec_parms
*args
)
3052 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
3054 unsigned long flags
;
3056 if (usbos_info
== NULL
)
3059 spin_lock_irqsave(&usbos_info
->txlock
, flags
);
3061 spin_unlock_irqrestore(&usbos_info
->txlock
, flags
);
3067 * if an error condition was detected in this module, the higher DBUS layer (dbus_usb.c) has to
3071 dbus_usbos_errhandler(void *bus
, int err
)
3073 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
3075 if (usbos_info
== NULL
)
3078 if (usbos_info
->cbarg
&& usbos_info
->cbs
) {
3079 if (usbos_info
->cbs
->errhandler
)
3080 usbos_info
->cbs
->errhandler(usbos_info
->cbarg
, err
);
3087 * if a change in bus state was detected in this module, the higher DBUS layer (dbus_usb.c) has to
3091 dbus_usbos_state_change(void *bus
, int state
)
3093 usbos_info_t
*usbos_info
= (usbos_info_t
*) bus
;
3095 if (usbos_info
== NULL
)
3098 if (usbos_info
->cbarg
&& usbos_info
->cbs
) {
3099 if (usbos_info
->cbs
->state_change
)
3100 usbos_info
->cbs
->state_change(usbos_info
->cbarg
, state
);
3103 usbos_info
->pub
->busstate
= state
;
3108 dbus_bus_osl_register(int vid
, int pid
, probe_cb_t prcb
,
3109 disconnect_cb_t discb
, void *prarg
, dbus_intf_t
**intf
, void *param1
, void *param2
)
3111 bzero(&g_probe_info
, sizeof(probe_info_t
));
3114 disconnect_cb
= discb
;
3117 devid_table
[0].idVendor
= vid
;
3118 devid_table
[0].idProduct
= pid
;
3120 *intf
= &dbus_usbos_intf
;
3124 return DBUS_ERR_NODEVICE
;
3128 dbus_bus_osl_deregister()
3130 g_probe_info
.dereged
= TRUE
;
3132 if (disconnect_cb
&& disc_arg
&& (g_probe_info
.disc_cb_done
== FALSE
)) {
3133 disconnect_cb(disc_arg
);
3143 dbus_usbos_intf_attach(dbus_pub_t
*pub
, void *cbarg
, dbus_intf_callbacks_t
*cbs
)
3145 usbos_info_t
*usbos_info
;
3147 if (g_probe_info
.dldone
== FALSE
) {
3148 DBUSERR(("%s: err device not downloaded!\n", __FUNCTION__
));
3152 /* Sanity check for BUS_INFO() */
3153 ASSERT(OFFSETOF(usbos_info_t
, pub
) == 0);
3155 usbos_info
= MALLOC(pub
->osh
, sizeof(usbos_info_t
));
3156 if (usbos_info
== NULL
)
3159 bzero(usbos_info
, sizeof(usbos_info_t
));
3161 usbos_info
->pub
= pub
;
3162 usbos_info
->cbarg
= cbarg
;
3163 usbos_info
->cbs
= cbs
;
3165 /* Needed for disconnect() */
3166 g_probe_info
.usbos_info
= usbos_info
;
3168 /* Update USB Info */
3169 usbos_info
->usb
= g_probe_info
.usb
;
3170 usbos_info
->rx_pipe
= g_probe_info
.rx_pipe
;
3171 usbos_info
->rx_pipe2
= g_probe_info
.rx_pipe2
;
3172 usbos_info
->tx_pipe
= g_probe_info
.tx_pipe
;
3173 usbos_info
->intr_pipe
= g_probe_info
.intr_pipe
;
3174 usbos_info
->intr_size
= g_probe_info
.intr_size
;
3175 usbos_info
->interval
= g_probe_info
.interval
;
3176 usbos_info
->pub
->device_speed
= g_probe_info
.device_speed
;
3177 if (usbos_info
->rx_pipe2
) {
3178 usbos_info
->pub
->attrib
.has_2nd_bulk_in_ep
= 1;
3180 usbos_info
->pub
->attrib
.has_2nd_bulk_in_ep
= 0;
3183 if (usbos_info
->tx_pipe
)
3184 usbos_info
->maxps
= usb_maxpacket(usbos_info
->usb
,
3185 usbos_info
->tx_pipe
, usb_pipeout(usbos_info
->tx_pipe
));
3187 INIT_LIST_HEAD(&usbos_info
->req_rxfreeq
);
3188 INIT_LIST_HEAD(&usbos_info
->req_txfreeq
);
3189 INIT_LIST_HEAD(&usbos_info
->req_rxpostedq
);
3190 INIT_LIST_HEAD(&usbos_info
->req_txpostedq
);
3191 spin_lock_init(&usbos_info
->rxfree_lock
);
3192 spin_lock_init(&usbos_info
->txfree_lock
);
3193 spin_lock_init(&usbos_info
->rxposted_lock
);
3194 spin_lock_init(&usbos_info
->txposted_lock
);
3195 spin_lock_init(&usbos_info
->rxlock
);
3196 spin_lock_init(&usbos_info
->txlock
);
3198 atomic_set(&usbos_info
->rxposted
, 0);
3199 atomic_set(&usbos_info
->txposted
, 0);
3201 #ifdef DBUS_LINUX_RXDPC
3202 INIT_LIST_HEAD(&usbos_info
->req_rxpendingq
);
3203 spin_lock_init(&usbos_info
->rxpending_lock
);
3204 #endif /* DBUS_LINUX_RXDPC */
3206 #if defined(DBUS_LINUX_HIST)
3207 usbos_info
->txposted_hist
= MALLOC(pub
->osh
, (usbos_info
->pub
->ntxq
+1) * sizeof(int));
3208 if (usbos_info
->txposted_hist
) {
3209 bzero(usbos_info
->txposted_hist
, (usbos_info
->pub
->ntxq
+1) * sizeof(int));
3211 usbos_info
->rxposted_hist
= MALLOC(pub
->osh
, (usbos_info
->pub
->nrxq
+1) * sizeof(int));
3212 if (usbos_info
->rxposted_hist
) {
3213 bzero(usbos_info
->rxposted_hist
, (usbos_info
->pub
->nrxq
+1) * sizeof(int));
3216 #ifdef USB_DISABLE_INT_EP
3217 usbos_info
->intr_urb
= NULL
;
3219 if (!(usbos_info
->intr_urb
= USB_ALLOC_URB())) {
3220 DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__
));
3225 if (!(usbos_info
->ctl_urb
= USB_ALLOC_URB())) {
3226 DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__
));
3230 if (!(usbos_info
->ctl_tx_urb
= USB_ALLOC_URB())) {
3231 DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__
));
3235 init_waitqueue_head(&usbos_info
->wait
);
3237 if (!(usbos_info
->blk_urb
= USB_ALLOC_URB())) { /* for embedded image downloading */
3238 DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__
));
3242 usbos_info
->rxbuf_len
= (uint
)usbos_info
->pub
->rxsize
;
3245 #ifdef DBUS_LINUX_RXDPC /* Initialize DPC thread */
3246 sema_init(&usbos_info
->dpc_sem
, 0);
3247 init_completion(&usbos_info
->dpc_exited
);
3248 usbos_info
->dpc_pid
= kernel_thread(dbus_usbos_dpc_thread
, usbos_info
, 0);
3249 if (usbos_info
->dpc_pid
< 0) {
3250 DBUSERR(("%s: failed to create dpc thread\n", __FUNCTION__
));
3253 #endif /* DBUS_LINUX_RXDPC */
3255 atomic_set(&usbos_info
->txallocated
, 0);
3256 if (DBUS_OK
!= dbus_usbos_urbreqs_alloc(usbos_info
,
3257 usbos_info
->pub
->ntxq
, FALSE
)) {
3261 atomic_set(&usbos_info
->rxallocated
, 0);
3262 if (DBUS_OK
!= dbus_usbos_urbreqs_alloc(usbos_info
,
3264 usbos_info
->pub
->nrxq
,
3266 MIN(DBUS_USB_RXQUEUE_BATCH_ADD
, usbos_info
->pub
->nrxq
),
3273 if (dbus_usbos_thread_init(usbos_info
) == NULL
)
3275 #endif /* USBOS_THREAD */
3277 #ifdef USBOS_TX_THREAD
3278 if (dbus_usbos_tx_thread_init(usbos_info
) == NULL
)
3280 #endif /* USBOS_TX_THREAD */
3282 pub
->dev_info
= g_probe_info
.usb
;
3284 #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX)
3285 spin_lock_init(&usbos_info
->fastpath_lock
);
3286 if (optimize_init(usbos_info
, usbos_info
->usb
, usbos_info
->tx_pipe
,
3287 usbos_info
->rx_pipe
, usbos_info
->rx_pipe2
) != 0) {
3288 DBUSERR(("%s: optimize_init failed!\n", __FUNCTION__
));
3292 #endif /* EHCI_FASTPATH_TX || EHCI_FASTPATH_RX */
3294 return (void *) usbos_info
;
3296 #ifdef DBUS_LINUX_RXDPC
3297 if (usbos_info
->dpc_pid
>= 0) {
3298 KILL_PROC(usbos_info
->dpc_pid
, SIGTERM
);
3299 wait_for_completion(&usbos_info
->dpc_exited
);
3301 #endif /* DBUS_LINUX_RXDPC */
3302 if (usbos_info
->intr_urb
) {
3303 USB_FREE_URB(usbos_info
->intr_urb
);
3304 usbos_info
->intr_urb
= NULL
;
3307 if (usbos_info
->ctl_urb
) {
3308 USB_FREE_URB(usbos_info
->ctl_urb
);
3309 usbos_info
->ctl_urb
= NULL
;
3312 if (usbos_info
->ctl_tx_urb
) {
3313 USB_FREE_URB(usbos_info
->ctl_tx_urb
);
3314 usbos_info
->ctl_tx_urb
= NULL
;
3317 #if defined(BCM_REQUEST_FW)
3318 if (usbos_info
->blk_urb
) {
3319 USB_FREE_URB(usbos_info
->blk_urb
);
3320 usbos_info
->blk_urb
= NULL
;
3324 dbus_usbos_urbreqs_free(usbos_info
, TRUE
);
3325 atomic_set(&usbos_info
->rxallocated
, 0);
3326 dbus_usbos_urbreqs_free(usbos_info
, FALSE
);
3327 atomic_set(&usbos_info
->txallocated
, 0);
3329 g_probe_info
.usbos_info
= NULL
;
3331 MFREE(pub
->osh
, usbos_info
, sizeof(usbos_info_t
));
3337 dbus_usbos_intf_detach(dbus_pub_t
*pub
, void *info
)
3339 usbos_info_t
*usbos_info
= (usbos_info_t
*) info
;
3340 osl_t
*osh
= pub
->osh
;
3342 if (usbos_info
== NULL
) {
3346 #ifdef USBOS_TX_THREAD
3347 dbus_usbos_tx_thread_deinit(usbos_info
);
3348 #endif /* USBOS_TX_THREAD */
3350 #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX)
3351 optimize_deinit(usbos_info
, usbos_info
->usb
);
3353 /* Must unlink all URBs prior to driver unload;
3354 * otherwise an URB callback can occur after driver
3355 * has been de-allocated and rmmod'd
3357 dbusos_stop(usbos_info
);
3359 if (usbos_info
->intr_urb
) {
3360 USB_FREE_URB(usbos_info
->intr_urb
);
3361 usbos_info
->intr_urb
= NULL
;
3364 if (usbos_info
->ctl_urb
) {
3365 USB_FREE_URB(usbos_info
->ctl_urb
);
3366 usbos_info
->ctl_urb
= NULL
;
3369 if (usbos_info
->ctl_tx_urb
) {
3370 USB_FREE_URB(usbos_info
->ctl_tx_urb
);
3371 usbos_info
->ctl_tx_urb
= NULL
;
3374 if (usbos_info
->blk_urb
) {
3375 USB_FREE_URB(usbos_info
->blk_urb
);
3376 usbos_info
->blk_urb
= NULL
;
3379 dbus_usbos_urbreqs_free(usbos_info
, TRUE
);
3380 atomic_set(&usbos_info
->rxallocated
, 0);
3381 dbus_usbos_urbreqs_free(usbos_info
, FALSE
);
3382 atomic_set(&usbos_info
->txallocated
, 0);
3384 #if defined(DBUS_LINUX_HIST)
3385 if (usbos_info
->txposted_hist
) {
3386 MFREE(osh
, usbos_info
->txposted_hist
, (usbos_info
->pub
->ntxq
+1) * sizeof(int));
3388 if (usbos_info
->rxposted_hist
) {
3389 MFREE(osh
, usbos_info
->rxposted_hist
, (usbos_info
->pub
->nrxq
+1) * sizeof(int));
3393 dbus_usbos_thread_deinit(usbos_info
);
3394 #endif /* USBOS_THREAD */
3396 g_probe_info
.usbos_info
= NULL
;
3397 MFREE(osh
, usbos_info
, sizeof(usbos_info_t
));
3401 #ifdef USBOS_TX_THREAD
3403 dbus_usbos_tx_thread_init(usbos_info_t
*usbos_info
)
3405 spin_lock_init(&usbos_info
->usbos_tx_list_lock
);
3406 INIT_LIST_HEAD(&usbos_info
->usbos_tx_list
);
3407 init_waitqueue_head(&usbos_info
->usbos_tx_queue_head
);
3409 usbos_info
->usbos_tx_kt
= kthread_create(dbus_usbos_tx_thread_func
,
3410 usbos_info
, "usb-tx-thread");
3412 if (IS_ERR(usbos_info
->usbos_tx_kt
)) {
3413 DBUSERR(("Thread Creation failed\n"));
3417 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_UNSCHEDULED
;
3418 wake_up_process(usbos_info
->usbos_tx_kt
);
3420 return (usbos_info
->usbos_tx_kt
);
3424 dbus_usbos_tx_thread_deinit(usbos_info_t
*usbos_info
)
3428 if (usbos_info
->usbos_tx_kt
) {
3429 wake_up_interruptible(&usbos_info
->usbos_tx_queue_head
);
3430 kthread_stop(usbos_info
->usbos_tx_kt
);
3433 /* Move pending requests to free queue so they can be freed */
3434 while ((req
= dbus_usbos_qdeq(
3435 &usbos_info
->usbos_tx_list
, &usbos_info
->usbos_tx_list_lock
)) != NULL
) {
3436 dbus_usbos_qenq(&usbos_info
->req_txfreeq
, req
, &usbos_info
->txfree_lock
);
3441 * Allow USB in-band resume to block by submitting CTRL and DATA URBs in a separate thread.
3444 dbus_usbos_tx_thread_func(void *data
)
3446 usbos_info_t
*usbos_info
= (usbos_info_t
*)data
;
3448 dbus_irb_tx_t
*txirb
;
3450 unsigned long flags
;
3452 #ifdef WL_THREADNICE
3453 set_user_nice(current
, WL_THREADNICE
);
3457 /* Wait until there are URBs to submit */
3458 wait_event_interruptible_timeout(
3459 usbos_info
->usbos_tx_queue_head
,
3460 !list_empty(&usbos_info
->usbos_tx_list
) ||
3461 usbos_info
->ctl_state
== USBOS_REQUEST_STATE_SCHEDULED
,
3464 if (kthread_should_stop())
3467 /* Submit CTRL URB if needed */
3468 if (usbos_info
->ctl_state
== USBOS_REQUEST_STATE_SCHEDULED
) {
3470 /* Increment the interface PM usage counter. If the interface was
3471 * suspended, this call blocks until it has been resumed.
3473 USB_AUTOPM_GET_INTERFACE(g_probe_info
.intf
);
3475 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_SUBMITTED
;
3477 ret
= USB_SUBMIT_URB(usbos_info
->ctl_tx_urb
);
3479 DBUSERR(("%s CTRL USB_SUBMIT_URB failed, status %d\n",
3480 __FUNCTION__
, ret
));
3482 usbos_info
->ctl_state
= USBOS_REQUEST_STATE_UNSCHEDULED
;
3484 /* Enable USB autosuspend if no packets are being sent */
3485 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info
.intf
);
3489 /* Submit all available TX URBs */
3490 while ((req
= dbus_usbos_qdeq(&usbos_info
->usbos_tx_list
,
3491 &usbos_info
->usbos_tx_list_lock
)) != NULL
) {
3493 /* Increment the interface PM usage counter. If the interface was
3494 * suspended, this call blocks until it has been resumed.
3496 USB_AUTOPM_GET_INTERFACE(g_probe_info
.intf
);
3498 spin_lock_irqsave(&usbos_info
->txlock
, flags
);
3500 ret
= USB_SUBMIT_URB(req
->urb
);
3502 /* URB submitted successfully */
3503 dbus_usbos_qenq(&usbos_info
->req_txpostedq
, req
,
3504 &usbos_info
->txposted_lock
);
3505 atomic_inc(&usbos_info
->txposted
);
3507 /* Submitting the URB failed. */
3508 DBUSERR(("%s TX USB_SUBMIT_URB failed, status %d\n",
3509 __FUNCTION__
, ret
));
3511 /* Enable USB autosuspend if no packets are being sent */
3512 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info
.intf
);
3515 spin_unlock_irqrestore(&usbos_info
->txlock
, flags
);
3518 /* Cleanup and notify higher layers */
3519 dbus_usbos_qenq(&usbos_info
->req_txfreeq
, req
,
3520 &usbos_info
->txfree_lock
);
3523 if (txirb
->send_buf
) {
3524 MFREE(usbos_info
->pub
->osh
, txirb
->send_buf
, req
->buf_len
);
3525 txirb
->send_buf
= NULL
;
3529 if (likely (usbos_info
->cbarg
&& usbos_info
->cbs
)) {
3530 if (likely (usbos_info
->cbs
->send_irb_complete
!= NULL
))
3531 usbos_info
->cbs
->send_irb_complete(
3532 usbos_info
->cbarg
, txirb
, DBUS_ERR_TXDROP
);
3540 #endif /* USBOS_TX_THREAD */
3544 * Increase system performance by creating a USB thread that runs parallel to other system
3548 dbus_usbos_thread_init(usbos_info_t
*usbos_info
)
3550 usbos_list_entry_t
*entry
;
3551 unsigned long flags
, ii
;
3553 spin_lock_init(&usbos_info
->usbos_list_lock
);
3554 spin_lock_init(&usbos_info
->ctrl_lock
);
3555 INIT_LIST_HEAD(&usbos_info
->usbos_list
);
3556 INIT_LIST_HEAD(&usbos_info
->usbos_free_list
);
3557 init_waitqueue_head(&usbos_info
->usbos_queue_head
);
3558 atomic_set(&usbos_info
->usbos_list_cnt
, 0);
3561 for (ii
= 0; ii
< (usbos_info
->pub
->nrxq
+ usbos_info
->pub
->ntxq
); ii
++) {
3562 entry
= MALLOC(usbos_info
->pub
->osh
, sizeof(usbos_list_entry_t
));
3564 spin_lock_irqsave(&usbos_info
->usbos_list_lock
, flags
);
3565 list_add_tail((struct list_head
*) entry
, &usbos_info
->usbos_free_list
);
3566 spin_unlock_irqrestore(&usbos_info
->usbos_list_lock
, flags
);
3568 DBUSERR(("Failed to create list\n"));
3572 usbos_info
->usbos_kt
= kthread_create(dbus_usbos_thread_func
,
3573 usbos_info
, "usb-thread");
3575 if (IS_ERR(usbos_info
->usbos_kt
)) {
3576 DBUSERR(("Thread Creation failed\n"));
3580 wake_up_process(usbos_info
->usbos_kt
);
3582 return (usbos_info
->usbos_kt
);
3587 dbus_usbos_thread_deinit(usbos_info_t
*usbos_info
)
3589 struct list_head
*cur
, *next
;
3590 usbos_list_entry_t
*entry
;
3591 unsigned long flags
;
3593 if (usbos_info
->usbos_kt
) {
3594 wake_up_interruptible(&usbos_info
->usbos_queue_head
);
3595 kthread_stop(usbos_info
->usbos_kt
);
3598 list_for_each_safe(cur
, next
, &usbos_info
->usbos_list
)
3600 entry
= list_entry(cur
, struct usbos_list_entry
, list
);
3601 /* detach this entry from the list and then free the entry */
3602 spin_lock_irqsave(&usbos_info
->usbos_list_lock
, flags
);
3604 MFREE(usbos_info
->pub
->osh
, entry
, sizeof(usbos_list_entry_t
));
3605 spin_unlock_irqrestore(&usbos_info
->usbos_list_lock
, flags
);
3608 list_for_each_safe(cur
, next
, &usbos_info
->usbos_free_list
)
3610 entry
= list_entry(cur
, struct usbos_list_entry
, list
);
3611 /* detach this entry from the list and then free the entry */
3612 spin_lock_irqsave(&usbos_info
->usbos_list_lock
, flags
);
3614 MFREE(usbos_info
->pub
->osh
, entry
, sizeof(usbos_list_entry_t
));
3615 spin_unlock_irqrestore(&usbos_info
->usbos_list_lock
, flags
);
3619 /** Process completed URBs in a worker thread */
3621 dbus_usbos_thread_func(void *data
)
3623 usbos_info_t
*usbos_info
= (usbos_info_t
*)data
;
3624 usbos_list_entry_t
*entry
;
3625 struct list_head
*cur
, *next
;
3626 unsigned long flags
;
3628 #ifdef WL_THREADNICE
3629 set_user_nice(current
, WL_THREADNICE
);
3633 /* If the list is empty, then go to sleep */
3634 wait_event_interruptible_timeout
3635 (usbos_info
->usbos_queue_head
,
3636 atomic_read(&usbos_info
->usbos_list_cnt
) > 0,
3639 if (kthread_should_stop())
3642 spin_lock_irqsave(&usbos_info
->usbos_list_lock
, flags
);
3644 /* For each entry on the list, process it. Remove the entry from
3645 * the list when done.
3647 list_for_each_safe(cur
, next
, &usbos_info
->usbos_list
)
3652 usbos_info_t
*usbos_info
;
3654 entry
= list_entry(cur
, struct usbos_list_entry
, list
);
3658 req
= entry
->urb_context
;
3659 len
= entry
->urb_length
;
3660 stat
= entry
->urb_status
;
3661 usbos_info
= req
->usbinfo
;
3663 /* detach this entry from the list and attach it to the free list */
3665 spin_unlock_irqrestore(&usbos_info
->usbos_list_lock
, flags
);
3667 dbus_usbos_recv_complete_handle(req
, len
, stat
);
3669 spin_lock_irqsave(&usbos_info
->usbos_list_lock
, flags
);
3671 list_add_tail(cur
, &usbos_info
->usbos_free_list
);
3673 atomic_dec(&usbos_info
->usbos_list_cnt
);
3676 spin_unlock_irqrestore(&usbos_info
->usbos_list_lock
, flags
);
3683 /* Called on Linux calling URB callback, see dbus_usbos_recv_complete() */
3685 dbus_usbos_dispatch_schedule(CALLBACK_ARGS
)
3687 urb_req_t
*req
= urb
->context
;
3688 usbos_info_t
*usbos_info
= req
->usbinfo
;
3689 usbos_list_entry_t
*entry
;
3690 unsigned long flags
;
3691 struct list_head
*cur
;
3693 spin_lock_irqsave(&usbos_info
->usbos_list_lock
, flags
);
3695 cur
= usbos_info
->usbos_free_list
.next
;
3696 entry
= list_entry(cur
, struct usbos_list_entry
, list
);
3698 /* detach this entry from the free list and prepare it insert it to use list */
3702 entry
->urb_context
= urb
->context
;
3703 entry
->urb_length
= urb
->actual_length
;
3704 entry
->urb_status
= urb
->status
;
3706 atomic_inc(&usbos_info
->usbos_list_cnt
);
3707 list_add_tail(cur
, &usbos_info
->usbos_list
);
3710 DBUSERR(("!!!!!!OUT OF MEMORY!!!!!!!\n"));
3713 spin_unlock_irqrestore(&usbos_info
->usbos_list_lock
, flags
);
3716 wake_up_interruptible(&usbos_info
->usbos_queue_head
);
3720 #endif /* USBOS_THREAD */
3722 #ifdef USB_TRIGGER_DEBUG
3724 dbus_usbos_ctl_send_debugtrig(usbos_info_t
* usbinfo
)
3728 if (usbinfo
== NULL
)
3733 dbus_usbos_dl_cmd(usbinfo
, DL_DBGTRIG
, &id
, sizeof(bootrom_id_t
));
3735 /* ignore the result for now */
3738 #endif /* USB_TRIGGER_DEBUG */
3741 #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX)
3742 /** New optimized code for USB AP */
3743 void inline optimize_ehci_qtd_init(struct ehci_qtd
*qtd
, dma_addr_t dma
)
3745 memset(qtd
, 0, sizeof(*qtd
));
3747 qtd
->qtd_self
= dma
;
3748 qtd
->qtd_status
= cpu_to_le32(EHCI_QTD_HALTED
);
3749 qtd
->qtd_next
= EHCI_NULL
;
3750 qtd
->qtd_altnext
= EHCI_NULL
;
3751 qtd
->obj_next
= NULL
;
3753 /* qtd->buff = NULL; */
3754 qtd
->xacterrs
= EHCI_QTD_XACTERR_MAX
;
3758 struct ehci_qtd
*optimize_ehci_qtd_alloc(gfp_t flags
)
3760 struct ehci_qtd
*qtd
;
3763 usbos_info_t
*usbos_info
= g_probe_info
.usbos_info
;
3765 struct dma_pool
*pool
= usbos_info
->qtd_pool
;
3767 qtd
= dma_pool_alloc(pool
, flags
, &dma
);
3769 optimize_ehci_qtd_init(qtd
, dma
);
3774 void optimize_ehci_qtd_free(struct ehci_qtd
*qtd
)
3776 usbos_info_t
*usbos_info
= g_probe_info
.usbos_info
;
3777 struct dma_pool
*pool
= usbos_info
->qtd_pool
;
3778 dma_pool_free(pool
, qtd
, qtd
->qtd_self
);
3782 * Loosely follows qtd_copy_status
3783 * Greatly simplified as there are only three options: normal, short read, and disaster
3785 static int BCMFASTPATH
get_qtd_status(struct ehci_qtd
*qtd
, int token
, int *actual_length
)
3787 int status
= -EINPROGRESS
;
3789 *actual_length
+= qtd
->length
- EHCI_QTD_GET_BYTES(token
);
3791 /* Short read is not an error */
3792 if (unlikely (SHORT_READ_Q (token
)))
3793 status
= -EREMOTEIO
;
3795 /* Check for serious problems */
3796 if (token
& EHCI_QTD_HALTED
) {
3798 if (token
& (EHCI_QTD_BABBLE
| EHCI_QTD_MISSEDMICRO
| EHCI_QTD_BUFERR
|
3800 printk("EHCI Fastpath: Serious USB issue qtd %p token %08x --> status %d\n",
3801 qtd
, token
, status
);
3808 static void dump_qtd(struct ehci_qtd
*qtd
)
3810 printk("qtd_next %08x qtd_altnext %08x qtd_status %08x\n", qtd
->qtd_next
,
3811 qtd
->qtd_altnext
, qtd
->qtd_status
);
3814 static void dump_qh(struct ehci_qh
*qh
)
3816 struct ehci_qtd
*qtd
= (struct ehci_qtd
*)(qh
->qh_curqtd
| 0xa0000000);
3817 printk("EHCI Fastpath: QH %p Dump\n", qh
);
3818 printk("qtd_next %08x info1 %08x info2 %08x current %08x\n", qh
->qh_link
, qh
->qh_endp
,
3819 qh
->qh_endphub
, qh
->qh_curqtd
);
3820 printk("overlay\n");
3821 dump_qtd((struct ehci_qtd
*)&qh
->ow_next
);
3822 while ((((int)qtd
)&EHCI_NULL
) == 0)
3824 printk("QTD %p\n", qtd
);
3825 dump_qtd((struct ehci_qtd
*)qtd
);
3826 qtd
= (struct ehci_qtd
*)(qtd
->qtd_next
| 0xa0000000);
3832 * This code assumes the caller holding a lock
3833 * It is currently called from scan_async that should have the lock
3834 * Lock shall be dropped around the actual completion, then reacquired
3835 * This is a clean implementation of the qh_completions()
3837 static void BCMFASTPATH
ehci_bypass_callback(int pipeindex
, struct ehci_qh
*qh
, spinlock_t
*lock
)
3839 /* Loop variables */
3840 struct ehci_qtd
*qtd
, /* current QTD */
3841 *end
= qh
->dummy
, /* "afterend" */
3845 usbos_info_t
*usbos_info
= g_probe_info
.usbos_info
;
3847 /* printk("EHCI Fastpath: callback pipe %d QH %p lock %p\n", pipeindex, qh, lock); */
3850 * This code should not require any interlocking with QTD additions
3851 * The additions never touch QH, we should never touch 'end'
3852 * Note that QTD additions will keep 'end' in place
3854 for (qtd
= qh
->first_qtd
; qtd
!= end
; qtd
= next
)
3856 u32 status
; /* Status bits from QTD */
3858 /* Get the status bits from the QTD */
3860 status
= hc32_to_cpu(qtd
->qtd_status
);
3862 if ((status
& EHCI_QTD_ACTIVE
) == 0) {
3863 if (unlikely((status
& EHCI_QTD_HALTED
) != 0)) {
3864 /* Retry transaction errors until we
3865 * reach the software xacterr limit
3867 if ((status
& EHCI_QTD_XACTERR
) &&
3868 EHCI_QTD_GET_CERR(status
) == 0 &&
3869 --qtd
->xacterrs
> 0) {
3870 /* Reset the token in the qtd and the
3871 * qh overlay (which still contains
3872 * the qtd) so that we pick up from
3875 printk("EHCI Fastpath: detected XactErr "
3876 "qtd %p len %d/%d retry %d\n",
3877 qtd
, qtd
->length
- EHCI_QTD_GET_BYTES(status
),
3879 EHCI_QTD_XACTERR_MAX
- qtd
->xacterrs
);
3881 status
&= ~EHCI_QTD_HALTED
;
3882 status
|= EHCI_QTD_ACTIVE
| EHCI_QTD_SET_CERR(3);
3883 qtd
->qtd_status
= cpu_to_le32(status
);
3885 qh
->ow_status
= cpu_to_le32(status
);
3890 /* QTD processing was aborted - highly unlikely (never seen, so not
3891 * tested). In very new 2.6, we can retry. In 2.4 and older 2.6,
3892 * life sucks (the USB stack does the same)
3894 printk("EHCI Fastpath: QTD halted\n");
3899 /* Inactive QTD is an afterend, finished the list */
3902 /* Remove the QTD from software QH. This should be done before dropping the lock
3903 * in for upper layer
3905 next
= qtd
->obj_next
;
3906 qh
->first_qtd
= next
;
3908 /* Upper layer processing. */
3909 if (EHCI_QTD_GET_PID(status
) == 0) /* OUT pipe */
3911 if (qtd
->rpc
== NULL
)
3913 usbos_info
->waitdone
= TRUE
;
3914 wake_up_interruptible(&usbos_info
->wait
);
3915 usbos_info
->sync_urb_status
= 0;
3920 /* usb_info_t *usb_info = (usb_info_t *) handle; */
3921 usb_info_t
*usb_info
= (usb_info_t
*) usbos_info
->cbarg
;
3922 /* if(usb_info && usb_info->cbs && usb_info->cbs->send_irb_complete)
3923 * usb_info->cbs->send_irb_complete(usb_info->cbarg, txirb, status);
3926 dbus_info_t
*dbus_info
= (dbus_info_t
*)usb_info
->cbarg
;
3928 /* Free the coalesce buffer, if multi-buffer packet only. Do not
3929 * rely on buff, as it might not even exist
3931 if (PKTNEXT(usbos_info
->pub
->osh
, qtd
->rpc
)) {
3932 /* printk("k-Freeing %p\n", qtd->buff); */
3936 if (dbus_info
->cbs
&& dbus_info
->cbs
->send_complete
)
3938 atomic_dec(&s_tx_pending
);
3940 /* printk("Sending to RPC qtd %p\n", qtd); */
3941 #if !(defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) || defined(BCM_RPC_TOC))
3942 #error Configuration not supported; read dbus_if_send_irb_complete for guidelines
3944 dbus_info
->cbs
->send_complete(dbus_info
->cbarg
, qtd
->rpc
,
3946 if ((atomic_read(&s_tx_pending
) < 16) &&
3947 dbus_info
->txoff
&& !dbus_info
->txoverride
) {
3948 dbus_flowctrl_tx(dbus_info
, OFF
);
3952 /* Things could have happened while the lock was gone,
3953 * resync to the hardware
3955 next
= qh
->first_qtd
;
3960 optimize_ehci_qtd_free(qtd
);
3964 /* Simulates the upstream travel */
3965 usb_info_t
*usb_info
= (usb_info_t
*) usbos_info
->cbarg
;
3966 dbus_info_t
*dbus_info
= (dbus_info_t
*)usb_info
->cbarg
;
3967 /* unsigned long flags; */
3968 int actual_length
= 0;
3970 /* All our reads must be short */
3971 if (!SHORT_READ_Q (status
)) ASSERT(0);
3973 /* Done with hardware, convert status to error codes */
3974 status
= get_qtd_status(qtd
, status
, &actual_length
);
3984 case -ECONNRESET
: /* canceled */
3987 DBUSERR(("%s: ehci unlink. status %x\n", __FUNCTION__
, status
));
3991 if (g_probe_info
.dereged
) {
3992 printk("%s: DBUS deregistering, ignoring recv callback\n",
3998 usbos_info
->usb
->bus
->controller
,
3999 (dma_addr_t
)qtd
->qtd_buffer_hi
[0],
4004 if (dbus_info
->pub
.busstate
!= DBUS_STATE_DOWN
) {
4006 void *buf
= qtd
->rpc
;
4008 ASSERT(buf
!= NULL
);
4010 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
4011 /* Note that these ifdefs are indirectly coming from
4012 * dbus_usbos_recv_urb_submit The code itself is from
4013 * dbus_if_recv_irb_complete that makes the decision
4014 * at runtime, yet it is only pkt or buf depending on
4015 * the NOCOPY setup, never both :-)
4017 if (dbus_info
->cbs
&& dbus_info
->cbs
->recv_pkt
)
4018 dbus_info
->cbs
->recv_pkt(dbus_info
->cbarg
, buf
);
4020 if (actual_length
> 0) {
4021 if (dbus_info
->cbs
&& dbus_info
->cbs
->recv_buf
)
4022 dbus_info
->cbs
->recv_buf(dbus_info
->cbarg
,
4023 buf
, actual_length
);
4028 /* Things could have happened while the lock was gone,
4029 * resync to the hardware
4031 next
= qh
->first_qtd
;
4034 /* Reinitialize this qtd since it will be reused. */
4035 optimize_ehci_qtd_init(qtd
, qtd
->qtd_self
);
4037 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
4038 /* Note that these ifdefs are coming from
4039 * dbus_usbos_recv_urb_submit. In the NOCOPY configuration,
4040 * force an allocation of a new packet
4042 optimize_submit_rx_request(&dbus_info
->pub
, 1, qtd
, NULL
);
4045 /* In the copy mode, simply reuse the buffer; upper level
4046 * had already consumed the data
4048 optimize_submit_rx_request(&dbus_info
->pub
, 1, qtd
, buf
);
4050 /* Not to free this qtd because it will be reused. */
4054 printk("%s: DBUS down, ignoring recv callback\n", __FUNCTION__
);
4056 optimize_ehci_qtd_free(qtd
);
4061 static void optimize_urb_callback(struct urb
*urb
)
4063 struct usb_ctrlrequest
*req
= urb
->context
;
4069 /* Shall be called under an external lock (currently RPC_TP_LOCK) */
4070 static int optimize_submit_urb(struct usb_device
*usb
, void *ptr
, int request
)
4072 struct usb_ctrlrequest
*req
;
4075 if ((urb
= USB_ALLOC_URB()) == NULL
) {
4076 printk("EHCI Fastpath: Error allocating URB in optimize_EP!");
4080 if ((req
= kmalloc(sizeof(struct usb_ctrlrequest
), GFP_ATOMIC
)) == NULL
) {
4081 printk("EHCI Fastpath: Failed to allocate memory for control request in"
4087 req
->bRequestType
= (USB_TYPE_VENDOR
| USB_RECIP_OTHER
);
4088 req
->bRequest
= request
;
4090 /* Use this instead of a buffer */
4091 req
->wValue
= ((int)ptr
& 0xffff);
4092 req
->wIndex
= ((((int)ptr
)>>16) & 0xffff);
4095 printk("EHCI Fastpath: usb_dev %p\n", usb
);
4096 printk("EHCI Fastpath: bus %p\n", usb
->bus
);
4097 printk("EHCI Fastpath: Hub %p\n", usb
->bus
->root_hub
);
4099 usb_fill_control_urb(
4102 usb_sndctrlpipe(usb
->bus
->root_hub
, 0),
4106 optimize_urb_callback
,
4109 USB_SUBMIT_URB(urb
);
4111 if (urb
->status
!= 0) {
4112 printk("EHCI Fastpath: Cannot submit URB in optimize_EP: %d\n", urb
->status
);
4118 static int epnum(int pipe
)
4120 int epn
= usb_pipeendpoint(pipe
);
4121 if (usb_pipein (pipe
))
4127 static int optimize_init(usbos_info_t
*usbos_info
, struct usb_device
*usb
, int out
, int in
, int in2
)
4129 int retval
= -EPIPE
;
4131 atomic_set(&s_tx_pending
, 0);
4132 /* atomic_set(&s_rx_pending, 0); */
4134 usbos_info
->tx_ep
= epnum(out
);
4135 usbos_info
->rx_ep
= epnum(in
);
4136 usbos_info
->rx2_ep
= epnum(in2
);
4137 usbos_info
->usb_device
= usb
;
4139 /* printk("EHCI Fastpath: Create pool %p %p %p\n", usb, usb->bus, usb->bus->controller); */
4141 /* QTDs for bulk transfers - separate pool */
4142 usbos_info
->qtd_pool
= dma_pool_create("usbnet_qtd",
4143 usb
->bus
->controller
,
4144 sizeof(struct ehci_qtd
),
4145 EHCI_QTD_ALIGN
/* byte alignment (for hw parts) */,
4146 4096 /* can't cross 4K */);
4147 if (!usbos_info
->qtd_pool
) {
4148 printk("EHCI Fastpath: Cannot create the QTD pool\n");
4152 /* detaching the EP */
4153 if (optimize_submit_urb(usb
, usb
, EHCI_SET_BYPASS_DEV
) != 0)
4155 optimize_submit_urb(usb
, ehci_bypass_callback
, EHCI_SET_BYPASS_CB
);
4156 optimize_submit_urb(usb
, usbos_info
->qtd_pool
, EHCI_SET_BYPASS_POOL
);
4157 #ifdef EHCI_FASTPATH_TX
4158 optimize_submit_urb(usb
, (void*)((0<<16)|usbos_info
->tx_ep
), EHCI_FASTPATH
);
4160 #ifdef EHCI_FASTPATH_RX
4161 optimize_submit_urb(usb
, (void*)((1<<16)|usbos_info
->rx_ep
), EHCI_FASTPATH
);
4164 /* getting the QH */
4165 printk("EHCI Fastpath: EP in %d EP in2 %d EP out %d\n", usbos_info
->rx_ep
,
4166 usbos_info
->rx2_ep
, usbos_info
->tx_ep
);
4174 static int optimize_deinit_qtds(struct ehci_qh
*qh
, int coalesce_buf
)
4176 usbos_info_t
*usbos_info
= g_probe_info
.usbos_info
;
4177 struct ehci_qtd
*qtd
, *end
, *next
;
4178 unsigned long flags
;
4185 printk("%s %d. qh = %p\n", __func__
, __LINE__
, qh
);
4187 spin_lock_irqsave(&usbos_info
->fastpath_lock
, flags
);
4188 for (qtd
= qh
->first_qtd
; qtd
!= end
; qtd
= next
) {
4189 next
= qtd
->obj_next
;
4190 qh
->first_qtd
= next
;
4192 /* Free the coalesce buffer, if multi-buffer packet only. Do not
4193 * rely on buff, as it might not even exist
4195 if (coalesce_buf
&& PKTNEXT(usbos_info
->pub
->osh
, qtd
->rpc
)) {
4196 printk("k-Freeing %p, ", qtd
->buff
);
4199 printk("freeing qtd %p\n", qtd
);
4201 optimize_ehci_qtd_free(qtd
);
4203 spin_unlock_irqrestore(&usbos_info
->fastpath_lock
, flags
);
4209 static BCMFASTPATH
struct ehci_qh
*get_ep(usbos_info_t
*usbos_info
, int ep
)
4212 struct usb_host_endpoint
*epp
= NULL
;
4215 case 0: epp
= usbos_info
->usb_device
->ep_out
[usbos_info
->tx_ep
&0xf]; break;
4216 case 1: epp
= usbos_info
->usb_device
->ep_in
[usbos_info
->rx_ep
&0xf]; break;
4217 case 2: epp
= usbos_info
->usb_device
->ep_in
[usbos_info
->rx2_ep
&0xf]; break;
4221 return (struct ehci_qh
*)epp
->hcpriv
;
4226 case 0: return (struct ehci_qh
*)(((struct hcd_dev
*)(usbos_info
->
4227 usb_device
->hcpriv
))->ep
[usbos_info
->tx_ep
]);
4228 case 1: return (struct ehci_qh
*)(((struct hcd_dev
*)(usbos_info
->
4229 usb_device
->hcpriv
))->ep
[usbos_info
->rx_ep
]);
4230 case 2: return (struct ehci_qh
*)(((struct hcd_dev
*)(usbos_info
->
4231 usb_device
->hcpriv
))->ep
[usbos_info
->rx2_ep
]);
4235 #endif /* KERNEL26 */
4238 int optimize_deinit(usbos_info_t
*usbos_info
, struct usb_device
*usb
)
4240 optimize_deinit_qtds(get_ep(usbos_info
, 0), 1);
4241 optimize_deinit_qtds(get_ep(usbos_info
, 1), 0);
4242 #if defined(EHCI_FASTPATH_TX) || defined(EHCI_FASTPATH_RX)
4243 optimize_submit_urb(usb
, (void *)0, EHCI_CLR_EP_BYPASS
);
4245 dma_pool_destroy(usbos_info
->qtd_pool
);
4249 /** Reassemble the segmented packet */
4250 static int BCMFASTPATH
optimize_gather(const dbus_pub_t
*pub
, void *pkt
, void **buf
)
4254 void *transfer_buf
= kmalloc(pkttotlen(pub
->osh
, pkt
),
4256 *buf
= transfer_buf
;
4258 if (!transfer_buf
) {
4259 printk("fail to alloc to usb buffer\n");
4264 int pktlen
= PKTLEN(pub
->osh
, pkt
);
4265 bcopy(PKTDATA(pub
->osh
, pkt
), transfer_buf
, pktlen
);
4266 transfer_buf
+= pktlen
;
4268 pkt
= PKTNEXT(pub
->osh
, pkt
);
4271 /* printk("Coalesced a %d-byte buffer\n", len); */
4276 int BCMFASTPATH
optimize_qtd_fill_with_rpc(const dbus_pub_t
*pub
, int epn
,
4277 struct ehci_qtd
*qtd
, void *rpc
, int token
, int len
)
4282 return optimize_qtd_fill_with_data(pub
, epn
, qtd
, data
, token
, len
);
4284 ASSERT(rpc
!= NULL
);
4285 data
= PKTDATA(pub
->osh
, rpc
);
4288 if (PKTNEXT(pub
->osh
, rpc
)) {
4289 len
= optimize_gather(pub
, rpc
, &data
);
4293 return optimize_qtd_fill_with_data(pub
, epn
, qtd
, data
, token
, len
);
4296 /** Fill the QTD from the data buffer */
4297 int BCMFASTPATH
optimize_qtd_fill_with_data(const dbus_pub_t
*pub
, int epn
,
4298 struct ehci_qtd
*qtd
, void *data
, int token
, int len
)
4300 int i
, bytes_fit
, page_offset
;
4301 dma_addr_t addr
= 0;
4303 /* struct usb_host_endpoint *ep = get_ep(epn); */
4304 usbos_info_t
*usbos_info
= g_probe_info
.usbos_info
;
4306 token
|= (EHCI_QTD_ACTIVE
| EHCI_QTD_IOC
); /* Allow execution, force interrupt */
4309 addr
= dma_map_single(
4310 usbos_info
->usb
->bus
->controller
,
4313 EHCI_QTD_GET_PID(token
) ? DMA_FROM_DEVICE
: DMA_TO_DEVICE
);
4316 qtd
->qtd_buffer
[0] = cpu_to_hc32((u32
)addr
);
4317 /* Here qtd->qtd_buffer_hi[0] is leveraged to store addr value, which
4318 * is needed when invoking dma_unmap_single() in ehci_bypass_callback().
4319 * This is valid for EHCI 32bit only.
4321 qtd
->qtd_buffer_hi
[0] = cpu_to_hc32((u32
)addr
);
4322 page_offset
= (addr
& (EHCI_PAGE_SIZE
-1));
4323 bytes_fit
= EHCI_PAGE_SIZE
- page_offset
;
4324 addr
-= page_offset
;
4325 if (len
< bytes_fit
)
4328 addr
+= EHCI_PAGE_SIZE
;
4330 for (i
= 1; bytes_fit
< len
&& i
< EHCI_QTD_NBUFFERS
; i
++) {
4331 qtd
->qtd_buffer
[i
] = cpu_to_hc32((u32
)addr
);
4332 qtd
->qtd_buffer_hi
[i
] = 0;
4333 addr
+= EHCI_PAGE_SIZE
;
4334 if ((bytes_fit
+ EHCI_PAGE_SIZE
) < len
)
4335 bytes_fit
+= EHCI_PAGE_SIZE
;
4340 if (bytes_fit
!= len
)
4345 qtd
->qtd_status
= cpu_to_hc32((bytes_fit
<< 16) | token
);
4346 qtd
->length
= bytes_fit
;
4352 /** Reimplementation of qh_append_tds()
4353 * Returns nonzero if too many requests pending
4355 int BCMFASTPATH
optimize_submit_async(struct ehci_qtd
*qtd
, int epn
)
4357 /* Clean implementation along the lines of qh_append_tds() */
4359 struct ehci_qtd
*afterend
; /* Element at the end of the QTD chain (after the
4360 * last useful one, "after-end")
4364 unsigned long flags
;
4366 usbos_info_t
*usbos_info
= g_probe_info
.usbos_info
;
4367 struct ehci_qh
*qh
= get_ep(usbos_info
, epn
);
4368 usb_info_t
*usb_info
= (usb_info_t
*) usbos_info
->cbarg
;
4369 dbus_info_t
*dbus_info
= (dbus_info_t
*)usb_info
->cbarg
;
4371 /* printk("Submit qtd %p to pipe %d (%p)\n", qtd, epn, qh); */
4374 printk("EHCI Fastpath: Attempt of optimized submit to a non-optimized pipe\n");
4378 spin_lock_irqsave(&usbos_info
->fastpath_lock
, flags
);
4380 /* Limit outstanding - for rpc behavior only */
4381 /* printk("QH qtd_status %08x\n", qh->hw->qtd_status); */
4383 if ((qtd
->qtd_status
& (1<<8)) == 0)
4385 atomic_inc(&s_tx_pending
);
4386 if (atomic_read(&s_tx_pending
) > 16*2) /* (dbus_info->tx_low_watermark * 3)) */
4387 dbus_flowctrl_tx(dbus_info
, TRUE
);
4394 * Standard list processing trick:
4395 * * old "afterend" is filled with the incoming data while still HALTed
4396 * * new element is appended and prepared to serve as new afterend
4397 * * now old afterend is activated
4398 * This way, HW never races the SW - no semaphores are necessary, as long as this function
4399 * is not reentered for the same QH
4402 /* Make new QTD to be HALTed, wait for it to actually happen */
4403 status
= qtd
->qtd_status
;
4404 qtd
->qtd_status
= cpu_to_le32(EHCI_QTD_HALTED
);
4407 /* Now copy all information from the new QTD to the old afterend,
4408 * except the own HW address
4410 afterend
= qh
->dummy
;
4411 hw_addr
= afterend
->qtd_self
;
4413 afterend
->qtd_self
= hw_addr
;
4415 /* The new QTD is ready to serve as a new afterend, append it */
4417 afterend
->qtd_next
= qtd
->qtd_self
;
4418 afterend
->qtd_altnext
= qtd
->qtd_self
; /* Always assume short read. Harmless in our case */
4419 afterend
->obj_next
= qtd
;
4421 /* Wait for writes to happen and enable the old afterend (now containing the QTD data) */
4423 afterend
->qtd_status
= status
;
4426 spin_unlock_irqrestore(&usbos_info
->fastpath_lock
, flags
);
4431 void BCMFASTPATH
optimize_submit_rx_request(const dbus_pub_t
*pub
, int epn
, struct ehci_qtd
*qtd_in
,
4434 usbos_info_t
*usbos_info
= g_probe_info
.usbos_info
;
4435 int len
= usbos_info
->rxbuf_len
;
4437 struct ehci_qtd
*qtd
;
4438 int token
= EHCI_QTD_SET_CERR(3) | EHCI_QTD_SET_PID(1);
4440 if (qtd_in
== NULL
) {
4441 qtd
= optimize_ehci_qtd_alloc(GFP_KERNEL
);
4443 printk("EHCI Fastpath: Out of QTDs\n");
4452 /* NOCOPY, allocate own packet */
4453 /* Follow dbus_usbos_recv_urb_submit */
4454 pkt
= PKTGET(usbos_info
->pub
->osh
, len
, FALSE
);
4456 printk("%s: PKTGET failed\n", __FUNCTION__
);
4457 optimize_ehci_qtd_free(qtd
);
4460 /* consider the packet "native" so we don't count it as MALLOCED in the osl */
4461 PKTTONATIVE(usbos_info
->pub
->osh
, pkt
);
4463 buf
= PKTDATA(usbos_info
->pub
->osh
, pkt
);
4469 optimize_qtd_fill_with_data(pub
, epn
, qtd
, buf
, token
, len
);
4470 optimize_submit_async(qtd
, epn
);
4472 #endif /* EHCI_FASTPATH_TX || EHCI_FASTPATH_RX */
4474 #ifdef BCM_REQUEST_FW
4476 get_file_buf(char *file_path
, char **filebuf
, int *filelen
)
4481 DBUSINFO(("File path = %s %d \n", file_path
, strlen(file_path
)));
4483 fp
= osl_os_open_image(file_path
);
4485 DBUSERR(("%s: file is Not exist \n", __FUNCTION__
));
4488 *filelen
= osl_os_image_size(fp
);
4489 *filebuf
= vmalloc(*filelen
);
4490 if (*filebuf
== NULL
) {
4492 DBUSERR(("%s: filebuf alloc fail \n", __FUNCTION__
));
4496 tmp_len
= osl_os_get_image_block(*filebuf
, *filelen
, fp
);
4497 if (tmp_len
!= *filelen
) {
4498 DBUSERR(("%s: file get fail \n", __FUNCTION__
));
4503 osl_os_close_image(fp
);
4505 if (*filelen
== 0) {
4514 dbus_get_fw_nvfile(int devid
, int chiprev
, uint8
**fw
, int *fwlen
, int type
, uint16 boardtype
,
4518 const struct firmware
*firmware
= NULL
;
4523 strncpy(fw_name
, "brcm/bcm", FW_NAME_PREFIX_LEN
);
4524 fw_name
[FW_NAME_PREFIX_LEN
] = '\0';
4525 if (type
== DBUS_FIRMWARE
) {
4527 case BCM4350_CHIP_ID
:
4528 case BCM4354_CHIP_ID
:
4529 case BCM43556_CHIP_ID
:
4530 case BCM43558_CHIP_ID
:
4531 case BCM43566_CHIP_ID
:
4532 case BCM43568_CHIP_ID
:
4533 case BCM43570_CHIP_ID
:
4534 case BCM4358_CHIP_ID
:
4535 strcat(fw_name
, "4350");
4537 case BCM43143_CHIP_ID
:
4538 strcat(fw_name
, "43143");
4540 case BCM43234_CHIP_ID
:
4541 case BCM43235_CHIP_ID
:
4542 case BCM43236_CHIP_ID
:
4543 strcat(fw_name
, "43236");
4545 case BCM43242_CHIP_ID
:
4546 strcat(fw_name
, "43242");
4548 case BCM43238_CHIP_ID
:
4549 strcat(fw_name
, "43238");
4551 case BCM43526_CHIP_ID
:
4552 strcat(fw_name
, "43526");
4554 case BCM43569_CHIP_ID
:
4555 strcat(fw_name
, "43569");
4558 strcat(fw_name
, "a0");
4561 strcat(fw_name
, "a2");
4568 DBUSERR(("unsupported device %x\n", devid
));
4572 strcat(fw_name
, "-firmware.bin");
4573 if (firmware_path
[0] != '\0') {
4577 snprintf(fw_name
, sizeof(fw_name
), "%s%s", firmware_path
, fw_name
);
4578 err
= get_file_buf(fw_name
, &filebuf
, &filelen
);
4580 DBUSERR(("fail to request firmware %s\n", fw_name
));
4584 if ((filebuf
!= NULL
) && (filelen
!= 0)) {
4585 *fw
= (uint8
*)filebuf
;
4592 err
= request_firmware(&firmware
, fw_name
, &g_probe_info
.usb
->dev
);
4594 DBUSERR(("fail to request firmware %s\n", fw_name
));
4600 case BCM4350_CHIP_ID
:
4601 case BCM4354_CHIP_ID
:
4602 case BCM43556_CHIP_ID
:
4603 case BCM43558_CHIP_ID
:
4604 case BCM43566_CHIP_ID
:
4605 case BCM43568_CHIP_ID
:
4606 case BCM43570_CHIP_ID
:
4607 case BCM4358_CHIP_ID
:
4608 strcat(fw_name
, "4350");
4610 case BCM43143_CHIP_ID
:
4611 strcat(fw_name
, "43143");
4613 case BCM43234_CHIP_ID
:
4614 strcat(fw_name
, "43234");
4616 case BCM43235_CHIP_ID
:
4617 strcat(fw_name
, "43235");
4619 case BCM43236_CHIP_ID
:
4620 strcat(fw_name
, "43236");
4622 case BCM43238_CHIP_ID
:
4623 strcat(fw_name
, "43238");
4625 case BCM43242_CHIP_ID
:
4626 strcat(fw_name
, "43242");
4628 case BCM43526_CHIP_ID
:
4629 strcat(fw_name
, "43526");
4631 case BCM43569_CHIP_ID
:
4632 strcat(fw_name
, "43569");
4635 strcat(fw_name
, "a0");
4638 strcat(fw_name
, "a2");
4645 DBUSERR(("unsupported device %x\n", devid
));
4649 /* load board specific nvram file */
4650 snprintf(fw_name
, sizeof(fw_name
), "%s-%2x-%2x.nvm", fw_name
,
4651 boardtype
, boardrev
);
4652 fw_name
[strlen(fw_name
)] = '\0';
4654 if (nvram_path
[0] != '\0') {
4657 err
= get_file_buf(fw_name
, &filebuf
, &filelen
);
4659 snprintf(fw_name
, sizeof(fw_name
), "%s%s.nvm",
4660 nvram_path
, fw_name
);
4661 fw_name
[strlen(fw_name
)] = '\0';
4662 err
= get_file_buf(fw_name
, &filebuf
, &filelen
);
4664 DBUSERR(("fail to get firmware %s\n", fw_name
));
4669 if ((filebuf
!= NULL
) && (filelen
!= 0)) {
4670 *fw
= (uint8
*)filebuf
;
4677 err
= request_firmware(&firmware
, fw_name
, &g_probe_info
.usb
->dev
);
4679 /* board specific file missing - load the generic nvram file */
4680 snprintf(fw_name
, sizeof(fw_name
), "%s.nvm", fw_name
);
4681 err
= request_firmware(&firmware
, fw_name
,
4682 &g_probe_info
.usb
->dev
);
4690 if ((nvram_path
[0] != '\0') || (firmware_path
[0] != '\0'))
4693 if (firmware
== NULL
) {
4697 *fwlen
= firmware
->size
;
4698 *fw
= (uint8
*)firmware
->data
;
4700 return (void *)firmware
;
4704 dbus_release_fw_nvfile(void *firmware
)
4706 release_firmware((struct firmware
*)firmware
);
4708 #endif /* #ifdef BCM_REQUEST_FW */
4710 /** For a composite device the interface order is not guaranteed,
4711 * scan the device struct for the WLAN interface
4713 #ifdef BCMUSBDEV_COMPOSITE
4715 dbus_usbos_intf_wlan(struct usb_device
*usb
)
4717 int i
, num_of_eps
, ep
, intf_wlan
= -1;
4718 int num_intf
= CONFIGDESC(usb
)->bNumInterfaces
;
4719 struct usb_endpoint_descriptor
*endpoint
;
4721 for (i
= 0; i
< num_intf
; i
++) {
4722 if (IFDESC(usb
, i
).bInterfaceClass
!= USB_CLASS_VENDOR_SPEC
)
4724 num_of_eps
= IFDESC(usb
, i
).bNumEndpoints
;
4726 for (ep
= 0; ep
< num_of_eps
; ep
++) {
4727 endpoint
= &IFEPDESC(usb
, i
, ep
);
4728 if ((endpoint
->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK
) ==
4729 USB_ENDPOINT_XFER_BULK
) {
4734 if (ep
< num_of_eps
)
4740 #endif /* BCMUSBDEV_COMPOSITE */