1 /*
2 * Dongle BUS interface
3 * USB Linux Implementation
4 *
5 * Copyright (C) 1999-2016, Broadcom Corporation
6 *
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:
12 *
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
17 * of the license of that module. An independent module is a module which is
18 * not derived from this software. The special exception does not apply to any
19 * modifications of the software.
20 *
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.
24 *
25 *
26 * <<Broadcom-WL-IPTag/Open:>>
27 *
28 * $Id: dbus_usb_linux.c 564663 2015-06-18 02:34:42Z $
29 */
30
31 /**
32 * @file @brief
33 * This file contains DBUS code that is USB *and* OS (Linux) specific. DBUS is a
34 * Broadcom proprietary host specific abstraction layer.
35 */
36
37 #include <typedefs.h>
38 #include <osl.h>
39
40 /**
41 * DBUS_LINUX_RXDPC is created for router platform performance tuning. A
42 * separate thread is created to handle USB RX and avoid the call chain getting
43 * too long and enhance cache hit rate.
44 *
45 * DBUS_LINUX_RXDPC setting is in wlconfig file.
46 */
47
48 /*
49 * If DBUS_LINUX_RXDPC is off, spin_lock_bh() for CTFPOOL in
50 * linux_osl.c has to be changed to spin_lock_irqsave() because
51 * PKTGET/PKTFREE are no longer in bottom half.
52 *
53 * Right now we have another queue rpcq in wl_linux.c. Maybe we
54 * can eliminate that one to reduce the overhead.
55 *
56 * Enabling 2nd EP and DBUS_LINUX_RXDPC causing traffic from
57 * both EP's to be queued in the same rx queue. If we want
58 * RXDPC to work with 2nd EP. The EP for RPC call return
59 * should bypass the dpc and go directly up.
60 */
61
62 #include <usbrdl.h>
63 #include <bcmendian.h>
64 #include <linux/init.h>
65 #include <linux/kernel.h>
66 #include <linux/slab.h>
67 #include <linux/usb.h>
68 #include <linux/skbuff.h>
69 #include <linux/netdevice.h>
70 #include <linux/random.h>
71 #include <linux/spinlock.h>
72 #include <linux/list.h>
73 #include <asm/uaccess.h>
74 #include <asm/unaligned.h>
75 #include <dbus.h>
76 #include <bcmutils.h>
77 #include <bcmdevs.h>
78 #include <linux/usb.h>
79 #include <usbrdl.h>
80 #include <linux/firmware.h>
81 #include <dngl_stats.h>
82 #include <dhd.h>
83
84 #if defined(USBOS_THREAD) || defined(USBOS_TX_THREAD)
85
86 /**
87 * The usb-thread is designed to provide currency on multiprocessors and SMP
88 * linux kernels. On the dual cores platform, the WLAN driver, without threads,
89 * executed only on CPU0. The driver consumed almost of 100% on CPU0, while CPU1
90 * remained idle. The behavior was observed on Broadcom's STB.
91 *
92 * The WLAN driver consumed most of CPU0 and not CPU1 because tasklets/queues,
93 * software irq, and hardware irq are executing from CPU0, only. CPU0 became the
94 * system's bottle-neck. TPUT is lower and system's responsiveness is slower.
95 *
96 * To improve system responsiveness and TPUT usb-thread was implemented. The
97 * system's threads could be scheduled to run on any core. One core could be
98 * processing data in the usb-layer and the other core could be processing data
99 * in the wl-layer.
100 *
101 * For further info see [WlThreadAndUsbThread] Twiki.
102 */
103
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 */
111
112 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
113 #define KERNEL26
114 #endif
115
116 /**
117 * Starting with the 3.10 kernel release, dynamic PM support for USB is present
118 * whenever the kernel was built with CONFIG_PM_RUNTIME enabled. The
119 * CONFIG_USB_SUSPEND option has been eliminated.
120 */
121 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)) && \
122 defined(CONFIG_USB_SUSPEND)) || \
123 ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) && \
124 defined(CONFIG_PM_RUNTIME)) || \
125 (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
126 /* For USB power management support, see Linux kernel:
127 * Documentation/usb/power-management.txt */
128 #define USB_SUSPEND_AVAILABLE
129 #endif
130
131 /* Define alternate fw/nvram paths used in Android */
132 #ifdef OEM_ANDROID
133 #define CONFIG_ANDROID_BCMDHD_FW_PATH "broadcom/dhd/firmware/fw.bin.trx"
134 #define CONFIG_ANDROID_BCMDHD_NVRAM_PATH "broadcom/dhd/nvrams/nvm.txt"
135 #endif /* OEM_ANDROID */
136
usb_submit_urb_linux(struct urb * urb)137 static inline int usb_submit_urb_linux(struct urb *urb)
138 {
139 #ifdef BCM_MAX_URB_LEN
140 if (urb && (urb->transfer_buffer_length > BCM_MAX_URB_LEN)) {
141 DBUSERR(("URB transfer length=%d exceeded %d ra=%p\n",
142 urb->transfer_buffer_length, BCM_MAX_URB_LEN,
143 __builtin_return_address(0)));
144 return DBUS_ERR;
145 }
146 #endif
147
148 #ifdef KERNEL26
149 return usb_submit_urb(urb, GFP_ATOMIC);
150 #else
151 return usb_submit_urb(urb);
152 #endif
153 }
154
155 #define USB_SUBMIT_URB(urb) usb_submit_urb_linux(urb)
156
157 #ifdef KERNEL26
158
159 #define USB_ALLOC_URB() usb_alloc_urb(0, GFP_ATOMIC)
160 #define USB_UNLINK_URB(urb) (usb_kill_urb(urb))
161 #define USB_FREE_URB(urb) (usb_free_urb(urb))
162 #define USB_REGISTER() usb_register(&dbus_usbdev)
163 #define USB_DEREGISTER() usb_deregister(&dbus_usbdev)
164
165 #ifdef USB_SUSPEND_AVAILABLE
166
167 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33))
168 #define USB_AUTOPM_SET_INTERFACE(intf) usb_autopm_set_interface(intf)
169 #else
170 #define USB_ENABLE_AUTOSUSPEND(udev) usb_enable_autosuspend(udev)
171 #define USB_DISABLE_AUTOSUSPEND(udev) usb_disable_autosuspend(udev)
172 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) */
173
174 #define USB_AUTOPM_GET_INTERFACE(intf) usb_autopm_get_interface(intf)
175 #define USB_AUTOPM_PUT_INTERFACE(intf) usb_autopm_put_interface(intf)
176 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf) \
177 usb_autopm_get_interface_async(intf)
178 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf) \
179 usb_autopm_put_interface_async(intf)
180 #define USB_MARK_LAST_BUSY(dev) usb_mark_last_busy(dev)
181
182 #else /* USB_SUSPEND_AVAILABLE */
183
184 #define USB_AUTOPM_GET_INTERFACE(intf) \
185 do { \
186 } while (0)
187 #define USB_AUTOPM_PUT_INTERFACE(intf) \
188 do { \
189 } while (0)
190 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf) \
191 do { \
192 } while (0)
193 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf) \
194 do { \
195 } while (0)
196 #define USB_MARK_LAST_BUSY(dev) \
197 do { \
198 } while (0)
199 #endif /* USB_SUSPEND_AVAILABLE */
200
201 #define USB_CONTROL_MSG(dev, pipe, request, requesttype, value, index, data, \
202 size, timeout) \
203 usb_control_msg((dev), (pipe), (request), (requesttype), (value), (index), \
204 (data), (size), (timeout))
205 #define USB_BULK_MSG(dev, pipe, data, len, actual_length, timeout) \
206 usb_bulk_msg((dev), (pipe), (data), (len), (actual_length), (timeout))
207 #define USB_BUFFER_ALLOC(dev, size, mem, dma) \
208 usb_buffer_alloc(dev, size, mem, dma)
209 #define USB_BUFFER_FREE(dev, size, data, dma) \
210 usb_buffer_free(dev, size, data, dma)
211
212 #ifdef WL_URB_ZPKT
213 #define URB_QUEUE_BULK URB_ZERO_PACKET
214 #else
215 #define URB_QUEUE_BULK 0
216 #endif /* WL_URB_ZPKT */
217
218 #define CALLBACK_ARGS struct urb *urb, struct pt_regs *regs
219 #define CALLBACK_ARGS_DATA urb, regs
220 #define CONFIGDESC(usb) (&((usb)->actconfig)->desc)
221 #define IFPTR(usb, idx) ((usb)->actconfig->interface[idx])
222 #define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0])
223 #define IFDESC(usb, idx) IFALTS((usb), (idx)).desc
224 #define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[ep]).desc
225
226 #else /* KERNEL26 */
227
228 #define USB_ALLOC_URB() usb_alloc_urb(0)
229 #define USB_UNLINK_URB(urb) usb_unlink_urb(urb)
230 #define USB_FREE_URB(urb) (usb_free_urb(urb))
231 #define USB_REGISTER() usb_register(&dbus_usbdev)
232 #define USB_DEREGISTER() usb_deregister(&dbus_usbdev)
233 #define USB_AUTOPM_GET_INTERFACE(intf) \
234 do { \
235 } while (0)
236 #define USB_AUTOPM_GET_INTERFACE_ASYNC(intf) \
237 do { \
238 } while (0)
239 #define USB_AUTOPM_PUT_INTERFACE_ASYNC(intf) \
240 do { \
241 } while (0)
242 #define USB_MARK_LAST_BUSY(dev) \
243 do { \
244 } while (0)
245
246 #define USB_CONTROL_MSG(dev, pipe, request, requesttype, value, index, data, \
247 size, timeout) \
248 usb_control_msg((dev), (pipe), (request), (requesttype), (value), (index), \
249 (data), (size), (timeout))
250 #define USB_BUFFER_ALLOC(dev, size, mem, dma) kmalloc(size, mem)
251 #define USB_BUFFER_FREE(dev, size, data, dma) kfree(data)
252
253 #ifdef WL_URB_ZPKT
254 #define URB_QUEUE_BULK USB_QUEUE_BULK | URB_ZERO_PACKET
255 #else
256 #define URB_QUEUE_BULK 0
257 #endif /* WL_URB_ZPKT */
258
259 #define CALLBACK_ARGS struct urb *urb
260 #define CALLBACK_ARGS_DATA urb
261 #define CONFIGDESC(usb) ((usb)->actconfig)
262 #define IFPTR(usb, idx) (&(usb)->actconfig->interface[idx])
263 #define IFALTS(usb, idx) ((usb)->actconfig->interface[idx].altsetting[0])
264 #define IFDESC(usb, idx) IFALTS((usb), (idx))
265 #define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[ep])
266
267 #endif /* KERNEL26 */
268
269 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
270 #define USB_SPEED_SUPER 5
271 #endif /* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) */
272
273 #define CONTROL_IF 0
274 #define BULK_IF 0
275
276 #ifdef BCMUSBDEV_COMPOSITE
277 #define USB_COMPIF_MAX 4
278
279 #define USB_CLASS_WIRELESS 0xe0
280 #define USB_CLASS_MISC 0xef
281 #define USB_SUBCLASS_COMMON 0x02
282 #define USB_PROTO_IAD 0x01
283 #define USB_PROTO_VENDOR 0xff
284
285 #define USB_QUIRK_NO_SET_INTF 0x04 /* device does not support set_interface */
286 #endif /* BCMUSBDEV_COMPOSITE */
287
288 #define USB_SYNC_WAIT_TIMEOUT 300 /* ms */
289
290 /* Private data kept in skb */
291 #define SKB_PRIV(skb, idx) (&((void **)skb->cb)[idx])
292 #define SKB_PRIV_URB(skb) (*(struct urb **)SKB_PRIV(skb, 0))
293
294 #ifndef DBUS_USB_RXQUEUE_BATCH_ADD
295 /* items to add each time within limit */
296 #define DBUS_USB_RXQUEUE_BATCH_ADD 8
297 #endif
298
299 #ifndef DBUS_USB_RXQUEUE_LOWER_WATERMARK
300 /* add a new batch req to rx queue when waiting item count reduce to this number
301 */
302 #define DBUS_USB_RXQUEUE_LOWER_WATERMARK 4
303 #endif
304
305 enum usbos_suspend_state {
306 USBOS_SUSPEND_STATE_DEVICE_ACTIVE =
307 0, /* Device is busy, won't allow suspend */
308 USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be suspended */
309 /* Wating PM to suspend */
310 USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */
311 };
312
313 enum usbos_request_state {
314 USBOS_REQUEST_STATE_UNSCHEDULED = 0, /* USB TX request not scheduled */
315 USBOS_REQUEST_STATE_SCHEDULED, /* USB TX request given to TX thread */
316 USBOS_REQUEST_STATE_SUBMITTED /* USB TX request submitted */
317 };
318
319 typedef struct {
320 uint32 notification;
321 uint32 reserved;
322 } intr_t;
323
324 typedef struct {
325 dbus_pub_t *pub;
326
327 void *cbarg;
328 dbus_intf_callbacks_t *cbs;
329
330 /* Imported */
331 struct usb_device *usb; /* USB device pointer from OS */
332 struct urb *intr_urb; /* URB for interrupt endpoint */
333 struct list_head req_rxfreeq;
334 struct list_head req_txfreeq;
335 struct list_head req_rxpostedq; /* Posted down to USB driver for RX */
336 struct list_head req_txpostedq; /* Posted down to USB driver for TX */
337 spinlock_t rxfree_lock; /* Lock for rx free list */
338 spinlock_t txfree_lock; /* Lock for tx free list */
339 spinlock_t rxposted_lock; /* Lock for rx posted list */
340 spinlock_t txposted_lock; /* Lock for tx posted list */
341 uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2; /* Pipe numbers for USB I/O */
342 uint rxbuf_len;
343
344 struct list_head req_rxpendingq; /* RXDPC: Pending for dpc to send up */
345 spinlock_t rxpending_lock; /* RXDPC: Lock for rx pending list */
346 long dpc_pid;
347 struct semaphore dpc_sem;
348 struct completion dpc_exited;
349 int rxpending;
350
351 struct urb *ctl_urb;
352 int ctl_in_pipe, ctl_out_pipe;
353 struct usb_ctrlrequest ctl_write;
354 struct usb_ctrlrequest ctl_read;
355 struct semaphore ctl_lock; /* Lock for CTRL transfers via tx_thread */
356 #ifdef USBOS_TX_THREAD
357 enum usbos_request_state ctl_state;
358 #endif /* USBOS_TX_THREAD */
359
360 spinlock_t rxlock; /* Lock for rxq management */
361 spinlock_t txlock; /* Lock for txq management */
362
363 int intr_size; /* Size of interrupt message */
364 int interval; /* Interrupt polling interval */
365 intr_t intr; /* Data buffer for interrupt endpoint */
366
367 int maxps;
368 atomic_t txposted;
369 atomic_t rxposted;
370 atomic_t txallocated;
371 atomic_t rxallocated;
372 bool rxctl_deferrespok; /* Get a response for setup from dongle */
373
374 wait_queue_head_t wait;
375 bool waitdone;
376 int sync_urb_status;
377
378 struct urb *blk_urb; /* Used for downloading embedded image */
379
380 #ifdef USBOS_THREAD
381 spinlock_t ctrl_lock;
382 spinlock_t usbos_list_lock;
383 struct list_head usbos_list;
384 struct list_head usbos_free_list;
385 atomic_t usbos_list_cnt;
386 wait_queue_head_t usbos_queue_head;
387 struct task_struct *usbos_kt;
388 #endif /* USBOS_THREAD */
389
390 #ifdef USBOS_TX_THREAD
391 spinlock_t usbos_tx_list_lock;
392 struct list_head usbos_tx_list;
393 wait_queue_head_t usbos_tx_queue_head;
394 struct task_struct *usbos_tx_kt;
395 #endif /* USBOS_TX_THREAD */
396
397 struct dma_pool *qtd_pool; /* QTD pool for USB optimization only */
398 int tx_ep, rx_ep, rx2_ep; /* EPs for USB optimization */
399 struct usb_device *usb_device; /* USB device for optimization */
400 } usbos_info_t;
401
402 typedef struct urb_req {
403 void *pkt;
404 int buf_len;
405 struct urb *urb;
406 void *arg;
407 usbos_info_t *usbinfo;
408 struct list_head urb_list;
409 } urb_req_t;
410
411 #ifdef USBOS_THREAD
412 typedef struct usbos_list_entry {
413 struct list_head list; /* must be first */
414 void *urb_context;
415 int urb_length;
416 int urb_status;
417 } usbos_list_entry_t;
418
419 static void *dbus_usbos_thread_init(usbos_info_t *usbos_info);
420 static void dbus_usbos_thread_deinit(usbos_info_t *usbos_info);
421 static void dbus_usbos_dispatch_schedule(CALLBACK_ARGS);
422 static int dbus_usbos_thread_func(void *data);
423 #endif /* USBOS_THREAD */
424
425 #ifdef USBOS_TX_THREAD
426 void *dbus_usbos_tx_thread_init(usbos_info_t *usbos_info);
427 void dbus_usbos_tx_thread_deinit(usbos_info_t *usbos_info);
428 int dbus_usbos_tx_thread_func(void *data);
429 #endif /* USBOS_TX_THREAD */
430
431 /* Shared Function prototypes */
432 bool dbus_usbos_dl_cmd(usbos_info_t *usbinfo, uint8 cmd, void *buffer,
433 int buflen);
434 int dbus_usbos_wait(usbos_info_t *usbinfo, uint16 ms);
435 bool dbus_usbos_dl_send_bulk(usbos_info_t *usbinfo, void *buffer, int len);
436 int dbus_write_membytes(usbos_info_t *usbinfo, bool set, uint32 address,
437 uint8 *data, uint size);
438
439 /* Local function prototypes */
440 static void dbus_usbos_send_complete(CALLBACK_ARGS);
441 static void dbus_usbos_recv_complete(CALLBACK_ARGS);
442 static int dbus_usbos_errhandler(void *bus, int err);
443 static int dbus_usbos_state_change(void *bus, int state);
444 static void dbusos_stop(usbos_info_t *usbos_info);
445
446 #ifdef KERNEL26
447 static int dbus_usbos_probe(struct usb_interface *intf,
448 const struct usb_device_id *id);
449 static void dbus_usbos_disconnect(struct usb_interface *intf);
450 #if defined(USB_SUSPEND_AVAILABLE)
451 static int dbus_usbos_resume(struct usb_interface *intf);
452 static int dbus_usbos_suspend(struct usb_interface *intf, pm_message_t message);
453 /* at the moment, used for full dongle host driver only */
454 static int dbus_usbos_reset_resume(struct usb_interface *intf);
455 #endif /* USB_SUSPEND_AVAILABLE */
456 #else /* KERNEL26 */
457 static void *dbus_usbos_probe(struct usb_device *usb, unsigned int ifnum,
458 const struct usb_device_id *id);
459 static void dbus_usbos_disconnect(struct usb_device *usb, void *ptr);
460 #endif /* KERNEL26 */
461
462 /**
463 * have to disable missing-field-initializers warning as last element {}
464 * triggers it and different versions of kernel have different number of members
465 * so it is impossible to specify the initializer. BTW issuing the warning here
466 * is bug og GCC as universal zero {0} specified in C99 standard as correct way
467 * of initialization of struct to all zeros
468 */
469 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && \
470 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
471 #pragma GCC diagnostic push
472 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
473 #endif
474
475 static struct usb_device_id devid_table[] = {
476 {USB_DEVICE(BCM_DNGL_VID, 0x0000)}, /* Configurable via register() */
477 #if defined(BCM_REQUEST_FW)
478 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4328)},
479 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4322)},
480 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4319)},
481 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43236)},
482 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43143)},
483 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43242)},
484 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4360)},
485 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_4350)},
486 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BL_PID_43569)},
487 #endif
488 #ifdef EXTENDED_VID_PID
489 EXTENDED_VID_PID,
490 #endif /* EXTENDED_VID_PID */
491 {USB_DEVICE(BCM_DNGL_VID, BCM_DNGL_BDC_PID)}, /* Default BDC */
492 {}};
493
494 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && \
495 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
496 #pragma GCC diagnostic pop
497 #endif
498
499 MODULE_DEVICE_TABLE(usb, devid_table);
500
501 /** functions called by the Linux kernel USB subsystem */
502 static struct usb_driver dbus_usbdev = {
503 name : "dbus_usbdev",
504 probe : dbus_usbos_probe,
505 disconnect : dbus_usbos_disconnect,
506 id_table : devid_table,
507 #if defined(USB_SUSPEND_AVAILABLE)
508 suspend : dbus_usbos_suspend,
509 resume : dbus_usbos_resume,
510 reset_resume : dbus_usbos_reset_resume,
511 /* Linux USB core will allow autosuspend for devices bound to this driver */
512 supports_autosuspend : 1
513 #endif /* USB_SUSPEND_AVAILABLE */
514 };
515
516 /**
517 * This stores USB info during Linux probe callback since attach() is not called
518 * yet at this point
519 */
520 typedef struct {
521 void *usbos_info;
522 struct usb_device *usb; /* USB device pointer from OS */
523 uint rx_pipe; /* Pipe numbers for USB I/O */
524 uint tx_pipe; /* Pipe numbers for USB I/O */
525 uint intr_pipe; /* Pipe numbers for USB I/O */
526 uint rx_pipe2; /* Pipe numbers for USB I/O */
527 int intr_size; /* Size of interrupt message */
528 int interval; /* Interrupt polling interval */
529 bool dldone;
530 int vid;
531 int pid;
532 bool dereged;
533 bool disc_cb_done;
534 DEVICE_SPEED device_speed;
535 enum usbos_suspend_state suspend_state;
536 struct usb_interface *intf;
537 } probe_info_t;
538
539 /*
540 * USB Linux dbus_intf_t
541 */
542 static void *dbus_usbos_intf_attach(dbus_pub_t *pub, void *cbarg,
543 dbus_intf_callbacks_t *cbs);
544 static void dbus_usbos_intf_detach(dbus_pub_t *pub, void *info);
545 static int dbus_usbos_intf_send_irb(void *bus, dbus_irb_tx_t *txirb);
546 static int dbus_usbos_intf_recv_irb(void *bus, dbus_irb_rx_t *rxirb);
547 static int dbus_usbos_intf_recv_irb_from_ep(void *bus, dbus_irb_rx_t *rxirb,
548 uint32 ep_idx);
549 static int dbus_usbos_intf_cancel_irb(void *bus, dbus_irb_tx_t *txirb);
550 static int dbus_usbos_intf_send_ctl(void *bus, uint8 *buf, int len);
551 static int dbus_usbos_intf_recv_ctl(void *bus, uint8 *buf, int len);
552 static int dbus_usbos_intf_get_attrib(void *bus, dbus_attrib_t *attrib);
553 static int dbus_usbos_intf_up(void *bus);
554 static int dbus_usbos_intf_down(void *bus);
555 static int dbus_usbos_intf_stop(void *bus);
556 static int dbus_usbos_readreg(void *bus, uint32 regaddr, int datalen,
557 uint32 *value);
558 extern int dbus_usbos_loopback_tx(void *usbos_info_ptr, int cnt, int size);
559 int dbus_usbos_writereg(void *bus, uint32 regaddr, int datalen, uint32 data);
560 static int dbus_usbos_intf_set_config(void *bus, dbus_config_t *config);
561 static bool dbus_usbos_intf_recv_needed(void *bus);
562 static void *dbus_usbos_intf_exec_rxlock(void *bus, exec_cb_t cb,
563 struct exec_parms *args);
564 static void *dbus_usbos_intf_exec_txlock(void *bus, exec_cb_t cb,
565 struct exec_parms *args);
566 #ifdef BCMUSBDEV_COMPOSITE
567 static int dbus_usbos_intf_wlan(struct usb_device *usb);
568 #endif /* BCMUSBDEV_COMPOSITE */
569
570 /** functions called by dbus_usb.c */
571 static dbus_intf_t dbus_usbos_intf = {
572 .attach = dbus_usbos_intf_attach,
573 .detach = dbus_usbos_intf_detach,
574 .up = dbus_usbos_intf_up,
575 .down = dbus_usbos_intf_down,
576 .send_irb = dbus_usbos_intf_send_irb,
577 .recv_irb = dbus_usbos_intf_recv_irb,
578 .cancel_irb = dbus_usbos_intf_cancel_irb,
579 .send_ctl = dbus_usbos_intf_send_ctl,
580 .recv_ctl = dbus_usbos_intf_recv_ctl,
581 .get_stats = NULL,
582 .get_attrib = dbus_usbos_intf_get_attrib,
583 .remove = NULL,
584 .resume = NULL,
585 .suspend = NULL,
586 .stop = dbus_usbos_intf_stop,
587 .reset = NULL,
588 .pktget = NULL,
589 .pktfree = NULL,
590 .iovar_op = NULL,
591 .dump = NULL,
592 .set_config = dbus_usbos_intf_set_config,
593 .get_config = NULL,
594 .device_exists = NULL,
595 .dlneeded = NULL,
596 .dlstart = NULL,
597 .dlrun = NULL,
598 .recv_needed = dbus_usbos_intf_recv_needed,
599 .exec_rxlock = dbus_usbos_intf_exec_rxlock,
600 .exec_txlock = dbus_usbos_intf_exec_txlock,
601
602 .tx_timer_init = NULL,
603 .tx_timer_start = NULL,
604 .tx_timer_stop = NULL,
605
606 .sched_dpc = NULL,
607 .lock = NULL,
608 .unlock = NULL,
609 .sched_probe_cb = NULL,
610
611 .shutdown = NULL,
612
613 .recv_stop = NULL,
614 .recv_resume = NULL,
615
616 .recv_irb_from_ep = dbus_usbos_intf_recv_irb_from_ep,
617 .readreg = dbus_usbos_readreg};
618
619 static probe_info_t g_probe_info;
620 static probe_cb_t probe_cb = NULL;
621 static disconnect_cb_t disconnect_cb = NULL;
622 static void *probe_arg = NULL;
623 static void *disc_arg = NULL;
624
625 static volatile int loopback_rx_cnt, loopback_tx_cnt;
626 int loopback_size;
627 bool is_loopback_pkt(void *buf);
628 int matches_loopback_pkt(void *buf);
629
630 /**
631 * multiple code paths in this file dequeue a URB request, this function makes
632 * sure that it happens in a concurrency save manner. Don't call this from a
633 * sleepable process context.
634 */
dbus_usbos_qdeq(struct list_head * urbreq_q,spinlock_t * lock)635 static urb_req_t *BCMFASTPATH dbus_usbos_qdeq(struct list_head *urbreq_q,
636 spinlock_t *lock)
637 {
638 unsigned long flags;
639 urb_req_t *req;
640
641 ASSERT(urbreq_q != NULL);
642
643 spin_lock_irqsave(lock, flags);
644
645 if (list_empty(urbreq_q)) {
646 req = NULL;
647 } else {
648 ASSERT(urbreq_q->next != NULL);
649 ASSERT(urbreq_q->next != urbreq_q);
650 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
651 #pragma GCC diagnostic push
652 #pragma GCC diagnostic ignored "-Wcast-qual"
653 #endif
654 req = list_entry(urbreq_q->next, urb_req_t, urb_list);
655 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
656 #pragma GCC diagnostic pop
657 #endif
658 list_del_init(&req->urb_list);
659 }
660
661 spin_unlock_irqrestore(lock, flags);
662
663 return req;
664 }
665
dbus_usbos_qenq(struct list_head * urbreq_q,urb_req_t * req,spinlock_t * lock)666 static void BCMFASTPATH dbus_usbos_qenq(struct list_head *urbreq_q,
667 urb_req_t *req, spinlock_t *lock)
668 {
669 unsigned long flags;
670
671 spin_lock_irqsave(lock, flags);
672
673 list_add_tail(&req->urb_list, urbreq_q);
674
675 spin_unlock_irqrestore(lock, flags);
676 }
677
678 /**
679 * multiple code paths in this file remove a URB request from a list, this
680 * function makes sure that it happens in a concurrency save manner. Don't call
681 * this from a sleepable process context. Is quite similar to dbus_usbos_qdeq(),
682 * I wonder why this function is needed.
683 */
dbus_usbos_req_del(urb_req_t * req,spinlock_t * lock)684 static void dbus_usbos_req_del(urb_req_t *req, spinlock_t *lock)
685 {
686 unsigned long flags;
687
688 spin_lock_irqsave(lock, flags);
689
690 list_del_init(&req->urb_list);
691
692 spin_unlock_irqrestore(lock, flags);
693 }
694
695 /**
696 * Driver requires a pool of URBs to operate. This function is called during
697 * initialization (attach phase), allocates a number of URBs, and puts them
698 * on the free (req_rxfreeq and req_txfreeq) queue
699 */
dbus_usbos_urbreqs_alloc(usbos_info_t * usbos_info,uint32 count,bool is_rx)700 static int dbus_usbos_urbreqs_alloc(usbos_info_t *usbos_info, uint32 count,
701 bool is_rx)
702 {
703 int i;
704 int allocated = 0;
705 int err = DBUS_OK;
706
707 for (i = 0; i < count; i++) {
708 urb_req_t *req;
709
710 req = MALLOC(usbos_info->pub->osh, sizeof(urb_req_t));
711 if (req == NULL) {
712 DBUSERR(("%s: MALLOC req failed\n", __FUNCTION__));
713 err = DBUS_ERR_NOMEM;
714 goto fail;
715 }
716 bzero(req, sizeof(urb_req_t));
717
718 req->urb = USB_ALLOC_URB();
719 if (req->urb == NULL) {
720 DBUSERR(("%s: USB_ALLOC_URB req->urb failed\n", __FUNCTION__));
721 err = DBUS_ERR_NOMEM;
722 goto fail;
723 }
724
725 INIT_LIST_HEAD(&req->urb_list);
726
727 if (is_rx) {
728 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
729 /* don't allocate now. Do it on demand */
730 req->pkt = NULL;
731 #else
732 /* pre-allocate buffers never to be released */
733 req->pkt = MALLOC(usbos_info->pub->osh, usbos_info->rxbuf_len);
734 if (req->pkt == NULL) {
735 DBUSERR(("%s: MALLOC req->pkt failed\n", __FUNCTION__));
736 err = DBUS_ERR_NOMEM;
737 goto fail;
738 }
739 #endif
740 req->buf_len = usbos_info->rxbuf_len;
741 dbus_usbos_qenq(&usbos_info->req_rxfreeq, req,
742 &usbos_info->rxfree_lock);
743 } else {
744 req->buf_len = 0;
745 dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
746 &usbos_info->txfree_lock);
747 }
748 allocated++;
749 continue;
750
751 fail:
752 if (req) {
753 if (is_rx && req->pkt) {
754 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
755 /* req->pkt is NULL in "NOCOPY" mode */
756 #else
757 MFREE(usbos_info->pub->osh, req->pkt, req->buf_len);
758 #endif
759 }
760 if (req->urb) {
761 USB_FREE_URB(req->urb);
762 }
763 MFREE(usbos_info->pub->osh, req, sizeof(urb_req_t));
764 }
765 break;
766 }
767
768 atomic_add(allocated,
769 is_rx ? &usbos_info->rxallocated : &usbos_info->txallocated);
770
771 if (is_rx) {
772 DBUSTRACE(("%s: add %d (total %d) rx buf, each has %d bytes\n",
773 __FUNCTION__, allocated,
774 atomic_read(&usbos_info->rxallocated),
775 usbos_info->rxbuf_len));
776 } else {
777 DBUSTRACE(("%s: add %d (total %d) tx req\n", __FUNCTION__, allocated,
778 atomic_read(&usbos_info->txallocated)));
779 }
780
781 return err;
782 } /* dbus_usbos_urbreqs_alloc */
783
784 /** Typically called during detach or when attach failed. Don't call until all
785 * URBs unlinked */
dbus_usbos_urbreqs_free(usbos_info_t * usbos_info,bool is_rx)786 static int dbus_usbos_urbreqs_free(usbos_info_t *usbos_info, bool is_rx)
787 {
788 int rtn = 0;
789 urb_req_t *req;
790 struct list_head *req_q;
791 spinlock_t *lock;
792
793 if (is_rx) {
794 req_q = &usbos_info->req_rxfreeq;
795 lock = &usbos_info->rxfree_lock;
796 } else {
797 req_q = &usbos_info->req_txfreeq;
798 lock = &usbos_info->txfree_lock;
799 }
800 while ((req = dbus_usbos_qdeq(req_q, lock)) != NULL) {
801 if (is_rx) {
802 if (req->pkt) {
803 /* We do MFREE instead of PKTFREE because the pkt has been
804 * converted to native already
805 */
806 MFREE(usbos_info->pub->osh, req->pkt, req->buf_len);
807 req->pkt = NULL;
808 req->buf_len = 0;
809 }
810 } else {
811 /* sending req should not be assigned pkt buffer */
812 ASSERT(req->pkt == NULL);
813 }
814
815 if (req->urb) {
816 USB_FREE_URB(req->urb);
817 req->urb = NULL;
818 }
819 MFREE(usbos_info->pub->osh, req, sizeof(urb_req_t));
820
821 rtn++;
822 }
823 return rtn;
824 } /* dbus_usbos_urbreqs_free */
825
826 /**
827 * called by Linux kernel on URB completion. Upper DBUS layer (dbus_usb.c) has
828 * to be notified of send completion.
829 */
dbus_usbos_send_complete(CALLBACK_ARGS)830 void dbus_usbos_send_complete(CALLBACK_ARGS)
831 {
832 urb_req_t *req = urb->context;
833 dbus_irb_tx_t *txirb = req->arg;
834 usbos_info_t *usbos_info = req->usbinfo;
835 unsigned long flags;
836 int status = DBUS_OK;
837 int txposted;
838
839 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
840
841 spin_lock_irqsave(&usbos_info->txlock, flags);
842
843 dbus_usbos_req_del(req, &usbos_info->txposted_lock);
844 txposted = atomic_dec_return(&usbos_info->txposted);
845 if (unlikely(txposted < 0)) {
846 DBUSERR(("%s ERROR: txposted is negative (%d)!!\n", __FUNCTION__,
847 txposted));
848 }
849 spin_unlock_irqrestore(&usbos_info->txlock, flags);
850
851 if (unlikely(urb->status)) {
852 status = DBUS_ERR_TXFAIL;
853 DBUSTRACE(("txfail status %d\n", urb->status));
854 }
855
856 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
857 /* sending req should not be assigned pkt buffer */
858 ASSERT(req->pkt == NULL);
859 #endif
860 /* txirb should always be set, except for ZLP. ZLP is reusing this callback
861 * function. */
862 if (txirb != NULL) {
863 if (txirb->send_buf != NULL) {
864 MFREE(usbos_info->pub->osh, txirb->send_buf, req->buf_len);
865 txirb->send_buf = NULL;
866 req->buf_len = 0;
867 }
868 if (likely(usbos_info->cbarg && usbos_info->cbs)) {
869 if (likely(usbos_info->cbs->send_irb_complete != NULL)) {
870 usbos_info->cbs->send_irb_complete(usbos_info->cbarg, txirb,
871 status);
872 }
873 }
874 }
875
876 dbus_usbos_qenq(&usbos_info->req_txfreeq, req, &usbos_info->txfree_lock);
877 } /* dbus_usbos_send_complete */
878
879 /**
880 * In order to receive USB traffic from the dongle, we need to supply the Linux
881 * kernel with a free URB that is going to contain received data.
882 */
dbus_usbos_recv_urb_submit(usbos_info_t * usbos_info,dbus_irb_rx_t * rxirb,uint32 ep_idx)883 static int BCMFASTPATH dbus_usbos_recv_urb_submit(usbos_info_t *usbos_info,
884 dbus_irb_rx_t *rxirb,
885 uint32 ep_idx)
886 {
887 urb_req_t *req;
888 int ret = DBUS_OK;
889 unsigned long flags;
890 void *p;
891 uint rx_pipe;
892 int rxposted;
893
894 BCM_REFERENCE(rxposted);
895
896 if (!(req = dbus_usbos_qdeq(&usbos_info->req_rxfreeq,
897 &usbos_info->rxfree_lock))) {
898 DBUSTRACE(("%s No free URB!\n", __FUNCTION__));
899 return DBUS_ERR_RXDROP;
900 }
901
902 spin_lock_irqsave(&usbos_info->rxlock, flags);
903
904 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
905 req->pkt = rxirb->pkt = PKTGET(usbos_info->pub->osh, req->buf_len, FALSE);
906 if (!rxirb->pkt) {
907 DBUSERR(("%s: PKTGET failed\n", __FUNCTION__));
908 dbus_usbos_qenq(&usbos_info->req_rxfreeq, req,
909 &usbos_info->rxfree_lock);
910 ret = DBUS_ERR_RXDROP;
911 goto fail;
912 }
913 /* consider the packet "native" so we don't count it as MALLOCED in the osl
914 */
915 PKTTONATIVE(usbos_info->pub->osh, req->pkt);
916 rxirb->buf = NULL;
917 p = PKTDATA(usbos_info->pub->osh, req->pkt);
918 #else
919 if (req->buf_len != usbos_info->rxbuf_len) {
920 ASSERT(req->pkt);
921 MFREE(usbos_info->pub->osh, req->pkt, req->buf_len);
922 DBUSTRACE(("%s: replace rx buff: old len %d, new len %d\n",
923 __FUNCTION__, req->buf_len, usbos_info->rxbuf_len));
924 req->buf_len = 0;
925 req->pkt = MALLOC(usbos_info->pub->osh, usbos_info->rxbuf_len);
926 if (req->pkt == NULL) {
927 DBUSERR(("%s: MALLOC req->pkt failed\n", __FUNCTION__));
928 ret = DBUS_ERR_NOMEM;
929 goto fail;
930 }
931 req->buf_len = usbos_info->rxbuf_len;
932 }
933 rxirb->buf = req->pkt;
934 p = rxirb->buf;
935 #endif /* defined(BCM_RPC_NOCOPY) */
936 rxirb->buf_len = req->buf_len;
937 req->usbinfo = usbos_info;
938 req->arg = rxirb;
939 if (ep_idx == 0) {
940 rx_pipe = usbos_info->rx_pipe;
941 } else {
942 rx_pipe = usbos_info->rx_pipe2;
943 ASSERT(usbos_info->rx_pipe2);
944 }
945 /* Prepare the URB */
946 usb_fill_bulk_urb(req->urb, usbos_info->usb, rx_pipe, p, rxirb->buf_len,
947 (usb_complete_t)dbus_usbos_recv_complete, req);
948 req->urb->transfer_flags |= URB_QUEUE_BULK;
949
950 if ((ret = USB_SUBMIT_URB(req->urb))) {
951 DBUSERR(("%s USB_SUBMIT_URB failed. status %d\n", __FUNCTION__, ret));
952 dbus_usbos_qenq(&usbos_info->req_rxfreeq, req,
953 &usbos_info->rxfree_lock);
954 ret = DBUS_ERR_RXFAIL;
955 goto fail;
956 }
957 rxposted = atomic_inc_return(&usbos_info->rxposted);
958
959 dbus_usbos_qenq(&usbos_info->req_rxpostedq, req,
960 &usbos_info->rxposted_lock);
961 fail:
962 spin_unlock_irqrestore(&usbos_info->rxlock, flags);
963 return ret;
964 } /* dbus_usbos_recv_urb_submit */
965
966 /**
967 * Called by worked thread when a 'receive URB' completed or Linux kernel when
968 * it returns a URB to this driver.
969 */
dbus_usbos_recv_complete_handle(urb_req_t * req,int len,int status)970 static void BCMFASTPATH dbus_usbos_recv_complete_handle(urb_req_t *req, int len,
971 int status)
972 {
973 dbus_irb_rx_t *rxirb = req->arg;
974 usbos_info_t *usbos_info = req->usbinfo;
975 unsigned long flags;
976 int rxallocated, rxposted;
977 int dbus_status = DBUS_OK;
978 bool killed =
979 (g_probe_info.suspend_state == USBOS_SUSPEND_STATE_SUSPEND_PENDING) ? 1
980 : 0;
981
982 spin_lock_irqsave(&usbos_info->rxlock, flags);
983 dbus_usbos_req_del(req, &usbos_info->rxposted_lock);
984 rxposted = atomic_dec_return(&usbos_info->rxposted);
985 rxallocated = atomic_read(&usbos_info->rxallocated);
986 spin_unlock_irqrestore(&usbos_info->rxlock, flags);
987
988 if ((rxallocated < usbos_info->pub->nrxq) && (!status) &&
989 (rxposted == DBUS_USB_RXQUEUE_LOWER_WATERMARK)) {
990 DBUSTRACE(("%s: need more rx buf: rxallocated %d rxposted %d!\n",
991 __FUNCTION__, rxallocated, rxposted));
992 dbus_usbos_urbreqs_alloc(usbos_info,
993 MIN(DBUS_USB_RXQUEUE_BATCH_ADD,
994 usbos_info->pub->nrxq - rxallocated),
995 TRUE);
996 }
997
998 /* Handle errors */
999 if (status) {
1000 /*
1001 * Linux 2.4 disconnect: -ENOENT or -EILSEQ for CRC error; rmmod:
1002 * -ENOENT Linux 2.6 disconnect: -EPROTO, rmmod: -ESHUTDOWN
1003 */
1004 if ((status == -ENOENT && (!killed)) || status == -ESHUTDOWN) {
1005 /* NOTE: unlink() can not be called from URB callback().
1006 * Do not call dbusos_stop() here.
1007 */
1008 DBUSTRACE(("%s rx error %d\n", __FUNCTION__, status));
1009 dbus_usbos_state_change(usbos_info, DBUS_STATE_DOWN);
1010 } else if (status == -EPROTO) {
1011 DBUSTRACE(("%s rx error %d\n", __FUNCTION__, status));
1012 } else if (killed && (status == -EHOSTUNREACH || status == -ENOENT)) {
1013 /* Device is suspended */
1014 } else {
1015 DBUSTRACE(("%s rx error %d\n", __FUNCTION__, status));
1016 dbus_usbos_errhandler(usbos_info, DBUS_ERR_RXFAIL);
1017 }
1018
1019 /* On error, don't submit more URBs yet */
1020 rxirb->buf = NULL;
1021 rxirb->actual_len = 0;
1022 dbus_status = DBUS_ERR_RXFAIL;
1023 goto fail;
1024 }
1025
1026 /* Make the skb represent the received urb */
1027 rxirb->actual_len = len;
1028
1029 if (rxirb->actual_len < sizeof(uint32)) {
1030 DBUSTRACE(("small pkt len %d, process as ZLP\n", rxirb->actual_len));
1031 dbus_status = DBUS_ERR_RXZLP;
1032 }
1033
1034 fail:
1035 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
1036 /* detach the packet from the queue */
1037 req->pkt = NULL;
1038 #endif /* BCM_RPC_NOCOPY || BCM_RPC_RXNOCOPY */
1039
1040 if (usbos_info->cbarg && usbos_info->cbs) {
1041 if (usbos_info->cbs->recv_irb_complete) {
1042 usbos_info->cbs->recv_irb_complete(usbos_info->cbarg, rxirb,
1043 dbus_status);
1044 }
1045 }
1046
1047 dbus_usbos_qenq(&usbos_info->req_rxfreeq, req, &usbos_info->rxfree_lock);
1048
1049 /* Mark the interface as busy to reset USB autosuspend timer */
1050 USB_MARK_LAST_BUSY(usbos_info->usb);
1051 } /* dbus_usbos_recv_complete_handle */
1052
1053 /** called by Linux kernel when it returns a URB to this driver */
dbus_usbos_recv_complete(CALLBACK_ARGS)1054 static void dbus_usbos_recv_complete(CALLBACK_ARGS)
1055 {
1056 #ifdef USBOS_THREAD
1057 dbus_usbos_dispatch_schedule(CALLBACK_ARGS_DATA);
1058 #else /* !USBOS_THREAD */
1059 dbus_usbos_recv_complete_handle(urb->context, urb->actual_length,
1060 urb->status);
1061 #endif /* USBOS_THREAD */
1062 }
1063
1064 /**
1065 * If Linux notifies our driver that a control read or write URB has completed,
1066 * we should notify the DBUS layer above us (dbus_usb.c in this case).
1067 */
dbus_usbos_ctl_complete(usbos_info_t * usbos_info,int type,int urbstatus)1068 static void dbus_usbos_ctl_complete(usbos_info_t *usbos_info, int type,
1069 int urbstatus)
1070 {
1071 int status = DBUS_ERR;
1072
1073 if (usbos_info == NULL) {
1074 return;
1075 }
1076
1077 switch (urbstatus) {
1078 case 0:
1079 status = DBUS_OK;
1080 break;
1081 case -EINPROGRESS:
1082 case -ENOENT:
1083 default:
1084 #ifdef INTR_EP_ENABLE
1085 DBUSERR((
1086 "%s:%d fail status %d bus:%d susp:%d intr:%d ctli:%d ctlo:%d\n",
1087 __FUNCTION__, type, urbstatus, usbos_info->pub->busstate,
1088 g_probe_info.suspend_state, usbos_info->intr_urb_submitted,
1089 usbos_info->ctlin_urb_submitted,
1090 usbos_info->ctlout_urb_submitted));
1091 #else
1092 DBUSERR(("%s: failed with status %d\n", __FUNCTION__, urbstatus));
1093 status = DBUS_ERR;
1094 break;
1095 #endif /* INTR_EP_ENABLE */
1096 }
1097
1098 if (usbos_info->cbarg && usbos_info->cbs) {
1099 if (usbos_info->cbs->ctl_complete) {
1100 usbos_info->cbs->ctl_complete(usbos_info->cbarg, type, status);
1101 }
1102 }
1103 }
1104
1105 /** called by Linux */
dbus_usbos_ctlread_complete(CALLBACK_ARGS)1106 static void dbus_usbos_ctlread_complete(CALLBACK_ARGS)
1107 {
1108 usbos_info_t *usbos_info = (usbos_info_t *)urb->context;
1109
1110 ASSERT(urb);
1111 usbos_info = (usbos_info_t *)urb->context;
1112
1113 dbus_usbos_ctl_complete(usbos_info, DBUS_CBCTL_READ, urb->status);
1114
1115 #ifdef USBOS_THREAD
1116 if (usbos_info->rxctl_deferrespok) {
1117 usbos_info->ctl_read.bRequestType =
1118 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
1119 usbos_info->ctl_read.bRequest = 1;
1120 }
1121 #endif
1122
1123 up(&usbos_info->ctl_lock);
1124
1125 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
1126 }
1127
1128 /** called by Linux */
dbus_usbos_ctlwrite_complete(CALLBACK_ARGS)1129 static void dbus_usbos_ctlwrite_complete(CALLBACK_ARGS)
1130 {
1131 usbos_info_t *usbos_info = (usbos_info_t *)urb->context;
1132
1133 ASSERT(urb);
1134 usbos_info = (usbos_info_t *)urb->context;
1135
1136 dbus_usbos_ctl_complete(usbos_info, DBUS_CBCTL_WRITE, urb->status);
1137
1138 #ifdef USBOS_TX_THREAD
1139 usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
1140 #endif /* USBOS_TX_THREAD */
1141
1142 up(&usbos_info->ctl_lock);
1143
1144 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
1145 }
1146
1147 #ifdef INTR_EP_ENABLE
1148 /** called by Linux */
dbus_usbos_intr_complete(CALLBACK_ARGS)1149 static void dbus_usbos_intr_complete(CALLBACK_ARGS)
1150 {
1151 usbos_info_t *usbos_info = (usbos_info_t *)urb->context;
1152 bool killed =
1153 (g_probe_info.suspend_state == USBOS_SUSPEND_STATE_SUSPEND_PENDING) ? 1
1154 : 0;
1155
1156 if (usbos_info == NULL || usbos_info->pub == NULL) {
1157 return;
1158 }
1159 if ((urb->status == -ENOENT && (!killed)) || urb->status == -ESHUTDOWN ||
1160 urb->status == -ENODEV) {
1161 dbus_usbos_state_change(usbos_info, DBUS_STATE_DOWN);
1162 }
1163
1164 if (usbos_info->pub->busstate == DBUS_STATE_DOWN) {
1165 DBUSERR(("%s: intr cb when DBUS down, ignoring\n", __FUNCTION__));
1166 return;
1167 }
1168 dbus_usbos_ctl_complete(usbos_info, DBUS_CBINTR_POLL, urb->status);
1169 }
1170 #endif /* INTR_EP_ENABLE */
1171
1172 /**
1173 * when the bus is going to sleep or halt, the Linux kernel requires us to take
1174 * ownership of our URBs again. Multiple code paths in this file require a list
1175 * of URBs to be cancelled in a concurrency save manner.
1176 */
dbus_usbos_unlink(struct list_head * urbreq_q,spinlock_t * lock)1177 static void dbus_usbos_unlink(struct list_head *urbreq_q, spinlock_t *lock)
1178 {
1179 urb_req_t *req;
1180
1181 /* dbus_usbos_recv_complete() adds req back to req_freeq */
1182 while ((req = dbus_usbos_qdeq(urbreq_q, lock)) != NULL) {
1183 ASSERT(req->urb != NULL);
1184 USB_UNLINK_URB(req->urb);
1185 }
1186 }
1187
1188 /** multiple code paths in this file require the bus to stop */
dbus_usbos_cancel_all_urbs(usbos_info_t * usbos_info)1189 static void dbus_usbos_cancel_all_urbs(usbos_info_t *usbos_info)
1190 {
1191 int rxposted, txposted;
1192
1193 DBUSTRACE(("%s: unlink all URBs\n", __FUNCTION__));
1194
1195 #ifdef USBOS_TX_THREAD
1196 usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
1197
1198 /* Yield the CPU to TX thread so all pending requests are submitted */
1199 while (!list_empty(&usbos_info->usbos_tx_list)) {
1200 wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
1201 OSL_SLEEP(0xA);
1202 }
1203 #endif /* USBOS_TX_THREAD */
1204
1205 /* tell Linux kernel to cancel a single intr, ctl and blk URB */
1206 if (usbos_info->intr_urb) {
1207 USB_UNLINK_URB(usbos_info->intr_urb);
1208 }
1209 if (usbos_info->ctl_urb) {
1210 USB_UNLINK_URB(usbos_info->ctl_urb);
1211 }
1212 if (usbos_info->blk_urb) {
1213 USB_UNLINK_URB(usbos_info->blk_urb);
1214 }
1215
1216 dbus_usbos_unlink(&usbos_info->req_txpostedq, &usbos_info->txposted_lock);
1217 dbus_usbos_unlink(&usbos_info->req_rxpostedq, &usbos_info->rxposted_lock);
1218
1219 /* Wait until the callbacks for all submitted URBs have been called, because
1220 * the handler needs to know is an USB suspend is in progress.
1221 */
1222 SPINWAIT((atomic_read(&usbos_info->txposted) != 0 ||
1223 atomic_read(&usbos_info->rxposted) != 0),
1224 0x2710);
1225
1226 txposted = atomic_read(&usbos_info->txposted);
1227 rxposted = atomic_read(&usbos_info->rxposted);
1228 if (txposted != 0 || rxposted != 0) {
1229 DBUSERR(("%s ERROR: REQs posted, rx=%d tx=%d!\n", __FUNCTION__,
1230 rxposted, txposted));
1231 }
1232 } /* dbus_usbos_cancel_all_urbs */
1233
1234 /** multiple code paths require the bus to stop */
dbusos_stop(usbos_info_t * usbos_info)1235 static void dbusos_stop(usbos_info_t *usbos_info)
1236 {
1237 urb_req_t *req;
1238 int rxposted;
1239 req = NULL;
1240 BCM_REFERENCE(req);
1241
1242 ASSERT(usbos_info);
1243
1244 dbus_usbos_state_change(usbos_info, DBUS_STATE_DOWN);
1245
1246 dbus_usbos_cancel_all_urbs(usbos_info);
1247
1248 #ifdef USBOS_THREAD
1249 /* yield the CPU to rx packet thread */
1250 while (1) {
1251 if (atomic_read(&usbos_info->usbos_list_cnt) <= 0) {
1252 break;
1253 }
1254 wake_up_interruptible(&usbos_info->usbos_queue_head);
1255 OSL_SLEEP(0x3);
1256 }
1257 #endif /* USBOS_THREAD */
1258
1259 rxposted = atomic_read(&usbos_info->rxposted);
1260 if (rxposted > 0) {
1261 DBUSERR(
1262 ("%s ERROR: rx REQs posted=%d in stop!\n", __FUNCTION__, rxposted));
1263 }
1264
1265 ASSERT(atomic_read(&usbos_info->txposted) == 0 && rxposted == 0);
1266 } /* dbusos_stop */
1267
1268 #if defined(USB_SUSPEND_AVAILABLE)
1269
1270 /**
1271 * Linux kernel sports a 'USB auto suspend' feature. See:
1272 * http://lwn.net/Articles/373550/ The suspend method is called by the Linux
1273 * kernel to warn the driver that the device is going to be suspended. If the
1274 * driver returns a negative error code, the suspend will be aborted. If the
1275 * driver returns 0, it must cancel all outstanding URBs (usb_kill_urb()) and
1276 * not submit any more.
1277 */
dbus_usbos_suspend(struct usb_interface * intf,pm_message_t message)1278 static int dbus_usbos_suspend(struct usb_interface *intf, pm_message_t message)
1279 {
1280 DBUSERR(
1281 ("%s suspend state: %d\n", __FUNCTION__, g_probe_info.suspend_state));
1282 /* DHD for full dongle model */
1283 g_probe_info.suspend_state = USBOS_SUSPEND_STATE_SUSPEND_PENDING;
1284 dbus_usbos_state_change((usbos_info_t *)g_probe_info.usbos_info,
1285 DBUS_STATE_SLEEP);
1286 dbus_usbos_cancel_all_urbs((usbos_info_t *)g_probe_info.usbos_info);
1287 g_probe_info.suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
1288
1289 return 0;
1290 }
1291
1292 /**
1293 * The resume method is called to tell the driver that the device has been
1294 * resumed and the driver can return to normal operation. URBs may once more be
1295 * submitted.
1296 */
dbus_usbos_resume(struct usb_interface * intf)1297 static int dbus_usbos_resume(struct usb_interface *intf)
1298 {
1299 DBUSERR(("%s Device resumed\n", __FUNCTION__));
1300
1301 dbus_usbos_state_change((usbos_info_t *)g_probe_info.usbos_info,
1302 DBUS_STATE_UP);
1303 g_probe_info.suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
1304 return 0;
1305 }
1306
1307 /**
1308 * This function is directly called by the Linux kernel, when the suspended
1309 * device has been reset instead of being resumed
1310 */
dbus_usbos_reset_resume(struct usb_interface * intf)1311 static int dbus_usbos_reset_resume(struct usb_interface *intf)
1312 {
1313 DBUSERR(("%s Device reset resumed\n", __FUNCTION__));
1314
1315 /* The device may have lost power, so a firmware download may be required */
1316 dbus_usbos_state_change((usbos_info_t *)g_probe_info.usbos_info,
1317 DBUS_STATE_DL_NEEDED);
1318 g_probe_info.suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
1319 return 0;
1320 }
1321
1322 #endif /* USB_SUSPEND_AVAILABLE */
1323
1324 /**
1325 * Called by Linux kernel at initialization time, kernel wants to know if our
1326 * driver will accept the caller supplied USB interface. Note that USB drivers
1327 * are bound to interfaces, and not to USB devices.
1328 */
1329 #ifdef KERNEL26
1330 #define DBUS_USBOS_PROBE() \
1331 static int dbus_usbos_probe(struct usb_interface *intf, \
1332 const struct usb_device_id *id)
1333 #define DBUS_USBOS_DISCONNECT() \
1334 static void dbus_usbos_disconnect(struct usb_interface *intf)
1335 #else
1336 #define DBUS_USBOS_PROBE() \
1337 static void *dbus_usbos_probe(struct usb_device *usb, unsigned int ifnum, \
1338 const struct usb_device_id *id)
1339 #define DBUS_USBOS_DISCONNECT() \
1340 static void dbus_usbos_disconnect(struct usb_device *usb, void *ptr)
1341 #endif /* KERNEL26 */
1342
DBUS_USBOS_PROBE()1343 DBUS_USBOS_PROBE()
1344 {
1345 int ep;
1346 struct usb_endpoint_descriptor *endpoint;
1347 int ret = 0;
1348 #ifdef KERNEL26
1349 struct usb_device *usb = interface_to_usbdev(intf);
1350 #else
1351 int claimed = 0;
1352 #endif
1353 int num_of_eps;
1354 #ifdef BCMUSBDEV_COMPOSITE
1355 int wlan_if = -1;
1356 bool intr_ep = FALSE;
1357 #endif /* BCMUSBDEV_COMPOSITE */
1358 wifi_adapter_info_t *adapter;
1359
1360 DHD_MUTEX_LOCK();
1361
1362 DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
1363 usb->bus->busnum, usb->portnum));
1364 adapter = dhd_wifi_platform_attach_adapter(
1365 USB_BUS, usb->bus->busnum, usb->portnum, WIFI_STATUS_POWER_ON);
1366 if (adapter == NULL) {
1367 DBUSERR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
1368 goto fail;
1369 }
1370
1371 #ifdef BCMUSBDEV_COMPOSITE
1372 wlan_if = dbus_usbos_intf_wlan(usb);
1373 #ifdef KERNEL26
1374 if ((wlan_if >= 0) && (IFPTR(usb, wlan_if) == intf))
1375 #else
1376 if (wlan_if == ifnum)
1377 #endif /* KERNEL26 */
1378 {
1379 #endif /* BCMUSBDEV_COMPOSITE */
1380 g_probe_info.usb = usb;
1381 g_probe_info.dldone = TRUE;
1382 #ifdef BCMUSBDEV_COMPOSITE
1383 } else {
1384 DBUSTRACE(("dbus_usbos_probe: skip probe for non WLAN interface\n"));
1385 ret = BCME_UNSUPPORTED;
1386 goto fail;
1387 }
1388 #endif /* BCMUSBDEV_COMPOSITE */
1389
1390 #ifdef KERNEL26
1391 g_probe_info.intf = intf;
1392 #endif /* KERNEL26 */
1393
1394 #ifdef BCMUSBDEV_COMPOSITE
1395 if (IFDESC(usb, wlan_if).bInterfaceNumber > USB_COMPIF_MAX)
1396 #else
1397 if (IFDESC(usb, CONTROL_IF).bInterfaceNumber)
1398 #endif /* BCMUSBDEV_COMPOSITE */
1399 {
1400 ret = -1;
1401 goto fail;
1402 }
1403 if (id != NULL) {
1404 g_probe_info.vid = id->idVendor;
1405 g_probe_info.pid = id->idProduct;
1406 }
1407
1408 #ifdef KERNEL26
1409 usb_set_intfdata(intf, &g_probe_info);
1410 #endif
1411
1412 /* Check that the device supports only one configuration */
1413 if (usb->descriptor.bNumConfigurations != 1) {
1414 ret = -1;
1415 goto fail;
1416 }
1417
1418 if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
1419 #ifdef BCMUSBDEV_COMPOSITE
1420 if ((usb->descriptor.bDeviceClass != USB_CLASS_MISC) &&
1421 (usb->descriptor.bDeviceClass != USB_CLASS_WIRELESS)) {
1422 #endif /* BCMUSBDEV_COMPOSITE */
1423 ret = -1;
1424 goto fail;
1425 #ifdef BCMUSBDEV_COMPOSITE
1426 }
1427 #endif /* BCMUSBDEV_COMPOSITE */
1428 }
1429
1430 /*
1431 * Only the BDC interface configuration is supported:
1432 * Device class: USB_CLASS_VENDOR_SPEC
1433 * if0 class: USB_CLASS_VENDOR_SPEC
1434 * if0/ep0: control
1435 * if0/ep1: bulk in
1436 * if0/ep2: bulk out (ok if swapped with bulk in)
1437 */
1438 if (CONFIGDESC(usb)->bNumInterfaces != 1) {
1439 #ifdef BCMUSBDEV_COMPOSITE
1440 if (CONFIGDESC(usb)->bNumInterfaces > USB_COMPIF_MAX) {
1441 #endif /* BCMUSBDEV_COMPOSITE */
1442 ret = -1;
1443 goto fail;
1444 #ifdef BCMUSBDEV_COMPOSITE
1445 }
1446 #endif /* BCMUSBDEV_COMPOSITE */
1447 }
1448
1449 /* Check interface */
1450 #ifndef KERNEL26
1451 #ifdef BCMUSBDEV_COMPOSITE
1452 if (usb_interface_claimed(IFPTR(usb, wlan_if)))
1453 #else
1454 if (usb_interface_claimed(IFPTR(usb, CONTROL_IF)))
1455 #endif /* BCMUSBDEV_COMPOSITE */
1456 {
1457 ret = -1;
1458 goto fail;
1459 }
1460 #endif /* !KERNEL26 */
1461
1462 #ifdef BCMUSBDEV_COMPOSITE
1463 if ((IFDESC(usb, wlan_if).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
1464 IFDESC(usb, wlan_if).bInterfaceSubClass != 0x2 ||
1465 IFDESC(usb, wlan_if).bInterfaceProtocol != 0xff) &&
1466 (IFDESC(usb, wlan_if).bInterfaceClass != USB_CLASS_MISC ||
1467 IFDESC(usb, wlan_if).bInterfaceSubClass != USB_SUBCLASS_COMMON ||
1468 IFDESC(usb, wlan_if).bInterfaceProtocol != USB_PROTO_IAD))
1469 #else
1470 if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
1471 IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 0x2 ||
1472 IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff)
1473 #endif /* BCMUSBDEV_COMPOSITE */
1474 {
1475 #ifdef BCMUSBDEV_COMPOSITE
1476 DBUSERR(
1477 ("%s: invalid control interface: class %d, subclass %d, proto %d\n",
1478 __FUNCTION__, IFDESC(usb, wlan_if).bInterfaceClass,
1479 IFDESC(usb, wlan_if).bInterfaceSubClass,
1480 IFDESC(usb, wlan_if).bInterfaceProtocol));
1481 #else
1482 DBUSERR(
1483 ("%s: invalid control interface: class %d, subclass %d, proto %d\n",
1484 __FUNCTION__, IFDESC(usb, CONTROL_IF).bInterfaceClass,
1485 IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
1486 IFDESC(usb, CONTROL_IF).bInterfaceProtocol));
1487 #endif /* BCMUSBDEV_COMPOSITE */
1488 ret = -1;
1489 goto fail;
1490 }
1491
1492 /* Check control endpoint */
1493 #ifdef BCMUSBDEV_COMPOSITE
1494 endpoint = &IFEPDESC(usb, wlan_if, 0);
1495 #else
1496 endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
1497 #endif /* BCMUSBDEV_COMPOSITE */
1498 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1499 USB_ENDPOINT_XFER_INT) {
1500 #ifdef BCMUSBDEV_COMPOSITE
1501 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1502 USB_ENDPOINT_XFER_BULK) {
1503 #endif /* BCMUSBDEV_COMPOSITE */
1504 DBUSERR(("%s: invalid control endpoint %d\n", __FUNCTION__,
1505 endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK));
1506 ret = -1;
1507 goto fail;
1508 #ifdef BCMUSBDEV_COMPOSITE
1509 }
1510 #endif /* BCMUSBDEV_COMPOSITE */
1511 }
1512
1513 #ifdef BCMUSBDEV_COMPOSITE
1514 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
1515 USB_ENDPOINT_XFER_INT) {
1516 #endif /* BCMUSBDEV_COMPOSITE */
1517 g_probe_info.intr_pipe = usb_rcvintpipe(
1518 usb, endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
1519 #ifdef BCMUSBDEV_COMPOSITE
1520 intr_ep = TRUE;
1521 }
1522 #endif /* BCMUSBDEV_COMPOSITE */
1523
1524 #ifndef KERNEL26
1525 /* Claim interface */
1526 #ifdef BCMUSBDEV_COMPOSITE
1527 usb_driver_claim_interface(&dbus_usbdev, IFPTR(usb, wlan_if),
1528 &g_probe_info);
1529 #else
1530 usb_driver_claim_interface(&dbus_usbdev, IFPTR(usb, CONTROL_IF),
1531 &g_probe_info);
1532 #endif /* BCMUSBDEV_COMPOSITE */
1533 claimed = 1;
1534 #endif /* !KERNEL26 */
1535 g_probe_info.rx_pipe = 0;
1536 g_probe_info.rx_pipe2 = 0;
1537 g_probe_info.tx_pipe = 0;
1538 #ifdef BCMUSBDEV_COMPOSITE
1539 if (intr_ep) {
1540 ep = 1;
1541 } else {
1542 ep = 0;
1543 }
1544 num_of_eps = IFDESC(usb, wlan_if).bNumEndpoints - 1;
1545 #else
1546 num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
1547 #endif /* BCMUSBDEV_COMPOSITE */
1548
1549 if ((num_of_eps != 0x2) && (num_of_eps != 0x3)) {
1550 #ifdef BCMUSBDEV_COMPOSITE
1551 if (num_of_eps > 0x7)
1552 #endif /* BCMUSBDEV_COMPOSITE */
1553 ASSERT(0);
1554 }
1555 /* Check data endpoints and get pipes */
1556 #ifdef BCMUSBDEV_COMPOSITE
1557 for (; ep <= num_of_eps; ep++)
1558 #else
1559 for (ep = 1; ep <= num_of_eps; ep++)
1560 #endif /* BCMUSBDEV_COMPOSITE */
1561 {
1562 #ifdef BCMUSBDEV_COMPOSITE
1563 endpoint = &IFEPDESC(usb, wlan_if, ep);
1564 #else
1565 endpoint = &IFEPDESC(usb, BULK_IF, ep);
1566 #endif /* BCMUSBDEV_COMPOSITE */
1567 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
1568 USB_ENDPOINT_XFER_BULK) {
1569 DBUSERR(("%s: invalid data endpoint %d\n", __FUNCTION__, ep));
1570 ret = -1;
1571 goto fail;
1572 }
1573
1574 if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
1575 USB_DIR_IN) {
1576 /* direction: dongle->host */
1577 if (!g_probe_info.rx_pipe) {
1578 g_probe_info.rx_pipe =
1579 usb_rcvbulkpipe(usb, (endpoint->bEndpointAddress &
1580 USB_ENDPOINT_NUMBER_MASK));
1581 } else {
1582 g_probe_info.rx_pipe2 =
1583 usb_rcvbulkpipe(usb, (endpoint->bEndpointAddress &
1584 USB_ENDPOINT_NUMBER_MASK));
1585 }
1586 } else {
1587 g_probe_info.tx_pipe = usb_sndbulkpipe(
1588 usb, (endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK));
1589 }
1590 }
1591
1592 /* Allocate interrupt URB and data buffer */
1593 /* RNDIS says 8-byte intr, our old drivers used 4-byte */
1594 #ifdef BCMUSBDEV_COMPOSITE
1595 g_probe_info.intr_size =
1596 (IFEPDESC(usb, wlan_if, 0).wMaxPacketSize == 0x10) ? 0x8 : 0x4;
1597 g_probe_info.interval = IFEPDESC(usb, wlan_if, 0).bInterval;
1598 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21))
1599 usb->quirks |= USB_QUIRK_NO_SET_INTF;
1600 #endif
1601 #else
1602 g_probe_info.intr_size =
1603 (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == 0x10) ? 0x8 : 0x4;
1604 g_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
1605 #endif /* BCMUSBDEV_COMPOSITE */
1606
1607 #ifndef KERNEL26
1608 /* usb_fill_int_urb does the interval decoding in 2.6 */
1609 if (usb->speed == USB_SPEED_HIGH) {
1610 g_probe_info.interval = 1 << (g_probe_info.interval - 1);
1611 }
1612 #endif
1613 if (usb->speed == USB_SPEED_SUPER) {
1614 g_probe_info.device_speed = SUPER_SPEED;
1615 DBUSERR(("super speed device detected\n"));
1616 } else if (usb->speed == USB_SPEED_HIGH) {
1617 g_probe_info.device_speed = HIGH_SPEED;
1618 DBUSERR(("high speed device detected\n"));
1619 } else {
1620 g_probe_info.device_speed = FULL_SPEED;
1621 DBUSERR(("full speed device detected\n"));
1622 }
1623 if (g_probe_info.dereged == FALSE && probe_cb) {
1624 disc_arg =
1625 probe_cb(probe_arg, "", USB_BUS, usb->bus->busnum, usb->portnum, 0);
1626 }
1627
1628 g_probe_info.disc_cb_done = FALSE;
1629
1630 #ifdef KERNEL26
1631 intf->needs_remote_wakeup = 1;
1632 #endif /* KERNEL26 */
1633 DHD_MUTEX_UNLOCK();
1634
1635 /* Success */
1636 #ifdef KERNEL26
1637 return DBUS_OK;
1638 #else
1639 usb_inc_dev_use(usb);
1640 return &g_probe_info;
1641 #endif
1642
1643 fail:
1644 printf("%s: Exit ret=%d\n", __FUNCTION__, ret);
1645 #ifdef BCMUSBDEV_COMPOSITE
1646 if (ret != BCME_UNSUPPORTED)
1647 #endif /* BCMUSBDEV_COMPOSITE */
1648 DBUSERR(("%s: failed with errno %d\n", __FUNCTION__, ret));
1649 #ifndef KERNEL26
1650 if (claimed)
1651 #ifdef BCMUSBDEV_COMPOSITE
1652 usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, wlan_if));
1653 #else
1654 usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, CONTROL_IF));
1655 #endif /* BCMUSBDEV_COMPOSITE */
1656 #endif /* !KERNEL26 */
1657
1658 DHD_MUTEX_UNLOCK();
1659 #ifdef KERNEL26
1660 usb_set_intfdata(intf, NULL);
1661 return ret;
1662 #else
1663 return NULL;
1664 #endif
1665 } /* dbus_usbos_probe */
1666
1667 /** Called by Linux kernel, is the counter part of dbus_usbos_probe() */
DBUS_USBOS_DISCONNECT()1668 DBUS_USBOS_DISCONNECT()
1669 {
1670 #ifdef KERNEL26
1671 struct usb_device *usb = interface_to_usbdev(intf);
1672 probe_info_t *probe_usb_init_data = usb_get_intfdata(intf);
1673 #else
1674 probe_info_t *probe_usb_init_data = (probe_info_t *)ptr;
1675 #endif
1676 usbos_info_t *usbos_info;
1677
1678 DHD_MUTEX_LOCK();
1679
1680 DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
1681 usb->bus->busnum, usb->portnum));
1682
1683 if (probe_usb_init_data) {
1684 usbos_info = (usbos_info_t *)probe_usb_init_data->usbos_info;
1685 if (usbos_info) {
1686 if ((probe_usb_init_data->dereged == FALSE) && disconnect_cb &&
1687 disc_arg) {
1688 disconnect_cb(disc_arg);
1689 disc_arg = NULL;
1690 probe_usb_init_data->disc_cb_done = TRUE;
1691 }
1692 }
1693 }
1694
1695 if (usb) {
1696 #ifndef KERNEL26
1697 #ifdef BCMUSBDEV_COMPOSITE
1698 usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, wlan_if));
1699 #else
1700 usb_driver_release_interface(&dbus_usbdev, IFPTR(usb, CONTROL_IF));
1701 #endif /* BCMUSBDEV_COMPOSITE */
1702 usb_dec_dev_use(usb);
1703 #endif /* !KERNEL26 */
1704 }
1705 DHD_MUTEX_UNLOCK();
1706 } /* dbus_usbos_disconnect */
1707
1708 #define LOOPBACK_PKT_START 0xBABE1234
1709
is_loopback_pkt(void * buf)1710 bool is_loopback_pkt(void *buf)
1711 {
1712 uint32 *buf_ptr = (uint32 *)buf;
1713
1714 if (*buf_ptr == LOOPBACK_PKT_START) {
1715 return TRUE;
1716 }
1717 return FALSE;
1718 }
1719
matches_loopback_pkt(void * buf)1720 int matches_loopback_pkt(void *buf)
1721 {
1722 int i, j;
1723 unsigned char *cbuf = (unsigned char *)buf;
1724
1725 for (i = 0x4; i < loopback_size; i++) {
1726 if (cbuf[i] != (i % 0x100)) {
1727 printf("%s: mismatch at i=%d %d : ", __FUNCTION__, i, cbuf[i]);
1728 for (j = i; ((j < i + 0x10) && (j < loopback_size)); j++) {
1729 printf("%d ", cbuf[j]);
1730 }
1731 printf("\n");
1732 return 0;
1733 }
1734 }
1735 loopback_rx_cnt++;
1736 return 1;
1737 }
1738
dbus_usbos_loopback_tx(void * usbos_info_ptr,int cnt,int size)1739 int dbus_usbos_loopback_tx(void *usbos_info_ptr, int cnt, int size)
1740 {
1741 usbos_info_t *usbos_info = (usbos_info_t *)usbos_info_ptr;
1742 unsigned char *buf;
1743 int j;
1744 void *p = NULL;
1745 int rc, last_rx_cnt;
1746 int tx_failed_cnt;
1747 int max_size = 1650;
1748 int usb_packet_size = 512;
1749 int min_packet_size = 10;
1750
1751 if (size % usb_packet_size == 0) {
1752 size = size - 1;
1753 DBUSERR(("%s: overriding size=%d \n", __FUNCTION__, size));
1754 }
1755
1756 if (size < min_packet_size) {
1757 size = min_packet_size;
1758 DBUSERR(("%s: overriding size=%d\n", __FUNCTION__, min_packet_size));
1759 }
1760 if (size > max_size) {
1761 size = max_size;
1762 DBUSERR(("%s: overriding size=%d\n", __FUNCTION__, max_size));
1763 }
1764
1765 loopback_tx_cnt = 0;
1766 loopback_rx_cnt = 0;
1767 tx_failed_cnt = 0;
1768 loopback_size = size;
1769
1770 while (loopback_tx_cnt < cnt) {
1771 uint32 *x;
1772 int pkt_size = loopback_size;
1773
1774 p = PKTGET(usbos_info->pub->osh, pkt_size, TRUE);
1775 if (p == NULL) {
1776 DBUSERR(("%s:%d Failed to allocate packet sz=%d\n", __FUNCTION__,
1777 __LINE__, pkt_size));
1778 return BCME_ERROR;
1779 }
1780 x = (uint32 *)PKTDATA(usbos_info->pub->osh, p);
1781 *x = LOOPBACK_PKT_START;
1782 buf = (unsigned char *)x;
1783 for (j = 0x4; j < pkt_size; j++) {
1784 buf[j] = j % 0x100;
1785 }
1786 rc = dbus_send_buf(usbos_info->pub, buf, pkt_size, p);
1787 if (rc != BCME_OK) {
1788 DBUSERR(("%s:%d Freeing packet \n", __FUNCTION__, __LINE__));
1789 PKTFREE(usbos_info->pub->osh, p, TRUE);
1790 dbus_usbos_wait(usbos_info, 1);
1791 tx_failed_cnt++;
1792 } else {
1793 loopback_tx_cnt++;
1794 tx_failed_cnt = 0;
1795 }
1796 if (tx_failed_cnt == 0x5) {
1797 DBUSERR(("%s : Failed to send loopback packets cnt=%d "
1798 "loopback_tx_cnt=%d\n",
1799 __FUNCTION__, cnt, loopback_tx_cnt));
1800 break;
1801 }
1802 }
1803 printf("Transmitted %d loopback packets of size %d\n", loopback_tx_cnt,
1804 loopback_size);
1805
1806 last_rx_cnt = loopback_rx_cnt;
1807 while (loopback_rx_cnt < loopback_tx_cnt) {
1808 dbus_usbos_wait(usbos_info, 1);
1809 if (loopback_rx_cnt <= last_rx_cnt) {
1810 DBUSERR(("%s: Matched rx cnt stuck at %d \n", __FUNCTION__,
1811 last_rx_cnt));
1812 return BCME_ERROR;
1813 }
1814 last_rx_cnt = loopback_rx_cnt;
1815 }
1816 printf("Received %d loopback packets of size %d\n", loopback_tx_cnt,
1817 loopback_size);
1818
1819 return BCME_OK;
1820 } /* dbus_usbos_loopback_tx */
1821
1822 /**
1823 * Higher layer (dbus_usb.c) wants to transmit an I/O Request Block
1824 * @param[in] txirb txirb->pkt, if non-zero, contains a single or a chain of
1825 * packets
1826 */
dbus_usbos_intf_send_irb(void * bus,dbus_irb_tx_t * txirb)1827 static int dbus_usbos_intf_send_irb(void *bus, dbus_irb_tx_t *txirb)
1828 {
1829 usbos_info_t *usbos_info = (usbos_info_t *)bus;
1830 urb_req_t *req, *req_zlp = NULL;
1831 int ret = DBUS_OK;
1832 unsigned long flags;
1833 void *pkt;
1834 uint32 buffer_length;
1835 uint8 *buf;
1836
1837 if ((usbos_info == NULL) || !usbos_info->tx_pipe) {
1838 return DBUS_ERR;
1839 }
1840
1841 if (txirb->pkt != NULL) {
1842 buffer_length = pkttotlen(usbos_info->pub->osh, txirb->pkt);
1843 /* In case of multiple packets the values below may be overwritten */
1844 txirb->send_buf = NULL;
1845 buf = PKTDATA(usbos_info->pub->osh, txirb->pkt);
1846 } else { /* txirb->buf != NULL */
1847 ASSERT(txirb->buf != NULL);
1848 ASSERT(txirb->send_buf == NULL);
1849 buffer_length = txirb->len;
1850 buf = txirb->buf;
1851 }
1852
1853 if (!(req = dbus_usbos_qdeq(&usbos_info->req_txfreeq,
1854 &usbos_info->txfree_lock))) {
1855 DBUSERR(("%s No free URB!\n", __FUNCTION__));
1856 return DBUS_ERR_TXDROP;
1857 }
1858
1859 /* If not using standard Linux kernel functionality for handling Zero Length
1860 * Packet(ZLP), the dbus needs to generate ZLP when length is multiple of
1861 * MaxPacketSize.
1862 */
1863 #ifndef WL_URB_ZPKT
1864 if (!(buffer_length % usbos_info->maxps)) {
1865 if (!(req_zlp = dbus_usbos_qdeq(&usbos_info->req_txfreeq,
1866 &usbos_info->txfree_lock))) {
1867 DBUSERR(("%s No free URB for ZLP!\n", __FUNCTION__));
1868 dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
1869 &usbos_info->txfree_lock);
1870 return DBUS_ERR_TXDROP;
1871 }
1872
1873 /* No txirb, so that dbus_usbos_send_complete can differentiate between
1874 * DATA and ZLP.
1875 */
1876 req_zlp->arg = NULL;
1877 req_zlp->usbinfo = usbos_info;
1878 req_zlp->buf_len = 0;
1879
1880 usb_fill_bulk_urb(req_zlp->urb, usbos_info->usb, usbos_info->tx_pipe,
1881 NULL, 0, (usb_complete_t)dbus_usbos_send_complete,
1882 req_zlp);
1883
1884 req_zlp->urb->transfer_flags |= URB_QUEUE_BULK;
1885 }
1886 #endif /* !WL_URB_ZPKT */
1887
1888 #ifndef USBOS_TX_THREAD
1889 /* Disable USB autosuspend until this request completes, request USB resume
1890 * if needed. Because this call runs asynchronously, there is no guarantee
1891 * the bus is resumed before the URB is submitted, and the URB might be
1892 * dropped. Use USBOS_TX_THREAD to avoid this.
1893 */
1894 USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info.intf);
1895 #endif /* !USBOS_TX_THREAD */
1896
1897 spin_lock_irqsave(&usbos_info->txlock, flags);
1898
1899 req->arg = txirb;
1900 req->usbinfo = usbos_info;
1901 req->buf_len = 0;
1902
1903 /* Prepare the URB */
1904 if (txirb->pkt != NULL) {
1905 uint32 pktlen;
1906 uint8 *transfer_buf;
1907
1908 /* For multiple packets, allocate contiguous buffer and copy packet data
1909 * to it */
1910 if (PKTNEXT(usbos_info->pub->osh, txirb->pkt)) {
1911 transfer_buf = MALLOC(usbos_info->pub->osh, buffer_length);
1912 if (!transfer_buf) {
1913 ret = DBUS_ERR_TXDROP;
1914 DBUSERR(("fail to alloc to usb buffer\n"));
1915 goto fail;
1916 }
1917
1918 pkt = txirb->pkt;
1919 txirb->send_buf = transfer_buf;
1920 req->buf_len = buffer_length;
1921
1922 while (pkt) {
1923 pktlen = PKTLEN(usbos_info->pub->osh, pkt);
1924 bcopy(PKTDATA(usbos_info->pub->osh, pkt), transfer_buf, pktlen);
1925 transfer_buf += pktlen;
1926 pkt = PKTNEXT(usbos_info->pub->osh, pkt);
1927 }
1928
1929 ASSERT(((uint8 *)txirb->send_buf + buffer_length) == transfer_buf);
1930
1931 /* Overwrite buf pointer with pointer to allocated contiguous
1932 * transfer_buf
1933 */
1934 buf = txirb->send_buf;
1935 }
1936 }
1937
1938 usb_fill_bulk_urb(req->urb, usbos_info->usb, usbos_info->tx_pipe, buf,
1939 buffer_length, (usb_complete_t)dbus_usbos_send_complete,
1940 req);
1941
1942 req->urb->transfer_flags |= URB_QUEUE_BULK;
1943
1944 #ifdef USBOS_TX_THREAD
1945 /* Enqueue TX request, the TX thread will resume the bus if needed and
1946 * submit it asynchronously
1947 */
1948 dbus_usbos_qenq(&usbos_info->usbos_tx_list, req,
1949 &usbos_info->usbos_tx_list_lock);
1950 if (req_zlp != NULL) {
1951 dbus_usbos_qenq(&usbos_info->usbos_tx_list, req_zlp,
1952 &usbos_info->usbos_tx_list_lock);
1953 }
1954 spin_unlock_irqrestore(&usbos_info->txlock, flags);
1955
1956 wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
1957 return DBUS_OK;
1958 #else
1959 if ((ret = USB_SUBMIT_URB(req->urb))) {
1960 ret = DBUS_ERR_TXDROP;
1961 goto fail;
1962 }
1963
1964 dbus_usbos_qenq(&usbos_info->req_txpostedq, req,
1965 &usbos_info->txposted_lock);
1966 atomic_inc(&usbos_info->txposted);
1967
1968 if (req_zlp != NULL) {
1969 if ((ret = USB_SUBMIT_URB(req_zlp->urb))) {
1970 DBUSERR(("failed to submit ZLP URB!\n"));
1971 ASSERT(0);
1972 ret = DBUS_ERR_TXDROP;
1973 goto fail2;
1974 }
1975
1976 dbus_usbos_qenq(&usbos_info->req_txpostedq, req_zlp,
1977 &usbos_info->txposted_lock);
1978 /* Also increment txposted for zlp packet, as it will be decremented in
1979 * dbus_usbos_send_complete()
1980 */
1981 atomic_inc(&usbos_info->txposted);
1982 }
1983
1984 spin_unlock_irqrestore(&usbos_info->txlock, flags);
1985 return DBUS_OK;
1986 #endif /* USBOS_TX_THREAD */
1987
1988 fail:
1989 if (txirb->send_buf != NULL) {
1990 MFREE(usbos_info->pub->osh, txirb->send_buf, req->buf_len);
1991 txirb->send_buf = NULL;
1992 req->buf_len = 0;
1993 }
1994 dbus_usbos_qenq(&usbos_info->req_txfreeq, req, &usbos_info->txfree_lock);
1995 #ifndef USBOS_TX_THREAD
1996 fail2:
1997 #endif
1998 if (req_zlp != NULL) {
1999 dbus_usbos_qenq(&usbos_info->req_txfreeq, req_zlp,
2000 &usbos_info->txfree_lock);
2001 }
2002
2003 spin_unlock_irqrestore(&usbos_info->txlock, flags);
2004
2005 #ifndef USBOS_TX_THREAD
2006 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2007 #endif /* !USBOS_TX_THREAD */
2008
2009 return ret;
2010 } /* dbus_usbos_intf_send_irb */
2011
2012 /** Higher layer (dbus_usb.c) recycles a received (and used) packet. */
dbus_usbos_intf_recv_irb(void * bus,dbus_irb_rx_t * rxirb)2013 static int dbus_usbos_intf_recv_irb(void *bus, dbus_irb_rx_t *rxirb)
2014 {
2015 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2016 int ret = DBUS_OK;
2017
2018 if (usbos_info == NULL) {
2019 return DBUS_ERR;
2020 }
2021
2022 ret = dbus_usbos_recv_urb_submit(usbos_info, rxirb, 0);
2023 return ret;
2024 }
2025
dbus_usbos_intf_recv_irb_from_ep(void * bus,dbus_irb_rx_t * rxirb,uint32 ep_idx)2026 static int dbus_usbos_intf_recv_irb_from_ep(void *bus, dbus_irb_rx_t *rxirb,
2027 uint32 ep_idx)
2028 {
2029 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2030 int ret = DBUS_OK;
2031
2032 if (usbos_info == NULL) {
2033 return DBUS_ERR;
2034 }
2035
2036 #ifdef INTR_EP_ENABLE
2037 /* By specifying the ep_idx value of 0xff, the cdc layer is asking to
2038 * submit an interrupt URB
2039 */
2040 if (rxirb == NULL && ep_idx == 0xff) {
2041 /* submit intr URB */
2042 if ((ret = USB_SUBMIT_URB(usbos_info->intr_urb)) < 0) {
2043 DBUSERR(("%s intr USB_SUBMIT_URB failed, status %d\n", __FUNCTION__,
2044 ret));
2045 }
2046 return ret;
2047 }
2048 #else
2049 if (rxirb == NULL) {
2050 return DBUS_ERR;
2051 }
2052 #endif /* INTR_EP_ENABLE */
2053
2054 ret = dbus_usbos_recv_urb_submit(usbos_info, rxirb, ep_idx);
2055 return ret;
2056 }
2057
2058 /** Higher layer (dbus_usb.c) want to cancel an IRB */
dbus_usbos_intf_cancel_irb(void * bus,dbus_irb_tx_t * txirb)2059 static int dbus_usbos_intf_cancel_irb(void *bus, dbus_irb_tx_t *txirb)
2060 {
2061 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2062
2063 if (usbos_info == NULL) {
2064 return DBUS_ERR;
2065 }
2066
2067 return DBUS_ERR;
2068 }
2069
2070 /** Only one CTL transfer can be pending at any time. This function may block.
2071 */
dbus_usbos_intf_send_ctl(void * bus,uint8 * buf,int len)2072 static int dbus_usbos_intf_send_ctl(void *bus, uint8 *buf, int len)
2073 {
2074 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2075 uint16 size;
2076 #ifndef USBOS_TX_THREAD
2077 int status;
2078 #endif /* USBOS_TX_THREAD */
2079
2080 if ((usbos_info == NULL) || (buf == NULL) || (len == 0)) {
2081 return DBUS_ERR;
2082 }
2083
2084 if (usbos_info->ctl_urb == NULL) {
2085 return DBUS_ERR;
2086 }
2087
2088 /* Block until a pending CTL transfer has completed */
2089 if (down_interruptible(&usbos_info->ctl_lock) != 0) {
2090 return DBUS_ERR_TXCTLFAIL;
2091 }
2092
2093 #ifdef USBOS_TX_THREAD
2094 ASSERT(usbos_info->ctl_state == USBOS_REQUEST_STATE_UNSCHEDULED);
2095 #else
2096 /* Disable USB autosuspend until this request completes, request USB resume
2097 * if needed. Because this call runs asynchronously, there is no guarantee
2098 * the bus is resumed before the URB is submitted, and the URB might be
2099 * dropped. Use USBOS_TX_THREAD to avoid this.
2100 */
2101 USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info.intf);
2102 #endif /* USBOS_TX_THREAD */
2103
2104 size = len;
2105 usbos_info->ctl_write.wLength = cpu_to_le16p(&size);
2106 usbos_info->ctl_urb->transfer_buffer_length = size;
2107
2108 usb_fill_control_urb(usbos_info->ctl_urb, usbos_info->usb,
2109 usb_sndctrlpipe(usbos_info->usb, 0),
2110 (unsigned char *)&usbos_info->ctl_write, buf, size,
2111 (usb_complete_t)dbus_usbos_ctlwrite_complete,
2112 usbos_info);
2113
2114 #ifdef USBOS_TX_THREAD
2115 /* Enqueue CTRL request for transmission by the TX thread. The
2116 * USB bus will first be resumed if needed.
2117 */
2118 usbos_info->ctl_state = USBOS_REQUEST_STATE_SCHEDULED;
2119 wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
2120 #else
2121 status = USB_SUBMIT_URB(usbos_info->ctl_urb);
2122 if (status < 0) {
2123 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__, status));
2124 up(&usbos_info->ctl_lock);
2125
2126 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2127
2128 return DBUS_ERR_TXCTLFAIL;
2129 }
2130 #endif /* USBOS_TX_THREAD */
2131
2132 return DBUS_OK;
2133 } /* dbus_usbos_intf_send_ctl */
2134
2135 /** This function does not seem to be called by anyone, including dbus_usb.c */
dbus_usbos_intf_recv_ctl(void * bus,uint8 * buf,int len)2136 static int dbus_usbos_intf_recv_ctl(void *bus, uint8 *buf, int len)
2137 {
2138 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2139 int status;
2140 uint16 size;
2141
2142 if ((usbos_info == NULL) || (buf == NULL) || (len == 0)) {
2143 return DBUS_ERR;
2144 }
2145
2146 if (usbos_info->ctl_urb == NULL) {
2147 return DBUS_ERR;
2148 }
2149
2150 /* Block until a pending CTRL transfer has completed */
2151 if (down_interruptible(&usbos_info->ctl_lock) != 0) {
2152 return DBUS_ERR_TXCTLFAIL;
2153 }
2154
2155 /* Disable USB autosuspend until this request completes, request USB resume
2156 * if needed. */
2157 USB_AUTOPM_GET_INTERFACE_ASYNC(g_probe_info.intf);
2158
2159 size = len;
2160 usbos_info->ctl_read.wLength = cpu_to_le16p(&size);
2161 usbos_info->ctl_urb->transfer_buffer_length = size;
2162
2163 if (usbos_info->rxctl_deferrespok) {
2164 /* BMAC model */
2165 usbos_info->ctl_read.bRequestType =
2166 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
2167 usbos_info->ctl_read.bRequest = DL_DEFER_RESP_OK;
2168 } else {
2169 /* full dongle model */
2170 usbos_info->ctl_read.bRequestType =
2171 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2172 usbos_info->ctl_read.bRequest = 1;
2173 }
2174
2175 usb_fill_control_urb(usbos_info->ctl_urb, usbos_info->usb,
2176 usb_rcvctrlpipe(usbos_info->usb, 0),
2177 (unsigned char *)&usbos_info->ctl_read, buf, size,
2178 (usb_complete_t)dbus_usbos_ctlread_complete,
2179 usbos_info);
2180
2181 status = USB_SUBMIT_URB(usbos_info->ctl_urb);
2182 if (status < 0) {
2183 DBUSERR(("%s: usb_submit_urb failed %d\n", __FUNCTION__, status));
2184 up(&usbos_info->ctl_lock);
2185
2186 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2187
2188 return DBUS_ERR_RXCTLFAIL;
2189 }
2190
2191 return DBUS_OK;
2192 }
2193
dbus_usbos_intf_get_attrib(void * bus,dbus_attrib_t * attrib)2194 static int dbus_usbos_intf_get_attrib(void *bus, dbus_attrib_t *attrib)
2195 {
2196 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2197
2198 if ((usbos_info == NULL) || (attrib == NULL)) {
2199 return DBUS_ERR;
2200 }
2201
2202 attrib->bustype = DBUS_USB;
2203 attrib->vid = g_probe_info.vid;
2204 attrib->pid = g_probe_info.pid;
2205 attrib->devid = 0x4322;
2206
2207 attrib->nchan = 1;
2208
2209 /* MaxPacketSize for USB hi-speed bulk out is 512 bytes
2210 * and 64-bytes for full-speed.
2211 * When sending pkt > MaxPacketSize, Host SW breaks it
2212 * up into multiple packets.
2213 */
2214 attrib->mtu = usbos_info->maxps;
2215
2216 return DBUS_OK;
2217 }
2218
2219 /** Called by higher layer (dbus_usb.c) when it wants to 'up' the USB interface
2220 * to the dongle */
dbus_usbos_intf_up(void * bus)2221 static int dbus_usbos_intf_up(void *bus)
2222 {
2223 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2224 uint16 ifnum;
2225 #ifdef BCMUSBDEV_COMPOSITE
2226 int wlan_if = 0;
2227 #endif
2228 if (usbos_info == NULL) {
2229 return DBUS_ERR;
2230 }
2231
2232 if (usbos_info->usb == NULL) {
2233 return DBUS_ERR;
2234 }
2235
2236 #if defined(INTR_EP_ENABLE)
2237 /* full dongle use intr EP, bmac doesn't use it */
2238 if (usbos_info->intr_urb) {
2239 int ret;
2240
2241 usb_fill_int_urb(usbos_info->intr_urb, usbos_info->usb,
2242 usbos_info->intr_pipe, &usbos_info->intr,
2243 usbos_info->intr_size,
2244 (usb_complete_t)dbus_usbos_intr_complete, usbos_info,
2245 usbos_info->interval);
2246
2247 if ((ret = USB_SUBMIT_URB(usbos_info->intr_urb))) {
2248 DBUSERR(("%s USB_SUBMIT_URB failed with status %d\n", __FUNCTION__,
2249 ret));
2250 return DBUS_ERR;
2251 }
2252 }
2253 #endif
2254
2255 if (usbos_info->ctl_urb) {
2256 usbos_info->ctl_in_pipe = usb_rcvctrlpipe(usbos_info->usb, 0);
2257 usbos_info->ctl_out_pipe = usb_sndctrlpipe(usbos_info->usb, 0);
2258
2259 #ifdef BCMUSBDEV_COMPOSITE
2260 wlan_if = dbus_usbos_intf_wlan(usbos_info->usb);
2261 ifnum = cpu_to_le16(IFDESC(usbos_info->usb, wlan_if).bInterfaceNumber);
2262 #else
2263 ifnum =
2264 cpu_to_le16(IFDESC(usbos_info->usb, CONTROL_IF).bInterfaceNumber);
2265 #endif /* BCMUSBDEV_COMPOSITE */
2266 /* CTL Write */
2267 usbos_info->ctl_write.bRequestType =
2268 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2269 usbos_info->ctl_write.bRequest = 0;
2270 usbos_info->ctl_write.wValue = cpu_to_le16(0);
2271 usbos_info->ctl_write.wIndex = cpu_to_le16p(&ifnum);
2272
2273 /* CTL Read */
2274 usbos_info->ctl_read.bRequestType =
2275 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
2276 usbos_info->ctl_read.bRequest = 1;
2277 usbos_info->ctl_read.wValue = cpu_to_le16(0);
2278 usbos_info->ctl_read.wIndex = cpu_to_le16p(&ifnum);
2279 }
2280
2281 /* Success, indicate usbos_info is fully up */
2282 dbus_usbos_state_change(usbos_info, DBUS_STATE_UP);
2283
2284 return DBUS_OK;
2285 } /* dbus_usbos_intf_up */
2286
dbus_usbos_intf_down(void * bus)2287 static int dbus_usbos_intf_down(void *bus)
2288 {
2289 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2290
2291 if (usbos_info == NULL) {
2292 return DBUS_ERR;
2293 }
2294
2295 dbusos_stop(usbos_info);
2296 return DBUS_OK;
2297 }
2298
dbus_usbos_intf_stop(void * bus)2299 static int dbus_usbos_intf_stop(void *bus)
2300 {
2301 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2302
2303 if (usbos_info == NULL) {
2304 return DBUS_ERR;
2305 }
2306
2307 dbusos_stop(usbos_info);
2308 return DBUS_OK;
2309 }
2310
2311 /** Called by higher layer (dbus_usb.c) */
dbus_usbos_intf_set_config(void * bus,dbus_config_t * config)2312 static int dbus_usbos_intf_set_config(void *bus, dbus_config_t *config)
2313 {
2314 int err = DBUS_ERR;
2315 usbos_info_t *usbos_info = bus;
2316
2317 if (config->config_id == DBUS_CONFIG_ID_RXCTL_DEFERRES) {
2318 usbos_info->rxctl_deferrespok = config->rxctl_deferrespok;
2319 err = DBUS_OK;
2320 } else if (config->config_id == DBUS_CONFIG_ID_AGGR_LIMIT) {
2321 /* DBUS_CONFIG_ID_AGGR_LIMIT shouldn't be called after probe stage */
2322 ASSERT(disc_arg == NULL);
2323 ASSERT(config->aggr_param.maxrxsf > 0);
2324 ASSERT(config->aggr_param.maxrxsize > 0);
2325 if (config->aggr_param.maxrxsize > usbos_info->rxbuf_len) {
2326 int state = usbos_info->pub->busstate;
2327 dbus_usbos_unlink(&usbos_info->req_rxpostedq,
2328 &usbos_info->rxposted_lock);
2329 while (atomic_read(&usbos_info->rxposted)) {
2330 DBUSTRACE(("%s rxposted is %d, delay 1 ms\n", __FUNCTION__,
2331 atomic_read(&usbos_info->rxposted)));
2332 dbus_usbos_wait(usbos_info, 1);
2333 }
2334 usbos_info->rxbuf_len = config->aggr_param.maxrxsize;
2335 dbus_usbos_state_change(usbos_info, state);
2336 }
2337 err = DBUS_OK;
2338 }
2339
2340 return err;
2341 }
2342
2343 /** Called by dbus_usb.c when it wants to download firmware into the dongle */
dbus_usbos_dl_cmd(usbos_info_t * usbinfo,uint8 cmd,void * buffer,int buflen)2344 bool dbus_usbos_dl_cmd(usbos_info_t *usbinfo, uint8 cmd, void *buffer,
2345 int buflen)
2346 {
2347 int transferred;
2348 int index = 0;
2349 char *tmpbuf;
2350
2351 if ((usbinfo == NULL) || (buffer == NULL) || (buflen == 0)) {
2352 return FALSE;
2353 }
2354
2355 tmpbuf = (char *)MALLOC(usbinfo->pub->osh, buflen);
2356 if (!tmpbuf) {
2357 DBUSERR(("%s: Unable to allocate memory \n", __FUNCTION__));
2358 return FALSE;
2359 }
2360
2361 #ifdef BCM_REQUEST_FW
2362 if (cmd == DL_GO) {
2363 index = 1;
2364 }
2365 #endif
2366
2367 /* Disable USB autosuspend until this request completes, request USB resume
2368 * if needed. */
2369 USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2370
2371 transferred =
2372 USB_CONTROL_MSG(usbinfo->usb, usb_rcvctrlpipe(usbinfo->usb, 0), cmd,
2373 (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE), 0,
2374 index, (void *)tmpbuf, buflen, USB_CTRL_EP_TIMEOUT);
2375 if (transferred == buflen) {
2376 memcpy(buffer, tmpbuf, buflen);
2377 } else {
2378 DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__, transferred));
2379 }
2380
2381 USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2382
2383 MFREE(usbinfo->pub->osh, tmpbuf, buflen);
2384 return (transferred == buflen);
2385 }
2386
2387 /**
2388 * Called by dbus_usb.c when it wants to download a buffer into the dongle (e.g.
2389 * as part of the download process, when writing nvram variables).
2390 */
dbus_write_membytes(usbos_info_t * usbinfo,bool set,uint32 address,uint8 * data,uint size)2391 int dbus_write_membytes(usbos_info_t *usbinfo, bool set, uint32 address,
2392 uint8 *data, uint size)
2393 {
2394 hwacc_t hwacc;
2395 int write_bytes = 4;
2396 int status;
2397 int retval = 0;
2398
2399 DBUSTRACE(("Enter:%s\n", __FUNCTION__));
2400
2401 /* Read is not supported */
2402 if (set == 0) {
2403 DBUSERR(("Currently read is not supported!!\n"));
2404 return -1;
2405 }
2406
2407 USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2408
2409 hwacc.cmd = DL_CMD_WRHW;
2410 hwacc.addr = address;
2411
2412 DBUSTRACE(("Address:%x size:%d", hwacc.addr, size));
2413 do {
2414 if (size >= 0x4) {
2415 write_bytes = 0x4;
2416 } else if (size >= 0x2) {
2417 write_bytes = 0x2;
2418 } else {
2419 write_bytes = 1;
2420 }
2421
2422 hwacc.len = write_bytes;
2423
2424 while (size >= write_bytes) {
2425 hwacc.data = *((unsigned int *)data);
2426
2427 status = USB_CONTROL_MSG(
2428 usbinfo->usb, usb_sndctrlpipe(usbinfo->usb, 0), DL_WRHW,
2429 (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE), 1, 0,
2430 (char *)&hwacc, sizeof(hwacc_t), USB_CTRL_EP_TIMEOUT);
2431 if (status < 0) {
2432 retval = -1;
2433 DBUSERR((" Ctrl write hwacc failed w/status %d @ address:%x \n",
2434 status, hwacc.addr));
2435 goto err;
2436 }
2437
2438 hwacc.addr += write_bytes;
2439 data += write_bytes;
2440 size -= write_bytes;
2441 }
2442 } while (size > 0);
2443
2444 err:
2445 USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2446
2447 return retval;
2448 }
2449
dbus_usbos_readreg(void * bus,uint32 regaddr,int datalen,uint32 * value)2450 int dbus_usbos_readreg(void *bus, uint32 regaddr, int datalen, uint32 *value)
2451 {
2452 usbos_info_t *usbinfo = (usbos_info_t *)bus;
2453 int ret = DBUS_OK;
2454 int transferred;
2455 uint32 cmd;
2456 hwacc_t hwacc;
2457
2458 if (usbinfo == NULL) {
2459 return DBUS_ERR;
2460 }
2461
2462 if (datalen == 1) {
2463 cmd = DL_RDHW8;
2464 } else if (datalen == 0x2) {
2465 cmd = DL_RDHW16;
2466 } else {
2467 cmd = DL_RDHW32;
2468 }
2469
2470 USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2471
2472 transferred =
2473 USB_CONTROL_MSG(usbinfo->usb, usb_rcvctrlpipe(usbinfo->usb, 0), cmd,
2474 (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE),
2475 (uint16)(regaddr), (uint16)(regaddr >> 16),
2476 (void *)&hwacc, sizeof(hwacc_t), USB_CTRL_EP_TIMEOUT);
2477 if (transferred >= sizeof(hwacc_t)) {
2478 *value = hwacc.data;
2479 } else {
2480 DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__, transferred));
2481 ret = DBUS_ERR;
2482 }
2483
2484 USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2485
2486 return ret;
2487 }
2488
dbus_usbos_writereg(void * bus,uint32 regaddr,int datalen,uint32 data)2489 int dbus_usbos_writereg(void *bus, uint32 regaddr, int datalen, uint32 data)
2490 {
2491 usbos_info_t *usbinfo = (usbos_info_t *)bus;
2492 int ret = DBUS_OK;
2493 int transferred;
2494 uint32 cmd = DL_WRHW;
2495 hwacc_t hwacc;
2496
2497 if (usbinfo == NULL) {
2498 return DBUS_ERR;
2499 }
2500
2501 USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2502
2503 hwacc.cmd = DL_WRHW;
2504 hwacc.addr = regaddr;
2505 hwacc.data = data;
2506 hwacc.len = datalen;
2507
2508 transferred = USB_CONTROL_MSG(
2509 usbinfo->usb, usb_sndctrlpipe(usbinfo->usb, 0), cmd,
2510 (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE), 1, 0,
2511 (void *)&hwacc, sizeof(hwacc_t), USB_CTRL_EP_TIMEOUT);
2512 if (transferred != sizeof(hwacc_t)) {
2513 DBUSERR(("%s: usb_control_msg failed %d\n", __FUNCTION__, transferred));
2514 ret = DBUS_ERR;
2515 }
2516
2517 USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2518
2519 return ret;
2520 }
2521
dbus_usbos_wait(usbos_info_t * usbinfo,uint16 ms)2522 int dbus_usbos_wait(usbos_info_t *usbinfo, uint16 ms)
2523 {
2524 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
2525 if (in_interrupt()) {
2526 mdelay(ms);
2527 } else {
2528 msleep_interruptible(ms);
2529 }
2530 #else
2531 wait_ms(ms);
2532 #endif
2533 return DBUS_OK;
2534 }
2535
2536 /** Called by dbus_usb.c as part of the firmware download process */
dbus_usbos_dl_send_bulk(usbos_info_t * usbinfo,void * buffer,int len)2537 bool dbus_usbos_dl_send_bulk(usbos_info_t *usbinfo, void *buffer, int len)
2538 {
2539 bool ret = TRUE;
2540 int status;
2541 int transferred = 0;
2542
2543 if (usbinfo == NULL) {
2544 return DBUS_ERR;
2545 }
2546
2547 USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2548
2549 status = USB_BULK_MSG(usbinfo->usb, usbinfo->tx_pipe, buffer, len,
2550 &transferred, USB_BULK_EP_TIMEOUT);
2551 if (status < 0) {
2552 DBUSERR(("%s: usb_bulk_msg failed %d\n", __FUNCTION__, status));
2553 ret = FALSE;
2554 }
2555
2556 USB_AUTOPM_PUT_INTERFACE(g_probe_info.intf);
2557
2558 return ret;
2559 }
2560
dbus_usbos_intf_recv_needed(void * bus)2561 static bool dbus_usbos_intf_recv_needed(void *bus)
2562 {
2563 return FALSE;
2564 }
2565
2566 /**
2567 * Higher layer (dbus_usb.c) wants to execute a function on the condition that
2568 * the rx spin lock has been acquired.
2569 */
dbus_usbos_intf_exec_rxlock(void * bus,exec_cb_t cb,struct exec_parms * args)2570 static void *dbus_usbos_intf_exec_rxlock(void *bus, exec_cb_t cb,
2571 struct exec_parms *args)
2572 {
2573 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2574 void *ret;
2575 unsigned long flags;
2576
2577 if (usbos_info == NULL) {
2578 return NULL;
2579 }
2580
2581 spin_lock_irqsave(&usbos_info->rxlock, flags);
2582 ret = cb(args);
2583 spin_unlock_irqrestore(&usbos_info->rxlock, flags);
2584
2585 return ret;
2586 }
2587
dbus_usbos_intf_exec_txlock(void * bus,exec_cb_t cb,struct exec_parms * args)2588 static void *dbus_usbos_intf_exec_txlock(void *bus, exec_cb_t cb,
2589 struct exec_parms *args)
2590 {
2591 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2592 void *ret;
2593 unsigned long flags;
2594
2595 if (usbos_info == NULL) {
2596 return NULL;
2597 }
2598
2599 spin_lock_irqsave(&usbos_info->txlock, flags);
2600 ret = cb(args);
2601 spin_unlock_irqrestore(&usbos_info->txlock, flags);
2602
2603 return ret;
2604 }
2605
2606 /**
2607 * if an error condition was detected in this module, the higher DBUS layer
2608 * (dbus_usb.c) has to be notified.
2609 */
dbus_usbos_errhandler(void * bus,int err)2610 int dbus_usbos_errhandler(void *bus, int err)
2611 {
2612 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2613
2614 if (usbos_info == NULL) {
2615 return DBUS_ERR;
2616 }
2617
2618 if (usbos_info->cbarg && usbos_info->cbs) {
2619 if (usbos_info->cbs->errhandler) {
2620 usbos_info->cbs->errhandler(usbos_info->cbarg, err);
2621 }
2622 }
2623
2624 return DBUS_OK;
2625 }
2626
2627 /**
2628 * if a change in bus state was detected in this module, the higher DBUS layer
2629 * (dbus_usb.c) has to be notified.
2630 */
dbus_usbos_state_change(void * bus,int state)2631 int dbus_usbos_state_change(void *bus, int state)
2632 {
2633 usbos_info_t *usbos_info = (usbos_info_t *)bus;
2634
2635 if (usbos_info == NULL) {
2636 return DBUS_ERR;
2637 }
2638
2639 if (usbos_info->cbarg && usbos_info->cbs) {
2640 if (usbos_info->cbs->state_change) {
2641 usbos_info->cbs->state_change(usbos_info->cbarg, state);
2642 }
2643 }
2644
2645 usbos_info->pub->busstate = state;
2646 return DBUS_OK;
2647 }
2648
dbus_bus_osl_register(int vid,int pid,probe_cb_t prcb,disconnect_cb_t discb,void * prarg,dbus_intf_t ** intf,void * param1,void * param2)2649 int dbus_bus_osl_register(int vid, int pid, probe_cb_t prcb,
2650 disconnect_cb_t discb, void *prarg,
2651 dbus_intf_t **intf, void *param1, void *param2)
2652 {
2653 bzero(&g_probe_info, sizeof(probe_info_t));
2654
2655 probe_cb = prcb;
2656 disconnect_cb = discb;
2657 probe_arg = prarg;
2658
2659 devid_table[0].idVendor = vid;
2660 devid_table[0].idProduct = pid;
2661
2662 *intf = &dbus_usbos_intf;
2663
2664 USB_REGISTER();
2665
2666 return DBUS_ERR_NODEVICE;
2667 }
2668
dbus_bus_osl_deregister()2669 int dbus_bus_osl_deregister()
2670 {
2671 g_probe_info.dereged = TRUE;
2672
2673 DHD_MUTEX_LOCK();
2674 if (disconnect_cb && disc_arg && (g_probe_info.disc_cb_done == FALSE)) {
2675 disconnect_cb(disc_arg);
2676 disc_arg = NULL;
2677 }
2678 DHD_MUTEX_UNLOCK();
2679
2680 USB_DEREGISTER();
2681
2682 return DBUS_OK;
2683 }
2684
dbus_usbos_intf_attach(dbus_pub_t * pub,void * cbarg,dbus_intf_callbacks_t * cbs)2685 void *dbus_usbos_intf_attach(dbus_pub_t *pub, void *cbarg,
2686 dbus_intf_callbacks_t *cbs)
2687 {
2688 usbos_info_t *usbos_info;
2689
2690 if (g_probe_info.dldone == FALSE) {
2691 DBUSERR(("%s: err device not downloaded!\n", __FUNCTION__));
2692 return NULL;
2693 }
2694
2695 /* Sanity check for BUS_INFO() */
2696 ASSERT(OFFSETOF(usbos_info_t, pub) == 0);
2697
2698 usbos_info = MALLOC(pub->osh, sizeof(usbos_info_t));
2699 if (usbos_info == NULL) {
2700 return NULL;
2701 }
2702
2703 bzero(usbos_info, sizeof(usbos_info_t));
2704
2705 usbos_info->pub = pub;
2706 usbos_info->cbarg = cbarg;
2707 usbos_info->cbs = cbs;
2708
2709 /* Needed for disconnect() */
2710 g_probe_info.usbos_info = usbos_info;
2711
2712 /* Update USB Info */
2713 usbos_info->usb = g_probe_info.usb;
2714 usbos_info->rx_pipe = g_probe_info.rx_pipe;
2715 usbos_info->rx_pipe2 = g_probe_info.rx_pipe2;
2716 usbos_info->tx_pipe = g_probe_info.tx_pipe;
2717 usbos_info->intr_pipe = g_probe_info.intr_pipe;
2718 usbos_info->intr_size = g_probe_info.intr_size;
2719 usbos_info->interval = g_probe_info.interval;
2720 usbos_info->pub->device_speed = g_probe_info.device_speed;
2721 if (usbos_info->rx_pipe2) {
2722 usbos_info->pub->attrib.has_2nd_bulk_in_ep = 1;
2723 } else {
2724 usbos_info->pub->attrib.has_2nd_bulk_in_ep = 0;
2725 }
2726
2727 if (usbos_info->tx_pipe) {
2728 usbos_info->maxps = usb_maxpacket(usbos_info->usb, usbos_info->tx_pipe,
2729 usb_pipeout(usbos_info->tx_pipe));
2730 }
2731
2732 INIT_LIST_HEAD(&usbos_info->req_rxfreeq);
2733 INIT_LIST_HEAD(&usbos_info->req_txfreeq);
2734 INIT_LIST_HEAD(&usbos_info->req_rxpostedq);
2735 INIT_LIST_HEAD(&usbos_info->req_txpostedq);
2736 spin_lock_init(&usbos_info->rxfree_lock);
2737 spin_lock_init(&usbos_info->txfree_lock);
2738 spin_lock_init(&usbos_info->rxposted_lock);
2739 spin_lock_init(&usbos_info->txposted_lock);
2740 spin_lock_init(&usbos_info->rxlock);
2741 spin_lock_init(&usbos_info->txlock);
2742
2743 atomic_set(&usbos_info->rxposted, 0);
2744 atomic_set(&usbos_info->txposted, 0);
2745
2746 #ifdef USB_DISABLE_INT_EP
2747 usbos_info->intr_urb = NULL;
2748 #else
2749 if (!(usbos_info->intr_urb = USB_ALLOC_URB())) {
2750 DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__));
2751 goto fail;
2752 }
2753 #endif
2754
2755 if (!(usbos_info->ctl_urb = USB_ALLOC_URB())) {
2756 DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__));
2757 goto fail;
2758 }
2759
2760 init_waitqueue_head(&usbos_info->wait);
2761
2762 if (!(usbos_info->blk_urb =
2763 USB_ALLOC_URB())) { /* for embedded image downloading */
2764 DBUSERR(("%s: usb_alloc_urb (tx) failed\n", __FUNCTION__));
2765 goto fail;
2766 }
2767
2768 usbos_info->rxbuf_len = (uint)usbos_info->pub->rxsize;
2769
2770 atomic_set(&usbos_info->txallocated, 0);
2771 if (DBUS_OK !=
2772 dbus_usbos_urbreqs_alloc(usbos_info, usbos_info->pub->ntxq, FALSE)) {
2773 goto fail;
2774 }
2775
2776 atomic_set(&usbos_info->rxallocated, 0);
2777 if (DBUS_OK != dbus_usbos_urbreqs_alloc(usbos_info,
2778 MIN(DBUS_USB_RXQUEUE_BATCH_ADD, usbos_info->pub->nrxq),
2779 TRUE)) {
2780 goto fail;
2781 }
2782
2783 sema_init(&usbos_info->ctl_lock, 1);
2784
2785 #ifdef USBOS_THREAD
2786 if (dbus_usbos_thread_init(usbos_info) == NULL) {
2787 goto fail;
2788 }
2789 #endif /* USBOS_THREAD */
2790
2791 #ifdef USBOS_TX_THREAD
2792 if (dbus_usbos_tx_thread_init(usbos_info) == NULL) {
2793 goto fail;
2794 }
2795 #endif /* USBOS_TX_THREAD */
2796
2797 pub->dev_info = g_probe_info.usb;
2798
2799 return (void *)usbos_info;
2800 fail:
2801 if (usbos_info->intr_urb) {
2802 USB_FREE_URB(usbos_info->intr_urb);
2803 usbos_info->intr_urb = NULL;
2804 }
2805
2806 if (usbos_info->ctl_urb) {
2807 USB_FREE_URB(usbos_info->ctl_urb);
2808 usbos_info->ctl_urb = NULL;
2809 }
2810
2811 #if defined(BCM_REQUEST_FW)
2812 if (usbos_info->blk_urb) {
2813 USB_FREE_URB(usbos_info->blk_urb);
2814 usbos_info->blk_urb = NULL;
2815 }
2816 #endif
2817
2818 dbus_usbos_urbreqs_free(usbos_info, TRUE);
2819 atomic_set(&usbos_info->rxallocated, 0);
2820 dbus_usbos_urbreqs_free(usbos_info, FALSE);
2821 atomic_set(&usbos_info->txallocated, 0);
2822
2823 g_probe_info.usbos_info = NULL;
2824
2825 MFREE(pub->osh, usbos_info, sizeof(usbos_info_t));
2826 return NULL;
2827 } /* dbus_usbos_intf_attach */
2828
dbus_usbos_intf_detach(dbus_pub_t * pub,void * info)2829 void dbus_usbos_intf_detach(dbus_pub_t *pub, void *info)
2830 {
2831 usbos_info_t *usbos_info = (usbos_info_t *)info;
2832 osl_t *osh = pub->osh;
2833
2834 if (usbos_info == NULL) {
2835 return;
2836 }
2837
2838 #ifdef USBOS_TX_THREAD
2839 dbus_usbos_tx_thread_deinit(usbos_info);
2840 #endif /* USBOS_TX_THREAD */
2841
2842 /* Must unlink all URBs prior to driver unload;
2843 * otherwise an URB callback can occur after driver
2844 * has been de-allocated and rmmod'd
2845 */
2846 dbusos_stop(usbos_info);
2847
2848 if (usbos_info->intr_urb) {
2849 USB_FREE_URB(usbos_info->intr_urb);
2850 usbos_info->intr_urb = NULL;
2851 }
2852
2853 if (usbos_info->ctl_urb) {
2854 USB_FREE_URB(usbos_info->ctl_urb);
2855 usbos_info->ctl_urb = NULL;
2856 }
2857
2858 if (usbos_info->blk_urb) {
2859 USB_FREE_URB(usbos_info->blk_urb);
2860 usbos_info->blk_urb = NULL;
2861 }
2862
2863 dbus_usbos_urbreqs_free(usbos_info, TRUE);
2864 atomic_set(&usbos_info->rxallocated, 0);
2865 dbus_usbos_urbreqs_free(usbos_info, FALSE);
2866 atomic_set(&usbos_info->txallocated, 0);
2867
2868 #ifdef USBOS_THREAD
2869 dbus_usbos_thread_deinit(usbos_info);
2870 #endif /* USBOS_THREAD */
2871
2872 g_probe_info.usbos_info = NULL;
2873 MFREE(osh, usbos_info, sizeof(usbos_info_t));
2874 } /* dbus_usbos_intf_detach */
2875
2876 #ifdef USBOS_TX_THREAD
2877
dbus_usbos_tx_thread_init(usbos_info_t * usbos_info)2878 void *dbus_usbos_tx_thread_init(usbos_info_t *usbos_info)
2879 {
2880 spin_lock_init(&usbos_info->usbos_tx_list_lock);
2881 INIT_LIST_HEAD(&usbos_info->usbos_tx_list);
2882 init_waitqueue_head(&usbos_info->usbos_tx_queue_head);
2883
2884 usbos_info->usbos_tx_kt =
2885 kthread_create(dbus_usbos_tx_thread_func, usbos_info, "usb-tx-thread");
2886
2887 if (IS_ERR(usbos_info->usbos_tx_kt)) {
2888 DBUSERR(("Thread Creation failed\n"));
2889 return (NULL);
2890 }
2891
2892 usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
2893 wake_up_process(usbos_info->usbos_tx_kt);
2894
2895 return (usbos_info->usbos_tx_kt);
2896 }
2897
dbus_usbos_tx_thread_deinit(usbos_info_t * usbos_info)2898 void dbus_usbos_tx_thread_deinit(usbos_info_t *usbos_info)
2899 {
2900 urb_req_t *req;
2901
2902 if (usbos_info->usbos_tx_kt) {
2903 wake_up_interruptible(&usbos_info->usbos_tx_queue_head);
2904 kthread_stop(usbos_info->usbos_tx_kt);
2905 }
2906
2907 /* Move pending requests to free queue so they can be freed */
2908 while ((req = dbus_usbos_qdeq(&usbos_info->usbos_tx_list,
2909 &usbos_info->usbos_tx_list_lock)) != NULL) {
2910 dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
2911 &usbos_info->txfree_lock);
2912 }
2913 }
2914
2915 /**
2916 * Allow USB in-band resume to block by submitting CTRL and DATA URBs on a
2917 * separate thread.
2918 */
dbus_usbos_tx_thread_func(void * data)2919 int dbus_usbos_tx_thread_func(void *data)
2920 {
2921 usbos_info_t *usbos_info = (usbos_info_t *)data;
2922 urb_req_t *req;
2923 dbus_irb_tx_t *txirb;
2924 int ret;
2925 unsigned long flags;
2926
2927 #ifdef WL_THREADNICE
2928 set_user_nice(current, WL_THREADNICE);
2929 #endif
2930
2931 while (1) {
2932 /* Wait until there are URBs to submit */
2933 wait_event_interruptible_timeout(
2934 usbos_info->usbos_tx_queue_head,
2935 !list_empty(&usbos_info->usbos_tx_list) ||
2936 usbos_info->ctl_state == USBOS_REQUEST_STATE_SCHEDULED,
2937 0x64);
2938
2939 if (kthread_should_stop()) {
2940 break;
2941 }
2942
2943 /* Submit CTRL URB if needed */
2944 if (usbos_info->ctl_state == USBOS_REQUEST_STATE_SCHEDULED) {
2945 /* Disable USB autosuspend until this request completes. If the
2946 * interface was suspended, this call blocks until it has been
2947 * resumed.
2948 */
2949 USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2950
2951 usbos_info->ctl_state = USBOS_REQUEST_STATE_SUBMITTED;
2952
2953 ret = USB_SUBMIT_URB(usbos_info->ctl_urb);
2954 if (ret != 0) {
2955 DBUSERR(("%s CTRL USB_SUBMIT_URB failed, status %d\n",
2956 __FUNCTION__, ret));
2957
2958 usbos_info->ctl_state = USBOS_REQUEST_STATE_UNSCHEDULED;
2959 up(&usbos_info->ctl_lock);
2960
2961 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2962 }
2963 }
2964
2965 /* Submit all available TX URBs */
2966 while ((req = dbus_usbos_qdeq(&usbos_info->usbos_tx_list,
2967 &usbos_info->usbos_tx_list_lock)) !=
2968 NULL) {
2969 /* Disable USB autosuspend until this request completes. If the
2970 * interface was suspended, this call blocks until it has been
2971 * resumed.
2972 */
2973 USB_AUTOPM_GET_INTERFACE(g_probe_info.intf);
2974
2975 spin_lock_irqsave(&usbos_info->txlock, flags);
2976
2977 ret = USB_SUBMIT_URB(req->urb);
2978 if (ret == 0) {
2979 /* URB submitted successfully */
2980 dbus_usbos_qenq(&usbos_info->req_txpostedq, req,
2981 &usbos_info->txposted_lock);
2982 atomic_inc(&usbos_info->txposted);
2983 } else {
2984 /* Submitting the URB failed. */
2985 DBUSERR(("%s TX USB_SUBMIT_URB failed, status %d\n",
2986 __FUNCTION__, ret));
2987
2988 USB_AUTOPM_PUT_INTERFACE_ASYNC(g_probe_info.intf);
2989 }
2990
2991 spin_unlock_irqrestore(&usbos_info->txlock, flags);
2992
2993 if (ret != 0) {
2994 /* Cleanup and notify higher layers */
2995 dbus_usbos_qenq(&usbos_info->req_txfreeq, req,
2996 &usbos_info->txfree_lock);
2997
2998 txirb = req->arg;
2999 if (txirb->send_buf) {
3000 MFREE(usbos_info->pub->osh, txirb->send_buf, req->buf_len);
3001 txirb->send_buf = NULL;
3002 req->buf_len = 0;
3003 }
3004
3005 if (likely(usbos_info->cbarg && usbos_info->cbs)) {
3006 if (likely(usbos_info->cbs->send_irb_complete != NULL)) {
3007 usbos_info->cbs->send_irb_complete(
3008 usbos_info->cbarg, txirb, DBUS_ERR_TXDROP);
3009 }
3010 }
3011 }
3012 }
3013 }
3014
3015 return 0;
3016 } /* dbus_usbos_tx_thread_func */
3017
3018 #endif /* USBOS_TX_THREAD */
3019
3020 #ifdef USBOS_THREAD
3021
3022 /**
3023 * Increase system performance by creating a USB thread that runs parallel to
3024 * other system activity.
3025 */
dbus_usbos_thread_init(usbos_info_t * usbos_info)3026 static void *dbus_usbos_thread_init(usbos_info_t *usbos_info)
3027 {
3028 usbos_list_entry_t *entry;
3029 unsigned long flags, ii;
3030
3031 spin_lock_init(&usbos_info->usbos_list_lock);
3032 spin_lock_init(&usbos_info->ctrl_lock);
3033 INIT_LIST_HEAD(&usbos_info->usbos_list);
3034 INIT_LIST_HEAD(&usbos_info->usbos_free_list);
3035 init_waitqueue_head(&usbos_info->usbos_queue_head);
3036 atomic_set(&usbos_info->usbos_list_cnt, 0);
3037
3038 for (ii = 0; ii < (usbos_info->pub->nrxq + usbos_info->pub->ntxq); ii++) {
3039 entry = MALLOC(usbos_info->pub->osh, sizeof(usbos_list_entry_t));
3040 if (entry) {
3041 spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3042 list_add_tail((struct list_head *)entry,
3043 &usbos_info->usbos_free_list);
3044 spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3045 } else {
3046 DBUSERR(("Failed to create list\n"));
3047 }
3048 }
3049
3050 usbos_info->usbos_kt =
3051 kthread_create(dbus_usbos_thread_func, usbos_info, "usb-thread");
3052
3053 if (IS_ERR(usbos_info->usbos_kt)) {
3054 DBUSERR(("Thread Creation failed\n"));
3055 return (NULL);
3056 }
3057
3058 wake_up_process(usbos_info->usbos_kt);
3059
3060 return (usbos_info->usbos_kt);
3061 }
3062
dbus_usbos_thread_deinit(usbos_info_t * usbos_info)3063 static void dbus_usbos_thread_deinit(usbos_info_t *usbos_info)
3064 {
3065 struct list_head *cur, *next;
3066 usbos_list_entry_t *entry;
3067 unsigned long flags;
3068
3069 if (usbos_info->usbos_kt) {
3070 wake_up_interruptible(&usbos_info->usbos_queue_head);
3071 kthread_stop(usbos_info->usbos_kt);
3072 }
3073 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3074 #pragma GCC diagnostic push
3075 #pragma GCC diagnostic ignored "-Wcast-qual"
3076 #endif
3077 list_for_each_safe(cur, next, &usbos_info->usbos_list)
3078 {
3079 entry = list_entry(cur, struct usbos_list_entry, list);
3080 /* detach this entry from the list and then free the entry */
3081 spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3082 list_del(cur);
3083 MFREE(usbos_info->pub->osh, entry, sizeof(usbos_list_entry_t));
3084 spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3085 }
3086
3087 list_for_each_safe(cur, next, &usbos_info->usbos_free_list)
3088 {
3089 entry = list_entry(cur, struct usbos_list_entry, list);
3090 /* detach this entry from the list and then free the entry */
3091 spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3092 list_del(cur);
3093 MFREE(usbos_info->pub->osh, entry, sizeof(usbos_list_entry_t));
3094 spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3095 }
3096 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3097 #pragma GCC diagnostic pop
3098 #endif
3099 }
3100
3101 /** Process completed URBs in a worker thread */
dbus_usbos_thread_func(void * data)3102 static int dbus_usbos_thread_func(void *data)
3103 {
3104 usbos_info_t *usbos_info = (usbos_info_t *)data;
3105 usbos_list_entry_t *entry;
3106 struct list_head *cur, *next;
3107 unsigned long flags;
3108
3109 #ifdef WL_THREADNICE
3110 set_user_nice(current, WL_THREADNICE);
3111 #endif
3112
3113 while (1) {
3114 /* If the list is empty, then go to sleep */
3115 wait_event_interruptible_timeout(
3116 usbos_info->usbos_queue_head,
3117 atomic_read(&usbos_info->usbos_list_cnt) > 0, 0x64);
3118
3119 if (kthread_should_stop()) {
3120 break;
3121 }
3122
3123 spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3124
3125 /* For each entry on the list, process it. Remove the entry from
3126 * the list when done.
3127 */
3128 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3129 #pragma GCC diagnostic push
3130 #pragma GCC diagnostic ignored "-Wcast-qual"
3131 #endif
3132 list_for_each_safe(cur, next, &usbos_info->usbos_list)
3133 {
3134 urb_req_t *req;
3135 int len;
3136 int stat;
3137 usbos_info_t *usbos_info_local;
3138
3139 entry = list_entry(cur, struct usbos_list_entry, list);
3140 if (entry == NULL) {
3141 break;
3142 }
3143
3144 req = entry->urb_context;
3145 len = entry->urb_length;
3146 stat = entry->urb_status;
3147 usbos_info_local = req->usbinfo;
3148
3149 /* detach this entry from the list and attach it to the free list */
3150 list_del_init(cur);
3151 spin_unlock_irqrestore(&usbos_info_local->usbos_list_lock, flags);
3152
3153 dbus_usbos_recv_complete_handle(req, len, stat);
3154
3155 spin_lock_irqsave(&usbos_info_local->usbos_list_lock, flags);
3156
3157 list_add_tail(cur, &usbos_info_local->usbos_free_list);
3158
3159 atomic_dec(&usbos_info_local->usbos_list_cnt);
3160 }
3161
3162 spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3163 }
3164 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3165 #pragma GCC diagnostic pop
3166 #endif
3167
3168 return 0;
3169 } /* dbus_usbos_thread_func */
3170
3171 /** Called on Linux calling URB callback, see dbus_usbos_recv_complete() */
dbus_usbos_dispatch_schedule(CALLBACK_ARGS)3172 static void dbus_usbos_dispatch_schedule(CALLBACK_ARGS)
3173 {
3174 urb_req_t *req = urb->context;
3175 usbos_info_t *usbos_info = req->usbinfo;
3176 usbos_list_entry_t *entry;
3177 unsigned long flags;
3178 struct list_head *cur;
3179
3180 spin_lock_irqsave(&usbos_info->usbos_list_lock, flags);
3181
3182 cur = usbos_info->usbos_free_list.next;
3183 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3184 #pragma GCC diagnostic push
3185 #pragma GCC diagnostic ignored "-Wcast-qual"
3186 #endif
3187 entry = list_entry(cur, struct usbos_list_entry, list);
3188 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
3189 #pragma GCC diagnostic pop
3190 #endif
3191
3192 /* detach this entry from the free list and prepare it insert it to use list
3193 */
3194 list_del_init(cur);
3195
3196 if (entry) {
3197 entry->urb_context = urb->context;
3198 entry->urb_length = urb->actual_length;
3199 entry->urb_status = urb->status;
3200
3201 atomic_inc(&usbos_info->usbos_list_cnt);
3202 list_add_tail(cur, &usbos_info->usbos_list);
3203 } else {
3204 DBUSERR(("!!!!!!OUT OF MEMORY!!!!!!!\n"));
3205 }
3206
3207 spin_unlock_irqrestore(&usbos_info->usbos_list_lock, flags);
3208
3209 /* thread */
3210 wake_up_interruptible(&usbos_info->usbos_queue_head);
3211 } /* dbus_usbos_dispatch_schedule */
3212
3213 #endif /* USBOS_THREAD */
3214
3215 #ifdef BCM_REQUEST_FW
3216
3217 struct request_fw_context {
3218 const struct firmware *firmware;
3219 struct semaphore lock;
3220 };
3221
3222 /*
3223 * Callback for dbus_request_firmware().
3224 */
dbus_request_firmware_done(const struct firmware * firmware,void * ctx)3225 static void dbus_request_firmware_done(const struct firmware *firmware,
3226 void *ctx)
3227 {
3228 struct request_fw_context *context = (struct request_fw_context *)ctx;
3229
3230 /* Store the received firmware handle in the context and wake requester */
3231 context->firmware = firmware;
3232 up(&context->lock);
3233 }
3234
3235 /*
3236 * Send a firmware request and wait for completion.
3237 *
3238 * The use of the asynchronous version of request_firmware() is needed to avoid
3239 * kernel oopses when we just come out of system hibernate.
3240 */
dbus_request_firmware(const char * name,const struct firmware ** firmware)3241 static int dbus_request_firmware(const char *name,
3242 const struct firmware **firmware)
3243 {
3244 struct request_fw_context *context;
3245 int ret;
3246
3247 context = kzalloc(sizeof(*context), GFP_KERNEL);
3248 if (!context) {
3249 return -ENOMEM;
3250 }
3251
3252 sema_init(&context->lock, 0);
3253
3254 ret = request_firmware_nowait(THIS_MODULE, true, name,
3255 &g_probe_info.usb->dev, GFP_KERNEL, context,
3256 dbus_request_firmware_done);
3257 if (ret) {
3258 kfree(context);
3259 return ret;
3260 }
3261
3262 /* Wait for completion */
3263 if (down_interruptible(&context->lock) != 0) {
3264 kfree(context);
3265 return -ERESTARTSYS;
3266 }
3267
3268 *firmware = context->firmware;
3269 kfree(context);
3270
3271 return *firmware != NULL ? 0 : -ENOENT;
3272 }
3273
dbus_get_fwfile(int devid,int chiprev,uint8 ** fw,int * fwlen,uint16 boardtype,uint16 boardrev)3274 static void *dbus_get_fwfile(int devid, int chiprev, uint8 **fw, int *fwlen,
3275 uint16 boardtype, uint16 boardrev)
3276 {
3277 const struct firmware *firmware = NULL;
3278 #ifndef OEM_ANDROID
3279 s8 *device_id = NULL;
3280 s8 *chip_rev = "";
3281 #endif /* OEM_ANDROID */
3282 s8 file_name[64];
3283 int ret;
3284
3285 #ifndef OEM_ANDROID
3286 switch (devid) {
3287 case BCM4350_CHIP_ID:
3288 case BCM4354_CHIP_ID:
3289 case BCM43556_CHIP_ID:
3290 case BCM43558_CHIP_ID:
3291 case BCM43566_CHIP_ID:
3292 case BCM43568_CHIP_ID:
3293 case BCM43570_CHIP_ID:
3294 case BCM4358_CHIP_ID:
3295 device_id = "4350";
3296 break;
3297 case BCM43143_CHIP_ID:
3298 device_id = "43143";
3299 break;
3300 case BCM43234_CHIP_ID:
3301 case BCM43235_CHIP_ID:
3302 case BCM43236_CHIP_ID:
3303 device_id = "43236";
3304 break;
3305 case BCM43242_CHIP_ID:
3306 device_id = "43242";
3307 break;
3308 case BCM43238_CHIP_ID:
3309 device_id = "43238";
3310 break;
3311 case BCM43526_CHIP_ID:
3312 device_id = "43526";
3313 break;
3314 case BCM43569_CHIP_ID:
3315 device_id = "43569";
3316 switch (chiprev) {
3317 case 0:
3318 chip_rev = "a0";
3319 break;
3320 case 0x2:
3321 chip_rev = "a2";
3322 break;
3323 default:
3324 break;
3325 }
3326 break;
3327 default:
3328 DBUSERR(("unsupported device %x\n", devid));
3329 return NULL;
3330 }
3331
3332 /* Load firmware */
3333 snprintf(file_name, sizeof(file_name), "brcm/bcm%s%s-firmware.bin",
3334 device_id, chip_rev);
3335 #else
3336 snprintf(file_name, sizeof(file_name), "%s", CONFIG_ANDROID_BCMDHD_FW_PATH);
3337 #endif /* OEM_ANDROID */
3338
3339 ret = dbus_request_firmware(file_name, &firmware);
3340 if (ret) {
3341 DBUSERR(("fail to request firmware %s\n", file_name));
3342 return NULL;
3343 }
3344
3345 *fwlen = firmware->size;
3346 *fw = (uint8 *)firmware->data;
3347 return (void *)firmware;
3348 }
3349
dbus_get_nvfile(int devid,int chiprev,uint8 ** fw,int * fwlen,uint16 boardtype,uint16 boardrev)3350 static void *dbus_get_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen,
3351 uint16 boardtype, uint16 boardrev)
3352 {
3353 const struct firmware *firmware = NULL;
3354 #ifndef OEM_ANDROID
3355 s8 *device_id = NULL;
3356 s8 *chip_rev = "";
3357 #endif /* OEM_ANDROID */
3358 s8 file_name[64];
3359 int ret;
3360
3361 #ifndef OEM_ANDROID
3362 switch (devid) {
3363 case BCM4350_CHIP_ID:
3364 case BCM4354_CHIP_ID:
3365 case BCM43556_CHIP_ID:
3366 case BCM43558_CHIP_ID:
3367 case BCM43566_CHIP_ID:
3368 case BCM43568_CHIP_ID:
3369 case BCM43570_CHIP_ID:
3370 case BCM4358_CHIP_ID:
3371 device_id = "4350";
3372 break;
3373 case BCM43143_CHIP_ID:
3374 device_id = "43143";
3375 break;
3376 case BCM43234_CHIP_ID:
3377 device_id = "43234";
3378 break;
3379 case BCM43235_CHIP_ID:
3380 device_id = "43235";
3381 break;
3382 case BCM43236_CHIP_ID:
3383 device_id = "43236";
3384 break;
3385 case BCM43238_CHIP_ID:
3386 device_id = "43238";
3387 break;
3388 case BCM43242_CHIP_ID:
3389 device_id = "43242";
3390 break;
3391 case BCM43526_CHIP_ID:
3392 device_id = "43526";
3393 break;
3394 case BCM43569_CHIP_ID:
3395 device_id = "43569";
3396 switch (chiprev) {
3397 case 0:
3398 chip_rev = "a0";
3399 break;
3400 case 0x2:
3401 chip_rev = "a2";
3402 break;
3403 default:
3404 break;
3405 }
3406 break;
3407 default:
3408 DBUSERR(("unsupported device %x\n", devid));
3409 return NULL;
3410 }
3411
3412 /* Load board specific nvram file */
3413 snprintf(file_name, sizeof(file_name), "brcm/bcm%s%s-%2x-%2x.nvm",
3414 device_id, chip_rev, boardtype, boardrev);
3415 #else
3416 snprintf(file_name, sizeof(file_name), "%s",
3417 CONFIG_ANDROID_BCMDHD_NVRAM_PATH);
3418 #endif /* OEM_ANDROID */
3419
3420 ret = dbus_request_firmware(file_name, &firmware);
3421 if (ret) {
3422 DBUSERR(("fail to request nvram %s\n", file_name));
3423
3424 #ifndef OEM_ANDROID
3425 /* Load generic nvram file */
3426 snprintf(file_name, sizeof(file_name), "brcm/bcm%s%s.nvm", device_id,
3427 chip_rev);
3428
3429 ret = dbus_request_firmware(file_name, &firmware);
3430 #endif /* OEM_ANDROID */
3431 if (ret) {
3432 DBUSERR(("fail to request nvram %s\n", file_name));
3433 return NULL;
3434 }
3435 }
3436
3437 *fwlen = firmware->size;
3438 *fw = (uint8 *)firmware->data;
3439 return (void *)firmware;
3440 }
3441
dbus_get_fw_nvfile(int devid,int chiprev,uint8 ** fw,int * fwlen,int type,uint16 boardtype,uint16 boardrev)3442 void *dbus_get_fw_nvfile(int devid, int chiprev, uint8 **fw, int *fwlen,
3443 int type, uint16 boardtype, uint16 boardrev)
3444 {
3445 switch (type) {
3446 case DBUS_FIRMWARE:
3447 return dbus_get_fwfile(devid, chiprev, fw, fwlen, boardtype,
3448 boardrev);
3449 case DBUS_NVFILE:
3450 return dbus_get_nvfile(devid, chiprev, fw, fwlen, boardtype,
3451 boardrev);
3452 default:
3453 return NULL;
3454 }
3455 }
3456
dbus_release_fw_nvfile(void * firmware)3457 void dbus_release_fw_nvfile(void *firmware)
3458 {
3459 release_firmware((struct firmware *)firmware);
3460 }
3461 #endif /* BCM_REQUEST_FW */
3462
3463 #ifdef BCMUSBDEV_COMPOSITE
3464 /**
3465 * For a composite device the interface order is not guaranteed, scan the device
3466 * struct for the WLAN interface.
3467 */
dbus_usbos_intf_wlan(struct usb_device * usb)3468 static int dbus_usbos_intf_wlan(struct usb_device *usb)
3469 {
3470 int i, num_of_eps, ep, intf_wlan = -1;
3471 int num_intf = CONFIGDESC(usb)->bNumInterfaces;
3472 struct usb_endpoint_descriptor *endpoint;
3473
3474 for (i = 0; i < num_intf; i++) {
3475 if (IFDESC(usb, i).bInterfaceClass != USB_CLASS_VENDOR_SPEC) {
3476 continue;
3477 }
3478 num_of_eps = IFDESC(usb, i).bNumEndpoints;
3479
3480 for (ep = 0; ep < num_of_eps; ep++) {
3481 endpoint = &IFEPDESC(usb, i, ep);
3482 if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
3483 USB_ENDPOINT_XFER_BULK) {
3484 intf_wlan = i;
3485 break;
3486 }
3487 }
3488 if (ep < num_of_eps) {
3489 break;
3490 }
3491 }
3492
3493 return intf_wlan;
3494 }
3495 #endif /* BCMUSBDEV_COMPOSITE */
3496