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