xref: /OK3568_Linux_fs/external/rkwifibt/drivers/infineon/dhd_sdio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * DHD Bus Module for SDIO
3  *
4  * Portions of this code are copyright (c) 2021 Cypress Semiconductor Corporation
5  *
6  * Copyright (C) 1999-2017, Broadcom Corporation
7  *
8  *      Unless you and Broadcom execute a separate written software license
9  * agreement governing use of this software, this software is licensed to you
10  * under the terms of the GNU General Public License version 2 (the "GPL"),
11  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12  * following added to such license:
13  *
14  *      As a special exception, the copyright holders of this software give you
15  * permission to link this software with independent modules, and to copy and
16  * distribute the resulting executable under terms of your choice, provided that
17  * you also meet, for each linked independent module, the terms and conditions of
18  * the license of that module.  An independent module is a module which is not
19  * derived from this software.  The special exception does not apply to any
20  * modifications of the software.
21  *
22  *      Notwithstanding the above, under no circumstances may you combine this
23  * software in any way with any other Broadcom software provided under a license
24  * other than the GPL, without Broadcom's express prior written consent.
25  *
26  *
27  * <<Broadcom-WL-IPTag/Open:>>
28  *
29  * $Id: dhd_sdio.c 701844 2017-05-26 18:56:40Z $
30  */
31 
32 #include <typedefs.h>
33 #include <osl.h>
34 #include <bcmsdh.h>
35 
36 #include <bcmdefs.h>
37 #include <bcmutils.h>
38 #include <bcmendian.h>
39 #include <bcmdevs.h>
40 
41 #include <siutils.h>
42 #include <hndpmu.h>
43 #include <hndsoc.h>
44 #include <bcmsdpcm.h>
45 #include <hnd_armtrap.h>
46 #include <hnd_cons.h>
47 #include <sbchipc.h>
48 #include <sbhnddma.h>
49 
50 #include <sdio.h>
51 #ifdef BCMSPI
52 #include <spid.h>
53 #endif /* BCMSPI */
54 #include <sbsdio.h>
55 #include <sbsdpcmdev.h>
56 #include <bcmsdpcm.h>
57 #include <bcmsdbus.h>
58 #include <trxhdr.h>
59 
60 #ifdef DHD_KSO_MMC_RETUNE
61 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) || defined(CONFIG_DHD_PLAT_ROCKCHIP))
62 #include <linux/mmc/sdio_func.h>
63 #include <linux/mmc/host.h>
64 #include "bcmsdh_sdmmc.h"
65 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) */
66 #endif /* DHD_KSO_MMC_RETURN */
67 
68 #include <ethernet.h>
69 #include <802.1d.h>
70 #include <802.11.h>
71 
72 #include <dngl_stats.h>
73 #include <dhd.h>
74 #include <dhd_bus.h>
75 #include <dhd_proto.h>
76 #include <dhd_dbg.h>
77 #include <dhdioctl.h>
78 #include <sdiovar.h>
79 
80 #ifdef PROP_TXSTATUS
81 #include <dhd_wlfc.h>
82 #endif // endif
83 #ifdef DHDTCPACK_SUPPRESS
84 #include <dhd_ip.h>
85 #endif /* DHDTCPACK_SUPPRESS */
86 
87 #ifdef BT_OVER_SDIO
88 #include <dhd_bt_interface.h>
89 #endif /* BT_OVER_SDIO */
90 
91 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
92 #include <debugger.h>
93 #endif /* DEBUGGER || DHD_DSCOPE */
94 
95 bool dhd_mp_halting(dhd_pub_t *dhdp);
96 extern void bcmsdh_waitfor_iodrain(void *sdh);
97 extern void bcmsdh_reject_ioreqs(void *sdh, bool reject);
98 extern bool bcmsdh_fatal_error(void *sdh);
99 static int dhdsdio_suspend(void *context);
100 static int dhdsdio_resume(void *context);
101 
102 #ifndef DHDSDIO_MEM_DUMP_FNAME
103 #define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
104 #endif // endif
105 
106 #define QLEN		(1024) /* bulk rx and tx queue lengths */
107 #define FCHI		(QLEN - 10)
108 #define FCLOW		(FCHI / 2)
109 #define PRIOMASK	7
110 
111 #define F0_BLOCK_SIZE 32
112 #define TXRETRIES	2	/* # of retries for tx frames */
113 #define READ_FRM_CNT_RETRIES	3
114 #ifndef DHD_RXBOUND
115 #define DHD_RXBOUND	50	/* Default for max rx frames in one scheduling */
116 #endif // endif
117 
118 #ifndef DHD_TXBOUND
119 #define DHD_TXBOUND	20	/* Default for max tx frames in one scheduling */
120 #endif // endif
121 
122 #define DHD_TXMINMAX	1	/* Max tx frames if rx still pending */
123 
124 #define MEMBLOCK	2048		/* Block size used for downloading of dongle image */
125 #define MAX_MEMBLOCK  (32 * 1024)	/* Block size used for downloading of dongle image */
126 
127 #define MAX_DATA_BUF	(64 * 1024)	/* Must be large enough to hold biggest possible glom */
128 
129 #ifdef DHD_SDIO_MEM_BUF
130 #define MAX_MEM_BUF     (4 * 1024)
131 #endif /* DHD_SDIO_MEM_BUF */
132 
133 #ifndef DHD_FIRSTREAD
134 #define DHD_FIRSTREAD   32
135 #endif // endif
136 #if !ISPOWEROF2(DHD_FIRSTREAD)
137 #error DHD_FIRSTREAD is not a power of 2!
138 #endif // endif
139 
140 /* Total length of frame header for dongle protocol */
141 #define SDPCM_HDRLEN	(SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
142 #define SDPCM_HDRLEN_TXGLOM	(SDPCM_HDRLEN + SDPCM_HWEXT_LEN)
143 #define MAX_TX_PKTCHAIN_CNT	SDPCM_MAXGLOM_SIZE
144 
145 #ifdef SDTEST
146 #define SDPCM_RESERVE	(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
147 #else
148 #define SDPCM_RESERVE	(SDPCM_HDRLEN + DHD_SDALIGN)
149 #endif // endif
150 
151 /* Space for header read, limit for data packets */
152 #ifndef MAX_HDR_READ
153 #define MAX_HDR_READ	32
154 #endif // endif
155 #if !ISPOWEROF2(MAX_HDR_READ)
156 #error MAX_HDR_READ is not a power of 2!
157 #endif // endif
158 
159 #define MAX_RX_DATASZ	2048
160 
161 #define SDIO_FUNC_BLOCK_SIZE_SHIFT	16
162 #define F2_BLOCK_SIZE_256		256
163 
164 /* Maximum milliseconds to wait for F2 to come up */
165 #ifdef BCMQT
166 #define DHD_WAIT_F2RDY  30000
167 #else
168 #define DHD_WAIT_F2RDY	3000
169 #endif /* BCMQT */
170 
171 /* Maximum usec to wait for HTAVAIL to come up */
172 #ifdef BCMQT
173 #define DHD_WAIT_HTAVAIL	10000000
174 #else
175 #define DHD_WAIT_HTAVAIL	10000
176 #endif /* BCMQT */
177 
178 /* Bump up limit on waiting for HT to account for first startup;
179  * if the image is doing a CRC calculation before programming the PMU
180  * for HT availability, it could take a couple hundred ms more, so
181  * max out at a 1 second (1000000us).
182  */
183 #if (PMU_MAX_TRANSITION_DLY <= 1000000)
184 #undef PMU_MAX_TRANSITION_DLY
185 #define PMU_MAX_TRANSITION_DLY 1000000
186 #endif // endif
187 
188 /* hooks for limiting threshold custom tx num in rx processing */
189 #define DEFAULT_TXINRX_THRES    0
190 #ifndef CUSTOM_TXINRX_THRES
191 #define CUSTOM_TXINRX_THRES     DEFAULT_TXINRX_THRES
192 #endif // endif
193 
194 /* Value for ChipClockCSR during initial setup */
195 #define DHD_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
196 #define DHD_INIT_CLKCTL2	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
197 
198 /* Flags for SDH calls */
199 #define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
200 
201 /* Packet free applicable unconditionally for sdio and sdspi.  Conditional if
202  * bufpool was present for gspi bus.
203  */
204 #define PKTFREE2()		if ((bus->bus != SPI_BUS) || bus->usebufpool) \
205 					PKTFREE(bus->dhd->osh, pkt, FALSE);
206 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
207 
208 #if defined(MULTIPLE_SUPPLICANT)
209 DEFINE_MUTEX(_dhd_sdio_mutex_lock_);
210 #endif // endif
211 
212 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW
213 extern unsigned int system_hw_rev;
214 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
215 
216 /* Device console log buffer state */
217 #define CONSOLE_LINE_MAX	192
218 #define CONSOLE_BUFFER_MAX	2024
219 typedef struct dhd_console {
220 	uint		count;			/* Poll interval msec counter */
221 	uint		log_addr;		/* Log struct address (fixed) */
222 	hnd_log_t	log;			/* Log struct (host copy) */
223 	uint		bufsize;		/* Size of log buffer */
224 	uint8		*buf;			/* Log buffer (host copy) */
225 	uint		last;			/* Last buffer read index */
226 } dhd_console_t;
227 
228 #define	REMAP_ENAB(bus)			((bus)->remap)
229 #define	REMAP_ISADDR(bus, a)		(((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
230 #define	KSO_ENAB(bus)			((bus)->kso)
231 #define	SR_ENAB(bus)			((bus)->_srenab)
232 #define	SLPAUTO_ENAB(bus)		((SR_ENAB(bus)) && ((bus)->_slpauto))
233 
234 #define	MIN_RSRC_SR			0x3
235 #define	CORE_CAPEXT_ADDR_OFFSET		(0x64c)
236 #define	CORE_CAPEXT_SR_SUPPORTED_MASK	(1 << 1)
237 #define RCTL_MACPHY_DISABLE_MASK	(1 << 26)
238 #define RCTL_LOGIC_DISABLE_MASK		(1 << 27)
239 
240 #define	OOB_WAKEUP_ENAB(bus)		((bus)->_oobwakeup)
241 #define	GPIO_DEV_SRSTATE		16	/* Host gpio17 mapped to device gpio0 SR state */
242 #define	GPIO_DEV_SRSTATE_TIMEOUT	320000	/* 320ms */
243 #define	GPIO_DEV_WAKEUP			17	/* Host gpio17 mapped to device gpio1 wakeup */
244 #define	CC_CHIPCTRL2_GPIO1_WAKEUP	(1  << 0)
245 #define	CC_CHIPCTRL3_SR_ENG_ENABLE	(1  << 2)
246 #define OVERFLOW_BLKSZ512_WM		96
247 #define OVERFLOW_BLKSZ512_MES		80
248 
249 #define CC_PMUCC3	(0x3)
250 
251 #ifdef DHD_UCODE_DOWNLOAD
252 /* Ucode host download related macros */
253 #define UCODE_DOWNLOAD_REQUEST  0xCAFECAFE
254 #define UCODE_DOWNLOAD_COMPLETE 0xABCDABCD
255 #endif /* DHD_UCODE_DOWNLOAD */
256 
257 #if defined(BT_OVER_SDIO)
258 #define BTMEM_OFFSET			0x19000000
259 /* BIT0 => WLAN Power UP and BIT1=> WLAN Wake */
260 #define BT2WLAN_PWRUP_WAKE		0x03
261 #define BT2WLAN_PWRUP_ADDR		0x640894	/* This address is specific to 43012B0 */
262 
263 #define BTFW_MAX_STR_LEN		600
264 #define BTFW_DOWNLOAD_BLK_SIZE		(BTFW_MAX_STR_LEN/2 + 8)
265 
266 #define BTFW_ADDR_MODE_UNKNOWN		0
267 #define BTFW_ADDR_MODE_EXTENDED		1
268 #define BTFW_ADDR_MODE_SEGMENT		2
269 #define BTFW_ADDR_MODE_LINEAR32		3
270 
271 #define BTFW_HEX_LINE_TYPE_DATA				0
272 #define BTFW_HEX_LINE_TYPE_END_OF_DATA			1
273 #define BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS	2
274 #define BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS		4
275 #define BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS	5
276 
277 #endif /* defined (BT_OVER_SDIO) */
278 
279 /* Private data for SDIO bus interaction */
280 typedef struct dhd_bus {
281 	dhd_pub_t	*dhd;
282 
283 	bcmsdh_info_t	*sdh;			/* Handle for BCMSDH calls */
284 	si_t		*sih;			/* Handle for SI calls */
285 	char		*vars;			/* Variables (from CIS and/or other) */
286 	uint		varsz;			/* Size of variables buffer */
287 	uint32		sbaddr;			/* Current SB window pointer (-1, invalid) */
288 
289 	sdpcmd_regs_t	*regs;			/* Registers for SDIO core */
290 	uint		sdpcmrev;		/* SDIO core revision */
291 	uint		armrev;			/* CPU core revision */
292 	uint		ramrev;			/* SOCRAM core revision */
293 	uint32		ramsize;		/* Size of RAM in SOCRAM (bytes) */
294 	uint32		orig_ramsize;		/* Size of RAM in SOCRAM (bytes) */
295 	uint32		srmemsize;		/* Size of SRMEM */
296 
297 	uint32		bus;			/* gSPI or SDIO bus */
298 	uint32		bus_num;		/* bus number */
299 	uint32		slot_num;		/* slot ID */
300 	uint32		hostintmask;	/* Copy of Host Interrupt Mask */
301 	uint32		intstatus;		/* Intstatus bits (events) pending */
302 	bool		dpc_sched;		/* Indicates DPC schedule (intrpt rcvd) */
303 	bool		fcstate;		/* State of dongle flow-control */
304 
305 	uint16		cl_devid;		/* cached devid for dhdsdio_probe_attach() */
306 	char		*fw_path;		/* module_param: path to firmware image */
307 	char		*nv_path;		/* module_param: path to nvram vars file */
308 
309 #ifdef DHD_MAP_CHIP_FIRMWARE_PATH
310 	uint	    chipmodule;		/**< chip module ID */
311 #endif /* DHD_MAP_CHIP_FIRMWARE_PATH */
312 
313 	uint		blocksize;		/* Block size of SDIO transfers */
314 	uint		roundup;		/* Max roundup limit */
315 
316 	struct pktq	txq;			/* Queue length used for flow-control */
317 	uint8		flowcontrol;		/* per prio flow control bitmask */
318 	uint8		tx_seq;			/* Transmit sequence number (next) */
319 	uint8		tx_max;			/* Maximum transmit sequence allowed */
320 
321 	uint8		hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
322 	uint8		*rxhdr;			/* Header of current rx frame (in hdrbuf) */
323 	uint16		nextlen;		/* Next Read Len from last header */
324 	uint8		rx_seq;			/* Receive sequence number (expected) */
325 	bool		rxskip;			/* Skip receive (awaiting NAK ACK) */
326 
327 	void		*glomd;			/* Packet containing glomming descriptor */
328 	void		*glom;			/* Packet chain for glommed superframe */
329 	uint		glomerr;		/* Glom packet read errors */
330 
331 	uint8		*rxbuf;			/* Buffer for receiving control packets */
332 	uint		rxblen;			/* Allocated length of rxbuf */
333 	uint8		*rxctl;			/* Aligned pointer into rxbuf */
334 	uint8		*databuf;		/* Buffer for receiving big glom packet */
335 	uint8		*dataptr;		/* Aligned pointer into databuf */
336 	uint		rxlen;			/* Length of valid data in buffer */
337 
338 	uint8		sdpcm_ver;		/* Bus protocol reported by dongle */
339 
340 	bool		intr;			/* Use interrupts */
341 	bool		poll;			/* Use polling */
342 	bool		ipend;			/* Device interrupt is pending */
343 	bool		intdis;			/* Interrupts disabled by isr */
344 	uint 		intrcount;		/* Count of device interrupt callbacks */
345 	uint		lastintrs;		/* Count as of last watchdog timer */
346 	uint		spurious;		/* Count of spurious interrupts */
347 	uint		pollrate;		/* Ticks between device polls */
348 	uint		polltick;		/* Tick counter */
349 	uint		pollcnt;		/* Count of active polls */
350 
351 	dhd_console_t	console;		/* Console output polling support */
352 	uint		console_addr;		/* Console address from shared struct */
353 
354 	uint		regfails;		/* Count of R_REG/W_REG failures */
355 
356 	uint		clkstate;		/* State of sd and backplane clock(s) */
357 	bool		activity;		/* Activity flag for clock down */
358 	int32		idletime;		/* Control for activity timeout */
359 	int32		idlecount;		/* Activity timeout counter */
360 	int32		idleclock;		/* How to set bus driver when idle */
361 	int32		sd_divisor;		/* Speed control to bus driver */
362 	int32		sd_mode;		/* Mode control to bus driver */
363 	int32		sd_rxchain;		/* If bcmsdh api accepts PKT chains */
364 	bool		use_rxchain;		/* If dhd should use PKT chains */
365 	bool		sleeping;		/* Is SDIO bus sleeping? */
366 #if defined(SUPPORT_P2P_GO_PS)
367 	wait_queue_head_t bus_sleep;
368 #endif /* LINUX && SUPPORT_P2P_GO_PS */
369 	uint		rxflow_mode;		/* Rx flow control mode */
370 	bool		rxflow;			/* Is rx flow control on */
371 	uint		prev_rxlim_hit;		/* Is prev rx limit exceeded (per dpc schedule) */
372 	bool		alp_only;		/* Don't use HT clock (ALP only) */
373 	/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
374 	bool		usebufpool;
375 	int32		txinrx_thres;	/* num of in-queued pkts */
376 	int32		dotxinrx;	/* tx first in dhdsdio_readframes */
377 #ifdef SDTEST
378 	/* external loopback */
379 	bool		ext_loop;
380 	uint8		loopid;
381 
382 	/* pktgen configuration */
383 	uint		pktgen_freq;		/* Ticks between bursts */
384 	uint		pktgen_count;		/* Packets to send each burst */
385 	uint		pktgen_print;		/* Bursts between count displays */
386 	uint		pktgen_total;		/* Stop after this many */
387 	uint		pktgen_minlen;		/* Minimum packet data len */
388 	uint		pktgen_maxlen;		/* Maximum packet data len */
389 	uint		pktgen_mode;		/* Configured mode: tx, rx, or echo */
390 	uint		pktgen_stop;		/* Number of tx failures causing stop */
391 
392 	/* active pktgen fields */
393 	uint		pktgen_tick;		/* Tick counter for bursts */
394 	uint		pktgen_ptick;		/* Burst counter for printing */
395 	uint		pktgen_sent;		/* Number of test packets generated */
396 	uint		pktgen_rcvd;		/* Number of test packets received */
397 	uint		pktgen_prev_time;	/* Time at which previous stats where printed */
398 	uint		pktgen_prev_sent;	/* Number of test packets generated when
399 						 * previous stats were printed
400 						 */
401 	uint		pktgen_prev_rcvd;	/* Number of test packets received when
402 						 * previous stats were printed
403 						 */
404 	uint		pktgen_fail;		/* Number of failed send attempts */
405 	uint16		pktgen_len;		/* Length of next packet to send */
406 #define PKTGEN_RCV_IDLE     (0)
407 #define PKTGEN_RCV_ONGOING  (1)
408 	uint16		pktgen_rcv_state;		/* receive state */
409 	uint		pktgen_rcvd_rcvsession;	/* test pkts rcvd per rcv session. */
410 #endif /* SDTEST */
411 
412 	/* Some additional counters */
413 	uint		tx_sderrs;		/* Count of tx attempts with sd errors */
414 	uint		fcqueued;		/* Tx packets that got queued */
415 	uint		rxrtx;			/* Count of rtx requests (NAK to dongle) */
416 	uint		rx_toolong;		/* Receive frames too long to receive */
417 	uint		rxc_errors;		/* SDIO errors when reading control frames */
418 	uint		rx_hdrfail;		/* SDIO errors on header reads */
419 	uint		rx_badhdr;		/* Bad received headers (roosync?) */
420 	uint		rx_badseq;		/* Mismatched rx sequence number */
421 	uint		fc_rcvd;		/* Number of flow-control events received */
422 	uint		fc_xoff;		/* Number which turned on flow-control */
423 	uint		fc_xon;			/* Number which turned off flow-control */
424 	uint		rxglomfail;		/* Failed deglom attempts */
425 	uint		rxglomframes;		/* Number of glom frames (superframes) */
426 	uint		rxglompkts;		/* Number of packets from glom frames */
427 	uint		f2rxhdrs;		/* Number of header reads */
428 	uint		f2rxdata;		/* Number of frame data reads */
429 	uint		f2txdata;		/* Number of f2 frame writes */
430 	uint		f1regdata;		/* Number of f1 register accesses */
431 	wake_counts_t	wake_counts;		/* Wake up counter */
432 #ifdef BCMSPI
433 	bool		dwordmode;
434 #endif /* BCMSPI */
435 #ifdef DHDENABLE_TAILPAD
436 	uint		tx_tailpad_chain;	/* Number of tail padding by chaining pad_pkt */
437 	uint		tx_tailpad_pktget;	/* Number of tail padding by new PKTGET */
438 #endif /* DHDENABLE_TAILPAD */
439 	uint8		*ctrl_frame_buf;
440 	uint32		ctrl_frame_len;
441 	bool		ctrl_frame_stat;
442 #ifndef BCMSPI
443 	uint32		rxint_mode;	/* rx interrupt mode */
444 #endif /* BCMSPI */
445 	bool		remap;		/* Contiguous 1MB RAM: 512K socram + 512K devram
446 					 * Available with socram rev 16
447 					 * Remap region not DMA-able
448 					 */
449 	bool		kso;
450 	bool		_slpauto;
451 	bool		_oobwakeup;
452 	bool		_srenab;
453 	bool        readframes;
454 	bool        reqbussleep;
455 	uint32		resetinstr;
456 	uint32		dongle_ram_base;
457 
458 	void		*glom_pkt_arr[SDPCM_MAXGLOM_SIZE];	/* Array of pkts for glomming */
459 	uint32		txglom_cnt;	/* Number of pkts in the glom array */
460 	uint32		txglom_total_len;	/* Total length of pkts in glom array */
461 	bool		txglom_enable;	/* Flag to indicate whether tx glom is enabled/disabled */
462 	uint32		txglomsize;	/* Glom size limitation */
463 #ifdef DHDENABLE_TAILPAD
464 	void		*pad_pkt;
465 #endif /* DHDENABLE_TAILPAD */
466 	uint32		dongle_trap_addr; /* device trap addr location in device memory */
467 #if defined(BT_OVER_SDIO)
468 	char		*btfw_path;	/* module_param: path to BT firmware image */
469 	uint32		bt_use_count; /* Counter that tracks whether BT is using the bus */
470 #endif /* defined (BT_OVER_SDIO) */
471 	bool		chipidpresent;	/* ChipID is present in SDIO core enum address space */
472 	bool		secureboot;		/* security related features are present */
473 #ifdef DHD_SDIO_MEM_BUF
474 	uint8       *membuf;
475 #endif /* DHD_SDIO_MEM_BUF */
476 } dhd_bus_t;
477 
478 /*
479  * Whenever DHD_IDLE_IMMEDIATE condition is handled, we have to now check if
480  * BT is active too. Instead of adding #ifdef code in all the places, we thought
481  * of adding one macro check as part of the if condition that checks for DHD_IDLE_IMMEDIATE
482  * In case of non BT over SDIO builds, this macro will always return TRUE. In case
483  * of the builds where BT_OVER_SDIO is enabled, it will expand to a condition check
484  * that checks if bt_use_count is zero. So this macro will return equate to 1 if
485  * bt_use_count is 0, indicating that there are no active users and if bt_use_count
486  * is non zero it would return 0 there by preventing the caller from executing the
487  * sleep calls.
488  */
489 #ifdef BT_OVER_SDIO
490 #define NO_OTHER_ACTIVE_BUS_USER(bus)		(bus->bt_use_count == 0)
491 #else
492 #define NO_OTHER_ACTIVE_BUS_USER(bus)		(1)
493 #endif /* BT_OVER_SDIO */
494 
495 /* clkstate */
496 #define CLK_NONE	0
497 #define CLK_SDONLY	1
498 #define CLK_PENDING	2	/* Not used yet */
499 #define CLK_AVAIL	3
500 
501 #define DHD_NOPMU(dhd)	(FALSE)
502 
503 #if defined(BCMSDIOH_STD)
504 #define BLK_64_MAXTXGLOM 20
505 #endif /* BCMSDIOH_STD */
506 
507 #ifdef DHD_DEBUG
508 static int qcount[NUMPRIO];
509 static int tx_packets[NUMPRIO];
510 #endif /* DHD_DEBUG */
511 
512 /* Deferred transmit */
513 const uint dhd_deferred_tx = 1;
514 
515 extern uint dhd_watchdog_ms;
516 extern uint sd_f1_blocksize;
517 
518 #ifdef BCMSPI_ANDROID
519 extern uint *dhd_spi_lockcount;
520 #endif /* BCMSPI_ANDROID */
521 
522 extern void dhd_os_wd_timer(void *bus, uint wdtick);
523 int dhd_enableOOB(dhd_pub_t *dhd, bool sleep);
524 
525 #ifdef DHD_PM_CONTROL_FROM_FILE
526 extern bool g_pm_control;
527 #endif /* DHD_PM_CONTROL_FROM_FILE */
528 
529 #ifdef DHD_FW_COREDUMP
530 uint tcm_dump_enable;
531 module_param(tcm_dump_enable, uint, 0);
532 #endif /* DHD_FW_COREDUMP */
533 
534 /* Tx/Rx bounds */
535 uint dhd_txbound;
536 uint dhd_rxbound;
537 uint dhd_txminmax = DHD_TXMINMAX;
538 
539 /* override the RAM size if possible */
540 #define DONGLE_MIN_RAMSIZE (128 *1024)
541 int dhd_dongle_ramsize;
542 
543 uint dhd_doflow = TRUE;
544 uint dhd_dpcpoll = FALSE;
545 
546 module_param(dhd_doflow, uint, 0644);
547 module_param(dhd_dpcpoll, uint, 0644);
548 
549 static bool dhd_alignctl;
550 
551 static bool sd1idle;
552 
553 static bool retrydata;
554 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
555 
556 #ifdef BCMSPI
557 /* At a watermark around 8 the spid hits underflow error. */
558 static uint watermark = 32;
559 static uint mesbusyctrl = 0;
560 #else
561 static uint watermark = 8;
562 static uint mesbusyctrl = 0;
563 #endif /* BCMSPI */
564 static const uint firstread = DHD_FIRSTREAD;
565 
566 /* Retry count for register access failures */
567 static const uint retry_limit = 2;
568 
569 /* Force even SD lengths (some host controllers mess up on odd bytes) */
570 static bool forcealign;
571 
572 #if defined(DEBUGGER)
573 static uint32 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr);
574 static void dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val);
575 
576 /** the debugger layer will call back into this (bus) layer to read/write dongle memory */
577 static struct dhd_dbg_bus_ops_s  bus_ops = {
578 	.read_u16 = NULL,
579 	.read_u32 = dhd_sdio_reg_read,
580 	.write_u32 = dhd_sdio_reg_write,
581 };
582 #endif /* DEBUGGER */
583 
584 #define ALIGNMENT  4
585 
586 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
587 extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
588 #endif // endif
589 
590 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
591 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
592 #endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
593 #define PKTALIGN(osh, p, len, align)					\
594 	do {								\
595 		uintptr datalign;						\
596 		datalign = (uintptr)PKTDATA((osh), (p));		\
597 		datalign = ROUNDUP(datalign, (align)) - datalign;	\
598 		ASSERT(datalign < (align));				\
599 		ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign));	\
600 		if (datalign)						\
601 			PKTPULL((osh), (p), (uint)datalign);			\
602 		PKTSETLEN((osh), (p), (len));				\
603 	} while (0)
604 
605 /* Limit on rounding up frames */
606 static const uint max_roundup = 512;
607 
608 /* Try doing readahead */
609 static bool dhd_readahead;
610 
611 #define TXCTL_CREDITS   2
612 
613 /* To check if there's window offered */
614 #define DATAOK(bus) \
615 	(((uint8)(bus->tx_max - bus->tx_seq) > TXCTL_CREDITS) && \
616 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
617 
618 /* To check if there's window offered for ctrl frame */
619 #define TXCTLOK(bus) \
620 	(((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
621 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
622 
623 /* Number of pkts available in dongle for data RX */
624 #define DATABUFCNT(bus) \
625 	((uint8)(bus->tx_max - bus->tx_seq) - 1)
626 
627 /* Macros to get register read/write status */
628 /* NOTE: these assume a local dhdsdio_bus_t *bus! */
629 #define R_SDREG(regvar, regaddr, retryvar) \
630 do { \
631 	retryvar = 0; \
632 	do { \
633 		regvar = R_REG(bus->dhd->osh, regaddr); \
634 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
635 	if (retryvar) { \
636 		bus->regfails += (retryvar-1); \
637 		if (retryvar > retry_limit) { \
638 			DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
639 			           __FUNCTION__, __LINE__)); \
640 			regvar = 0; \
641 		} \
642 	} \
643 } while (0)
644 
645 #define W_SDREG(regval, regaddr, retryvar) \
646 do { \
647 	retryvar = 0; \
648 	do { \
649 		W_REG(bus->dhd->osh, regaddr, regval); \
650 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
651 	if (retryvar) { \
652 		bus->regfails += (retryvar-1); \
653 		if (retryvar > retry_limit) \
654 			DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
655 			           __FUNCTION__, __LINE__)); \
656 	} \
657 } while (0)
658 
659 #define BUS_WAKE(bus) \
660 	do { \
661 		bus->idlecount = 0; \
662 		if ((bus)->sleeping) \
663 			dhdsdio_bussleep((bus), FALSE); \
664 	} while (0);
665 
666 /*
667  * pktavail interrupts from dongle to host can be managed in 3 different ways
668  * whenever there is a packet available in dongle to transmit to host.
669  *
670  * Mode 0:	Dongle writes the software host mailbox and host is interrupted.
671  * Mode 1:	(sdiod core rev >= 4)
672  *		Device sets a new bit in the intstatus whenever there is a packet
673  *		available in fifo.  Host can't clear this specific status bit until all the
674  *		packets are read from the FIFO.  No need to ack dongle intstatus.
675  * Mode 2:	(sdiod core rev >= 4)
676  *		Device sets a bit in the intstatus, and host acks this by writing
677  *		one to this bit.  Dongle won't generate anymore packet interrupts
678  *		until host reads all the packets from the dongle and reads a zero to
679  *		figure that there are no more packets.  No need to disable host ints.
680  *		Need to ack the intstatus.
681  */
682 
683 #define SDIO_DEVICE_HMB_RXINT		0	/* default old way */
684 #define SDIO_DEVICE_RXDATAINT_MODE_0	1	/* from sdiod rev 4 */
685 #define SDIO_DEVICE_RXDATAINT_MODE_1	2	/* from sdiod rev 4 */
686 
687 #define SDIO_FUNC_BLOCK_SIZE_SHIFT	16
688 #define F2_BLOCK			2
689 #define DEFAULT_SDIO_F2_BLKSIZE		512
690 
691 #ifdef BCMSPI
692 
693 #define FRAME_AVAIL_MASK(bus) I_HMB_FRAME_IND
694 
695 #define DHD_BUS			SPI_BUS
696 
697 /* check packet-available-interrupt in piggybacked dstatus */
698 #define PKT_AVAILABLE(bus, intstatus)	(bcmsdh_get_dstatus(bus->sdh) & STATUS_F2_PKT_AVAILABLE)
699 
700 #define HOSTINTMASK		(I_HMB_FC_CHANGE | I_HMB_HOST_INT)
701 
702 #define GSPI_PR55150_BAILOUT									\
703 do {												\
704 	uint32 dstatussw = bcmsdh_get_dstatus((void *)bus->sdh);				\
705 	uint32 dstatushw = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL);	\
706 	uint32 intstatuserr = 0;								\
707 	uint retries = 0;									\
708 												\
709 	R_SDREG(intstatuserr, &bus->regs->intstatus, retries);					\
710 	printf("dstatussw = 0x%x, dstatushw = 0x%x, intstatus = 0x%x\n",			\
711 	        dstatussw, dstatushw, intstatuserr); 						\
712 												\
713 	bus->nextlen = 0;									\
714 	*finished = TRUE;									\
715 } while (0)
716 
717 #else /* BCMSDIO */
718 
719 #define FRAME_AVAIL_MASK(bus) 	\
720 	((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL)
721 
722 #define DHD_BUS			SDIO_BUS
723 
724 #define PKT_AVAILABLE(bus, intstatus)	((intstatus) & (FRAME_AVAIL_MASK(bus)))
725 
726 #define HOSTINTMASK		(I_HMB_SW_MASK | I_CHIPACTIVE)
727 
728 #define GSPI_PR55150_BAILOUT
729 
730 #endif /* BCMSPI */
731 
732 extern uint sd_f2_blocksize;
733 
734 #ifdef DHD_MAP_CHIP_FIRMWARE_PATH
735 extern uint sd_chip_module;
736 #endif /* DHD_MAP_CHIP_FIRMWARE_PATH */
737 
738 #ifdef SDTEST
739 static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
740 static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count);
741 #endif // endif
742 
743 static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size);
744 #ifdef DHD_DEBUG
745 static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror);
746 #endif /* DHD_DEBUG */
747 
748 #if defined(DHD_FW_COREDUMP)
749 static int dhdsdio_mem_dump(dhd_bus_t *bus);
750 static int dhdsdio_get_mem_dump(dhd_bus_t *bus);
751 #endif /* DHD_FW_COREDUMP */
752 static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap);
753 static int dhdsdio_readshared_console(dhd_bus_t *bus);
754 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
755 static int dhdsdio_wait_bootloader_ready(dhd_bus_t *bus, hs_addrs_t *addr);
756 static int dhdsdio_dongle_host_get_handshake_address(dhd_bus_t *bus, hs_addrs_t *addr);
757 static int dhdsdio_dongle_host_pre_handshake(dhd_bus_t *bus, hs_addrs_t *addr);
758 static int dhdsdio_dongle_host_post_handshake(dhd_bus_t *bus, hs_addrs_t *addr);
759 static int dhdsdio_dongle_host_chk_validation(dhd_bus_t *bus, hs_addrs_t *addr);
760 static int dhdsdio_dongle_host_post_varswrite(dhd_bus_t *bus, hs_addrs_t *addr);
761 int dhdsdio_dongle_host_pre_wd_reset_sequence(dhd_bus_t *bus);
762 
763 static int dhdsdio_handshake_msg_reg_write(dhd_bus_t *bus, volatile void *addr,
764 	uint32 *buffer);
765 static int dhdsdio_handshake_msg_reg_read(dhd_bus_t *bus, volatile void *addr,
766 	uint32 *buffer);
767 static int dhdsdio_cfg_write_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset);
768 static int dhdsdio_cfg_read_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset);
769 static int dhdsdio_dongle_host_handshake_spinwait(dhd_bus_t *bus, volatile void *addr,
770 	uint32 bitshift, uint32 us);
771 
772 static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
773 static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
774 static void dhdsdio_disconnect(void *ptr);
775 static bool dhdsdio_chipmatch(uint16 chipid);
776 static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
777                                  void * regsva, uint16  devid);
778 static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
779 static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
780 static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation,
781 	bool reset_flag);
782 
783 static void dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size);
784 static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
785 	uint8 *buf, uint nbytes,
786 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
787 static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
788 	uint8 *buf, uint nbytes,
789 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry);
790 static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt);
791 static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
792 	int prev_chain_total_len, bool last_chained_pkt,
793 	int *pad_pkt_len, void **new_pkt);
794 static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt);
795 
796 static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh);
797 static int _dhdsdio_download_firmware(dhd_bus_t *bus);
798 
799 #ifdef DHD_UCODE_DOWNLOAD
800 static int dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path);
801 #endif /* DHD_UCODE_DOWNLOAD */
802 static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path);
803 static int dhdsdio_download_nvram(dhd_bus_t *bus);
804 static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep);
805 static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok);
806 static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus);
807 static bool dhdsdio_dpc(dhd_bus_t *bus);
808 static int dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len);
809 static int dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode);
810 static int dhdsdio_sdclk(dhd_bus_t *bus, bool on);
811 static void dhdsdio_advertise_bus_cleanup(dhd_pub_t *dhdp);
812 
813 #if defined(BT_OVER_SDIO)
814 static int extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value);
815 static int read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode,
816 	uint16 * hi_addr, uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes);
817 static int dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh);
818 static int _dhdsdio_download_btfw(struct dhd_bus *bus);
819 #endif /* defined (BT_OVER_SDIO) */
820 
821 #ifdef DHD_ULP
822 #include <dhd_ulp.h>
823 static int dhd_bus_ulp_reinit_fw(dhd_bus_t *bus);
824 #endif /* DHD_ULP */
825 
826 static void
dhdsdio_tune_fifoparam(struct dhd_bus * bus)827 dhdsdio_tune_fifoparam(struct dhd_bus *bus)
828 {
829 	int err;
830 	uint8 devctl, wm, mes;
831 
832 	if (bus->sih->buscorerev >= 15) {
833 		/* See .ppt in PR for these recommended values */
834 		if (bus->blocksize == 512) {
835 			wm = OVERFLOW_BLKSZ512_WM;
836 			mes = OVERFLOW_BLKSZ512_MES;
837 		} else {
838 			mes = bus->blocksize/4;
839 			wm = bus->blocksize/4;
840 		}
841 
842 		watermark = wm;
843 		mesbusyctrl = mes;
844 	} else {
845 		DHD_INFO(("skip fifotune: SdioRev(%d) is lower than minimal requested ver\n",
846 			bus->sih->buscorerev));
847 		return;
848 	}
849 
850 	/* Update watermark */
851 	if (wm > 0) {
852 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err);
853 
854 		devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
855 		devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
856 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
857 	}
858 
859 	/* Update MES */
860 	if (mes > 0) {
861 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
862 			(mes | SBSDIO_MESBUSYCTRL_ENAB), &err);
863 	}
864 
865 	DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n",
866 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err),
867 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err),
868 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err)));
869 }
870 
871 static void
dhd_dongle_setramsize(struct dhd_bus * bus,int mem_size)872 dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size)
873 {
874 	int32 min_size =  DONGLE_MIN_RAMSIZE;
875 	/* Restrict the ramsize to user specified limit */
876 	DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
877 		dhd_dongle_ramsize, min_size));
878 	if ((dhd_dongle_ramsize > min_size) &&
879 		(dhd_dongle_ramsize < (int32)bus->orig_ramsize))
880 		bus->ramsize = dhd_dongle_ramsize;
881 }
882 
883 static int
dhdsdio_set_siaddr_window(dhd_bus_t * bus,uint32 address)884 dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
885 {
886 	int err = 0;
887 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
888 	                 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
889 	if (!err)
890 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
891 		                 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
892 	if (!err)
893 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
894 		                 (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
895 	return err;
896 }
897 
898 #ifdef BCMSPI
899 static void
dhdsdio_wkwlan(dhd_bus_t * bus,bool on)900 dhdsdio_wkwlan(dhd_bus_t *bus, bool on)
901 {
902 	int err;
903 	uint32 regdata;
904 	bcmsdh_info_t *sdh = bus->sdh;
905 
906 	if (bus->sih->buscoretype == SDIOD_CORE_ID) {
907 		/* wake up wlan function :WAKE_UP goes as ht_avail_request and alp_avail_request */
908 		regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL);
909 		DHD_INFO(("F0 REG0 rd = 0x%x\n", regdata));
910 
911 		if (on == TRUE)
912 			regdata |= WAKE_UP;
913 		else
914 			regdata &= ~WAKE_UP;
915 
916 		bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err);
917 	}
918 }
919 #endif /* BCMSPI */
920 
921 #ifdef USE_OOB_GPIO1
922 static int
dhdsdio_oobwakeup_init(dhd_bus_t * bus)923 dhdsdio_oobwakeup_init(dhd_bus_t *bus)
924 {
925 	uint32 val, addr, data;
926 
927 	bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP);
928 
929 	addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
930 	data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
931 
932 	/* Set device for gpio1 wakeup */
933 	bcmsdh_reg_write(bus->sdh, addr, 4, 2);
934 	val = bcmsdh_reg_read(bus->sdh, data, 4);
935 	val |= CC_CHIPCTRL2_GPIO1_WAKEUP;
936 	bcmsdh_reg_write(bus->sdh, data, 4, val);
937 
938 	bus->_oobwakeup = TRUE;
939 
940 	return 0;
941 }
942 #endif /* USE_OOB_GPIO1 */
943 
944 /*
945  * Query if FW is in SR mode
946  */
947 static bool
dhdsdio_sr_cap(dhd_bus_t * bus)948 dhdsdio_sr_cap(dhd_bus_t *bus)
949 {
950 	bool cap = FALSE;
951 	uint32  core_capext, addr, data;
952 
953 	/* Query for SRcore in Chip else check for SR mode is enabled in FW */
954 	if (si_findcoreidx(bus->sih, SR_CORE_ID, 0) != BADIDX) {
955 		if (bus->sih->chip == CYW55500_CHIP_ID ||
956 		    bus->sih->chip == CYW55560_CHIP_ID) {
957 			return true;
958 		}
959 	}
960 
961 	if (bus->sih->chip == BCM43430_CHIP_ID ||
962 		bus->sih->chip == BCM43018_CHIP_ID) {
963 		/* check if fw initialized sr engine */
964 		addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, sr_control1);
965 		if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0)
966 			cap = TRUE;
967 
968 		return cap;
969 	}
970 	if (
971 		0) {
972 			core_capext = FALSE;
973 	} else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
974 		(bus->sih->chip == BCM4339_CHIP_ID) ||
975 		BCM4345_CHIP(bus->sih->chip) ||
976 		(bus->sih->chip == BCM4354_CHIP_ID) ||
977 		(bus->sih->chip == BCM4358_CHIP_ID) ||
978 		(BCM4349_CHIP(bus->sih->chip))		||
979 		(bus->sih->chip == BCM4350_CHIP_ID) ||
980 #ifdef UNRELEASEDCHIP_FOR_ANDROID
981 		(bus->sih->chip == BCM4362_CHIP_ID) ||
982 #endif /* UNRELEASEDCHIP_FOR_ANDROID */
983 		(bus->sih->chip == BCM43012_CHIP_ID) ||
984 		(bus->sih->chip == BCM43014_CHIP_ID) ||
985 		(bus->sih->chip == BCM43751_CHIP_ID) ||
986 		(bus->sih->chip == BCM4373_CHIP_ID)) {
987 		core_capext = TRUE;
988 	} else {
989 			core_capext = bcmsdh_reg_read(bus->sdh,
990 				si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, core_cap_ext)),
991 				4);
992 
993 			core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
994 	}
995 	if (!(core_capext))
996 		return FALSE;
997 
998 	if ((bus->sih->chip == BCM4335_CHIP_ID) ||
999 		(bus->sih->chip == BCM4339_CHIP_ID) ||
1000 		BCM4345_CHIP(bus->sih->chip) ||
1001 		(bus->sih->chip == BCM4354_CHIP_ID) ||
1002 		(bus->sih->chip == BCM4358_CHIP_ID) ||
1003 		(bus->sih->chip == BCM4350_CHIP_ID)) {
1004 		uint32 enabval = 0;
1005 		addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
1006 		data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
1007 		bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3);
1008 		enabval = bcmsdh_reg_read(bus->sdh, data, 4);
1009 
1010 		if ((bus->sih->chip == BCM4350_CHIP_ID) ||
1011 			BCM4345_CHIP(bus->sih->chip) ||
1012 			(bus->sih->chip == BCM4354_CHIP_ID) ||
1013 			(bus->sih->chip == BCM4358_CHIP_ID))
1014 			enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
1015 
1016 		if (enabval)
1017 			cap = TRUE;
1018 	} else {
1019 		data = bcmsdh_reg_read(bus->sdh,
1020 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, retention_ctl)),
1021 			4);
1022 		if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
1023 			cap = TRUE;
1024 	}
1025 
1026 	return cap;
1027 }
1028 
1029 static int
dhdsdio_sr_init(dhd_bus_t * bus)1030 dhdsdio_sr_init(dhd_bus_t *bus)
1031 {
1032 	uint8 val;
1033 	int err = 0;
1034 
1035 	if (bus->sih->chip == BCM43012_CHIP_ID ||
1036 	    bus->sih->chip == CYW55500_CHIP_ID ||
1037 	    bus->sih->chip == CYW55560_CHIP_ID) {
1038 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1039 		val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
1040 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1041 			1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT, &err);
1042 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1043 	} else {
1044 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1045 		val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
1046 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1047 			1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
1048 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1049 	}
1050 
1051 #ifdef USE_CMD14
1052 	/* Add CMD14 Support */
1053 	dhdsdio_devcap_set(bus,
1054 		(SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT));
1055 #endif /* USE_CMD14 */
1056 
1057 	if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
1058 		CHIPID(bus->sih->chip) == BCM43018_CHIP_ID ||
1059 		CHIPID(bus->sih->chip) == BCM4339_CHIP_ID ||
1060 		CHIPID(bus->sih->chip) == BCM43012_CHIP_ID ||
1061 		CHIPID(bus->sih->chip) == CYW55500_CHIP_ID ||
1062 		CHIPID(bus->sih->chip) == CYW55560_CHIP_ID ||
1063 #ifdef UNRELEASEDCHIP_FOR_ANDROID
1064 		CHIPID(bus->sih->chip) == BCM4362_CHIP_ID ||
1065 #endif /* UNRELEASEDCHIP_FOR_ANDROID */
1066 		CHIPID(bus->sih->chip) == BCM43014_CHIP_ID ||
1067 		CHIPID(bus->sih->chip) == BCM43751_CHIP_ID ||
1068 		FALSE)
1069 #ifdef BCMSPI
1070 		dhdsdio_wkwlan(bus, FALSE);
1071 #else
1072 		dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
1073 #endif /* BCMSPI */
1074 
1075 	if (bus->sih->chip == BCM43012_CHIP_ID ||
1076 	    bus->sih->chip == CYW55500_CHIP_ID ||
1077 	    bus->sih->chip == CYW55560_CHIP_ID) {
1078 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
1079 			SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_HT_AVAIL_REQ, &err);
1080 	} else {
1081 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
1082 			SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
1083 	}
1084 	bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
1085 
1086 	bus->_srenab = TRUE;
1087 
1088 	return 0;
1089 }
1090 
1091 /*
1092  * FIX: Be sure KSO bit is enabled
1093  * Currently, it's defaulting to 0 which should be 1.
1094  */
1095 static int
dhdsdio_clk_kso_init(dhd_bus_t * bus)1096 dhdsdio_clk_kso_init(dhd_bus_t *bus)
1097 {
1098 	uint8 val;
1099 	int err = 0;
1100 
1101 	/* set flag */
1102 	bus->kso = TRUE;
1103 
1104 	/*
1105 	 * Enable KeepSdioOn (KSO) bit for normal operation
1106 	 * Default is 0 (4334A0) so set it. Fixed in B0.
1107 	 */
1108 	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, NULL);
1109 	if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
1110 		val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
1111 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, val, &err);
1112 		if (err)
1113 			DHD_ERROR(("%s: SBSDIO_FUNC1_SLEEPCSR err: 0x%x\n", __FUNCTION__, err));
1114 	}
1115 
1116 	return 0;
1117 }
1118 
1119 #define KSO_DBG(x)          DHD_TRACE(x)
1120 #define KSO_WAIT_US 50
1121 #define KSO_WAIT_MS 1
1122 #define KSO_SLEEP_RETRY_COUNT 20
1123 #define KSO_WAKE_RETRY_COUNT 100
1124 #define ERROR_BCME_NODEVICE_MAX 1
1125 
1126 #define DEFAULT_MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
1127 #ifndef CUSTOM_MAX_KSO_ATTEMPTS
1128 #define CUSTOM_MAX_KSO_ATTEMPTS DEFAULT_MAX_KSO_ATTEMPTS
1129 #endif // endif
1130 
1131 static int
dhdsdio_clk_kso_enab(dhd_bus_t * bus,bool on)1132 dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
1133 {
1134 	uint8 wr_val = 0, rd_val, cmp_val, bmask;
1135 	int err = 0;
1136 	int try_cnt = 0;
1137 
1138 #ifdef DHD_KSO_MMC_RETUNE
1139 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) || defined(CONFIG_DHD_PLAT_ROCKCHIP))
1140 	struct sdioh_info *sd = (struct sdioh_info *)(bus->sdh->sdioh);
1141 	struct sdio_func *func = sd->func[1];
1142 	struct mmc_host *host = func->card->host;
1143 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) */
1144 #endif /* DHD_KSO_MMC_RETUNE */
1145 
1146 	KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
1147 
1148 #ifdef DHD_KSO_MMC_RETUNE
1149 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
1150 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
1151     sdio_retune_crc_disable(func);
1152 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1153     if (on) {
1154         mmc_retune_hold_now(host);
1155     }
1156 #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) */
1157 #ifdef CONFIG_DHD_PLAT_ROCKCHIP
1158     mmc_retune_disable(host);
1159 #endif /* CONFIG_DHD_PLAT_ROCKCHIP */
1160 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) */
1161 #endif /* DHD_KSO_MMC_RETUNE */
1162 
1163 	wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
1164 
1165 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
1166 
1167 	/* In case of 43012/555x0 chip, the chip could go down immediately after KSO bit is
1168 	 * cleared. So the further reads of KSO register could fail. Thereby just bailing out
1169 	 * immediately after clearing KSO bit, to avoid polling of KSO bit.
1170 	 */
1171 	if ((!on) && (bus->sih->chip == BCM43012_CHIP_ID ||
1172 			bus->sih->chip == CYW55500_CHIP_ID ||
1173 			bus->sih->chip == CYW55560_CHIP_ID)) {
1174 		goto exit;
1175 	}
1176 
1177 	if (on) {
1178 		cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |  SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
1179 		bmask = cmp_val;
1180 
1181 		OSL_SLEEP(3);
1182 
1183 	} else {
1184 		/* Put device to sleep, turn off  KSO  */
1185 		cmp_val = 0;
1186 		bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
1187 	}
1188 
1189 	do {
1190 		rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1191 		if (((rd_val & bmask) == cmp_val) && !err)
1192 			break;
1193 
1194 		KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err));
1195 
1196 		if (((try_cnt + 1) % KSO_SLEEP_RETRY_COUNT) == 0) {
1197 			OSL_SLEEP(KSO_WAIT_MS);
1198 		} else
1199 			OSL_DELAY(KSO_WAIT_US);
1200 
1201 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
1202 	} while (try_cnt++ < CUSTOM_MAX_KSO_ATTEMPTS);
1203 
1204 	if (try_cnt > 2)
1205 		KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n",
1206 			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
1207 
1208 	if (try_cnt > CUSTOM_MAX_KSO_ATTEMPTS)  {
1209 		DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n",
1210 			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
1211 	}
1212 
1213 exit:
1214 #ifdef DHD_KSO_MMC_RETUNE
1215 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
1216     if (on) {
1217         mmc_retune_release(host);
1218     }
1219 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
1220     sdio_retune_crc_enable(func);
1221 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1222 #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) */
1223 #ifdef CONFIG_DHD_PLAT_ROCKCHIP
1224     mmc_retune_enable(host);
1225 #endif /* CONFIG_DHD_PLAT_ROCKCHIP */
1226 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) */
1227 #endif /* DHD_KSO_MMC_RETUNE */
1228 
1229 	return err;
1230 }
1231 
1232 static int
dhdsdio_clk_kso_iovar(dhd_bus_t * bus,bool on)1233 dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bool on)
1234 {
1235 	int err = 0;
1236 
1237 	if (on == FALSE) {
1238 
1239 		BUS_WAKE(bus);
1240 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1241 
1242 		DHD_ERROR(("%s: KSO disable clk: 0x%x\n", __FUNCTION__,
1243 			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1244 			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1245 		dhdsdio_clk_kso_enab(bus, FALSE);
1246 	} else {
1247 		DHD_ERROR(("%s: KSO enable\n", __FUNCTION__));
1248 
1249 		/* Make sure we have SD bus access */
1250 		if (bus->clkstate == CLK_NONE) {
1251 			DHD_ERROR(("%s: Request SD clk\n", __FUNCTION__));
1252 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1253 		}
1254 
1255 		dhdsdio_clk_kso_enab(bus, TRUE);
1256 
1257 		DHD_ERROR(("%s: sleepcsr: 0x%x\n", __FUNCTION__,
1258 			dhdsdio_sleepcsr_get(bus)));
1259 	}
1260 
1261 	bus->kso = on;
1262 	BCM_REFERENCE(err);
1263 
1264 	return 0;
1265 }
1266 
1267 static uint8
dhdsdio_sleepcsr_get(dhd_bus_t * bus)1268 dhdsdio_sleepcsr_get(dhd_bus_t *bus)
1269 {
1270 	int err = 0;
1271 	uint8 val = 0;
1272 
1273 	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1274 	if (err)
1275 		DHD_TRACE(("Failed to read SLEEPCSR: %d\n", err));
1276 
1277 	return val;
1278 }
1279 
1280 uint8
dhdsdio_devcap_get(dhd_bus_t * bus)1281 dhdsdio_devcap_get(dhd_bus_t *bus)
1282 {
1283 	return bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL);
1284 }
1285 
1286 static int
dhdsdio_devcap_set(dhd_bus_t * bus,uint8 cap)1287 dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap)
1288 {
1289 	int err = 0;
1290 
1291 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, cap, &err);
1292 	if (err)
1293 		DHD_ERROR(("%s: devcap set err: 0x%x\n", __FUNCTION__, err));
1294 
1295 	return 0;
1296 }
1297 
1298 static int
dhdsdio_clk_devsleep_iovar(dhd_bus_t * bus,bool on)1299 dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on)
1300 {
1301 	int err = 0, retry;
1302 	uint8 val;
1303 
1304 	retry = 0;
1305 	if (on == TRUE) {
1306 		/* Enter Sleep */
1307 
1308 		/* Be sure we request clk before going to sleep
1309 		 * so we can wake-up with clk request already set
1310 		 * else device can go back to sleep immediately
1311 		 */
1312 		if (!SLPAUTO_ENAB(bus))
1313 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1314 		else {
1315 			val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
1316 			if ((val & SBSDIO_CSR_MASK) == 0) {
1317 				DHD_ERROR(("%s: No clock before enter sleep:0x%x\n",
1318 					__FUNCTION__, val));
1319 
1320 				/* Reset clock request */
1321 				bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
1322 					SBSDIO_ALP_AVAIL_REQ, &err);
1323 				DHD_ERROR(("%s: clock before sleep:0x%x\n", __FUNCTION__,
1324 					bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1325 					SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1326 			}
1327 		}
1328 
1329 		DHD_TRACE(("%s: clk before sleep: 0x%x\n", __FUNCTION__,
1330 			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1331 			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1332 #ifdef USE_CMD14
1333 		err = bcmsdh_sleep(bus->sdh, TRUE);
1334 #else
1335 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) {
1336 			if (sd1idle) {
1337 				/* Change to SD1 mode */
1338 				dhdsdio_set_sdmode(bus, 1);
1339 			}
1340 		}
1341 
1342 		err = dhdsdio_clk_kso_enab(bus, FALSE);
1343 		if (OOB_WAKEUP_ENAB(bus))
1344 		{
1345 			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE);  /* GPIO_1 is off */
1346 		}
1347 #endif /* USE_CMD14 */
1348 
1349 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock != DHD_IDLE_ACTIVE)) {
1350 			DHD_TRACE(("%s: Turnoff SD clk\n", __FUNCTION__));
1351 			/* Now remove the SD clock */
1352 			err = dhdsdio_sdclk(bus, FALSE);
1353 		}
1354 	} else {
1355 		/* Exit Sleep */
1356 		/* Make sure we have SD bus access */
1357 		if (bus->clkstate == CLK_NONE) {
1358 			DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__));
1359 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1360 		}
1361 #ifdef USE_CMD14
1362 		err = bcmsdh_sleep(bus->sdh, FALSE);
1363 		if (SLPAUTO_ENAB(bus) && (err != 0)) {
1364 			OSL_DELAY(10000);
1365 			DHD_TRACE(("%s: Resync device sleep\n", __FUNCTION__));
1366 
1367 			/* Toggle sleep to resync with host and device */
1368 			err = bcmsdh_sleep(bus->sdh, TRUE);
1369 			OSL_DELAY(10000);
1370 			err = bcmsdh_sleep(bus->sdh, FALSE);
1371 
1372 			if (err) {
1373 				OSL_DELAY(10000);
1374 				DHD_ERROR(("%s: CMD14 exit failed again!\n", __FUNCTION__));
1375 
1376 				/* Toggle sleep to resync with host and device */
1377 				err = bcmsdh_sleep(bus->sdh, TRUE);
1378 				OSL_DELAY(10000);
1379 				err = bcmsdh_sleep(bus->sdh, FALSE);
1380 				if (err) {
1381 					DHD_ERROR(("%s: CMD14 exit failed twice!\n", __FUNCTION__));
1382 					DHD_ERROR(("%s: FATAL: Device non-response!\n",
1383 						__FUNCTION__));
1384 					err = 0;
1385 				}
1386 			}
1387 		}
1388 #else
1389 		if (OOB_WAKEUP_ENAB(bus))
1390 		{
1391 			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE);  /* GPIO_1 is on */
1392 		}
1393 		do {
1394 			err = dhdsdio_clk_kso_enab(bus, TRUE);
1395 			if (err)
1396 				OSL_SLEEP(10);
1397 		} while ((err != 0) && (++retry < 3));
1398 
1399 		if (err != 0) {
1400 			DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry));
1401 #ifndef BT_OVER_SDIO
1402 			err = 0; /* continue anyway */
1403 #endif /* BT_OVER_SDIO */
1404 		}
1405 
1406 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) {
1407 			dhdsdio_set_sdmode(bus, bus->sd_mode);
1408 		}
1409 #endif /* !USE_CMD14 */
1410 
1411 		if (err == 0) {
1412 			uint8 csr;
1413 
1414 			/* Wait for device ready during transition to wake-up */
1415 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1416 				(((csr = dhdsdio_sleepcsr_get(bus)) &
1417 				SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) !=
1418 				(SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000));
1419 
1420 			DHD_TRACE(("%s: ExitSleep sleepcsr: 0x%x\n", __FUNCTION__, csr));
1421 
1422 			if (!(csr & SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) {
1423 				DHD_ERROR(("%s:ERROR: ExitSleep device NOT Ready! 0x%x\n",
1424 					__FUNCTION__, csr));
1425 				err = BCME_NODEVICE;
1426 			}
1427 
1428 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1429 				(((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1430 				SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) !=
1431 				(SBSDIO_HT_AVAIL)), (DHD_WAIT_HTAVAIL));
1432 
1433 			DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr));
1434 			if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) {
1435 				DHD_ERROR(("%s:ERROR: device NOT Ready! 0x%x\n",
1436 					__FUNCTION__, csr));
1437 				err = BCME_NODEVICE;
1438 			}
1439 		}
1440 	}
1441 
1442 	/* Update if successful */
1443 	if (err == 0)
1444 		bus->kso = on ? FALSE : TRUE;
1445 	else {
1446 		DHD_ERROR(("%s: Sleep request failed: kso:%d on:%d err:%d\n",
1447 			__FUNCTION__, bus->kso, on, err));
1448 		if (!on && retry > 2)
1449 			bus->kso = FALSE;
1450 	}
1451 
1452 	return err;
1453 }
1454 
1455 /* Turn backplane clock on or off */
1456 static int
dhdsdio_htclk(dhd_bus_t * bus,bool on,bool pendok)1457 dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
1458 {
1459 #define HT_AVAIL_ERROR_MAX 10
1460 	static int ht_avail_error = 0;
1461 	int err;
1462 	uint8 clkctl, clkreq, devctl;
1463 	bcmsdh_info_t *sdh;
1464 
1465 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1466 
1467 	clkctl = 0;
1468 	sdh = bus->sdh;
1469 
1470 	if (!KSO_ENAB(bus))
1471 		return BCME_OK;
1472 
1473 	if (SLPAUTO_ENAB(bus)) {
1474 		bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
1475 		return BCME_OK;
1476 	}
1477 
1478 	if (on) {
1479 		/* Request HT Avail */
1480 		clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
1481 
1482 #ifdef BCMSPI
1483 		dhdsdio_wkwlan(bus, TRUE);
1484 #endif /* BCMSPI */
1485 
1486 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1487 		if (err) {
1488 			ht_avail_error++;
1489 			if (ht_avail_error < HT_AVAIL_ERROR_MAX) {
1490 				DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
1491 			}
1492 
1493 #ifdef OEM_ANDROID
1494 			else if (ht_avail_error == HT_AVAIL_ERROR_MAX) {
1495 				bus->dhd->hang_reason = HANG_REASON_HT_AVAIL_ERROR;
1496 				dhd_os_send_hang_message(bus->dhd);
1497 			}
1498 #endif /* OEM_ANDROID */
1499 			return BCME_ERROR;
1500 		} else {
1501 			ht_avail_error = 0;
1502 		}
1503 
1504 		/* Check current status */
1505 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
1506 		if (err) {
1507 			DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
1508 			return BCME_ERROR;
1509 		}
1510 
1511 #if !defined(OOB_INTR_ONLY)
1512 		/* Go to pending and await interrupt if appropriate */
1513 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
1514 			/* Allow only clock-available interrupt */
1515 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1516 			if (err) {
1517 				DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
1518 				           __FUNCTION__, err));
1519 				return BCME_ERROR;
1520 			}
1521 
1522 			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
1523 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1524 			DHD_INFO(("CLKCTL: set PENDING\n"));
1525 			bus->clkstate = CLK_PENDING;
1526 			return BCME_OK;
1527 		} else
1528 #endif /* !defined (OOB_INTR_ONLY) */
1529 		{
1530 			if (bus->clkstate == CLK_PENDING) {
1531 				/* Cancel CA-only interrupt filter */
1532 				devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1533 				devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1534 				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1535 			}
1536 		}
1537 #ifndef BCMSDIOLITE
1538 		/* Otherwise, wait here (polling) for HT Avail */
1539 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1540 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1541 				((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
1542 			                                    SBSDIO_FUNC1_CHIPCLKCSR, &err)),
1543 			          !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
1544 		}
1545 		if (err) {
1546 			DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
1547 			return BCME_ERROR;
1548 		}
1549 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1550 			DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
1551 			           __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
1552 			return BCME_ERROR;
1553 		}
1554 #endif /* BCMSDIOLITE */
1555 		/* Mark clock available */
1556 		bus->clkstate = CLK_AVAIL;
1557 		DHD_INFO(("CLKCTL: turned ON\n"));
1558 
1559 #if defined(DHD_DEBUG)
1560 		if (bus->alp_only == TRUE) {
1561 #if !defined(BCMLXSDMMC)
1562 			if (!SBSDIO_ALPONLY(clkctl)) {
1563 				DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
1564 			}
1565 #endif /* !defined(BCMLXSDMMC) */
1566 		} else {
1567 			if (SBSDIO_ALPONLY(clkctl)) {
1568 				DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
1569 			}
1570 		}
1571 #endif /* defined (DHD_DEBUG) */
1572 
1573 		bus->activity = TRUE;
1574 #ifdef DHD_USE_IDLECOUNT
1575 		bus->idlecount = 0;
1576 #endif /* DHD_USE_IDLECOUNT */
1577 	} else {
1578 		clkreq = 0;
1579 
1580 		if (bus->clkstate == CLK_PENDING) {
1581 			/* Cancel CA-only interrupt filter */
1582 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1583 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1584 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1585 		}
1586 
1587 		bus->clkstate = CLK_SDONLY;
1588 		if (!SR_ENAB(bus)) {
1589 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1590 			DHD_INFO(("CLKCTL: turned OFF\n"));
1591 			if (err) {
1592 				DHD_ERROR(("%s: Failed access turning clock off: %d\n",
1593 				           __FUNCTION__, err));
1594 				return BCME_ERROR;
1595 			}
1596 		}
1597 #ifdef BCMSPI
1598 			dhdsdio_wkwlan(bus, FALSE);
1599 #endif /* BCMSPI */
1600 	}
1601 	return BCME_OK;
1602 }
1603 
1604 /* Change SD1/SD4 bus mode */
1605 static int
dhdsdio_set_sdmode(dhd_bus_t * bus,int32 sd_mode)1606 dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode)
1607 {
1608 	int err;
1609 
1610 	err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
1611 		&sd_mode, sizeof(sd_mode), TRUE);
1612 	if (err) {
1613 		DHD_ERROR(("%s: error changing sd_mode: %d\n",
1614 			__FUNCTION__, err));
1615 		return BCME_ERROR;
1616 	}
1617 	return BCME_OK;
1618 }
1619 
1620 /* Change idle/active SD state */
1621 static int
dhdsdio_sdclk(dhd_bus_t * bus,bool on)1622 dhdsdio_sdclk(dhd_bus_t *bus, bool on)
1623 {
1624 #ifndef BCMSPI
1625 	int err;
1626 	int32 iovalue;
1627 
1628 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1629 
1630 	if (on) {
1631 		if (bus->idleclock == DHD_IDLE_STOP) {
1632 			/* Turn on clock and restore mode */
1633 			iovalue = 1;
1634 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
1635 			                      &iovalue, sizeof(iovalue), TRUE);
1636 			if (err) {
1637 				DHD_ERROR(("%s: error enabling sd_clock: %d\n",
1638 				           __FUNCTION__, err));
1639 				return BCME_ERROR;
1640 			}
1641 
1642 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
1643 			/* Restore clock speed */
1644 			iovalue = bus->sd_divisor;
1645 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
1646 			                      &iovalue, sizeof(iovalue), TRUE);
1647 			if (err) {
1648 				DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
1649 				           __FUNCTION__, err));
1650 				return BCME_ERROR;
1651 			}
1652 		}
1653 		bus->clkstate = CLK_SDONLY;
1654 	} else {
1655 		/* Stop or slow the SD clock itself */
1656 		if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
1657 			DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
1658 			           __FUNCTION__, bus->sd_divisor, bus->sd_mode));
1659 			return BCME_ERROR;
1660 		}
1661 		if (bus->idleclock == DHD_IDLE_STOP) {
1662 			iovalue = 0;
1663 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
1664 			                      &iovalue, sizeof(iovalue), TRUE);
1665 			if (err) {
1666 				DHD_ERROR(("%s: error disabling sd_clock: %d\n",
1667 				           __FUNCTION__, err));
1668 				return BCME_ERROR;
1669 			}
1670 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
1671 			/* Set divisor to idle value */
1672 			iovalue = bus->idleclock;
1673 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
1674 			                      &iovalue, sizeof(iovalue), TRUE);
1675 			if (err) {
1676 				DHD_ERROR(("%s: error changing sd_divisor: %d\n",
1677 				           __FUNCTION__, err));
1678 				return BCME_ERROR;
1679 			}
1680 		}
1681 		bus->clkstate = CLK_NONE;
1682 	}
1683 #else /* BCMSPI */
1684 #endif /* !BCMSPI */
1685 
1686 	return BCME_OK;
1687 }
1688 
1689 /* Transition SD and backplane clock readiness */
1690 static int
dhdsdio_clkctl(dhd_bus_t * bus,uint target,bool pendok)1691 dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
1692 {
1693 	int ret = BCME_OK;
1694 #ifdef DHD_DEBUG
1695 	uint oldstate = bus->clkstate;
1696 #endif /* DHD_DEBUG */
1697 
1698 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1699 
1700 	/* Early exit if we're already there */
1701 	if (bus->clkstate == target) {
1702 		if (target == CLK_AVAIL) {
1703 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1704 			bus->activity = TRUE;
1705 #ifdef DHD_USE_IDLECOUNT
1706 			bus->idlecount = 0;
1707 #endif /* DHD_USE_IDLECOUNT */
1708 		}
1709 		return ret;
1710 	}
1711 
1712 	switch (target) {
1713 	case CLK_AVAIL:
1714 		/* Make sure SD clock is available */
1715 		if (bus->clkstate == CLK_NONE)
1716 			dhdsdio_sdclk(bus, TRUE);
1717 		/* Now request HT Avail on the backplane */
1718 		ret = dhdsdio_htclk(bus, TRUE, pendok);
1719 		if (ret == BCME_OK) {
1720 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1721 		bus->activity = TRUE;
1722 #ifdef DHD_USE_IDLECOUNT
1723 			bus->idlecount = 0;
1724 #endif /* DHD_USE_IDLECOUNT */
1725 		}
1726 		break;
1727 
1728 	case CLK_SDONLY:
1729 
1730 #ifdef BT_OVER_SDIO
1731 		/*
1732 		 * If the request is to switch off Back plane clock,
1733 		 * confirm that BT is inactive before doing so.
1734 		 * If this call had come from Non Watchdog context any way
1735 		 * the Watchdog would switch off the clock again when
1736 		 * nothing is to be done & Bt has finished using the bus.
1737 		 */
1738 		if (bus->bt_use_count != 0) {
1739 			DHD_INFO(("%s(): Req CLK_SDONLY, BT is active %d not switching off \r\n",
1740 				__FUNCTION__, bus->bt_use_count));
1741 			ret = BCME_OK;
1742 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1743 			break;
1744 		}
1745 
1746 		DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n",
1747 			__FUNCTION__));
1748 #endif /* BT_OVER_SDIO */
1749 
1750 		/* Remove HT request, or bring up SD clock */
1751 		if (bus->clkstate == CLK_NONE)
1752 			ret = dhdsdio_sdclk(bus, TRUE);
1753 		else if (bus->clkstate == CLK_AVAIL)
1754 			ret = dhdsdio_htclk(bus, FALSE, FALSE);
1755 		else
1756 			DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
1757 			           bus->clkstate, target));
1758 		if (ret == BCME_OK) {
1759 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1760 		}
1761 		break;
1762 
1763 	case CLK_NONE:
1764 
1765 #ifdef BT_OVER_SDIO
1766 		/*
1767 		 * If the request is to switch off Back plane clock,
1768 		 * confirm that BT is inactive before doing so.
1769 		 * If this call had come from Non Watchdog context any way
1770 		 * the Watchdog would switch off the clock again when
1771 		 * nothing is to be done & Bt has finished using the bus.
1772 		 */
1773 		if (bus->bt_use_count != 0) {
1774 			DHD_INFO(("%s(): Request CLK_NONE BT is active %d not switching off \r\n",
1775 				__FUNCTION__, bus->bt_use_count));
1776 			ret = BCME_OK;
1777 			break;
1778 		}
1779 
1780 		DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n",
1781 			__FUNCTION__));
1782 #endif /* BT_OVER_SDIO */
1783 
1784 		/* Make sure to remove HT request */
1785 		if (bus->clkstate == CLK_AVAIL)
1786 			ret = dhdsdio_htclk(bus, FALSE, FALSE);
1787 		/* Now remove the SD clock */
1788 		ret = dhdsdio_sdclk(bus, FALSE);
1789 #ifdef DHD_DEBUG
1790 		if (bus->dhd->dhd_console_ms == 0)
1791 #endif /* DHD_DEBUG */
1792 		if (bus->poll == 0)
1793 			dhd_os_wd_timer(bus->dhd, 0);
1794 		break;
1795 	}
1796 #ifdef DHD_DEBUG
1797 	DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
1798 #endif /* DHD_DEBUG */
1799 
1800 	return ret;
1801 }
1802 
1803 static int
dhdsdio_bussleep(dhd_bus_t * bus,bool sleep)1804 dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
1805 {
1806 	int err = 0;
1807 	bcmsdh_info_t *sdh = bus->sdh;
1808 	sdpcmd_regs_t *regs = bus->regs;
1809 	uint retries = 0;
1810 #if defined(BCMSDIOH_STD)
1811 	uint32 sd3_tuning_disable = FALSE;
1812 #endif /* BCMSDIOH_STD */
1813 
1814 	DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
1815 	         (sleep ? "SLEEP" : "WAKE"),
1816 	          (bus->sleeping ? "SLEEP" : "WAKE")));
1817 
1818 	if (bus->dhd->hang_was_sent)
1819 		return BCME_ERROR;
1820 
1821 	/* Done if we're already in the requested state */
1822 	if (sleep == bus->sleeping)
1823 		return BCME_OK;
1824 
1825 	/* Going to sleep: set the alarm and turn off the lights... */
1826 	if (sleep) {
1827 		/* Don't sleep if something is pending */
1828 #ifdef DHD_USE_IDLECOUNT
1829 		if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq) ||
1830 			bus->readframes || bus->ctrl_frame_stat)
1831 #else
1832 		if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq))
1833 #endif /* DHD_USE_IDLECOUNT */
1834 			return BCME_BUSY;
1835 
1836 #ifdef BT_OVER_SDIO
1837 		/*
1838 		 * The following is the assumption based on which the hook is placed.
1839 		 * From WLAN driver, either from the active contexts OR from the Watchdog contexts
1840 		 * we will be attempting to Go to Sleep. AT that moment if we see that BT is still
1841 		 * actively using the bus, we will return BCME_BUSY from here, but the bus->sleeping
1842 		 * state would not have changed. So the caller can then schedule the Watchdog again
1843 		 * which will come and attempt to sleep at a later point.
1844 		 *
1845 		 * In case if BT is the only one and is the last user, we don't switch off the clock
1846 		 * immediately, we allow the WLAN to decide when to sleep i.e from the watchdog.
1847 		 * Now if the watchdog becomes active and attempts to switch off the clock and if
1848 		 * another WLAN context is active they are any way serialized with sdlock.
1849 		 */
1850 		if (bus->bt_use_count != 0) {
1851 			DHD_INFO(("%s(): Cannot sleep BT is active \r\n", __FUNCTION__));
1852 			return BCME_BUSY;
1853 		}
1854 #endif /* !BT_OVER_SDIO */
1855 
1856 		if (!SLPAUTO_ENAB(bus)) {
1857 			/* Disable SDIO interrupts (no longer interested) */
1858 			bcmsdh_intr_disable(bus->sdh);
1859 
1860 			/* Make sure the controller has the bus up */
1861 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1862 
1863 			/* Tell device to start using OOB wakeup */
1864 			W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
1865 			if (retries > retry_limit)
1866 				DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
1867 
1868 			/* Turn off our contribution to the HT clock request */
1869 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1870 
1871 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
1872 				SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
1873 
1874 			/* Isolate the bus */
1875 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
1876 					SBSDIO_DEVCTL_PADS_ISO, NULL);
1877 		} else {
1878 			/* Leave interrupts enabled since device can exit sleep and
1879 			 * interrupt host
1880 			 */
1881 			err = dhdsdio_clk_devsleep_iovar(bus, TRUE /* sleep */);
1882 		}
1883 
1884 		/* Change state */
1885 		bus->sleeping = TRUE;
1886 #if defined(BCMSDIOH_STD)
1887 		sd3_tuning_disable = TRUE;
1888 		err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0,
1889 			&sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE);
1890 #endif /* BCMSDIOH_STD */
1891 #if defined(SUPPORT_P2P_GO_PS)
1892 		wake_up(&bus->bus_sleep);
1893 #endif /* LINUX && SUPPORT_P2P_GO_PS */
1894 	} else {
1895 		/* Waking up: bus power up is ok, set local state */
1896 
1897 		if (!SLPAUTO_ENAB(bus)) {
1898 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, &err);
1899 
1900 			/* Force pad isolation off if possible (in case power never toggled) */
1901 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
1902 
1903 			/* Make sure the controller has the bus up */
1904 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1905 
1906 			/* Send misc interrupt to indicate OOB not needed */
1907 			W_SDREG(0, &regs->tosbmailboxdata, retries);
1908 			if (retries <= retry_limit)
1909 				W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
1910 
1911 			if (retries > retry_limit)
1912 				DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
1913 
1914 			/* Make sure we have SD bus access */
1915 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1916 
1917 			/* Enable interrupts again */
1918 			if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
1919 				bus->intdis = FALSE;
1920 				bcmsdh_intr_enable(bus->sdh);
1921 			}
1922 		} else {
1923 			err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */);
1924 #ifdef BT_OVER_SDIO
1925 			if (err < 0) {
1926 				struct net_device *net = NULL;
1927 				dhd_pub_t *dhd = bus->dhd;
1928 				net = dhd_idx2net(dhd, 0);
1929 				if (net != NULL) {
1930 					DHD_ERROR(("<< WIFI HANG by KSO Enabled failure\n"));
1931 					dhd_os_sdunlock(dhd);
1932 					net_os_send_hang_message(net);
1933 					dhd_os_sdlock(dhd);
1934 				} else {
1935 					DHD_ERROR(("<< WIFI HANG Fail because net is NULL\n"));
1936 				}
1937 			}
1938 #endif /* BT_OVER_SDIO */
1939 		}
1940 
1941 		if (err == 0) {
1942 			/* Change state */
1943 			bus->sleeping = FALSE;
1944 #if defined(BCMSDIOH_STD)
1945 			sd3_tuning_disable = FALSE;
1946 			err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0,
1947 				&sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE);
1948 #endif /* BCMSDIOH_STD */
1949 		}
1950 	}
1951 
1952 	return err;
1953 }
1954 
1955 #ifdef BT_OVER_SDIO
1956 /*
1957  * Call this function to Get the Clock running.
1958  * Assumes that the caller holds the sdlock.
1959  * bus - Pointer to the dhd_bus handle
1960  * can_wait - TRUE if the caller can wait until the clock becomes ready
1961  *            FALSE if the caller cannot wait
1962  */
__dhdsdio_clk_enable(struct dhd_bus * bus,bus_owner_t owner,int can_wait)1963 int __dhdsdio_clk_enable(struct dhd_bus *bus, bus_owner_t owner, int can_wait)
1964 {
1965 	int ret = BCME_ERROR;
1966 
1967 	BCM_REFERENCE(owner);
1968 
1969 	bus->bt_use_count++;
1970 
1971 	/*
1972 	 * We can call BUS_WAKE, clkctl multiple times, both of the items
1973 	 * have states and if its already ON, no new configuration is done
1974 	 */
1975 
1976 	/* Wake up the Dongle FW from SR */
1977 	BUS_WAKE(bus);
1978 
1979 	/*
1980 	 * Make sure back plane ht clk is on
1981 	 * CLK_AVAIL - Turn On both SD & HT clock
1982 	 */
1983 	ret = dhdsdio_clkctl(bus, CLK_AVAIL, can_wait);
1984 
1985 	DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__,
1986 		bus->bt_use_count));
1987 	return ret;
1988 }
1989 
1990 /*
1991  * Call this function to relinquish the Clock.
1992  * Assumes that the caller holds the sdlock.
1993  * bus - Pointer to the dhd_bus handle
1994  * can_wait - TRUE if the caller can wait until the clock becomes ready
1995  *            FALSE if the caller cannot wait
1996  */
__dhdsdio_clk_disable(struct dhd_bus * bus,bus_owner_t owner,int can_wait)1997 int __dhdsdio_clk_disable(struct dhd_bus *bus, bus_owner_t owner, int can_wait)
1998 {
1999 	int ret = BCME_ERROR;
2000 
2001 	BCM_REFERENCE(owner);
2002 	BCM_REFERENCE(can_wait);
2003 
2004 	if (bus->bt_use_count == 0) {
2005 		DHD_ERROR(("%s(): Clocks are already turned off \r\n",
2006 			__FUNCTION__));
2007 		return ret;
2008 	}
2009 
2010 	bus->bt_use_count--;
2011 
2012 	/*
2013 	 * When the SDIO Bus is shared between BT & WLAN, we turn Off the clock
2014 	 * once the last user has relinqushed the same. But there are two schemes
2015 	 * in that too. We consider WLAN as the  bus master (even if its not
2016 	 * active). Even when the WLAN is OFF the DHD Watchdog is active.
2017 	 * So this Bus Watchdog is the context whill put the Bus to sleep.
2018 	 * Refer dhd_bus_watchdog function
2019 	 */
2020 
2021 	ret = BCME_OK;
2022 	DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__,
2023 		bus->bt_use_count));
2024 	return ret;
2025 }
2026 
dhdsdio_reset_bt_use_count(struct dhd_bus * bus)2027 void dhdsdio_reset_bt_use_count(struct dhd_bus *bus)
2028 {
2029 	/* reset bt use count */
2030 	bus->bt_use_count = 0;
2031 }
2032 #endif /* BT_OVER_SDIO */
2033 
2034 #ifdef USE_DYNAMIC_F2_BLKSIZE
dhdsdio_func_blocksize(dhd_pub_t * dhd,int function_num,int block_size)2035 int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
2036 {
2037 	int func_blk_size = function_num;
2038 	int bcmerr = 0;
2039 	int result;
2040 
2041 	bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size,
2042 		sizeof(int), &result, sizeof(int), IOV_GET);
2043 
2044 	if (bcmerr != BCME_OK) {
2045 		DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num));
2046 		return BCME_ERROR;
2047 	}
2048 
2049 	if (result != block_size) {
2050 		DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n",
2051 			__FUNCTION__, function_num, result, block_size));
2052 		func_blk_size = function_num << 16 | block_size;
2053 		bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL,
2054 			0, &func_blk_size, sizeof(int32), IOV_SET);
2055 		if (bcmerr != BCME_OK) {
2056 			DHD_ERROR(("%s: Set F%d Block size error\n", __FUNCTION__, function_num));
2057 			return BCME_ERROR;
2058 		}
2059 	}
2060 
2061 	return BCME_OK;
2062 }
2063 #endif /* USE_DYNAMIC_F2_BLKSIZE */
2064 
2065 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
2066 void
dhd_enable_oob_intr(struct dhd_bus * bus,bool enable)2067 dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
2068 {
2069 #if defined(BCMSPI_ANDROID)
2070 	bcmsdh_intr_enable(bus->sdh);
2071 #elif defined(HW_OOB)
2072 	bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
2073 #else
2074 	sdpcmd_regs_t *regs = bus->regs;
2075 	uint retries = 0;
2076 
2077 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2078 	if (enable == TRUE) {
2079 
2080 		/* Tell device to start using OOB wakeup */
2081 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
2082 		if (retries > retry_limit)
2083 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
2084 
2085 	} else {
2086 		/* Send misc interrupt to indicate OOB not needed */
2087 		W_SDREG(0, &regs->tosbmailboxdata, retries);
2088 		if (retries <= retry_limit)
2089 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
2090 	}
2091 
2092 	/* Turn off our contribution to the HT clock request */
2093 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
2094 #endif /* !defined(HW_OOB) */
2095 }
2096 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
2097 
2098 int
dhd_bus_txdata(struct dhd_bus * bus,void * pkt)2099 dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
2100 {
2101 	int ret = BCME_ERROR;
2102 	osl_t *osh;
2103 	uint datalen, prec;
2104 #ifdef REVERSE_AIFSN
2105 	uint prio;
2106 #endif /* REVERSE_AIFSN */
2107 #if defined(DHD_TX_DUMP)
2108 	uint8 *dump_data;
2109 #endif /* DHD_TX_DUMP */
2110 
2111 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2112 
2113 	osh = bus->dhd->osh;
2114 	datalen = PKTLEN(osh, pkt);
2115 
2116 #ifdef SDTEST
2117 	/* Push the test header if doing loopback */
2118 	if (bus->ext_loop) {
2119 		uint8* data;
2120 		PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
2121 		data = PKTDATA(osh, pkt);
2122 		*data++ = SDPCM_TEST_ECHOREQ;
2123 		*data++ = (uint8)bus->loopid++;
2124 		*data++ = (datalen >> 0);
2125 		*data++ = (datalen >> 8);
2126 		datalen += SDPCM_TEST_HDRLEN;
2127 	}
2128 #else /* SDTEST */
2129 	BCM_REFERENCE(datalen);
2130 #endif /* SDTEST */
2131 
2132 #ifdef DHD_ULP
2133 	dhd_ulp_set_path(bus->dhd, DHD_ULP_TX_DATA);
2134 #endif /* DHD_ULP */
2135 
2136 #if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP)
2137 	dump_data = PKTDATA(osh, pkt);
2138 	dump_data += 4; /* skip 4 bytes header */
2139 	{
2140 		int i;
2141 		DHD_ERROR(("TX DUMP\n"));
2142 
2143 		for (i = 0; i < (datalen - 4); i++) {
2144 			DHD_ERROR(("%02X ", dump_data[i]));
2145 			if ((i & 15) == 15)
2146 				printk("\n");
2147 		}
2148 		DHD_ERROR(("\n"));
2149 	}
2150 #endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */
2151 
2152 	prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
2153 #ifdef REVERSE_AIFSN
2154 	/* Updating the precedence value if aifsn are reverse than 802.11 */
2155 	if (bus->dhd->aifsn_reverse) {
2156 		prio = PKTPRIO(pkt) & PRIOMASK;
2157 		if (prio == PRIO_8021D_BE) {
2158 			prec = PRIO2PREC((PRIO_8021D_VI & PRIOMASK));
2159 		} else if (prio == PRIO_8021D_VI) {
2160 			prec = PRIO2PREC((PRIO_8021D_BE & PRIOMASK));
2161 		}
2162 	}
2163 #endif /* REVERSE_AIFSN */
2164 
2165 	/* Check for existing queue, current flow-control, pending event, or pending clock */
2166 	if (dhd_deferred_tx || bus->fcstate || pktq_n_pkts_tot(&bus->txq) || bus->dpc_sched ||
2167 	    (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
2168 	    (bus->clkstate != CLK_AVAIL)) {
2169 		bool deq_ret;
2170 		int pkq_len;
2171 
2172 		DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
2173 			pktq_n_pkts_tot(&bus->txq)));
2174 		bus->fcqueued++;
2175 
2176 		/* Priority based enq */
2177 		dhd_os_sdlock_txq(bus->dhd);
2178 		deq_ret = dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec);
2179 		dhd_os_sdunlock_txq(bus->dhd);
2180 
2181 		if (!deq_ret) {
2182 #ifdef PROP_TXSTATUS
2183 			if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) == 0)
2184 #endif /* PROP_TXSTATUS */
2185 			{
2186 #ifdef DHDTCPACK_SUPPRESS
2187 				if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
2188 					DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using\n",
2189 						__FUNCTION__, __LINE__));
2190 					dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
2191 				}
2192 #endif /* DHDTCPACK_SUPPRESS */
2193 				dhd_txcomplete(bus->dhd, pkt, FALSE);
2194 				PKTFREE(osh, pkt, TRUE);
2195 			}
2196 			ret = BCME_NORESOURCE;
2197 		} else
2198 			ret = BCME_OK;
2199 
2200 		dhd_os_sdlock_txq(bus->dhd);
2201 		pkq_len = pktq_n_pkts_tot(&bus->txq);
2202 		dhd_os_sdunlock_txq(bus->dhd);
2203 		if (pkq_len >= FCHI) {
2204 			bool wlfc_enabled = FALSE;
2205 #ifdef PROP_TXSTATUS
2206 			wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) !=
2207 				WLFC_UNSUPPORTED);
2208 #endif // endif
2209 			if (!wlfc_enabled && dhd_doflow) {
2210 				dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
2211 			}
2212 		}
2213 
2214 #ifdef DHD_DEBUG
2215 		dhd_os_sdlock_txq(bus->dhd);
2216 		if (pktqprec_n_pkts(&bus->txq, prec) > qcount[prec])
2217 			qcount[prec] = pktqprec_n_pkts(&bus->txq, prec);
2218 		dhd_os_sdunlock_txq(bus->dhd);
2219 #endif // endif
2220 
2221 		/* Schedule DPC if needed to send queued packet(s) */
2222 		if (dhd_deferred_tx && !bus->dpc_sched) {
2223 			bus->dpc_sched = TRUE;
2224 			dhd_sched_dpc(bus->dhd);
2225 		}
2226 	} else {
2227 		int chan = SDPCM_DATA_CHANNEL;
2228 
2229 #ifdef SDTEST
2230 		chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL);
2231 #endif // endif
2232 		/* Lock: we're about to use shared data/code (and SDIO) */
2233 		dhd_os_sdlock(bus->dhd);
2234 
2235 		/* Otherwise, send it now */
2236 		BUS_WAKE(bus);
2237 		/* Make sure back plane ht clk is on, no pending allowed */
2238 		dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
2239 
2240 		ret = dhdsdio_txpkt(bus, chan, &pkt, 1, TRUE);
2241 
2242 		if (ret != BCME_OK)
2243 			bus->dhd->tx_errors++;
2244 		else
2245 			bus->dhd->dstats.tx_bytes += datalen;
2246 
2247 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
2248 				NO_OTHER_ACTIVE_BUS_USER(bus)) {
2249 			bus->activity = FALSE;
2250 			dhdsdio_bussleep(bus, TRUE);
2251 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
2252 		}
2253 
2254 		dhd_os_sdunlock(bus->dhd);
2255 	}
2256 
2257 	return ret;
2258 }
2259 
2260 /* align packet data pointer and packet length to n-byte boundary, process packet headers,
2261  * a new packet may be allocated if there is not enough head and/or tail from for padding.
2262  * the caller is responsible for updating the glom size in the head packet (when glom is
2263  * used)
2264  *
2265  * pad_pkt_len: returns the length of extra padding needed from the padding packet, this parameter
2266  * is taken in tx glom mode only
2267  *
2268  * new_pkt: out, pointer of the new packet allocated due to insufficient head room for alignment
2269  * padding, NULL if not needed, the caller is responsible for freeing the new packet
2270  *
2271  * return: positive value - length of the packet, including head and tail padding
2272  *		   negative value - errors
2273  */
dhdsdio_txpkt_preprocess(dhd_bus_t * bus,void * pkt,int chan,int txseq,int prev_chain_total_len,bool last_chained_pkt,int * pad_pkt_len,void ** new_pkt)2274 static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
2275 	int prev_chain_total_len, bool last_chained_pkt,
2276 	int *pad_pkt_len, void **new_pkt)
2277 {
2278 	osl_t *osh;
2279 	uint8 *frame;
2280 	int pkt_len;
2281 	int modulo;
2282 	int head_padding;
2283 	int tail_padding = 0;
2284 	uint32 swheader;
2285 	uint32 swhdr_offset;
2286 	bool alloc_new_pkt = FALSE;
2287 	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
2288 
2289 	*new_pkt = NULL;
2290 	osh = bus->dhd->osh;
2291 
2292 #ifdef DHDTCPACK_SUPPRESS
2293 	if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
2294 		DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
2295 			__FUNCTION__, __LINE__));
2296 		dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
2297 	}
2298 #endif /* DHDTCPACK_SUPPRESS */
2299 
2300 	/* Add space for the SDPCM hardware/software headers */
2301 	PKTPUSH(osh, pkt, sdpcm_hdrlen);
2302 	ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
2303 
2304 	frame = (uint8*)PKTDATA(osh, pkt);
2305 	pkt_len = (uint16)PKTLEN(osh, pkt);
2306 
2307 #ifdef DHD_DEBUG
2308 	if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets))
2309 		tx_packets[PKTPRIO(pkt)]++;
2310 #endif /* DHD_DEBUG */
2311 
2312 	/* align the data pointer, allocate a new packet if there is not enough space (new
2313 	 * packet data pointer will be aligned thus no padding will be needed)
2314 	 */
2315 	head_padding = (uintptr)frame % DHD_SDALIGN;
2316 	if (PKTHEADROOM(osh, pkt) < head_padding) {
2317 		head_padding = 0;
2318 		alloc_new_pkt = TRUE;
2319 	} else {
2320 		/* gSPI expects that hw-header-len is equal to spi-command-len */
2321 #ifndef BCMSPI
2322 		uint cur_chain_total_len;
2323 		int chain_tail_padding = 0;
2324 
2325 		/* All packets need to be aligned by DHD_SDALIGN */
2326 		modulo = (pkt_len + head_padding) % DHD_SDALIGN;
2327 		tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
2328 
2329 		/* Total pkt chain length needs to be aligned by block size,
2330 		 * unless it is a single pkt chain with total length less than one block size,
2331 		 * which we prefer sending by byte mode.
2332 		 *
2333 		 * Do the chain alignment here if
2334 		 * 1. This is the last pkt of the chain of multiple pkts or a single pkt.
2335 		 * 2-1. This chain is of multiple pkts, or
2336 		 * 2-2. This is a single pkt whose size is longer than one block size.
2337 		 */
2338 		cur_chain_total_len = prev_chain_total_len +
2339 			(head_padding + pkt_len + tail_padding);
2340 		if (last_chained_pkt && bus->blocksize != 0 &&
2341 			(cur_chain_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
2342 			modulo = cur_chain_total_len % bus->blocksize;
2343 			chain_tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
2344 		}
2345 
2346 #ifdef DHDENABLE_TAILPAD
2347 		if (PKTTAILROOM(osh, pkt) < tail_padding) {
2348 			/* We don't have tail room to align by DHD_SDALIGN */
2349 			alloc_new_pkt = TRUE;
2350 			bus->tx_tailpad_pktget++;
2351 		} else if (PKTTAILROOM(osh, pkt) < tail_padding + chain_tail_padding) {
2352 			/* We have tail room for tail_padding of this pkt itself, but not for
2353 			 * total pkt chain alignment by block size.
2354 			 * Use the padding packet to avoid memory copy if applicable,
2355 			 * otherwise, just allocate a new pkt.
2356 			 */
2357 			if (bus->pad_pkt) {
2358 				*pad_pkt_len = chain_tail_padding;
2359 				bus->tx_tailpad_chain++;
2360 			} else {
2361 				alloc_new_pkt = TRUE;
2362 				bus->tx_tailpad_pktget++;
2363 			}
2364 		} else
2365 		/* This last pkt's tailroom is sufficient to hold both tail_padding
2366 		 * of the pkt itself and chain_tail_padding of total pkt chain
2367 		 */
2368 #endif /* DHDENABLE_TAILPAD */
2369 		tail_padding += chain_tail_padding;
2370 #endif /* !BCMSPI */
2371 	}
2372 
2373 	DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n",
2374 		__FUNCTION__, pkt_len, head_padding, tail_padding, *pad_pkt_len));
2375 
2376 	if (alloc_new_pkt) {
2377 		void *tmp_pkt;
2378 		int newpkt_size;
2379 		int cur_total_len;
2380 
2381 		ASSERT(*pad_pkt_len == 0);
2382 
2383 		DHD_INFO(("%s allocating new packet for padding\n", __FUNCTION__));
2384 
2385 		/* head pointer is aligned now, no padding needed */
2386 		head_padding = 0;
2387 
2388 		/* update the tail padding as it depends on the head padding, since a new packet is
2389 		 * allocated, the head padding is non longer needed and packet length is chagned
2390 		 */
2391 
2392 		cur_total_len = prev_chain_total_len + pkt_len;
2393 		if (last_chained_pkt && bus->blocksize != 0 &&
2394 			(cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
2395 			modulo = cur_total_len % bus->blocksize;
2396 			tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
2397 		} else {
2398 			modulo = pkt_len % DHD_SDALIGN;
2399 			tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
2400 		}
2401 
2402 		newpkt_size = PKTLEN(osh, pkt) + bus->blocksize + DHD_SDALIGN;
2403 		bus->dhd->tx_realloc++;
2404 		tmp_pkt = PKTGET(osh, newpkt_size, TRUE);
2405 		if (tmp_pkt == NULL) {
2406 			DHD_ERROR(("failed to alloc new %d byte packet\n", newpkt_size));
2407 			return BCME_NOMEM;
2408 		}
2409 		PKTALIGN(osh, tmp_pkt, PKTLEN(osh, pkt), DHD_SDALIGN);
2410 		bcopy(PKTDATA(osh, pkt), PKTDATA(osh, tmp_pkt), PKTLEN(osh, pkt));
2411 		*new_pkt = tmp_pkt;
2412 		pkt = tmp_pkt;
2413 	}
2414 
2415 	if (head_padding)
2416 		PKTPUSH(osh, pkt, head_padding);
2417 
2418 	frame = (uint8*)PKTDATA(osh, pkt);
2419 	bzero(frame, head_padding + sdpcm_hdrlen);
2420 	pkt_len = (uint16)PKTLEN(osh, pkt);
2421 
2422 	/* the header has the followming format
2423 	 * 4-byte HW frame tag: length, ~length (for glom this is the total length)
2424 	 *
2425 	 * 8-byte HW extesion flags (glom mode only) as the following:
2426 	 *			2-byte packet length, excluding HW tag and padding
2427 	 *			2-byte frame channel and frame flags (e.g. next frame following)
2428 	 *			2-byte header length
2429 	 *			2-byte tail padding size
2430 	 *
2431 	 * 8-byte SW frame tags as the following
2432 	 *			4-byte flags: host tx seq, channel, data offset
2433 	 *			4-byte flags: TBD
2434 	 */
2435 
2436 	swhdr_offset = SDPCM_FRAMETAG_LEN;
2437 
2438 	/* hardware frame tag:
2439 	 *
2440 	 * in tx-glom mode, dongle only checks the hardware frame tag in the first
2441 	 * packet and sees it as the total lenght of the glom (including tail padding),
2442 	 * for each packet in the glom, the packet length needs to be updated, (see
2443 	 * below PKTSETLEN)
2444 	 *
2445 	 * in non tx-glom mode, PKTLEN still need to include tail padding as to be
2446 	 * referred to in sdioh_request_buffer(). The tail length will be excluded in
2447 	 * dhdsdio_txpkt_postprocess().
2448 	 */
2449 	*(uint16*)frame = (uint16)htol16(pkt_len);
2450 	*(((uint16*)frame) + 1) = (uint16)htol16(~pkt_len);
2451 	pkt_len += tail_padding;
2452 
2453 	/* hardware extesion flags */
2454 	if (bus->txglom_enable) {
2455 		uint32 hwheader1;
2456 		uint32 hwheader2;
2457 
2458 		swhdr_offset += SDPCM_HWEXT_LEN;
2459 		hwheader1 = (pkt_len - SDPCM_FRAMETAG_LEN - tail_padding) |
2460 			(last_chained_pkt << 24);
2461 		hwheader2 = (tail_padding) << 16;
2462 		htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
2463 		htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
2464 	}
2465 	PKTSETLEN((osh), (pkt), (pkt_len));
2466 
2467 	/* software frame tags */
2468 	swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
2469 		| (txseq % SDPCM_SEQUENCE_WRAP) |
2470 		(((head_padding + sdpcm_hdrlen) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
2471 	htol32_ua_store(swheader, frame + swhdr_offset);
2472 	htol32_ua_store(0, frame + swhdr_offset + sizeof(swheader));
2473 
2474 	return pkt_len;
2475 }
2476 
dhdsdio_txpkt_postprocess(dhd_bus_t * bus,void * pkt)2477 static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt)
2478 {
2479 	osl_t *osh;
2480 	uint8 *frame;
2481 	int data_offset;
2482 	int tail_padding;
2483 	int swhdr_offset = SDPCM_FRAMETAG_LEN + (bus->txglom_enable ? SDPCM_HWEXT_LEN : 0);
2484 
2485 	(void)osh;
2486 	osh = bus->dhd->osh;
2487 
2488 	/* restore pkt buffer pointer, but keeps the header pushed by dhd_prot_hdrpush */
2489 	frame = (uint8*)PKTDATA(osh, pkt);
2490 
2491 	DHD_INFO(("%s PKTLEN before postprocess %d",
2492 		__FUNCTION__, PKTLEN(osh, pkt)));
2493 
2494 	/* PKTLEN still includes tail_padding, so exclude it.
2495 	 * We shall have head_padding + original pkt_len for PKTLEN afterwards.
2496 	 */
2497 	if (bus->txglom_enable) {
2498 		/* txglom pkts have tail_padding length in HW ext header */
2499 		tail_padding = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16;
2500 		PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - tail_padding);
2501 		DHD_INFO((" txglom pkt: tail_padding %d PKTLEN %d\n",
2502 			tail_padding, PKTLEN(osh, pkt)));
2503 	} else {
2504 		/* non-txglom pkts have head_padding + original pkt length in HW frame tag.
2505 		 * We cannot refer to this field for txglom pkts as the first pkt of the chain will
2506 		 * have the field for the total length of the chain.
2507 		 */
2508 		PKTSETLEN(osh, pkt, *(uint16*)frame);
2509 		DHD_INFO((" non-txglom pkt: HW frame tag len %d after PKTLEN %d\n",
2510 			*(uint16*)frame, PKTLEN(osh, pkt)));
2511 	}
2512 
2513 	data_offset = ltoh32_ua(frame + swhdr_offset);
2514 	data_offset = (data_offset & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT;
2515 	/* Get rid of sdpcm header + head_padding */
2516 	PKTPULL(osh, pkt, data_offset);
2517 
2518 	DHD_INFO(("%s data_offset %d, PKTLEN %d\n",
2519 		__FUNCTION__, data_offset, PKTLEN(osh, pkt)));
2520 
2521 	return BCME_OK;
2522 }
2523 
dhdsdio_txpkt(dhd_bus_t * bus,uint chan,void ** pkts,int num_pkt,bool free_pkt)2524 static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt)
2525 {
2526 	int i;
2527 	int ret = 0;
2528 	osl_t *osh;
2529 	bcmsdh_info_t *sdh;
2530 	void *pkt = NULL;
2531 	void *pkt_chain;
2532 	int total_len = 0;
2533 	void *head_pkt = NULL;
2534 	void *prev_pkt = NULL;
2535 	int pad_pkt_len = 0;
2536 	int new_pkt_num = 0;
2537 	void *new_pkts[MAX_TX_PKTCHAIN_CNT];
2538 	bool wlfc_enabled = FALSE;
2539 
2540 	if (bus->dhd->dongle_reset)
2541 		return BCME_NOTREADY;
2542 
2543 	if (num_pkt <= 0)
2544 		return BCME_BADARG;
2545 
2546 	sdh = bus->sdh;
2547 	osh = bus->dhd->osh;
2548 	/* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */
2549 	new_pkts[0] = NULL;
2550 
2551 	for (i = 0; i < num_pkt; i++) {
2552 		int pkt_len;
2553 		bool last_pkt;
2554 		void *new_pkt = NULL;
2555 
2556 		pkt = pkts[i];
2557 		ASSERT(pkt);
2558 		last_pkt = (i == num_pkt - 1);
2559 		pkt_len = dhdsdio_txpkt_preprocess(bus, pkt, chan, bus->tx_seq + i,
2560 			total_len, last_pkt, &pad_pkt_len, &new_pkt);
2561 		if (pkt_len <= 0)
2562 			goto done;
2563 		if (new_pkt) {
2564 			pkt = new_pkt;
2565 			new_pkts[new_pkt_num++] = new_pkt;
2566 		}
2567 		total_len += pkt_len;
2568 
2569 		PKTSETNEXT(osh, pkt, NULL);
2570 		/* insert the packet into the list */
2571 		head_pkt ? PKTSETNEXT(osh, prev_pkt, pkt) : (head_pkt = pkt);
2572 		prev_pkt = pkt;
2573 
2574 	}
2575 
2576 	/* Update the HW frame tag (total length) in the first pkt of the glom */
2577 	if (bus->txglom_enable) {
2578 		uint8 *frame;
2579 
2580 		total_len += pad_pkt_len;
2581 		frame = (uint8*)PKTDATA(osh, head_pkt);
2582 		*(uint16*)frame = (uint16)htol16(total_len);
2583 		*(((uint16*)frame) + 1) = (uint16)htol16(~total_len);
2584 
2585 	}
2586 
2587 #ifdef DHDENABLE_TAILPAD
2588 	/* if a padding packet if needed, insert it to the end of the link list */
2589 	if (pad_pkt_len) {
2590 		PKTSETLEN(osh, bus->pad_pkt, pad_pkt_len);
2591 		PKTSETNEXT(osh, pkt, bus->pad_pkt);
2592 	}
2593 #endif /* DHDENABLE_TAILPAD */
2594 
2595 	/* dhd_bcmsdh_send_buf ignores the buffer pointer if he packet
2596 	 * parameter is not NULL, for non packet chian we pass NULL pkt pointer
2597 	 * so it will take the aligned length and buffer pointer.
2598 	 */
2599 	pkt_chain = PKTNEXT(osh, head_pkt) ? head_pkt : NULL;
2600 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
2601 		PKTDATA(osh, head_pkt), total_len, pkt_chain, NULL, NULL, TXRETRIES);
2602 	if (ret == BCME_OK)
2603 		bus->tx_seq = (bus->tx_seq + num_pkt) % SDPCM_SEQUENCE_WRAP;
2604 
2605 	/* if a padding packet was needed, remove it from the link list as it not a data pkt */
2606 	if (pad_pkt_len && pkt)
2607 		PKTSETNEXT(osh, pkt, NULL);
2608 
2609 done:
2610 	pkt = head_pkt;
2611 	while (pkt) {
2612 		void *pkt_next = PKTNEXT(osh, pkt);
2613 		PKTSETNEXT(osh, pkt, NULL);
2614 		dhdsdio_txpkt_postprocess(bus, pkt);
2615 		pkt = pkt_next;
2616 	}
2617 
2618 	/* new packets might be allocated due to insufficient room for padding, but we
2619 	 * still have to indicate the original packets to upper layer
2620 	 */
2621 	for (i = 0; i < num_pkt; i++) {
2622 		pkt = pkts[i];
2623 		wlfc_enabled = FALSE;
2624 #ifdef PROP_TXSTATUS
2625 		if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt))) {
2626 			wlfc_enabled = (dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0) !=
2627 				WLFC_UNSUPPORTED);
2628 		}
2629 #endif /* PROP_TXSTATUS */
2630 		if (!wlfc_enabled) {
2631 			PKTSETNEXT(osh, pkt, NULL);
2632 			dhd_txcomplete(bus->dhd, pkt, ret != 0);
2633 			if (free_pkt)
2634 				PKTFREE(osh, pkt, TRUE);
2635 		}
2636 	}
2637 
2638 	for (i = 0; i < new_pkt_num; i++)
2639 		PKTFREE(osh, new_pkts[i], TRUE);
2640 
2641 	return ret;
2642 }
2643 
2644 static uint
dhdsdio_sendfromq(dhd_bus_t * bus,uint maxframes)2645 dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
2646 {
2647 	uint cnt = 0;
2648 	uint8 tx_prec_map;
2649 	uint16 txpktqlen = 0;
2650 	uint32 intstatus = 0;
2651 	uint retries = 0;
2652 	osl_t *osh;
2653 	uint datalen = 0;
2654 	dhd_pub_t *dhd = bus->dhd;
2655 	sdpcmd_regs_t *regs = bus->regs;
2656 #ifdef DHD_LOSSLESS_ROAMING
2657 	uint8 *pktdata;
2658 	struct ether_header *eh;
2659 #ifdef BDC
2660 	struct bdc_header *bdc_header;
2661 	uint8 data_offset;
2662 #endif // endif
2663 #endif /* DHD_LOSSLESS_ROAMING */
2664 
2665 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2666 
2667 	if (!KSO_ENAB(bus)) {
2668 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
2669 		return BCME_NODEVICE;
2670 	}
2671 
2672 	osh = dhd->osh;
2673 	tx_prec_map = ~bus->flowcontrol;
2674 #ifdef DHD_LOSSLESS_ROAMING
2675 	tx_prec_map &= dhd->dequeue_prec_map;
2676 #endif /* DHD_LOSSLESS_ROAMING */
2677 	for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) {
2678 		int i;
2679 		int num_pkt = 1;
2680 		void *pkts[MAX_TX_PKTCHAIN_CNT];
2681 		int prec_out;
2682 
2683 		dhd_os_sdlock_txq(bus->dhd);
2684 		if (bus->txglom_enable) {
2685 			uint32 glomlimit = (uint32)bus->txglomsize;
2686 #if defined(BCMSDIOH_STD)
2687 			if (bus->blocksize == 64) {
2688 				glomlimit = MIN((uint32)bus->txglomsize, BLK_64_MAXTXGLOM);
2689 			}
2690 #endif /* BCMSDIOH_STD */
2691 			num_pkt = MIN((uint32)DATABUFCNT(bus), glomlimit);
2692 			num_pkt = MIN(num_pkt, ARRAYSIZE(pkts));
2693 		}
2694 		num_pkt = MIN(num_pkt, pktq_mlen(&bus->txq, tx_prec_map));
2695 		for (i = 0; i < num_pkt; i++) {
2696 			pkts[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
2697 			if (!pkts[i]) {
2698 				DHD_ERROR(("%s: pktq_mlen non-zero when no pkt\n",
2699 					__FUNCTION__));
2700 				ASSERT(0);
2701 				break;
2702 			}
2703 #ifdef DHD_LOSSLESS_ROAMING
2704 			pktdata = (uint8 *)PKTDATA(osh, pkts[i]);
2705 #ifdef BDC
2706 			/* Skip BDC header */
2707 			bdc_header = (struct bdc_header *)pktdata;
2708 			data_offset = bdc_header->dataOffset;
2709 			pktdata += BDC_HEADER_LEN + (data_offset << 2);
2710 #endif // endif
2711 			eh = (struct ether_header *)pktdata;
2712 			if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
2713 				uint8 prio = (uint8)PKTPRIO(pkts[i]);
2714 
2715 				/* Restore to original priority for 802.1X packet */
2716 				if (prio == PRIO_8021D_NC) {
2717 					PKTSETPRIO(pkts[i], dhd->prio_8021x);
2718 #ifdef BDC
2719 					/* Restore to original priority in BDC header */
2720 					bdc_header->priority =
2721 						(dhd->prio_8021x & BDC_PRIORITY_MASK);
2722 #endif // endif
2723 				}
2724 			}
2725 #endif /* DHD_LOSSLESS_ROAMING */
2726 			PKTORPHAN(pkts[i]);
2727 			datalen += PKTLEN(osh, pkts[i]);
2728 		}
2729 		dhd_os_sdunlock_txq(bus->dhd);
2730 
2731 		if (i == 0)
2732 			break;
2733 		if (dhdsdio_txpkt(bus, SDPCM_DATA_CHANNEL, pkts, i, TRUE) != BCME_OK)
2734 			dhd->tx_errors++;
2735 		else
2736 			dhd->dstats.tx_bytes += datalen;
2737 		cnt += i;
2738 
2739 		/* In poll mode, need to check for other events */
2740 		if (!bus->intr && cnt)
2741 		{
2742 			/* Check device status, signal pending interrupt */
2743 			R_SDREG(intstatus, &regs->intstatus, retries);
2744 			bus->f2txdata++;
2745 			if (bcmsdh_regfail(bus->sdh))
2746 				break;
2747 			if (intstatus & bus->hostintmask)
2748 				bus->ipend = TRUE;
2749 		}
2750 
2751 	}
2752 
2753 	dhd_os_sdlock_txq(bus->dhd);
2754 	txpktqlen = pktq_n_pkts_tot(&bus->txq);
2755 	dhd_os_sdunlock_txq(bus->dhd);
2756 
2757 	/* Do flow-control if needed */
2758 	if (dhd->up && (dhd->busstate == DHD_BUS_DATA) && (txpktqlen < FCLOW)) {
2759 		bool wlfc_enabled = FALSE;
2760 #ifdef PROP_TXSTATUS
2761 		wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED);
2762 #endif // endif
2763 		if (!wlfc_enabled && dhd_doflow && dhd->txoff) {
2764 			dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
2765 		}
2766 	}
2767 
2768 	return cnt;
2769 }
2770 
2771 static void
dhdsdio_sendpendctl(dhd_bus_t * bus)2772 dhdsdio_sendpendctl(dhd_bus_t *bus)
2773 {
2774 	bcmsdh_info_t *sdh = bus->sdh;
2775 	int ret;
2776 	uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN;
2777 
2778 	if (bus->txglom_enable)
2779 		frame_seq += SDPCM_HWEXT_LEN;
2780 
2781 	if (*frame_seq != bus->tx_seq) {
2782 		DHD_INFO(("%s IOCTL frame seq lag detected!"
2783 			" frm_seq:%d != bus->tx_seq:%d, corrected\n",
2784 			__FUNCTION__, *frame_seq, bus->tx_seq));
2785 		*frame_seq = bus->tx_seq;
2786 	}
2787 
2788 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
2789 		(uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len,
2790 		NULL, NULL, NULL, 1);
2791 	if (ret == BCME_OK)
2792 		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
2793 
2794 	bus->ctrl_frame_stat = FALSE;
2795 	dhd_wait_event_wakeup(bus->dhd);
2796 }
2797 
2798 int
dhd_bus_txctl(struct dhd_bus * bus,uchar * msg,uint msglen)2799 dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
2800 {
2801 	static int err_nodevice = 0;
2802 	uint8 *frame;
2803 	uint16 len;
2804 	uint32 swheader;
2805 	uint8 doff = 0;
2806 	int ret = -1;
2807 	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
2808 
2809 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2810 
2811 	if (bus->dhd->dongle_reset)
2812 		return -EIO;
2813 
2814 	/* Back the pointer to make a room for bus header */
2815 	frame = msg - sdpcm_hdrlen;
2816 	len = (msglen += sdpcm_hdrlen);
2817 
2818 	/* Add alignment padding (optional for ctl frames) */
2819 	if (dhd_alignctl) {
2820 		if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
2821 			frame -= doff;
2822 			len += doff;
2823 			msglen += doff;
2824 			bzero(frame, doff + sdpcm_hdrlen);
2825 		}
2826 		ASSERT(doff < DHD_SDALIGN);
2827 	}
2828 	doff += sdpcm_hdrlen;
2829 
2830 #ifndef BCMSPI
2831 	/* Round send length to next SDIO block */
2832 	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
2833 		uint16 pad = bus->blocksize - (len % bus->blocksize);
2834 		if ((pad <= bus->roundup) && (pad < bus->blocksize))
2835 			len += pad;
2836 	} else if (len % DHD_SDALIGN) {
2837 		len += DHD_SDALIGN - (len % DHD_SDALIGN);
2838 	}
2839 #endif /* BCMSPI */
2840 
2841 	/* Satisfy length-alignment requirements */
2842 	if (forcealign && (len & (ALIGNMENT - 1)))
2843 		len = ROUNDUP(len, ALIGNMENT);
2844 
2845 	ASSERT(ISALIGNED((uintptr)frame, 2));
2846 
2847 	/* Need to lock here to protect txseq and SDIO tx calls */
2848 	dhd_os_sdlock(bus->dhd);
2849 
2850 	BUS_WAKE(bus);
2851 
2852 	/* Make sure backplane clock is on */
2853 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2854 
2855 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
2856 	*(uint16*)frame = htol16((uint16)msglen);
2857 	*(((uint16*)frame) + 1) = htol16(~msglen);
2858 
2859 	if (bus->txglom_enable) {
2860 		uint32 hwheader1, hwheader2;
2861 		/* Software tag: channel, sequence number, data offset */
2862 		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
2863 				| bus->tx_seq
2864 				| ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
2865 		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN);
2866 		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN
2867 			+ SDPCM_HWEXT_LEN + sizeof(swheader));
2868 
2869 		hwheader1 = (msglen - SDPCM_FRAMETAG_LEN) | (1 << 24);
2870 		hwheader2 = (len - (msglen)) << 16;
2871 		htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
2872 		htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
2873 
2874 		*(uint16*)frame = htol16(len);
2875 		*(((uint16*)frame) + 1) = htol16(~(len));
2876 	} else {
2877 		/* Software tag: channel, sequence number, data offset */
2878 		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
2879 		        | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
2880 		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
2881 		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
2882 	}
2883 
2884 #ifdef DHD_ULP
2885 	dhd_ulp_set_path(bus->dhd, DHD_ULP_TX_CTRL);
2886 
2887 	if (!TXCTLOK(bus) || !dhd_ulp_f2_ready(bus->dhd, bus->sdh))
2888 #else
2889 	if (!TXCTLOK(bus))
2890 #endif // endif
2891 	{
2892 		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
2893 			__FUNCTION__, bus->tx_max, bus->tx_seq));
2894 		bus->ctrl_frame_stat = TRUE;
2895 		/* Send from dpc */
2896 		bus->ctrl_frame_buf = frame;
2897 		bus->ctrl_frame_len = len;
2898 
2899 		if (!bus->dpc_sched) {
2900 			bus->dpc_sched = TRUE;
2901 			dhd_sched_dpc(bus->dhd);
2902 		}
2903 		if (bus->ctrl_frame_stat) {
2904 			dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
2905 		}
2906 
2907 		if (bus->ctrl_frame_stat == FALSE) {
2908 			DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
2909 			ret = 0;
2910 		} else {
2911 			bus->dhd->txcnt_timeout++;
2912 			if (!bus->dhd->hang_was_sent) {
2913 #ifdef CUSTOMER_HW4_DEBUG
2914 				uint32 status, retry = 0;
2915 				R_SDREG(status, &bus->regs->intstatus, retry);
2916 				DHD_TRACE_HW4(("%s: txcnt_timeout, INT status=0x%08X\n",
2917 					__FUNCTION__, status));
2918 				DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n",
2919 					__FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate));
2920 #endif /* CUSTOMER_HW4_DEBUG */
2921 				DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
2922 					__FUNCTION__, bus->dhd->txcnt_timeout));
2923 			}
2924 #ifdef DHD_FW_COREDUMP
2925 			/* Collect socram dump */
2926 			if ((bus->dhd->memdump_enabled) &&
2927 				(bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT)) {
2928 				/* collect core dump */
2929 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_TX;
2930 				dhd_os_sdunlock(bus->dhd);
2931 				dhd_bus_mem_dump(bus->dhd);
2932 				dhd_os_sdlock(bus->dhd);
2933 			}
2934 #endif /* DHD_FW_COREDUMP */
2935 			ret = -1;
2936 			bus->ctrl_frame_stat = FALSE;
2937 			goto done;
2938 		}
2939 	}
2940 
2941 	bus->dhd->txcnt_timeout = 0;
2942 	bus->ctrl_frame_stat = TRUE;
2943 
2944 	if (ret == -1) {
2945 #ifdef DHD_DEBUG
2946 		if (DHD_BYTES_ON() && DHD_CTL_ON()) {
2947 			prhex("Tx Frame", frame, len);
2948 		} else if (DHD_HDRS_ON()) {
2949 			prhex("TxHdr", frame, MIN(len, 16));
2950 		}
2951 #endif // endif
2952 		ret = dhd_bcmsdh_send_buffer(bus, frame, len);
2953 	}
2954 	bus->ctrl_frame_stat = FALSE;
2955 #ifdef DHD_ULP
2956 	dhd_ulp_enable_cached_sbwad(bus->dhd, bus->sdh);
2957 #endif /* DHD_ULP */
2958 
2959 done:
2960 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
2961 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
2962 		bus->activity = FALSE;
2963 		dhdsdio_bussleep(bus, TRUE);
2964 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
2965 	}
2966 
2967 	dhd_os_sdunlock(bus->dhd);
2968 
2969 	if (ret)
2970 		bus->dhd->tx_ctlerrs++;
2971 	else
2972 		bus->dhd->tx_ctlpkts++;
2973 
2974 	if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT) {
2975 #ifdef DHD_PM_CONTROL_FROM_FILE
2976 		if (g_pm_control == TRUE) {
2977 			return -BCME_ERROR;
2978 		} else {
2979 		return -ETIMEDOUT;
2980 		}
2981 #else
2982 		return -ETIMEDOUT;
2983 #endif /* DHD_PM_CONTROL_FROM_FILE */
2984 	}
2985 	if (ret == BCME_NODEVICE)
2986 		err_nodevice++;
2987 	else
2988 		err_nodevice = 0;
2989 
2990 	return ret ? err_nodevice >= ERROR_BCME_NODEVICE_MAX ? -ETIMEDOUT : -EIO : 0;
2991 }
2992 
2993 int
dhd_bus_rxctl(struct dhd_bus * bus,uchar * msg,uint msglen)2994 dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
2995 {
2996 	int timeleft;
2997 	uint rxlen = 0;
2998 
2999 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
3000 
3001 	if (bus->dhd->dongle_reset)
3002 		return -EIO;
3003 
3004 	/* Wait until control frame is available */
3005 	timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen);
3006 
3007 	dhd_os_sdlock(bus->dhd);
3008 	rxlen = bus->rxlen;
3009 	bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
3010 	bus->rxlen = 0;
3011 	dhd_os_sdunlock(bus->dhd);
3012 
3013 	if (rxlen) {
3014 		DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
3015 			__FUNCTION__, rxlen, msglen));
3016 	} else {
3017 		if (timeleft == 0) {
3018 #ifdef DHD_DEBUG
3019 			uint32 status, retry = 0;
3020 			R_SDREG(status, &bus->regs->intstatus, retry);
3021 			DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n",
3022 				__FUNCTION__, status));
3023 #else
3024 			DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
3025 #endif /* DHD_DEBUG */
3026 			if (!bus->dhd->dongle_trap_occured) {
3027 #ifdef DHD_FW_COREDUMP
3028 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT;
3029 #endif /* DHD_FW_COREDUMP */
3030 				dhd_os_sdlock(bus->dhd);
3031 				dhdsdio_checkdied(bus, NULL, 0);
3032 				dhd_os_sdunlock(bus->dhd);
3033 			}
3034 		} else {
3035 			DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
3036 			if (!bus->dhd->dongle_trap_occured) {
3037 #ifdef DHD_FW_COREDUMP
3038 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_UNKNOWN;
3039 #endif /* DHD_FW_COREDUMP */
3040 				dhd_os_sdlock(bus->dhd);
3041 				dhdsdio_checkdied(bus, NULL, 0);
3042 				dhd_os_sdunlock(bus->dhd);
3043 			}
3044 		}
3045 #ifdef DHD_FW_COREDUMP
3046 		/* Dump the ram image */
3047 		if (bus->dhd->memdump_enabled && !bus->dhd->dongle_trap_occured)
3048 			dhdsdio_mem_dump(bus);
3049 #endif /* DHD_FW_COREDUMP */
3050 	}
3051 	if (timeleft == 0) {
3052 		if (rxlen == 0)
3053 			bus->dhd->rxcnt_timeout++;
3054 		DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__,
3055 			bus->dhd->rxcnt_timeout, rxlen));
3056 #ifdef DHD_FW_COREDUMP
3057 		/* collect socram dump */
3058 		if (bus->dhd->memdump_enabled) {
3059 			bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_RX;
3060 			dhd_bus_mem_dump(bus->dhd);
3061 		}
3062 #endif /* DHD_FW_COREDUMP */
3063 	} else {
3064 		bus->dhd->rxcnt_timeout = 0;
3065 	}
3066 
3067 	if (rxlen)
3068 		bus->dhd->rx_ctlpkts++;
3069 	else
3070 		bus->dhd->rx_ctlerrs++;
3071 
3072 	if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT) {
3073 #ifdef DHD_PM_CONTROL_FROM_FILE
3074 		if (g_pm_control == TRUE) {
3075 			return -BCME_ERROR;
3076 		} else {
3077 			return -ETIMEDOUT;
3078 		}
3079 #else
3080 		return -ETIMEDOUT;
3081 #endif /* DHD_PM_CONTROL_FROM_FILE */
3082 	}
3083 	if (bus->dhd->dongle_trap_occured)
3084 		return -EREMOTEIO;
3085 
3086 	return rxlen ? (int)rxlen : -EIO;
3087 }
3088 
3089 /* IOVar table */
3090 enum {
3091 	IOV_INTR = 1,
3092 	IOV_POLLRATE,
3093 	IOV_SDREG,
3094 	IOV_SBREG,
3095 	IOV_SDCIS,
3096 #ifdef DHD_BUS_MEM_ACCESS
3097 	IOV_MEMBYTES,
3098 #endif /* DHD_BUS_MEM_ACCESS */
3099 	IOV_RAMSIZE,
3100 	IOV_RAMSTART,
3101 #ifdef DHD_DEBUG
3102 	IOV_CHECKDIED,
3103 	IOV_SERIALCONS,
3104 #endif /* DHD_DEBUG */
3105 	IOV_SET_DOWNLOAD_STATE,
3106 	IOV_SOCRAM_STATE,
3107 	IOV_FORCEEVEN,
3108 	IOV_SDIOD_DRIVE,
3109 	IOV_READAHEAD,
3110 	IOV_SDRXCHAIN,
3111 	IOV_ALIGNCTL,
3112 	IOV_SDALIGN,
3113 	IOV_DEVRESET,
3114 	IOV_CPU,
3115 #if defined(USE_SDIOFIFO_IOVAR)
3116 	IOV_WATERMARK,
3117 	IOV_MESBUSYCTRL,
3118 #endif /* USE_SDIOFIFO_IOVAR */
3119 #ifdef SDTEST
3120 	IOV_PKTGEN,
3121 	IOV_EXTLOOP,
3122 #endif /* SDTEST */
3123 	IOV_SPROM,
3124 	IOV_TXBOUND,
3125 	IOV_RXBOUND,
3126 	IOV_TXMINMAX,
3127 	IOV_IDLETIME,
3128 	IOV_IDLECLOCK,
3129 	IOV_SD1IDLE,
3130 	IOV_SLEEP,
3131 	IOV_DONGLEISOLATION,
3132 	IOV_KSO,
3133 	IOV_DEVSLEEP,
3134 	IOV_DEVCAP,
3135 	IOV_VARS,
3136 #ifdef SOFTAP
3137 	IOV_FWPATH,
3138 #endif // endif
3139 	IOV_TXGLOMSIZE,
3140 	IOV_TXGLOMMODE,
3141 	IOV_HANGREPORT,
3142 	IOV_TXINRX_THRES,
3143 	IOV_SDIO_SUSPEND
3144 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
3145 	IOV_GDB_SERVER,  /**< starts gdb server on given interface */
3146 #endif /* DEBUGGER || DHD_DSCOPE */
3147 };
3148 
3149 const bcm_iovar_t dhdsdio_iovars[] = {
3150 	{"intr",	IOV_INTR,	0, 0,	IOVT_BOOL,	0 },
3151 	{"sleep",	IOV_SLEEP,	0, 0,	IOVT_BOOL,	0 },
3152 	{"pollrate",	IOV_POLLRATE,	0, 0,	IOVT_UINT32,	0 },
3153 	{"idletime",	IOV_IDLETIME,	0, 0,	IOVT_INT32,	0 },
3154 	{"idleclock",	IOV_IDLECLOCK,	0, 0,	IOVT_INT32,	0 },
3155 	{"sd1idle",	IOV_SD1IDLE,	0, 0,	IOVT_BOOL,	0 },
3156 #ifdef DHD_BUS_MEM_ACCESS
3157 	{"membytes",	IOV_MEMBYTES,	0, 0,	IOVT_BUFFER,	2 * sizeof(int) },
3158 #endif /* DHD_BUS_MEM_ACCESS */
3159 	{"ramsize",	IOV_RAMSIZE,	0, 0,	IOVT_UINT32,	0 },
3160 	{"ramstart",	IOV_RAMSTART,	0, 0,	IOVT_UINT32,	0 },
3161 	{"dwnldstate",	IOV_SET_DOWNLOAD_STATE,	0, 0,	IOVT_BOOL,	0 },
3162 	{"socram_state",	IOV_SOCRAM_STATE,	0, 0,	IOVT_BOOL,	0 },
3163 	{"vars",	IOV_VARS,	0, 0,	IOVT_BUFFER,	0 },
3164 	{"sdiod_drive",	IOV_SDIOD_DRIVE, 0, 0,	IOVT_UINT32,	0 },
3165 	{"readahead",	IOV_READAHEAD,	0, 0,	IOVT_BOOL,	0 },
3166 	{"sdrxchain",	IOV_SDRXCHAIN,	0, 0,	IOVT_BOOL,	0 },
3167 	{"alignctl",	IOV_ALIGNCTL,	0, 0,	IOVT_BOOL,	0 },
3168 	{"sdalign",	IOV_SDALIGN,	0, 0,	IOVT_BOOL,	0 },
3169 	{"devreset",	IOV_DEVRESET,	0, 0,	IOVT_BOOL,	0 },
3170 #ifdef DHD_DEBUG
3171 	{"sdreg",	IOV_SDREG,	0, 0,	IOVT_BUFFER,	sizeof(sdreg_t) },
3172 	{"sbreg",	IOV_SBREG,	0, 0,	IOVT_BUFFER,	sizeof(sdreg_t) },
3173 	{"sd_cis",	IOV_SDCIS,	0, 0,	IOVT_BUFFER,	DHD_IOCTL_MAXLEN },
3174 	{"forcealign",	IOV_FORCEEVEN,	0, 0,	IOVT_BOOL,	0 },
3175 	{"txbound",	IOV_TXBOUND,	0, 0,	IOVT_UINT32,	0 },
3176 	{"rxbound",	IOV_RXBOUND,	0, 0,	IOVT_UINT32,	0 },
3177 	{"txminmax",	IOV_TXMINMAX,	0, 0,	IOVT_UINT32,	0 },
3178 	{"cpu",		IOV_CPU,	0, 0,	IOVT_BOOL,	0 },
3179 #ifdef DHD_DEBUG
3180 	{"checkdied",	IOV_CHECKDIED,	0, 0,	IOVT_BUFFER,	0 },
3181 	{"serial",	IOV_SERIALCONS,	0, 0,	IOVT_UINT32,	0 },
3182 #endif /* DHD_DEBUG  */
3183 #endif /* DHD_DEBUG */
3184 #ifdef SDTEST
3185 	{"extloop",	IOV_EXTLOOP,	0, 0,	IOVT_BOOL,	0 },
3186 	{"pktgen",	IOV_PKTGEN,	0, 0,	IOVT_BUFFER,	sizeof(dhd_pktgen_t) },
3187 #endif /* SDTEST */
3188 #if defined(USE_SDIOFIFO_IOVAR)
3189 	{"watermark",	IOV_WATERMARK,	0, 0,	IOVT_UINT32,	0 },
3190 	{"mesbusyctrl",	IOV_MESBUSYCTRL,	0, 0,	IOVT_UINT32,	0 },
3191 #endif /* USE_SDIOFIFO_IOVAR */
3192 	{"devcap", IOV_DEVCAP,	0, 0,	IOVT_UINT32,	0 },
3193 	{"dngl_isolation", IOV_DONGLEISOLATION,	0, 0,	IOVT_UINT32,	0 },
3194 	{"kso",	IOV_KSO,	0, 0,	IOVT_UINT32,	0 },
3195 	{"devsleep", IOV_DEVSLEEP,	0, 0,	IOVT_UINT32,	0 },
3196 #ifdef SOFTAP
3197 	{"fwpath", IOV_FWPATH, 0, 0, IOVT_BUFFER, 0 },
3198 #endif // endif
3199 	{"txglomsize", IOV_TXGLOMSIZE, 0, 0, IOVT_UINT32, 0 },
3200 	{"fw_hang_report", IOV_HANGREPORT, 0, 0, IOVT_BOOL, 0 },
3201 	{"txinrx_thres", IOV_TXINRX_THRES, 0, 0, IOVT_INT32, 0 },
3202 	{"sdio_suspend", IOV_SDIO_SUSPEND, 0, 0, IOVT_UINT32, 0 },
3203 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
3204 	{"gdb_server", IOV_GDB_SERVER,    0, 0,      IOVT_UINT32,    0 },
3205 #endif /* DEBUGGER || DHD_DSCOPE */
3206 	{NULL, 0, 0, 0, 0, 0 }
3207 };
3208 
3209 static void
dhd_dump_pct(struct bcmstrbuf * strbuf,char * desc,uint num,uint div)3210 dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
3211 {
3212 	uint q1, q2;
3213 
3214 	if (!div) {
3215 		bcm_bprintf(strbuf, "%s N/A", desc);
3216 	} else {
3217 		q1 = num / div;
3218 		q2 = (100 * (num - (q1 * div))) / div;
3219 		bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
3220 	}
3221 }
3222 
3223 void
dhd_bus_dump(dhd_pub_t * dhdp,struct bcmstrbuf * strbuf)3224 dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
3225 {
3226 	dhd_bus_t *bus = dhdp->bus;
3227 #if defined(DHD_WAKE_STATUS) && defined(DHD_WAKE_EVENT_STATUS)
3228 	int i;
3229 #endif // endif
3230 
3231 	bcm_bprintf(strbuf, "Bus SDIO structure:\n");
3232 	bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
3233 	            bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
3234 	bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n",
3235 	            bus->fcstate, pktq_n_pkts_tot(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
3236 	            bus->rxlen, bus->rx_seq);
3237 	bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
3238 	            bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
3239 
3240 #ifdef DHD_WAKE_STATUS
3241 	bcm_bprintf(strbuf, "wake %u rxwake %u readctrlwake %u\n",
3242 		bcmsdh_get_total_wake(bus->sdh), bus->wake_counts.rxwake,
3243 		bus->wake_counts.rcwake);
3244 #ifdef DHD_WAKE_RX_STATUS
3245 	bcm_bprintf(strbuf, " unicast %u multicast %u broadcast %u arp %u\n",
3246 		bus->wake_counts.rx_ucast, bus->wake_counts.rx_mcast,
3247 		bus->wake_counts.rx_bcast, bus->wake_counts.rx_arp);
3248 	bcm_bprintf(strbuf, " multi4 %u multi6 %u icmp6 %u multiother %u\n",
3249 		bus->wake_counts.rx_multi_ipv4, bus->wake_counts.rx_multi_ipv6,
3250 		bus->wake_counts.rx_icmpv6, bus->wake_counts.rx_multi_other);
3251 	bcm_bprintf(strbuf, " icmp6_ra %u, icmp6_na %u, icmp6_ns %u\n",
3252 		bus->wake_counts.rx_icmpv6_ra, bus->wake_counts.rx_icmpv6_na,
3253 		bus->wake_counts.rx_icmpv6_ns);
3254 #endif /* DHD_WAKE_RX_STATUS */
3255 #ifdef DHD_WAKE_EVENT_STATUS
3256 	for (i = 0; i < WLC_E_LAST; i++)
3257 		if (bus->wake_counts.rc_event[i] != 0)
3258 			bcm_bprintf(strbuf, " %s = %u\n", bcmevent_get_name(i),
3259 				bus->wake_counts.rc_event[i]);
3260 	bcm_bprintf(strbuf, "\n");
3261 #endif /* DHD_WAKE_EVENT_STATUS */
3262 #endif /* DHD_WAKE_STATUS */
3263 
3264 	bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
3265 	            bus->pollrate, bus->pollcnt, bus->regfails);
3266 
3267 	bcm_bprintf(strbuf, "\nAdditional counters:\n");
3268 #ifdef DHDENABLE_TAILPAD
3269 	bcm_bprintf(strbuf, "tx_tailpad_chain %u tx_tailpad_pktget %u\n",
3270 	            bus->tx_tailpad_chain, bus->tx_tailpad_pktget);
3271 #endif /* DHDENABLE_TAILPAD */
3272 	bcm_bprintf(strbuf, "tx_sderrs %u fcqueued %u rxrtx %u rx_toolong %u rxc_errors %u\n",
3273 	            bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
3274 	            bus->rxc_errors);
3275 	bcm_bprintf(strbuf, "rx_hdrfail %u badhdr %u badseq %u\n",
3276 	            bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
3277 	bcm_bprintf(strbuf, "fc_rcvd %u, fc_xoff %u, fc_xon %u\n",
3278 	            bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
3279 	bcm_bprintf(strbuf, "rxglomfail %u, rxglomframes %u, rxglompkts %u\n",
3280 	            bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
3281 	bcm_bprintf(strbuf, "f2rx (hdrs/data) %u (%u/%u), f2tx %u f1regs %u\n",
3282 	            (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
3283 	            bus->f2txdata, bus->f1regdata);
3284 	{
3285 		dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
3286 		             (bus->f2rxhdrs + bus->f2rxdata));
3287 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
3288 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
3289 		             (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
3290 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
3291 		bcm_bprintf(strbuf, "\n");
3292 
3293 		dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
3294 		             bus->dhd->rx_packets);
3295 		dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
3296 		bcm_bprintf(strbuf, "\n");
3297 
3298 		dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
3299 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
3300 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
3301 		             (bus->f2txdata + bus->f1regdata));
3302 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
3303 		bcm_bprintf(strbuf, "\n");
3304 
3305 		dhd_dump_pct(strbuf, "Total: pkts/f2rw",
3306 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
3307 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
3308 		dhd_dump_pct(strbuf, ", pkts/f1sd",
3309 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
3310 		dhd_dump_pct(strbuf, ", pkts/sd",
3311 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
3312 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
3313 		dhd_dump_pct(strbuf, ", pkts/int",
3314 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
3315 		bcm_bprintf(strbuf, "\n\n");
3316 	}
3317 
3318 #ifdef SDTEST
3319 	if (bus->pktgen_count) {
3320 		bcm_bprintf(strbuf, "pktgen config and count:\n");
3321 		bcm_bprintf(strbuf, "freq %u count %u print %u total %u min %u len %u\n",
3322 		            bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
3323 		            bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
3324 		bcm_bprintf(strbuf, "send attempts %u rcvd %u fail %u\n",
3325 		            bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
3326 	}
3327 #endif /* SDTEST */
3328 #ifdef DHD_DEBUG
3329 	bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
3330 	            bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
3331 	bcm_bprintf(strbuf, "blocksize %u roundup %u\n", bus->blocksize, bus->roundup);
3332 #endif /* DHD_DEBUG */
3333 	bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
3334 	            bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
3335 }
3336 
3337 void
dhd_bus_clearcounts(dhd_pub_t * dhdp)3338 dhd_bus_clearcounts(dhd_pub_t *dhdp)
3339 {
3340 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
3341 
3342 	bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
3343 	bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
3344 	bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
3345 #ifdef DHDENABLE_TAILPAD
3346 	bus->tx_tailpad_chain = bus->tx_tailpad_pktget = 0;
3347 #endif /* DHDENABLE_TAILPAD */
3348 	bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
3349 	bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
3350 	bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
3351 }
3352 
3353 #ifdef SDTEST
3354 static int
dhdsdio_pktgen_get(dhd_bus_t * bus,uint8 * arg)3355 dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
3356 {
3357 	dhd_pktgen_t pktgen;
3358 
3359 	pktgen.version = DHD_PKTGEN_VERSION;
3360 	pktgen.freq = bus->pktgen_freq;
3361 	pktgen.count = bus->pktgen_count;
3362 	pktgen.print = bus->pktgen_print;
3363 	pktgen.total = bus->pktgen_total;
3364 	pktgen.minlen = bus->pktgen_minlen;
3365 	pktgen.maxlen = bus->pktgen_maxlen;
3366 	pktgen.numsent = bus->pktgen_sent;
3367 	pktgen.numrcvd = bus->pktgen_rcvd;
3368 	pktgen.numfail = bus->pktgen_fail;
3369 	pktgen.mode = bus->pktgen_mode;
3370 	pktgen.stop = bus->pktgen_stop;
3371 
3372 	bcopy(&pktgen, arg, sizeof(pktgen));
3373 
3374 	return 0;
3375 }
3376 
3377 static int
dhdsdio_pktgen_set(dhd_bus_t * bus,uint8 * arg)3378 dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
3379 {
3380 	dhd_pktgen_t pktgen;
3381 	uint oldcnt, oldmode;
3382 
3383 	bcopy(arg, &pktgen, sizeof(pktgen));
3384 	if (pktgen.version != DHD_PKTGEN_VERSION)
3385 		return BCME_BADARG;
3386 
3387 	oldcnt = bus->pktgen_count;
3388 	oldmode = bus->pktgen_mode;
3389 
3390 	bus->pktgen_freq = pktgen.freq;
3391 	bus->pktgen_count = pktgen.count;
3392 	bus->pktgen_print = pktgen.print;
3393 	bus->pktgen_total = pktgen.total;
3394 	bus->pktgen_minlen = pktgen.minlen;
3395 	bus->pktgen_maxlen = pktgen.maxlen;
3396 	bus->pktgen_mode = pktgen.mode;
3397 	bus->pktgen_stop = pktgen.stop;
3398 
3399 	bus->pktgen_tick = bus->pktgen_ptick = 0;
3400 	bus->pktgen_prev_time = jiffies;
3401 	bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
3402 	bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
3403 
3404 	/* Clear counts for a new pktgen (mode change, or was stopped) */
3405 	if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) {
3406 		bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0;
3407 		bus->pktgen_prev_rcvd = bus->pktgen_fail = 0;
3408 	}
3409 
3410 	return 0;
3411 }
3412 #endif /* SDTEST */
3413 
3414 static void
dhdsdio_devram_remap(dhd_bus_t * bus,bool val)3415 dhdsdio_devram_remap(dhd_bus_t *bus, bool val)
3416 {
3417 	uint8 enable, protect, remap;
3418 
3419 	si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
3420 	remap = val ? TRUE : FALSE;
3421 	si_socdevram(bus->sih, TRUE, &enable, &protect, &remap);
3422 }
3423 
3424 static int
dhdsdio_membytes(dhd_bus_t * bus,bool write,uint32 address,uint8 * data,uint size)3425 dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
3426 {
3427 	int bcmerror = 0;
3428 	uint32 sdaddr;
3429 	uint dsize;
3430 
3431 	/* In remap mode, adjust address beyond socram and redirect
3432 	 * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
3433 	 * is not backplane accessible
3434 	 */
3435 	if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address)) {
3436 		address -= bus->orig_ramsize;
3437 		address += SOCDEVRAM_BP_ADDR;
3438 	}
3439 
3440 	/* Determine initial transfer parameters */
3441 	sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
3442 	if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
3443 		dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
3444 	else
3445 		dsize = size;
3446 
3447 	/* Set the backplane window to include the start address */
3448 	if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
3449 		DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
3450 		goto xfer_done;
3451 	}
3452 
3453 	/* Do the transfer(s) */
3454 	while (size) {
3455 #ifdef DHD_SDIO_MEM_BUF
3456         uint8 *pdata = data;
3457         uint offset = sdaddr;
3458         uint remain = dsize;
3459 
3460         while (remain > 0) {
3461             uint nbytes;
3462 
3463             if (remain > MAX_MEM_BUF) {
3464                 nbytes = MAX_MEM_BUF;
3465             } else {
3466                 nbytes = remain;
3467             }
3468 
3469     		DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
3470     		          __FUNCTION__, (write ? "write" : "read"), nbytes, offset,
3471     		          (address & SBSDIO_SBWINDOW_MASK)));
3472 
3473             if (write) {
3474                 memcpy(bus->membuf, pdata, nbytes);
3475             }
3476 
3477             if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, offset, bus->membuf, nbytes))) {
3478                 DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
3479                 break;
3480             }
3481 
3482             if (!write) {
3483                 memcpy(pdata, bus->membuf, nbytes);
3484             }
3485 
3486             pdata += nbytes;
3487             offset += nbytes;
3488             remain -= nbytes;
3489         }
3490 #else /* DHD_SDIO_MEM_BUF */
3491 		DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
3492 		          __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
3493 		          (address & SBSDIO_SBWINDOW_MASK)));
3494 
3495 		if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) {
3496 			DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
3497 			break;
3498 		}
3499 #endif /* DHD_SDIO_MEM_BUF */
3500 
3501 		/* Adjust for next transfer (if any) */
3502 		if ((size -= dsize)) {
3503 			data += dsize;
3504 			address += dsize;
3505 			if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
3506 				DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
3507 				break;
3508 			}
3509 			sdaddr = 0;
3510 			dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
3511 		}
3512 	}
3513 
3514 xfer_done:
3515 	/* Return the window to backplane enumeration space for core access */
3516 	if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
3517 		DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
3518 			bcmsdh_cur_sbwad(bus->sdh)));
3519 	}
3520 
3521 	return bcmerror;
3522 }
3523 
3524 static int
dhdsdio_readshared(dhd_bus_t * bus,sdpcm_shared_t * sh)3525 dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
3526 {
3527 	uint32 addr;
3528 	int rv, i;
3529 	uint32 shaddr = 0;
3530 
3531 	/* This temporary WAR for now */
3532 #if defined(PLATFORM_IMX)
3533 	return BCME_OK;
3534 #endif /* defined(PLATFORM_IMX) */
3535 
3536 	if (bus->sih == NULL) {
3537 		if (bus->dhd && bus->dhd->dongle_reset) {
3538 			DHD_ERROR(("%s: Dongle is in reset state\n", __FUNCTION__));
3539 			return BCME_NOTREADY;
3540 		} else {
3541 			ASSERT(bus->dhd);
3542 			ASSERT(bus->sih);
3543 			DHD_ERROR(("%s: The address of sih is invalid\n", __FUNCTION__));
3544 			return BCME_ERROR;
3545 		}
3546 	}
3547 	if ((CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
3548 		CHIPID(bus->sih->chip) == BCM43018_CHIP_ID) && !dhdsdio_sr_cap(bus))
3549 		bus->srmemsize = 0;
3550 
3551 	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
3552 	i = 0;
3553 	do {
3554 		/* Read last word in memory to determine address of sdpcm_shared structure */
3555 		if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
3556 			return rv;
3557 
3558 		addr = ltoh32(addr);
3559 
3560 		DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
3561 
3562 		/*
3563 		 * Check if addr is valid.
3564 		 * NVRAM length at the end of memory should have been overwritten.
3565 		 */
3566 		if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
3567 			if ((bus->srmemsize > 0) && (i++ == 0)) {
3568 				shaddr -= bus->srmemsize;
3569 			} else {
3570 				DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
3571 					__FUNCTION__, addr));
3572 				return BCME_ERROR;
3573 			}
3574 		} else
3575 			break;
3576 	} while (i < 2);
3577 
3578 	/* Read hndrte_shared structure */
3579 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
3580 		return rv;
3581 
3582 	/* Endianness */
3583 	sh->flags = ltoh32(sh->flags);
3584 	sh->trap_addr = ltoh32(sh->trap_addr);
3585 	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
3586 	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
3587 	sh->assert_line = ltoh32(sh->assert_line);
3588 	sh->console_addr = ltoh32(sh->console_addr);
3589 	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
3590 
3591 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
3592 		return BCME_OK;
3593 
3594 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
3595 		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
3596 		           "is different than sdpcm_shared version %d in dongle\n",
3597 		           __FUNCTION__, SDPCM_SHARED_VERSION,
3598 		           sh->flags & SDPCM_SHARED_VERSION_MASK));
3599 		return BCME_ERROR;
3600 	}
3601 
3602 	return BCME_OK;
3603 }
3604 
3605 static int
dhdsdio_readshared_console(dhd_bus_t * bus)3606 dhdsdio_readshared_console(dhd_bus_t *bus)
3607 {
3608 	uint32 addr;
3609 	int rv, i;
3610 	uint32 shaddr = 0;
3611 	sdpcm_shared_t sh_info;
3612 	sdpcm_shared_t *sh = &sh_info;
3613 	int retry = 10;
3614 
3615 	if ((CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
3616 		CHIPID(bus->sih->chip) == BCM43018_CHIP_ID) && !dhdsdio_sr_cap(bus)) {
3617 		bus->srmemsize = 0;
3618     }
3619 
3620 	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
3621 	i = 0;
3622 
3623 	do {
3624 		/* Read last word in memory to determine address of sdpcm_shared structure */
3625 		if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
3626 			return rv;
3627 
3628 		addr = ltoh32(addr);
3629 
3630 		DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
3631 
3632 		/*
3633 		 * Check if addr is valid.
3634 		 * NVRAM length at the end of memory should have been overwritten.
3635 		 */
3636 		if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
3637 			if ((bus->srmemsize > 0) && (i++ == 0)) {
3638 				shaddr -= bus->srmemsize;
3639 			} else {
3640 				DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
3641 					__FUNCTION__, addr));
3642 				OSL_SLEEP(50);
3643 			}
3644 		} else
3645 			break;
3646 	} while (i < retry);
3647 
3648 	if (i == retry)
3649 		return BCME_ERROR;
3650 
3651 	/* Read hndrte_shared structure */
3652 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
3653 		return rv;
3654 
3655 	/* Endianness */
3656 	sh->console_addr = ltoh32(sh->console_addr);
3657 	/* load bus console address */
3658 	bus->console_addr = sh->console_addr;
3659 
3660 	return BCME_OK;
3661 }
3662 
3663 #define CONSOLE_LINE_MAX	192
3664 
3665 #ifdef DHD_DEBUG
3666 static int
dhdsdio_readconsole(dhd_bus_t * bus)3667 dhdsdio_readconsole(dhd_bus_t *bus)
3668 {
3669 	dhd_console_t *c = &bus->console;
3670 	uint8 line[CONSOLE_LINE_MAX], ch;
3671 	uint32 n, idx, addr;
3672 	int rv;
3673 
3674 	if (!DHD_FWLOG_ON())
3675 		return 0;
3676 
3677 	/* Don't do anything until FWREADY updates console address */
3678 	if (bus->console_addr == 0)
3679 		return 0;
3680 
3681 	if (!KSO_ENAB(bus))
3682 		return 0;
3683 
3684 	/* Read console log struct */
3685 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, log);
3686 
3687 	/* Check if console log struct addr has changed */
3688 	/* Save the address(Local copy) */
3689 	if (c->log_addr != addr) {
3690 		/* Reset last index pointer */
3691 		c->last = 0;
3692 		/* Re-allocate memory if console address changes */
3693 		if (c->buf) {
3694 			MFREE(bus->dhd->osh, c->buf, c->bufsize);
3695 			c->buf = NULL;
3696 		}
3697 		/* Save new console address */
3698 		c->log_addr = addr;
3699 	}
3700 
3701 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
3702 		return rv;
3703 
3704 	/* Allocate console buffer (one time only) */
3705 	if (c->buf == NULL) {
3706 		c->bufsize = ltoh32(c->log.buf_size);
3707 		if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
3708 			return BCME_NOMEM;
3709 	}
3710 
3711 	idx = ltoh32(c->log.idx);
3712 
3713 	/* Protect against corrupt value */
3714 	if (idx > c->bufsize)
3715 		return BCME_ERROR;
3716 
3717 	/* Skip reading the console buffer if the index pointer has not moved */
3718 	if (idx == c->last)
3719 		return BCME_OK;
3720 
3721 	DHD_ERROR(("conlog: addr=0x%x, idx=0x%x, last=0x%x \n", c->log.buf,
3722 	   idx, c->last));
3723 
3724 	/* Read the console buffer */
3725 	addr = ltoh32(c->log.buf);
3726 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
3727 		return rv;
3728 
3729 	while (c->last != idx) {
3730 		for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
3731 			if (c->last == idx) {
3732 				/* This would output a partial line.  Instead, back up
3733 				 * the buffer pointer and output this line next time around.
3734 				 */
3735 				if (c->last >= n)
3736 					c->last -= n;
3737 				else
3738 					c->last = c->bufsize - n;
3739 				goto break2;
3740 			}
3741 			ch = c->buf[c->last];
3742 			c->last = (c->last + 1) % c->bufsize;
3743 			if (ch == '\n')
3744 				break;
3745 			line[n] = ch;
3746 		}
3747 
3748 		if (n > 0) {
3749 			if (line[n - 1] == '\r')
3750 				n--;
3751 			line[n] = 0;
3752 			printf("CONSOLE: %s\n", line);
3753 #ifdef LOG_INTO_TCPDUMP
3754 			dhd_sendup_log(bus->dhd, line, n);
3755 #endif /* LOG_INTO_TCPDUMP */
3756 		}
3757 	}
3758 break2:
3759 
3760 	return BCME_OK;
3761 }
3762 #endif /* DHD_DEBUG */
3763 
3764 static int
dhdsdio_checkdied(dhd_bus_t * bus,char * data,uint size)3765 dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size)
3766 {
3767 	int bcmerror = 0;
3768 	uint msize = 512;
3769 	char *mbuffer = NULL;
3770 	char *console_buffer = NULL;
3771 	uint maxstrlen = 256;
3772 	char *str = NULL;
3773 	sdpcm_shared_t l_sdpcm_shared;
3774 	struct bcmstrbuf strbuf;
3775 	uint32 console_ptr, console_size, console_index;
3776 	uint8 line[CONSOLE_LINE_MAX], ch;
3777 	uint32 n, i, addr;
3778 	int rv;
3779 
3780 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
3781 
3782 	if (DHD_NOCHECKDIED_ON())
3783 		return 0;
3784 
3785 	if (data == NULL) {
3786 		/*
3787 		 * Called after a rx ctrl timeout. "data" is NULL.
3788 		 * allocate memory to trace the trap or assert.
3789 		 */
3790 		size = msize;
3791 		mbuffer = data = MALLOC(bus->dhd->osh, msize);
3792 		if (mbuffer == NULL) {
3793 			DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
3794 			bcmerror = BCME_NOMEM;
3795 			goto done;
3796 		}
3797 	}
3798 
3799 	if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
3800 		DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
3801 		bcmerror = BCME_NOMEM;
3802 		goto done;
3803 	}
3804 
3805 	if ((bcmerror = dhdsdio_readshared(bus, &l_sdpcm_shared)) < 0)
3806 		goto done;
3807 
3808 	bcm_binit(&strbuf, data, size);
3809 
3810 	bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
3811 	            l_sdpcm_shared.msgtrace_addr, l_sdpcm_shared.console_addr);
3812 
3813 	if ((l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
3814 		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
3815 		 * (Avoids conflict with real asserts for programmatic parsing of output.)
3816 		 */
3817 		bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
3818 	}
3819 
3820 	if ((l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
3821 		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
3822 		 * (Avoids conflict with real asserts for programmatic parsing of output.)
3823 		 */
3824 		bcm_bprintf(&strbuf, "No trap%s in dongle",
3825 		          (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
3826 		          ?"/assrt" :"");
3827 	} else {
3828 		if (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
3829 			/* Download assert */
3830 			bcm_bprintf(&strbuf, "Dongle assert");
3831 			if (l_sdpcm_shared.assert_exp_addr != 0) {
3832 				str[0] = '\0';
3833 				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
3834 				                                 l_sdpcm_shared.assert_exp_addr,
3835 				                                 (uint8 *)str, maxstrlen)) < 0)
3836 					goto done;
3837 
3838 				str[maxstrlen - 1] = '\0';
3839 				bcm_bprintf(&strbuf, " expr \"%s\"", str);
3840 			}
3841 
3842 			if (l_sdpcm_shared.assert_file_addr != 0) {
3843 				str[0] = '\0';
3844 				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
3845 				                   l_sdpcm_shared.assert_file_addr,
3846 				                                 (uint8 *)str, maxstrlen)) < 0)
3847 					goto done;
3848 
3849 				str[maxstrlen - 1] = '\0';
3850 				bcm_bprintf(&strbuf, " file \"%s\"", str);
3851 			}
3852 
3853 			bcm_bprintf(&strbuf, " line %d ", l_sdpcm_shared.assert_line);
3854 		}
3855 
3856 		if (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
3857 			trap_t *tr = &bus->dhd->last_trap_info;
3858 			bus->dhd->dongle_trap_occured = TRUE;
3859 			if ((bcmerror = dhdsdio_membytes(bus, FALSE,
3860 			                                 l_sdpcm_shared.trap_addr,
3861 			                                 (uint8*)tr, sizeof(trap_t))) < 0)
3862 				goto done;
3863 
3864 			bus->dongle_trap_addr = ltoh32(l_sdpcm_shared.trap_addr);
3865 
3866 			dhd_bus_dump_trap_info(bus, &strbuf);
3867 
3868 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log);
3869 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
3870 				(uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
3871 				goto printbuf;
3872 
3873 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.buf_size);
3874 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
3875 				(uint8 *)&console_size, sizeof(console_size))) < 0)
3876 				goto printbuf;
3877 
3878 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.idx);
3879 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
3880 				(uint8 *)&console_index, sizeof(console_index))) < 0)
3881 				goto printbuf;
3882 
3883 			console_ptr = ltoh32(console_ptr);
3884 			console_size = ltoh32(console_size);
3885 			console_index = ltoh32(console_index);
3886 
3887 			if (console_size > CONSOLE_BUFFER_MAX ||
3888 				!(console_buffer = MALLOC(bus->dhd->osh, console_size)))
3889 				goto printbuf;
3890 
3891 			if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr,
3892 				(uint8 *)console_buffer, console_size)) < 0)
3893 				goto printbuf;
3894 
3895 			for (i = 0, n = 0; i < console_size; i += n + 1) {
3896 				for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
3897 					ch = console_buffer[(console_index + i + n) % console_size];
3898 					if (ch == '\n')
3899 						break;
3900 					line[n] = ch;
3901 				}
3902 
3903 				if (n > 0) {
3904 					if (line[n - 1] == '\r')
3905 						n--;
3906 					line[n] = 0;
3907 					/* Don't use DHD_ERROR macro since we print
3908 					 * a lot of information quickly. The macro
3909 					 * will truncate a lot of the printfs
3910 					 */
3911 
3912 					if (dhd_msg_level & DHD_ERROR_VAL)
3913 						printf("CONSOLE: %s\n", line);
3914 				}
3915 			}
3916 		}
3917 	}
3918 
3919 printbuf:
3920 	if (l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
3921 		DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
3922 	}
3923 
3924 #if defined(DHD_FW_COREDUMP)
3925 	if (bus->dhd->memdump_enabled && (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP)) {
3926 		/* Mem dump to a file on device */
3927 		bus->dhd->memdump_type = DUMP_TYPE_DONGLE_TRAP;
3928 		dhd_os_sdunlock(bus->dhd);
3929 		dhdsdio_mem_dump(bus);
3930 		dhd_os_sdlock(bus->dhd);
3931 	}
3932 #endif /* #if defined(DHD_FW_COREDUMP) */
3933 
3934 done:
3935 	if (mbuffer)
3936 		MFREE(bus->dhd->osh, mbuffer, msize);
3937 	if (str)
3938 		MFREE(bus->dhd->osh, str, maxstrlen);
3939 	if (console_buffer)
3940 		MFREE(bus->dhd->osh, console_buffer, console_size);
3941 
3942 	return bcmerror;
3943 }
3944 
3945 #if defined(DHD_FW_COREDUMP)
3946 int
dhd_bus_mem_dump(dhd_pub_t * dhdp)3947 dhd_bus_mem_dump(dhd_pub_t *dhdp)
3948 {
3949 	dhd_bus_t *bus = dhdp->bus;
3950 	if (dhdp->busstate == DHD_BUS_SUSPEND) {
3951 		DHD_ERROR(("%s: Bus is suspend so skip\n", __FUNCTION__));
3952 		return 0;
3953 	}
3954 	return dhdsdio_mem_dump(bus);
3955 }
3956 
3957 int
dhd_bus_get_mem_dump(dhd_pub_t * dhdp)3958 dhd_bus_get_mem_dump(dhd_pub_t *dhdp)
3959 {
3960 	if (!dhdp) {
3961 		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
3962 		return BCME_ERROR;
3963 	}
3964 
3965 	return dhdsdio_get_mem_dump(dhdp->bus);
3966 }
3967 
3968 static int
dhdsdio_get_mem_dump(dhd_bus_t * bus)3969 dhdsdio_get_mem_dump(dhd_bus_t *bus)
3970 {
3971 	int ret = BCME_ERROR;
3972 	int size = bus->ramsize;		/* Full mem size */
3973 	uint32 start = bus->dongle_ram_base;	/* Start address */
3974 	uint read_size = 0;			/* Read size of each iteration */
3975 	uint8 *p_buf = NULL, *databuf = NULL;
3976 
3977 	/* Get full mem size */
3978 	p_buf = dhd_get_fwdump_buf(bus->dhd, size);
3979 	if (!p_buf) {
3980 		DHD_ERROR(("%s: Out of memory (%d bytes)\n",
3981 			__FUNCTION__, size));
3982 		return BCME_ERROR;
3983 	}
3984 	if (!tcm_dump_enable) {
3985 		dhd_os_sdlock(bus->dhd);
3986 	}
3987 	BUS_WAKE(bus);
3988 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
3989 
3990 	/* Read mem content */
3991 	DHD_ERROR(("Dump dongle memory\n"));
3992 	databuf = p_buf;
3993 	while (size) {
3994 		read_size = MIN(MEMBLOCK, size);
3995 		ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size);
3996 		if (ret) {
3997 			DHD_ERROR(("%s: Error membytes %d\n", __FUNCTION__, ret));
3998 			ret = BCME_ERROR;
3999 			break;
4000 		}
4001 		/* Decrement size and increment start address */
4002 		size -= read_size;
4003 		start += read_size;
4004 		databuf += read_size;
4005 	}
4006 
4007 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
4008 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
4009 		bus->activity = FALSE;
4010 		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
4011 	}
4012 
4013 	dhd_os_sdunlock(bus->dhd);
4014 
4015 	return ret;
4016 }
4017 
4018 static int
dhdsdio_mem_dump(dhd_bus_t * bus)4019 dhdsdio_mem_dump(dhd_bus_t *bus)
4020 {
4021 	dhd_pub_t *dhdp;
4022 	int ret = BCME_ERROR;
4023 
4024 	dhdp = bus->dhd;
4025 	if (!dhdp) {
4026 		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
4027 		return ret;
4028 	}
4029 
4030 	ret = dhdsdio_get_mem_dump(bus);
4031 	if (ret) {
4032 		DHD_ERROR(("%s: failed to get mem dump, err=%d\n",
4033 			__FUNCTION__, ret));
4034 	} else {
4035 		/* schedule a work queue to perform actual memdump.
4036 		 * dhd_mem_dump() performs the job
4037 		 */
4038 		dhd_schedule_memdump(dhdp, dhdp->soc_ram, dhdp->soc_ram_length);
4039 		/* soc_ram free handled in dhd_{free,clear} */
4040 	}
4041 
4042 	return ret;
4043 }
4044 #endif /* DHD_FW_COREDUMP */
4045 
4046 int
dhd_socram_dump(dhd_bus_t * bus)4047 dhd_socram_dump(dhd_bus_t * bus)
4048 {
4049 #if defined(DHD_FW_COREDUMP)
4050 	return (dhdsdio_mem_dump(bus));
4051 #else
4052 	return -1;
4053 #endif // endif
4054 }
4055 
4056 int
dhdsdio_downloadvars(dhd_bus_t * bus,void * arg,int len)4057 dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
4058 {
4059 	int bcmerror = BCME_OK;
4060 
4061 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
4062 
4063 	if (bus->dhd->up &&
4064 #ifdef DHD_ULP
4065 		(DHD_ULP_DISABLED == dhd_ulp_get_ulp_state(bus->dhd)) &&
4066 #endif /* DHD_ULP */
4067 		1) {
4068 		bcmerror = BCME_NOTDOWN;
4069 		goto err;
4070 	}
4071 	if (!len) {
4072 		bcmerror = BCME_BUFTOOSHORT;
4073 		goto err;
4074 	}
4075 
4076 	/* Free the old ones and replace with passed variables */
4077 	if (bus->vars)
4078 		MFREE(bus->dhd->osh, bus->vars, bus->varsz);
4079 
4080 	bus->vars = MALLOC(bus->dhd->osh, len);
4081 	bus->varsz = bus->vars ? len : 0;
4082 	if (bus->vars == NULL) {
4083 		bcmerror = BCME_NOMEM;
4084 		goto err;
4085 	}
4086 
4087 	/* Copy the passed variables, which should include the terminating double-null */
4088 	bcopy(arg, bus->vars, bus->varsz);
4089 err:
4090 	return bcmerror;
4091 }
4092 
4093 #ifdef DHD_DEBUG
4094 static int
dhd_serialconsole(dhd_bus_t * bus,bool set,bool enable,int * bcmerror)4095 dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror)
4096 {
4097 	int int_val;
4098 	uint32 addr, data, uart_enab = 0;
4099 
4100 	addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
4101 	data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
4102 	*bcmerror = 0;
4103 
4104 	bcmsdh_reg_write(bus->sdh, addr, 4, 1);
4105 	if (bcmsdh_regfail(bus->sdh)) {
4106 		*bcmerror = BCME_SDIO_ERROR;
4107 		return -1;
4108 	}
4109 	int_val = bcmsdh_reg_read(bus->sdh, data, 4);
4110 	if (bcmsdh_regfail(bus->sdh)) {
4111 		*bcmerror = BCME_SDIO_ERROR;
4112 		return -1;
4113 	}
4114 
4115 	if (!set)
4116 		return (int_val & uart_enab);
4117 	if (enable)
4118 		int_val |= uart_enab;
4119 	else
4120 		int_val &= ~uart_enab;
4121 	bcmsdh_reg_write(bus->sdh, data, 4, int_val);
4122 	if (bcmsdh_regfail(bus->sdh)) {
4123 		*bcmerror = BCME_SDIO_ERROR;
4124 		return -1;
4125 	}
4126 
4127 	return (int_val & uart_enab);
4128 }
4129 #endif // endif
4130 
4131 static int
dhdsdio_doiovar(dhd_bus_t * bus,const bcm_iovar_t * vi,uint32 actionid,const char * name,void * params,int plen,void * arg,int len,int val_size)4132 dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
4133                 void *params, int plen, void *arg, int len, int val_size)
4134 {
4135 	int bcmerror = 0;
4136 	int32 int_val = 0;
4137 	bool bool_val = 0;
4138 
4139 	DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
4140 	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
4141 
4142 	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
4143 		goto exit;
4144 
4145 	if (plen >= (int)sizeof(int_val))
4146 		bcopy(params, &int_val, sizeof(int_val));
4147 
4148 	bool_val = (int_val != 0) ? TRUE : FALSE;
4149 
4150 	/* Some ioctls use the bus */
4151 	dhd_os_sdlock(bus->dhd);
4152 
4153 	/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
4154 	if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
4155 	                                actionid == IOV_GVAL(IOV_DEVRESET))) {
4156 		bcmerror = BCME_NOTREADY;
4157 		goto exit;
4158 	}
4159 
4160 	/*
4161 	 * Special handling for keepSdioOn: New SDIO Wake-up Mechanism
4162 	 */
4163 	if ((vi->varid == IOV_KSO) && (IOV_ISSET(actionid))) {
4164 		dhdsdio_clk_kso_iovar(bus, bool_val);
4165 		goto exit;
4166 	} else if ((vi->varid == IOV_DEVSLEEP) && (IOV_ISSET(actionid))) {
4167 		{
4168 			dhdsdio_clk_devsleep_iovar(bus, bool_val);
4169 			if (!SLPAUTO_ENAB(bus) && (bool_val == FALSE) && (bus->ipend)) {
4170 				DHD_ERROR(("INT pending in devsleep 1, dpc_sched: %d\n",
4171 					bus->dpc_sched));
4172 				if (!bus->dpc_sched) {
4173 					bus->dpc_sched = TRUE;
4174 					dhd_sched_dpc(bus->dhd);
4175 				}
4176 			}
4177 		}
4178 		goto exit;
4179 	}
4180 
4181 	/* Handle sleep stuff before any clock mucking */
4182 	if (vi->varid == IOV_SLEEP) {
4183 		if (IOV_ISSET(actionid)) {
4184 			bcmerror = dhdsdio_bussleep(bus, bool_val);
4185 		} else {
4186 			int_val = (int32)bus->sleeping;
4187 			bcopy(&int_val, arg, val_size);
4188 		}
4189 		goto exit;
4190 	}
4191 
4192 	/* Request clock to allow SDIO accesses */
4193 	if (!bus->dhd->dongle_reset) {
4194 		BUS_WAKE(bus);
4195 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
4196 	}
4197 
4198 	switch (actionid) {
4199 	case IOV_GVAL(IOV_INTR):
4200 		int_val = (int32)bus->intr;
4201 		bcopy(&int_val, arg, val_size);
4202 		break;
4203 
4204 	case IOV_SVAL(IOV_INTR):
4205 		bus->intr = bool_val;
4206 		bus->intdis = FALSE;
4207 		if (bus->dhd->up) {
4208 			if (bus->intr) {
4209 				DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
4210 				bcmsdh_intr_enable(bus->sdh);
4211 			} else {
4212 				DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
4213 				bcmsdh_intr_disable(bus->sdh);
4214 			}
4215 		}
4216 		break;
4217 
4218 	case IOV_GVAL(IOV_POLLRATE):
4219 		int_val = (int32)bus->pollrate;
4220 		bcopy(&int_val, arg, val_size);
4221 		break;
4222 
4223 	case IOV_SVAL(IOV_POLLRATE):
4224 		bus->pollrate = (uint)int_val;
4225 		bus->poll = (bus->pollrate != 0);
4226 		break;
4227 
4228 	case IOV_GVAL(IOV_IDLETIME):
4229 		int_val = bus->idletime;
4230 		bcopy(&int_val, arg, val_size);
4231 		break;
4232 
4233 	case IOV_SVAL(IOV_IDLETIME):
4234 		if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
4235 			bcmerror = BCME_BADARG;
4236 		} else {
4237 			bus->idletime = int_val;
4238 		}
4239 		break;
4240 
4241 	case IOV_GVAL(IOV_IDLECLOCK):
4242 		int_val = (int32)bus->idleclock;
4243 		bcopy(&int_val, arg, val_size);
4244 		break;
4245 
4246 	case IOV_SVAL(IOV_IDLECLOCK):
4247 		bus->idleclock = int_val;
4248 		break;
4249 
4250 	case IOV_GVAL(IOV_SD1IDLE):
4251 		int_val = (int32)sd1idle;
4252 		bcopy(&int_val, arg, val_size);
4253 		break;
4254 
4255 	case IOV_SVAL(IOV_SD1IDLE):
4256 		sd1idle = bool_val;
4257 		break;
4258 
4259 #ifdef DHD_DEBUG
4260 	case IOV_GVAL(IOV_CHECKDIED):
4261 		bcmerror = dhdsdio_checkdied(bus, arg, len);
4262 		break;
4263 #endif /* DHD_DEBUG */
4264 
4265 #ifdef DHD_BUS_MEM_ACCESS
4266 	case IOV_SVAL(IOV_MEMBYTES):
4267 	case IOV_GVAL(IOV_MEMBYTES):
4268 	{
4269 		uint32 address;
4270 		uint size, dsize;
4271 		uint8 *data;
4272 
4273 		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
4274 
4275 		ASSERT(plen >= 2*sizeof(int));
4276 
4277 		address = (uint32)int_val;
4278 		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
4279 		size = (uint)int_val;
4280 
4281 		/* Do some validation */
4282 		dsize = set ? plen - (2 * sizeof(int)) : len;
4283 		if (dsize < size) {
4284 			DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
4285 			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
4286 			bcmerror = BCME_BADARG;
4287 			break;
4288 		}
4289 
4290 		DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
4291 		          (set ? "write" : "read"), size, address));
4292 
4293 		/* check if CR4 */
4294 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
4295 			/*
4296 			 * If address is start of RAM (i.e. a downloaded image),
4297 			 * store the reset instruction to be written in 0
4298 			 */
4299 			if (set && address == bus->dongle_ram_base) {
4300 				bus->resetinstr = *(((uint32*)params) + 2);
4301 			}
4302 		} else {
4303 		/* If we know about SOCRAM, check for a fit */
4304 		if ((bus->orig_ramsize) &&
4305 		    ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize)))
4306 		{
4307 			uint8 enable, protect, remap;
4308 			si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
4309 			if (!enable || protect) {
4310 				DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
4311 					__FUNCTION__, bus->orig_ramsize, size, address));
4312 				DHD_ERROR(("%s: socram enable %d, protect %d\n",
4313 					__FUNCTION__, enable, protect));
4314 				bcmerror = BCME_BADARG;
4315 				break;
4316 			}
4317 
4318 			if (!REMAP_ENAB(bus) && (address >= SOCDEVRAM_ARM_ADDR)) {
4319 				uint32 devramsize = si_socdevram_size(bus->sih);
4320 				if ((address < SOCDEVRAM_ARM_ADDR) ||
4321 					(address + size > (SOCDEVRAM_ARM_ADDR + devramsize))) {
4322 					DHD_ERROR(("%s: bad address 0x%08x, size 0x%08x\n",
4323 						__FUNCTION__, address, size));
4324 					DHD_ERROR(("%s: socram range 0x%08x,size 0x%08x\n",
4325 						__FUNCTION__, SOCDEVRAM_ARM_ADDR, devramsize));
4326 					bcmerror = BCME_BADARG;
4327 					break;
4328 				}
4329 				/* move it such that address is real now */
4330 				address -= SOCDEVRAM_ARM_ADDR;
4331 				address += SOCDEVRAM_BP_ADDR;
4332 				DHD_INFO(("%s: Request to %s %d bytes @ Mapped address 0x%08x\n",
4333 					__FUNCTION__, (set ? "write" : "read"), size, address));
4334 			} else if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address) && remap) {
4335 				/* Can not access remap region while devram remap bit is set
4336 				 * ROM content would be returned in this case
4337 				 */
4338 				DHD_ERROR(("%s: Need to disable remap for address 0x%08x\n",
4339 					__FUNCTION__, address));
4340 				bcmerror = BCME_ERROR;
4341 				break;
4342 			}
4343 		}
4344 		}
4345 
4346 		/* Generate the actual data pointer */
4347 		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
4348 
4349 		/* Call to do the transfer */
4350 		bcmerror = dhdsdio_membytes(bus, set, address, data, size);
4351 
4352 		break;
4353 	}
4354 #endif /* DHD_BUS_MEM_ACCESS */
4355 
4356 	case IOV_GVAL(IOV_RAMSIZE):
4357 		int_val = (int32)bus->ramsize;
4358 		bcopy(&int_val, arg, val_size);
4359 		break;
4360 
4361 	case IOV_GVAL(IOV_RAMSTART):
4362 		int_val = (int32)bus->dongle_ram_base;
4363 		bcopy(&int_val, arg, val_size);
4364 		break;
4365 
4366 	case IOV_GVAL(IOV_SDIOD_DRIVE):
4367 		int_val = (int32)dhd_sdiod_drive_strength;
4368 		bcopy(&int_val, arg, val_size);
4369 		break;
4370 
4371 	case IOV_SVAL(IOV_SDIOD_DRIVE):
4372 		dhd_sdiod_drive_strength = int_val;
4373 		si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
4374 		break;
4375 
4376 	case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
4377 		bcmerror = dhdsdio_download_state(bus, bool_val);
4378 		break;
4379 
4380 	case IOV_SVAL(IOV_SOCRAM_STATE):
4381 		bcmerror = dhdsdio_download_state(bus, bool_val);
4382 		break;
4383 
4384 	case IOV_SVAL(IOV_VARS):
4385 		bcmerror = dhdsdio_downloadvars(bus, arg, len);
4386 		break;
4387 
4388 	case IOV_GVAL(IOV_READAHEAD):
4389 		int_val = (int32)dhd_readahead;
4390 		bcopy(&int_val, arg, val_size);
4391 		break;
4392 
4393 	case IOV_SVAL(IOV_READAHEAD):
4394 		if (bool_val && !dhd_readahead)
4395 			bus->nextlen = 0;
4396 		dhd_readahead = bool_val;
4397 		break;
4398 
4399 	case IOV_GVAL(IOV_SDRXCHAIN):
4400 		int_val = (int32)bus->use_rxchain;
4401 		bcopy(&int_val, arg, val_size);
4402 		break;
4403 
4404 	case IOV_SVAL(IOV_SDRXCHAIN):
4405 		if (bool_val && !bus->sd_rxchain)
4406 			bcmerror = BCME_UNSUPPORTED;
4407 		else
4408 			bus->use_rxchain = bool_val;
4409 		break;
4410 #ifndef BCMSPI
4411 	case IOV_GVAL(IOV_ALIGNCTL):
4412 		int_val = (int32)dhd_alignctl;
4413 		bcopy(&int_val, arg, val_size);
4414 		break;
4415 
4416 	case IOV_SVAL(IOV_ALIGNCTL):
4417 		dhd_alignctl = bool_val;
4418 		break;
4419 #endif /* BCMSPI */
4420 
4421 	case IOV_GVAL(IOV_SDALIGN):
4422 		int_val = DHD_SDALIGN;
4423 		bcopy(&int_val, arg, val_size);
4424 		break;
4425 
4426 #ifdef DHD_DEBUG
4427 	case IOV_GVAL(IOV_VARS):
4428 		if (bus->varsz < (uint)len)
4429 			bcopy(bus->vars, arg, bus->varsz);
4430 		else
4431 			bcmerror = BCME_BUFTOOSHORT;
4432 		break;
4433 #endif /* DHD_DEBUG */
4434 
4435 #ifdef DHD_DEBUG
4436 	case IOV_GVAL(IOV_SDREG):
4437 	{
4438 		sdreg_t *sd_ptr;
4439 		uintptr addr;
4440 		uint size;
4441 
4442 		sd_ptr = (sdreg_t *)params;
4443 
4444 		addr = ((uintptr)bus->regs + sd_ptr->offset);
4445 		size = sd_ptr->func;
4446 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
4447 		if (bcmsdh_regfail(bus->sdh))
4448 			bcmerror = BCME_SDIO_ERROR;
4449 		bcopy(&int_val, arg, sizeof(int32));
4450 		break;
4451 	}
4452 
4453 	case IOV_SVAL(IOV_SDREG):
4454 	{
4455 		sdreg_t *sd_ptr;
4456 		uintptr addr;
4457 		uint size;
4458 
4459 		sd_ptr = (sdreg_t *)params;
4460 
4461 		addr = ((uintptr)bus->regs + sd_ptr->offset);
4462 		size = sd_ptr->func;
4463 		bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
4464 		if (bcmsdh_regfail(bus->sdh))
4465 			bcmerror = BCME_SDIO_ERROR;
4466 		break;
4467 	}
4468 
4469 	/* Same as above, but offset is not backplane (not SDIO core) */
4470 	case IOV_GVAL(IOV_SBREG):
4471 	{
4472 		sdreg_t sdreg;
4473 		uint32 addr, size;
4474 
4475 		bcopy(params, &sdreg, sizeof(sdreg));
4476 
4477 		addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
4478 		size = sdreg.func;
4479 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
4480 		if (bcmsdh_regfail(bus->sdh))
4481 			bcmerror = BCME_SDIO_ERROR;
4482 		bcopy(&int_val, arg, sizeof(int32));
4483 		break;
4484 	}
4485 
4486 	case IOV_SVAL(IOV_SBREG):
4487 	{
4488 		sdreg_t sdreg;
4489 		uint32 addr, size;
4490 
4491 		bcopy(params, &sdreg, sizeof(sdreg));
4492 
4493 		addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
4494 		size = sdreg.func;
4495 		bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
4496 		if (bcmsdh_regfail(bus->sdh))
4497 			bcmerror = BCME_SDIO_ERROR;
4498 		break;
4499 	}
4500 
4501 	case IOV_GVAL(IOV_SDCIS):
4502 	{
4503 		*(char *)arg = 0;
4504 
4505 		bcmstrcat(arg, "\nFunc 0\n");
4506 		bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4507 		bcmstrcat(arg, "\nFunc 1\n");
4508 		bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4509 		bcmstrcat(arg, "\nFunc 2\n");
4510 		bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4511 		break;
4512 	}
4513 
4514 	case IOV_GVAL(IOV_FORCEEVEN):
4515 		int_val = (int32)forcealign;
4516 		bcopy(&int_val, arg, val_size);
4517 		break;
4518 
4519 	case IOV_SVAL(IOV_FORCEEVEN):
4520 		forcealign = bool_val;
4521 		break;
4522 
4523 	case IOV_GVAL(IOV_TXBOUND):
4524 		int_val = (int32)dhd_txbound;
4525 		bcopy(&int_val, arg, val_size);
4526 		break;
4527 
4528 	case IOV_SVAL(IOV_TXBOUND):
4529 		dhd_txbound = (uint)int_val;
4530 		break;
4531 
4532 	case IOV_GVAL(IOV_RXBOUND):
4533 		int_val = (int32)dhd_rxbound;
4534 		bcopy(&int_val, arg, val_size);
4535 		break;
4536 
4537 	case IOV_SVAL(IOV_RXBOUND):
4538 		dhd_rxbound = (uint)int_val;
4539 		break;
4540 
4541 	case IOV_GVAL(IOV_TXMINMAX):
4542 		int_val = (int32)dhd_txminmax;
4543 		bcopy(&int_val, arg, val_size);
4544 		break;
4545 
4546 	case IOV_SVAL(IOV_TXMINMAX):
4547 		dhd_txminmax = (uint)int_val;
4548 		break;
4549 
4550 #ifdef DHD_DEBUG
4551 	case IOV_GVAL(IOV_SERIALCONS):
4552 		int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror);
4553 		if (bcmerror != 0)
4554 			break;
4555 
4556 		bcopy(&int_val, arg, val_size);
4557 		break;
4558 
4559 	case IOV_SVAL(IOV_SERIALCONS):
4560 		dhd_serialconsole(bus, TRUE, bool_val, &bcmerror);
4561 		break;
4562 #endif /* DHD_DEBUG */
4563 
4564 #endif /* DHD_DEBUG */
4565 
4566 #ifdef SDTEST
4567 	case IOV_GVAL(IOV_EXTLOOP):
4568 		int_val = (int32)bus->ext_loop;
4569 		bcopy(&int_val, arg, val_size);
4570 		break;
4571 
4572 	case IOV_SVAL(IOV_EXTLOOP):
4573 		bus->ext_loop = bool_val;
4574 		break;
4575 
4576 	case IOV_GVAL(IOV_PKTGEN):
4577 		bcmerror = dhdsdio_pktgen_get(bus, arg);
4578 		break;
4579 
4580 	case IOV_SVAL(IOV_PKTGEN):
4581 		bcmerror = dhdsdio_pktgen_set(bus, arg);
4582 		break;
4583 #endif /* SDTEST */
4584 
4585 #if defined(USE_SDIOFIFO_IOVAR)
4586 	case IOV_GVAL(IOV_WATERMARK):
4587 		int_val = (int32)watermark;
4588 		bcopy(&int_val, arg, val_size);
4589 		break;
4590 
4591 	case IOV_SVAL(IOV_WATERMARK):
4592 		watermark = (uint)int_val;
4593 		watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark;
4594 		DHD_ERROR(("Setting watermark as 0x%x.\n", watermark));
4595 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL);
4596 		break;
4597 
4598 	case IOV_GVAL(IOV_MESBUSYCTRL):
4599 		int_val = (int32)mesbusyctrl;
4600 		bcopy(&int_val, arg, val_size);
4601 		break;
4602 
4603 	case IOV_SVAL(IOV_MESBUSYCTRL):
4604 		mesbusyctrl = (uint)int_val;
4605 		mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK)
4606 			? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl;
4607 		DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl));
4608 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
4609 			((uint8)mesbusyctrl | 0x80), NULL);
4610 		break;
4611 #endif // endif
4612 
4613 	case IOV_GVAL(IOV_DONGLEISOLATION):
4614 		int_val = bus->dhd->dongle_isolation;
4615 		bcopy(&int_val, arg, val_size);
4616 		break;
4617 
4618 	case IOV_SVAL(IOV_DONGLEISOLATION):
4619 		bus->dhd->dongle_isolation = bool_val;
4620 		break;
4621 
4622 	case IOV_SVAL(IOV_DEVRESET):
4623 		DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
4624 		           __FUNCTION__, bool_val, bus->dhd->dongle_reset,
4625 		           bus->dhd->busstate));
4626 
4627 		ASSERT(bus->dhd->osh);
4628 		/* ASSERT(bus->cl_devid); */
4629 
4630 		/* must release sdlock, since devreset also acquires it */
4631 		dhd_os_sdunlock(bus->dhd);
4632 		dhd_bus_devreset(bus->dhd, (uint8)bool_val);
4633 		dhd_os_sdlock(bus->dhd);
4634 		break;
4635 	/*
4636 	 * softap firmware is updated through module parameter or android private command
4637 	 */
4638 
4639 	case IOV_GVAL(IOV_DEVRESET):
4640 		DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
4641 
4642 		/* Get its status */
4643 		int_val = (bool) bus->dhd->dongle_reset;
4644 		bcopy(&int_val, arg, val_size);
4645 
4646 		break;
4647 
4648 	case IOV_GVAL(IOV_KSO):
4649 		int_val = dhdsdio_sleepcsr_get(bus);
4650 		bcopy(&int_val, arg, val_size);
4651 		break;
4652 
4653 	case IOV_GVAL(IOV_DEVCAP):
4654 		int_val = dhdsdio_devcap_get(bus);
4655 		bcopy(&int_val, arg, val_size);
4656 		break;
4657 
4658 	case IOV_SVAL(IOV_DEVCAP):
4659 		dhdsdio_devcap_set(bus, (uint8) int_val);
4660 		break;
4661 	case IOV_GVAL(IOV_TXGLOMSIZE):
4662 		int_val = (int32)bus->txglomsize;
4663 		bcopy(&int_val, arg, val_size);
4664 		break;
4665 
4666 	case IOV_SVAL(IOV_TXGLOMSIZE):
4667 		if (int_val > SDPCM_MAXGLOM_SIZE) {
4668 			bcmerror = BCME_ERROR;
4669 		} else {
4670 			bus->txglomsize = (uint)int_val;
4671 		}
4672 		break;
4673 	case IOV_SVAL(IOV_HANGREPORT):
4674 		bus->dhd->hang_report = bool_val;
4675 		DHD_ERROR(("%s: Set hang_report as %d\n", __FUNCTION__, bus->dhd->hang_report));
4676 		break;
4677 
4678 	case IOV_GVAL(IOV_HANGREPORT):
4679 		int_val = (int32)bus->dhd->hang_report;
4680 		bcopy(&int_val, arg, val_size);
4681 		break;
4682 
4683 	case IOV_GVAL(IOV_TXINRX_THRES):
4684 		int_val = bus->txinrx_thres;
4685 		bcopy(&int_val, arg, val_size);
4686 		break;
4687 	case IOV_SVAL(IOV_TXINRX_THRES):
4688 		if (int_val < 0) {
4689 			bcmerror = BCME_BADARG;
4690 		} else {
4691 			bus->txinrx_thres = int_val;
4692 		}
4693 		break;
4694 
4695 	case IOV_GVAL(IOV_SDIO_SUSPEND):
4696 		int_val = (bus->dhd->busstate == DHD_BUS_SUSPEND) ? 1 : 0;
4697 		bcopy(&int_val, arg, val_size);
4698 		break;
4699 
4700 	case IOV_SVAL(IOV_SDIO_SUSPEND):
4701 		if (bool_val) { /* Suspend */
4702 			dhdsdio_suspend(bus);
4703 		}
4704 		else { /* Resume */
4705 			dhdsdio_resume(bus);
4706 		}
4707 		break;
4708 
4709 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
4710 	case IOV_SVAL(IOV_GDB_SERVER):
4711 		if (bool_val == TRUE) {
4712 			debugger_init((void *) bus, &bus_ops, int_val, SI_ENUM_BASE(bus->sih));
4713 		} else {
4714 			debugger_close();
4715 		}
4716 		break;
4717 #endif /* DEBUGGER || DHD_DSCOPE */
4718 
4719 	default:
4720 		bcmerror = BCME_UNSUPPORTED;
4721 		break;
4722 	}
4723 
4724 exit:
4725 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
4726 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
4727 		bus->activity = FALSE;
4728 		dhdsdio_bussleep(bus, TRUE);
4729 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
4730 	}
4731 
4732 	dhd_os_sdunlock(bus->dhd);
4733 
4734 	return bcmerror;
4735 }
4736 
4737 static int
dhdsdio_write_vars(dhd_bus_t * bus)4738 dhdsdio_write_vars(dhd_bus_t *bus)
4739 {
4740 	int bcmerror = 0;
4741 	uint32 varsize, phys_size;
4742 	uint32 varaddr;
4743 	uint8 *vbuffer;
4744 	uint32 varsizew;
4745 #ifdef DHD_DEBUG
4746 	uint8 *nvram_ularray;
4747 #endif /* DHD_DEBUG */
4748 
4749 #define TOKENSIZE 4
4750 	/* Even if there are no vars are to be written, we still need to set the ramsize. */
4751 	varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
4752 	varaddr = bus->ramsize - varsize - TOKENSIZE;
4753 	varaddr += bus->dongle_ram_base;
4754 
4755 	if (bus->vars) {
4756 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 7)) {
4757 			if (((varaddr & 0x3C) == 0x3C) && (varsize > 4)) {
4758 				DHD_ERROR(("PR85623WAR in place\n"));
4759 				varsize += 4;
4760 				varaddr -= 4;
4761 			}
4762 		}
4763 
4764 		vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize + TOKENSIZE);
4765 		if (!vbuffer)
4766 			return BCME_NOMEM;
4767 
4768 		bzero(vbuffer, varsize + TOKENSIZE);
4769 		bcopy(bus->vars, vbuffer, bus->varsz);
4770 
4771 		/*
4772 		 * Determine the length token:
4773 		 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
4774 		 */
4775 		varsizew = varsize / 4;
4776 		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
4777 		varsizew = htol32(varsizew);
4778 
4779 		DHD_INFO(("length token=0x%08x\n", varsizew));
4780 		/* Write the length token to the last word */
4781 		bcopy((uint8*)&varsizew, &vbuffer[varsize], 4);
4782 
4783 		/* Write the vars list */
4784 		bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize + TOKENSIZE);
4785 		if (bcmerror) {
4786 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
4787 					__FUNCTION__, bcmerror, varsize, varaddr));
4788 			return bcmerror;
4789 		}
4790 
4791 #ifdef DHD_DEBUG
4792 		/* Verify NVRAM bytes */
4793 		DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
4794 		nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
4795 		if (!nvram_ularray) {
4796 			MFREE(bus->dhd->osh, vbuffer, varsize + TOKENSIZE);
4797 			return BCME_NOMEM;
4798 		}
4799 
4800 		/* Upload image to verify downloaded contents. */
4801 		memset(nvram_ularray, 0xaa, varsize);
4802 
4803 		/* Read the vars list to temp buffer for comparison */
4804 		bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
4805 		if (bcmerror) {
4806 				DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
4807 					__FUNCTION__, bcmerror, varsize, varaddr));
4808 		}
4809 		/* Compare the org NVRAM with the one read from RAM */
4810 		if (memcmp(vbuffer, nvram_ularray, varsize)) {
4811 			DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
4812 		} else
4813 			DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
4814 			__FUNCTION__));
4815 
4816 		MFREE(bus->dhd->osh, nvram_ularray, varsize);
4817 #endif /* DHD_DEBUG */
4818 		MFREE(bus->dhd->osh, vbuffer, varsize + TOKENSIZE);
4819 
4820 	}
4821 
4822 	phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
4823 
4824 	phys_size += bus->dongle_ram_base;
4825 
4826 	/* adjust to the user specified RAM */
4827 	DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
4828 		phys_size, bus->ramsize));
4829 	DHD_INFO(("Vars are at %d, orig varsize is %d\n",
4830 		varaddr, varsize));
4831 
4832 	return bcmerror;
4833 }
4834 
4835 bool
dhd_bus_is_multibp_capable(struct dhd_bus * bus)4836 dhd_bus_is_multibp_capable(struct dhd_bus *bus)
4837 {
4838 	return MULTIBP_CAP(bus->sih);
4839 }
4840 
4841 static int
dhdsdio_download_state(dhd_bus_t * bus,bool enter)4842 dhdsdio_download_state(dhd_bus_t *bus, bool enter)
4843 {
4844 	uint retries;
4845 	int bcmerror = 0;
4846 	int foundcr4 = 0;
4847 	hs_addrs_t bl_hs_addrs = {NULL, NULL};
4848 
4849 	if (!bus->sih)
4850 		return BCME_ERROR;
4851 
4852 	if (bus->secureboot) {
4853 		/* Host bootloader handshake TCM/REGS addresses init */
4854 		bcmerror = dhdsdio_dongle_host_get_handshake_address(bus, &bl_hs_addrs);
4855 		if (bcmerror) {
4856 			DHD_ERROR(("%s: REGS/TCM addresses not initialized\n", __FUNCTION__));
4857 			goto fail;
4858 		}
4859 	}
4860 
4861 	/* To enter download state, disable ARM and reset SOCRAM.
4862 	 * To exit download state, simply reset ARM (default is RAM boot).
4863 	 */
4864 	if (enter) {
4865 		bus->alp_only = TRUE;
4866 
4867 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
4868 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
4869 			if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
4870 				foundcr4 = 1;
4871 			} else {
4872 				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
4873 				bcmerror = BCME_ERROR;
4874 				goto fail;
4875 			}
4876 		}
4877 
4878 		if (!foundcr4) {
4879 			si_core_disable(bus->sih, 0);
4880 			if (bcmsdh_regfail(bus->sdh)) {
4881 				bcmerror = BCME_SDIO_ERROR;
4882 				goto fail;
4883 			}
4884 
4885 			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
4886 				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
4887 				bcmerror = BCME_ERROR;
4888 				goto fail;
4889 			}
4890 
4891 			si_core_reset(bus->sih, 0, 0);
4892 			if (bcmsdh_regfail(bus->sdh)) {
4893 				DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n",
4894 				           __FUNCTION__));
4895 				bcmerror = BCME_SDIO_ERROR;
4896 				goto fail;
4897 			}
4898 
4899 			/* Disable remap for download */
4900 			if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih))
4901 				dhdsdio_devram_remap(bus, FALSE);
4902 
4903 			if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
4904 				CHIPID(bus->sih->chip) == BCM43018_CHIP_ID) {
4905 				/* Disabling Remap for SRAM_3 */
4906 				si_socram_set_bankpda(bus->sih, 0x3, 0x0);
4907 			}
4908 
4909 			/* Clear the top bit of memory */
4910 			if (bus->ramsize) {
4911 				uint32 zeros = 0;
4912 				if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4,
4913 				                     (uint8*)&zeros, 4) < 0) {
4914 					bcmerror = BCME_SDIO_ERROR;
4915 					goto fail;
4916 				}
4917 			}
4918 		} else {
4919 			/* For CR4,
4920 			 * Halt ARM
4921 			 * Remove ARM reset
4922 			 * Read RAM base address [0x18_0000]
4923 			 * [next] Download firmware
4924 			 * [done at else] Populate the reset vector
4925 			 * [done at else] Remove ARM halt
4926 			 */
4927 			if (bus->secureboot) {
4928 				/* Skip ARM halt and reset in case of security bootloader */
4929 
4930 				/* Bootloader host pre handshake function */
4931 				if ((bcmerror =	dhdsdio_dongle_host_pre_handshake
4932 						(bus, &bl_hs_addrs))) {
4933 					DHD_ERROR(("%s: error %d dongle host pre handshake\n",
4934 						__FUNCTION__, bcmerror));
4935 					goto fail;
4936 				}
4937 				DHD_ERROR(("%s: dongle host pre handshake successful, dl FW\n",
4938 					__FUNCTION__));
4939 
4940 				/* This is necessary for console buffer initialization */
4941 				/* Read SDIO shared structure here */
4942 				if ((bcmerror = dhdsdio_readshared_console(bus)) < 0) {
4943 					DHD_ERROR(("%s: Shared region not initialized\n",
4944 						__FUNCTION__));
4945 				}
4946 #ifdef DHD_DEBUG
4947 				/* Console buffer read - First pass */
4948 				if ((bcmerror = dhdsdio_readconsole(bus)) < 0) {
4949 					DHD_ERROR(("%s: First pass console buffer read failed\n",
4950 						__FUNCTION__));
4951 				}
4952 #endif /* DHD_DEBUG */
4953 			} else {
4954 				/* Halt ARM & remove reset */
4955 				si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
4956 			}
4957 		}
4958 	} else {
4959 		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
4960 			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
4961 				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
4962 				bcmerror = BCME_ERROR;
4963 				goto fail;
4964 			}
4965 
4966 			if (!si_iscoreup(bus->sih)) {
4967 				DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
4968 				bcmerror = BCME_ERROR;
4969 				goto fail;
4970 			}
4971 
4972 			if ((bcmerror = dhdsdio_write_vars(bus))) {
4973 				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
4974 				goto fail;
4975 			}
4976 
4977 			/* Enable remap before ARM reset but after vars.
4978 			 * No backplane access in remap mode
4979 			 */
4980 			if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih))
4981 				dhdsdio_devram_remap(bus, TRUE);
4982 #ifdef BCMSDIOLITE
4983 			if (!si_setcore(bus->sih, CC_CORE_ID, 0)) {
4984 				DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__));
4985 				bcmerror = BCME_ERROR;
4986 				goto fail;
4987 			}
4988 #else
4989 			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
4990 			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
4991 				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
4992 				bcmerror = BCME_ERROR;
4993 				goto fail;
4994 			}
4995 #endif // endif
4996 			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
4997 
4998 			if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
4999 			    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5000 				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5001 				bcmerror = BCME_ERROR;
5002 				goto fail;
5003 			}
5004 		} else {
5005 			if (bus->secureboot) {
5006 #ifdef DHD_DEBUG
5007 				/* Console buffer read - Second pass */
5008 				if ((bcmerror = dhdsdio_readconsole(bus)) < 0) {
5009 					DHD_ERROR(("%s: Second pass console buffer read failed\n",
5010 						__FUNCTION__));
5011 				}
5012 #endif /* DHD_DEBUG */
5013 				/* FW and NVRAM download done notification to bootloader */
5014 				if ((bcmerror = dhdsdio_dongle_host_post_handshake(bus,
5015 						&bl_hs_addrs))) {
5016 					DHD_ERROR(("%s: error %d dongle host post handshake\n",
5017 						__FUNCTION__, bcmerror));
5018 					goto fail;
5019 				}
5020 				DHD_ERROR(("%s: FW download successful\n", __FUNCTION__));
5021 
5022 				/*
5023 				 * Check signature validation function
5024 				 * D2H_VALDN_DONE bit will be set in the following cases:
5025 				 * 1. Open mode: when a signature is not sent
5026 				 * 2. Secure mode: when a valid signature is sent
5027 				 * Write vars and nvram download only if the D2H_VALDN_DONE
5028 				 * bit has been set
5029 				 */
5030 				if ((bcmerror = dhdsdio_dongle_host_chk_validation(bus,
5031 						&bl_hs_addrs))) {
5032 					DHD_ERROR(("%s: error %d dongle host validation\n",
5033 						__FUNCTION__, bcmerror));
5034 					goto fail;
5035 				}
5036 			}
5037 
5038 			/* cr4 has no socram, but tcm's */
5039 			/* write vars */
5040 			if ((bcmerror = dhdsdio_write_vars(bus))) {
5041 				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
5042 				goto fail;
5043 			}
5044 #ifdef BCMSDIOLITE
5045 			if (!si_setcore(bus->sih, CC_CORE_ID, 0)) {
5046 				DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__));
5047 				bcmerror = BCME_ERROR;
5048 				goto fail;
5049 			}
5050 #else
5051 			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
5052 			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
5053 				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
5054 				bcmerror = BCME_ERROR;
5055 				goto fail;
5056 			}
5057 #endif // endif
5058 			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
5059 
5060 			/* switch back to arm core again */
5061 			if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
5062 				DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
5063 				bcmerror = BCME_ERROR;
5064 				goto fail;
5065 			}
5066 			/* write address 0 with reset instruction */
5067 			/* Except for chips eg. CYW555x0, which runs bootloader */
5068 			if (!bus->secureboot) {
5069 				bcmerror = dhdsdio_membytes(bus, TRUE, 0,
5070 						(uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
5071 
5072 				if (bcmerror == BCME_OK) {
5073 					uint32 tmp;
5074 
5075 					/* verify write */
5076 					bcmerror = dhdsdio_membytes(bus, FALSE, 0, (uint8 *)&tmp,
5077 							sizeof(tmp));
5078 
5079 					if (bcmerror == BCME_OK && tmp != bus->resetinstr) {
5080 						DHD_ERROR(("%s: Failed to write 0x%08x to addr 0\n",
5081 							__FUNCTION__, bus->resetinstr));
5082 						DHD_ERROR(("%s: contents of addr 0 is 0x%08x\n",
5083 							__FUNCTION__, tmp));
5084 						bcmerror = BCME_SDIO_ERROR;
5085 						goto fail;
5086 					}
5087 				}
5088 			}
5089 		}
5090 
5091 		/* now remove reset and halt and continue to run CR4 */
5092 		if (bus->secureboot) {
5093 #ifdef DHD_DEBUG
5094 			/* Console buffer read - Final pass */
5095 			if ((bcmerror = dhdsdio_readconsole(bus)) < 0) {
5096 				DHD_ERROR(("%s: Final pass console buffer read failed\n",
5097 					__FUNCTION__));
5098 			}
5099 #endif /* DHD_DEBUG */
5100 			/* Set write_vars done bit to let BL jump to mainline FW */
5101 			if ((bcmerror = dhdsdio_dongle_host_post_varswrite(bus, &bl_hs_addrs))) {
5102 					DHD_ERROR(("%s: error %d dongle_host_post_varswrite\n",
5103 						__FUNCTION__, bcmerror));
5104 					goto fail;
5105 			}
5106 			DHD_ERROR(("%s VARS done bit set, BL can jump to mainline FW\n",
5107 				__FUNCTION__));
5108 		} else {
5109 			si_core_reset(bus->sih, 0, 0);
5110 		}
5111 		if (bcmsdh_regfail(bus->sdh)) {
5112 			DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
5113 			bcmerror = BCME_SDIO_ERROR;
5114 			goto fail;
5115 		}
5116 
5117 		/* Allow HT Clock now that the ARM is running. */
5118 		bus->alp_only = FALSE;
5119 
5120 		bus->dhd->busstate = DHD_BUS_LOAD;
5121 	}
5122 
5123 fail:
5124 	if (bcmerror) {
5125 		if (bus->secureboot) {
5126 			/* Read the shared structure to determine console address */
5127 			if (dhdsdio_readshared_console(bus) < 0) {
5128 				DHD_ERROR(("%s: Shared region not initialized\n",
5129 					__FUNCTION__));
5130 			} else {
5131 #ifdef DHD_DEBUG
5132 				/* Console buffer read */
5133 				if (dhdsdio_readconsole(bus) < 0) {
5134 					DHD_ERROR(
5135 						("%s: console buffer read failed\n",
5136 							__FUNCTION__));
5137 				}
5138 #endif /* DHD_DEBUG */
5139 			}
5140 		}
5141 	}
5142 	/* Always return to SDIOD core */
5143 	if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
5144 		si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5145 
5146 	return bcmerror;
5147 }
5148 
5149 static int
dhdsdio_dongle_host_get_handshake_address(dhd_bus_t * bus,hs_addrs_t * addr)5150 dhdsdio_dongle_host_get_handshake_address(dhd_bus_t *bus, hs_addrs_t *addr)
5151 {
5152 	int bcmerror = BCME_OK;
5153 
5154 #ifndef HS_IN_TCM
5155 	addr->d2h = (uint32 *)SDIO_FN1_MSG_D2H_REG0;
5156 	addr->h2d = (uint32 *)SDIO_FN1_MSG_H2D_REG0;
5157 #endif /* HS_IN_TCM */
5158 
5159 	return bcmerror;
5160 }
5161 
5162 static int
dhdsdio_wait_bootloader_ready(dhd_bus_t * bus,hs_addrs_t * addr)5163 dhdsdio_wait_bootloader_ready(dhd_bus_t *bus, hs_addrs_t *addr)
5164 {
5165 	int bcmerror = BCME_OK;
5166 	int h2d_reg = 0x00000000;
5167 
5168 	/* Host initialization for dongle to host handshake */
5169 	bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg);
5170 	if (bcmerror) {
5171 		goto err;
5172 	}
5173 
5174 	bcmerror = dhdsdio_dongle_host_handshake_spinwait(bus, addr->d2h,
5175 			D2H_READY_SHIFT, D2H_READY_TIMEOUT_MS);
5176 
5177 err:
5178 	return bcmerror;
5179 }
5180 
5181 static int
dhdsdio_dongle_host_pre_handshake(dhd_bus_t * bus,hs_addrs_t * addr)5182 dhdsdio_dongle_host_pre_handshake(dhd_bus_t *bus, hs_addrs_t *addr)
5183 {
5184 	int bcmerror = BCME_OK;
5185 	int h2d_reg = 0x00000000;
5186 
5187 	/* Set H2D_DL_START indication to dongle that Host shall start FW download */
5188 	setbit(&h2d_reg, H2D_DL_START_SHIFT);
5189 	bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg);
5190 
5191 	return bcmerror;
5192 }
5193 
5194 static int
dhdsdio_dongle_host_post_handshake(dhd_bus_t * bus,hs_addrs_t * addr)5195 dhdsdio_dongle_host_post_handshake(dhd_bus_t *bus, hs_addrs_t *addr)
5196 {
5197 	int bcmerror = BCME_OK;
5198 	int h2d_reg = 0x00000000;
5199 
5200 	/* Reset download start */
5201 	clrbit(&h2d_reg, H2D_DL_START_SHIFT);
5202 
5203 	/* download done */
5204 	setbit(&h2d_reg, H2D_DL_DONE_SHIFT);
5205 	bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg);
5206 	if (bcmerror) {
5207 		goto err;
5208 	}
5209 
5210 	bcmerror = dhdsdio_dongle_host_handshake_spinwait(bus, addr->d2h,
5211 		D2H_TRX_HDR_PARSE_DONE_SHIFT, D2H_TRX_HDR_PARSE_DONE_TIMEOUT_MS);
5212 
5213 	if (bcmerror) {
5214 		/* Host notification to bootloader to get reset on error */
5215 		dhdsdio_handshake_msg_reg_read(bus, addr->h2d, &h2d_reg);
5216 		setbit(&h2d_reg, H2D_BL_RESET_ON_ERROR_SHIFT);
5217 		dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg);
5218 	}
5219 
5220 err:
5221 	return bcmerror;
5222 }
5223 
5224 static int
dhdsdio_dongle_host_chk_validation(dhd_bus_t * bus,hs_addrs_t * addr)5225 dhdsdio_dongle_host_chk_validation(dhd_bus_t *bus, hs_addrs_t *addr)
5226 {
5227 	int bcmerror = BCME_OK;
5228 	uint d2h_reg = 0x00000000;
5229 	uint h2d_reg = 0x00000000;
5230 
5231 	setbit(&h2d_reg, D2H_VALDN_DONE_SHIFT);
5232 	bcmerror = dhdsdio_dongle_host_handshake_spinwait(bus, addr->d2h,
5233 		D2H_VALDN_DONE_SHIFT, D2H_VALDN_DONE_TIMEOUT_MS);
5234 	if (!bcmerror) {
5235 
5236 		bcmerror = dhdsdio_handshake_msg_reg_read(bus, addr->d2h, &d2h_reg);
5237 		if (!bcmerror) {
5238 
5239 			if (isset(&d2h_reg, D2H_VALDN_RESULT_SHIFT)) {
5240 				DHD_ERROR(("%s: TRX img validation check successful\n",
5241 					__FUNCTION__));
5242 			} else {
5243 				DHD_ERROR(("%s: TRX img validation check failed\n", __FUNCTION__));
5244 				bcmerror = BCME_ERROR;
5245 			}
5246 		}
5247 	}
5248 
5249 	if (bcmerror) {
5250 		/* Host notification to bootloader to get reset on error
5251 		 * To avoid the race condition betweeen host and dongle
5252 		 */
5253 		dhdsdio_handshake_msg_reg_read(bus, addr->h2d, &h2d_reg);
5254 		setbit(&h2d_reg, H2D_BL_RESET_ON_ERROR_SHIFT);
5255 		dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg);
5256 	}
5257 
5258 	return bcmerror;
5259 }
5260 
5261 static int
dhdsdio_dongle_host_post_varswrite(dhd_bus_t * bus,hs_addrs_t * addr)5262 dhdsdio_dongle_host_post_varswrite(dhd_bus_t *bus, hs_addrs_t *addr)
5263 {
5264 	int bcmerror = BCME_OK;
5265 	uint h2d_reg = 0x00000000;
5266 
5267 	/* Set NVRAM done bit (Download done is already set) */
5268 	setbit(&h2d_reg, (H2D_DL_DONE_SHIFT));
5269 	setbit(&h2d_reg, (H2D_DL_NVRAM_DONE_SHIFT));
5270 	bcmerror = dhdsdio_handshake_msg_reg_write(bus, addr->h2d, &h2d_reg);
5271 
5272 	return bcmerror;
5273 }
5274 
5275 int
dhdsdio_dongle_host_pre_wd_reset_sequence(dhd_bus_t * bus)5276 dhdsdio_dongle_host_pre_wd_reset_sequence(dhd_bus_t *bus)
5277 {
5278 	uint h2d_reg = 0;
5279 	volatile void *regs = NULL;
5280 	int32 bcmerror = BCME_ERROR;
5281 
5282 	regs = (uint32 *)SDIO_FN1_MSG_H2D_REG0;
5283 	bcmerror = dhdsdio_handshake_msg_reg_write(bus, regs, &h2d_reg);
5284 
5285 	return bcmerror;
5286 }
5287 
5288 static int
dhdsdio_handshake_msg_reg_write(dhd_bus_t * bus,volatile void * addr,uint32 * buffer)5289 dhdsdio_handshake_msg_reg_write(dhd_bus_t *bus, volatile void *addr, uint32 *buffer)
5290 {
5291 	int bcmerror = BCME_OK;
5292 
5293 #ifndef HS_IN_TCM
5294 	BCM_REFERENCE(bcmerror);
5295 	bcmerror = dhdsdio_cfg_write_buffer(bus, buffer, (uint)(uintptr)addr);
5296 #endif // endif
5297 
5298 	return bcmerror;
5299 }
5300 
5301 static int
dhdsdio_handshake_msg_reg_read(dhd_bus_t * bus,volatile void * addr,uint32 * buffer)5302 dhdsdio_handshake_msg_reg_read(dhd_bus_t *bus, volatile void *addr, uint32 *buffer)
5303 {
5304 	int bcmerror = BCME_OK;
5305 
5306 #ifndef HS_IN_TCM
5307 	BCM_REFERENCE(bcmerror);
5308 	dhdsdio_cfg_read_buffer(bus, buffer, (uint)(uintptr)addr);
5309 #endif // endif
5310 
5311 	return bcmerror;
5312 }
5313 
5314 static int
dhdsdio_cfg_write_buffer(dhd_bus_t * bus,uint32 * buffer,uint offset)5315 dhdsdio_cfg_write_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset)
5316 {
5317 	int err = BCME_ERROR;
5318 
5319 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset, ((*buffer) >> 0)
5320 		 & CFG_WRITE_BYTE_MASK, &err);
5321 	if (!err) {
5322 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset+1, ((*buffer) >> 8)
5323 			& CFG_WRITE_BYTE_MASK, &err);
5324 	}
5325 	if (!err) {
5326 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset+2, ((*buffer) >> 16)
5327 			& CFG_WRITE_BYTE_MASK, &err);
5328 	}
5329 	if (!err) {
5330 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, offset+3, ((*buffer) >> 24)
5331 			& CFG_WRITE_BYTE_MASK, &err);
5332 	}
5333 
5334 	return err;
5335 }
5336 
5337 static int
dhdsdio_cfg_read_buffer(dhd_bus_t * bus,uint32 * buffer,uint offset)5338 dhdsdio_cfg_read_buffer(dhd_bus_t *bus, uint32 *buffer, uint offset)
5339 {
5340 	*buffer = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+0, NULL) << 0;
5341 	*buffer = *buffer | bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+1, NULL) << 8;
5342 	*buffer = *buffer | bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+2, NULL) << 16;
5343 	*buffer = *buffer | bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, offset+3, NULL) << 24;
5344 
5345 	return *buffer;
5346 }
5347 
5348 static int
dhdsdio_dongle_host_handshake_spinwait(dhd_bus_t * bus,volatile void * addr,uint32 bitshift,uint32 us)5349 dhdsdio_dongle_host_handshake_spinwait(dhd_bus_t *bus, volatile void *addr,
5350 	uint32 bitshift, uint32 us)
5351 {
5352 	uint32 countdown_;
5353 	uint32 read_addr = 0;
5354 	int bcmerror = BCME_OK;
5355 
5356 	for (countdown_ = (us) + (HS_POLL_PERIOD_MS - 1U); countdown_ >= HS_POLL_PERIOD_MS;
5357 		countdown_ -= HS_POLL_PERIOD_MS) {
5358 
5359 		bcmerror = dhdsdio_handshake_msg_reg_read(bus, addr, &read_addr);
5360 		if (bcmerror) {
5361 			bcmerror = BCME_ERROR;
5362 			break;
5363 		}
5364 
5365 		if (isset(&read_addr, bitshift)) {
5366 			bcmerror = BCME_OK;
5367 			break;
5368 		}
5369 
5370 		OSL_SLEEP(HS_POLL_PERIOD_MS);
5371 	}
5372 
5373 	if (countdown_ <= HS_POLL_PERIOD_MS) {
5374 		bcmerror = BCME_NOTREADY;
5375 	}
5376 
5377 	return bcmerror;
5378 }
5379 
5380 int
dhd_bus_iovar_op(dhd_pub_t * dhdp,const char * name,void * params,int plen,void * arg,int len,bool set)5381 dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
5382                  void *params, int plen, void *arg, int len, bool set)
5383 {
5384 	dhd_bus_t *bus = dhdp->bus;
5385 	const bcm_iovar_t *vi = NULL;
5386 	int bcmerror = 0;
5387 	int val_size;
5388 	uint32 actionid;
5389 
5390 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5391 
5392 	ASSERT(name);
5393 	ASSERT(len >= 0);
5394 
5395 	/* Get MUST have return space */
5396 	ASSERT(set || (arg && len));
5397 
5398 	/* Set does NOT take qualifiers */
5399 	ASSERT(!set || (!params && !plen));
5400 
5401 	/* Look up var locally; if not found pass to host driver */
5402 	if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
5403 		dhd_os_sdlock(bus->dhd);
5404 
5405 		BUS_WAKE(bus);
5406 
5407 		/* Turn on clock in case SD command needs backplane */
5408 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5409 
5410 		bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
5411 
5412 		/* Check for bus configuration changes of interest */
5413 
5414 		/* If it was divisor change, read the new one */
5415 		if (set && strcmp(name, "sd_divisor") == 0) {
5416 			if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
5417 			                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
5418 				bus->sd_divisor = -1;
5419 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
5420 			} else {
5421 				DHD_INFO(("%s: noted %s update, value now %d\n",
5422 				          __FUNCTION__, name, bus->sd_divisor));
5423 			}
5424 		}
5425 		/* If it was a mode change, read the new one */
5426 		if (set && strcmp(name, "sd_mode") == 0) {
5427 			if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
5428 			                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
5429 				bus->sd_mode = -1;
5430 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
5431 			} else {
5432 				DHD_INFO(("%s: noted %s update, value now %d\n",
5433 				          __FUNCTION__, name, bus->sd_mode));
5434 			}
5435 		}
5436 		/* Similar check for blocksize change */
5437 		if (set && strcmp(name, "sd_blocksize") == 0) {
5438 			int32 fnum = 2;
5439 			if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
5440 			                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
5441 				bus->blocksize = 0;
5442 				DHD_ERROR(("%s: fail on fn %d %s get\n",
5443 					__FUNCTION__, fnum, "sd_blocksize"));
5444 			} else {
5445 				DHD_INFO(("%s: noted fn %d %s update, value now %d\n",
5446 					__FUNCTION__, fnum, "sd_blocksize", bus->blocksize));
5447 
5448 				dhdsdio_tune_fifoparam(bus);
5449 			}
5450 		}
5451 		bus->roundup = MIN(max_roundup, bus->blocksize);
5452 
5453 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
5454 			NO_OTHER_ACTIVE_BUS_USER(bus)) {
5455 			bus->activity = FALSE;
5456 			dhdsdio_bussleep(bus, TRUE);
5457 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
5458 		}
5459 
5460 		dhd_os_sdunlock(bus->dhd);
5461 		goto exit;
5462 	}
5463 
5464 	DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
5465 	         name, (set ? "set" : "get"), len, plen));
5466 
5467 	/* set up 'params' pointer in case this is a set command so that
5468 	 * the convenience int and bool code can be common to set and get
5469 	 */
5470 	if (params == NULL) {
5471 		params = arg;
5472 		plen = len;
5473 	}
5474 
5475 	if (vi->type == IOVT_VOID)
5476 		val_size = 0;
5477 	else if (vi->type == IOVT_BUFFER)
5478 		val_size = len;
5479 	else
5480 		/* all other types are integer sized */
5481 		val_size = sizeof(int);
5482 
5483 	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
5484 	bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
5485 
5486 exit:
5487 	return bcmerror;
5488 }
5489 
5490 void
dhd_bus_stop(struct dhd_bus * bus,bool enforce_mutex)5491 dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
5492 {
5493 	osl_t *osh;
5494 	uint32 local_hostintmask;
5495 	uint8 saveclk;
5496 	uint retries;
5497 	int err;
5498 	bool wlfc_enabled = FALSE;
5499 	unsigned long flags;
5500 
5501 	if (!bus->dhd)
5502 		return;
5503 
5504 	osh = bus->dhd->osh;
5505 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5506 
5507 	bcmsdh_waitlockfree(bus->sdh);
5508 
5509 	if (enforce_mutex)
5510 		dhd_os_sdlock(bus->dhd);
5511 
5512 	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) {
5513 		/* if Firmware already hangs disbale any interrupt */
5514 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
5515 		bus->dhd->busstate = DHD_BUS_DOWN;
5516 		bus->hostintmask = 0;
5517 		bcmsdh_intr_disable(bus->sdh);
5518 	} else {
5519 
5520 		BUS_WAKE(bus);
5521 
5522 		if (KSO_ENAB(bus)) {
5523 
5524 		/* Enable clock for device interrupts */
5525 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5526 
5527 		/* Disable and clear interrupts at the chip level also */
5528 		W_SDREG(0, &bus->regs->hostintmask, retries);
5529 		local_hostintmask = bus->hostintmask;
5530 		bus->hostintmask = 0;
5531 
5532 		/* Change our idea of bus state */
5533 		DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
5534 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
5535 		bus->dhd->busstate = DHD_BUS_DOWN;
5536 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
5537 
5538 		/* Force clocks on backplane to be sure F2 interrupt propagates */
5539 		saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
5540 		if (!err) {
5541 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5542 			                 (saveclk | SBSDIO_FORCE_HT), &err);
5543 		}
5544 		if (err) {
5545 			DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
5546 			            __FUNCTION__, err));
5547 		}
5548 
5549 		/* Turn off the bus (F2), free any pending packets */
5550 		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
5551 		bcmsdh_intr_disable(bus->sdh);
5552 #ifndef BCMSPI
5553 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
5554 #endif /* !BCMSPI */
5555 
5556 		/* Clear any pending interrupts now that F2 is disabled */
5557 		W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
5558 		}
5559 
5560 		/* Turn off the backplane clock (only) */
5561 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
5562 	}
5563 
5564 #ifdef PROP_TXSTATUS
5565 	wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED);
5566 #endif // endif
5567 	if (!wlfc_enabled) {
5568 #ifdef DHDTCPACK_SUPPRESS
5569 		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
5570 		 * when there is a newly coming packet from network stack.
5571 		 */
5572 		dhd_tcpack_info_tbl_clean(bus->dhd);
5573 #endif /* DHDTCPACK_SUPPRESS */
5574 		dhd_os_sdlock_txq(bus->dhd);
5575 		/* Clear the data packet queues */
5576 		pktq_flush(osh, &bus->txq, TRUE);
5577 		dhd_os_sdunlock_txq(bus->dhd);
5578 	}
5579 
5580 	/* Clear any held glomming stuff */
5581 	if (bus->glomd)
5582 		PKTFREE(osh, bus->glomd, FALSE);
5583 
5584 	if (bus->glom)
5585 		PKTFREE(osh, bus->glom, FALSE);
5586 
5587 	bus->glom = bus->glomd = NULL;
5588 
5589 	/* Clear rx control and wake any waiters */
5590 	bus->rxlen = 0;
5591 	dhd_os_ioctl_resp_wake(bus->dhd);
5592 
5593 	/* Reset some F2 state stuff */
5594 	bus->rxskip = FALSE;
5595 	bus->tx_seq = bus->rx_seq = 0;
5596 
5597 	bus->tx_max = 4;
5598 
5599 	if (enforce_mutex)
5600 		dhd_os_sdunlock(bus->dhd);
5601 }
5602 
5603 #if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD)
5604 extern uint sd_txglom;
5605 #endif // endif
5606 void
dhd_txglom_enable(dhd_pub_t * dhdp,bool enable)5607 dhd_txglom_enable(dhd_pub_t *dhdp, bool enable)
5608 {
5609 	/* can't enable host txglom by default, some platforms have no
5610 	 * (or crappy) ADMA support and txglom will cause kernel assertions (e.g.
5611 	 * panda board)
5612 	 */
5613 	dhd_bus_t *bus = dhdp->bus;
5614 #ifdef BCMSDIOH_TXGLOM
5615 	uint32 rxglom;
5616 	int32 ret;
5617 
5618 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5619 
5620 #ifdef BCMSDIOH_STD
5621 	if (enable)
5622 		enable = sd_txglom;
5623 #endif /* BCMSDIOH_STD */
5624 
5625 	if (enable) {
5626 		rxglom = 1;
5627 		ret = dhd_iovar(dhdp, 0, "bus:rxglom", (char *)&rxglom, sizeof(rxglom), NULL, 0,
5628 				TRUE);
5629 		if (ret >= 0)
5630 			bus->txglom_enable = TRUE;
5631 		else {
5632 #ifdef BCMSDIOH_STD
5633 			sd_txglom = 0;
5634 #endif /* BCMSDIOH_STD */
5635 			bus->txglom_enable = FALSE;
5636 		}
5637 	} else
5638 #endif /* BCMSDIOH_TXGLOM */
5639 		bus->txglom_enable = FALSE;
5640 }
5641 
5642 int
dhd_bus_init(dhd_pub_t * dhdp,bool enforce_mutex)5643 dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
5644 {
5645 	dhd_bus_t *bus = dhdp->bus;
5646 	dhd_timeout_t tmo;
5647 	uint retries = 0;
5648 	uint8 ready, enable;
5649 	int err, ret = 0;
5650 #ifdef BCMSPI
5651 	uint32 dstatus = 0;	/* gSPI device-status bits */
5652 #else /* BCMSPI */
5653 	uint8 saveclk;
5654 #endif /* BCMSPI */
5655 
5656 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5657 
5658 	ASSERT(bus->dhd);
5659 	if (!bus->dhd)
5660 		return 0;
5661 
5662 #if (0)
5663 	if ((ret = dhdsdio_readshared_console(bus)) >= 0) {
5664 		DHD_ERROR(("initialized console"));
5665 #ifdef DHD_DEBUG
5666 		if ((ret = dhdsdio_readconsole(bus)) < 0) {
5667 			DHD_ERROR(("%s: Console buffer read failed\n",
5668 				__FUNCTION__));
5669 		}
5670 #endif /* DHD_DEBUG */
5671 	}
5672 #endif
5673 
5674 	if (enforce_mutex)
5675 		dhd_os_sdlock(bus->dhd);
5676 
5677 	/* Make sure backplane clock is on, needed to generate F2 interrupt */
5678 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5679 	if (bus->clkstate != CLK_AVAIL) {
5680 		DHD_ERROR(("%s: clock state is wrong. state = %d\n", __FUNCTION__, bus->clkstate));
5681 		ret = -1;
5682 		goto exit;
5683 	}
5684 
5685 #ifdef BCMSPI
5686 	/* fake "ready" for spi, wake-wlan would have already enabled F1 and F2 */
5687 	ready = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
5688 	enable = 0;
5689 
5690 	/* Give the dongle some time to do its thing and set IOR2 */
5691 	dhd_timeout_start(&tmo, WAIT_F2RXFIFORDY * WAIT_F2RXFIFORDY_DELAY * 1000);
5692 	while (!enable && !dhd_timeout_expired(&tmo)) {
5693 		dstatus = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL);
5694 		if (dstatus & STATUS_F2_RX_READY)
5695 			enable = TRUE;
5696 	}
5697 
5698 	if (enable) {
5699 		DHD_ERROR(("Took %u usec before dongle is ready\n", tmo.elapsed));
5700 		enable = ready;
5701 	} else {
5702 		DHD_ERROR(("dstatus when timed out on f2-fifo not ready = 0x%x\n", dstatus));
5703 		DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed));
5704 		ret = -1;
5705 		goto exit;
5706 	}
5707 
5708 #else /* !BCMSPI */
5709 	/* Force clocks on backplane to be sure F2 interrupt propagates */
5710 	saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
5711 
5712 	if (!err) {
5713 		if (bus->sih->chip == BCM43012_CHIP_ID ||
5714 		    bus->sih->chip == CYW55500_CHIP_ID ||
5715 		    bus->sih->chip == CYW55560_CHIP_ID) {
5716 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5717 				(saveclk | SBSDIO_HT_AVAIL_REQ), &err);
5718 		} else {
5719 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5720 				(saveclk | SBSDIO_FORCE_HT), &err);
5721 		}
5722 	}
5723 
5724 	if (err) {
5725 		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
5726 		ret = -1;
5727 		goto exit;
5728 	}
5729 
5730 	/* Enable function 2 (frame transfers) */
5731 	W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
5732 	        &bus->regs->tosbmailboxdata, retries);
5733 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
5734 
5735 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
5736 
5737 	/* Give the dongle some time to do its thing and set IOR2 */
5738 	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
5739 
5740 	ready = 0;
5741 	while (ready != enable && !dhd_timeout_expired(&tmo))
5742 	        ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
5743 
5744 #endif /* !BCMSPI */
5745 
5746 	DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
5747 	          __FUNCTION__, enable, ready, tmo.elapsed));
5748 
5749 	/* If F2 successfully enabled, set core and enable interrupts */
5750 	if (ready == enable) {
5751 		/* Make sure we're talking to the core. */
5752 #ifdef BCMSDIOLITE
5753 		bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0);
5754 		ASSERT(bus->regs != NULL);
5755 #else
5756 		if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
5757 			bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5758 		ASSERT(bus->regs != NULL);
5759 #endif // endif
5760 		/* Set up the interrupt mask and enable interrupts */
5761 		bus->hostintmask = HOSTINTMASK;
5762 		/* corerev 4 could use the newer interrupt logic to detect the frames */
5763 #ifndef BCMSPI
5764 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) &&
5765 			(bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) {
5766 			bus->hostintmask &= ~I_HMB_FRAME_IND;
5767 			bus->hostintmask |= I_XMTDATA_AVAIL;
5768 		}
5769 #endif /* BCMSPI */
5770 		/* Tell the device which interrupts are of our interest */
5771 		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
5772 
5773 		if (bus->sih->buscorerev < 15) {
5774 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
5775 				(uint8)watermark, &err);
5776 		}
5777 
5778 		/* Set bus state according to enable result */
5779 		dhdp->busstate = DHD_BUS_DATA;
5780 
5781 		/* Need to set fn2 block size to match fn1 block size.
5782 		 * Requests to fn2 go thru fn1. *
5783 		 * faltwig has this code contitioned with #if !BCMSPI_ANDROID.
5784 		 * It would be cleaner to use the ->sdh->block_sz[fno] instead of
5785 		 * 64, but this layer has no access to sdh types.
5786 		 */
5787 
5788 		/* bcmsdh_intr_unmask(bus->sdh); */
5789 
5790 		bus->intdis = FALSE;
5791 		if (bus->intr) {
5792 			DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
5793 #ifndef BCMSPI_ANDROID
5794 			bcmsdh_intr_enable(bus->sdh);
5795 #endif /* !BCMSPI_ANDROID */
5796 		} else {
5797 			DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
5798 			bcmsdh_intr_disable(bus->sdh);
5799 		}
5800 
5801 	}
5802 
5803 #ifndef BCMSPI
5804 
5805 	else {
5806 		/* Disable F2 again */
5807 		enable = SDIO_FUNC_ENABLE_1;
5808 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
5809 	}
5810 
5811 #ifdef DHD_FW_COREDUMP
5812 	if (bus->dhd->memdump_enabled && tcm_dump_enable) {
5813 		DHD_ERROR(("%s : Dumping the RAM", __FUNCTION__));
5814 		dhd_bus_mem_dump(bus->dhd);
5815 	}
5816 #endif /* DHD_FW_COREDUMP */
5817 
5818 	if (dhdsdio_sr_cap(bus)) {
5819 		dhdsdio_sr_init(bus);
5820 		/* Masking the chip active interrupt  permanantly */
5821 		bus->hostintmask &= ~I_CHIPACTIVE;
5822 		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
5823 		DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
5824 		__FUNCTION__, bus->hostintmask));
5825 	} else {
5826 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
5827 			SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
5828 	}
5829 #else /* BCMSPI */
5830 	{
5831 		if (dhdsdio_sr_cap(bus)) {
5832 			dhdsdio_sr_init(bus);
5833 			/* Masking the chip active interrupt  permanantly */
5834 			bus->hostintmask &= ~I_CHIPACTIVE;
5835 			W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
5836 			DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
5837 				__FUNCTION__, bus->hostintmask));
5838 		}
5839 	}
5840 #endif /* !BCMSPI */
5841 
5842 	/* If we didn't come up, turn off backplane clock */
5843 	if (dhdp->busstate != DHD_BUS_DATA)
5844 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
5845 
5846 exit:
5847 	if (enforce_mutex)
5848 		dhd_os_sdunlock(bus->dhd);
5849 
5850 	return ret;
5851 }
5852 
5853 static void
dhdsdio_rxfail(dhd_bus_t * bus,bool abort,bool rtx)5854 dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
5855 {
5856 	bcmsdh_info_t *sdh = bus->sdh;
5857 	sdpcmd_regs_t *regs = bus->regs;
5858 	uint retries = 0;
5859 	uint16 lastrbc;
5860 	uint8 hi, lo;
5861 	int err;
5862 
5863 	DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
5864 	           (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
5865 
5866 	if (!KSO_ENAB(bus)) {
5867 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
5868 		return;
5869 	}
5870 
5871 	if (abort) {
5872 		bcmsdh_abort(sdh, SDIO_FUNC_2);
5873 	}
5874 
5875 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
5876 	if (err) {
5877 		DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__));
5878 		goto fail;
5879 	}
5880 	bus->f1regdata++;
5881 
5882 	/* Wait until the packet has been flushed (device/FIFO stable) */
5883 	for (lastrbc = retries = 0xffff; retries > 0; retries--) {
5884 		hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
5885 		lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, &err);
5886 		if (err) {
5887 			DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__));
5888 			goto fail;
5889 		}
5890 
5891 		bus->f1regdata += 2;
5892 
5893 		if ((hi == 0) && (lo == 0))
5894 			break;
5895 
5896 		if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
5897 			DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
5898 			           __FUNCTION__, lastrbc, ((hi << 8) + lo)));
5899 		}
5900 		lastrbc = (hi << 8) + lo;
5901 	}
5902 
5903 	if (!retries) {
5904 		DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
5905 	} else {
5906 		DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
5907 	}
5908 
5909 	if (rtx) {
5910 		bus->rxrtx++;
5911 		W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
5912 		bus->f1regdata++;
5913 		if (retries <= retry_limit) {
5914 			bus->rxskip = TRUE;
5915 		}
5916 	}
5917 
5918 	/* Clear partial in any case */
5919 	bus->nextlen = 0;
5920 
5921 fail:
5922 	/* If we can't reach the device, signal failure */
5923 	if (err || bcmsdh_regfail(sdh)) {
5924 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
5925 		bus->dhd->busstate = DHD_BUS_DOWN;
5926 	}
5927 }
5928 
5929 static void
dhdsdio_read_control(dhd_bus_t * bus,uint8 * hdr,uint len,uint doff)5930 dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
5931 {
5932 	bcmsdh_info_t *sdh = bus->sdh;
5933 	uint rdlen, pad;
5934 
5935 	int sdret;
5936 
5937 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5938 
5939 	/* Control data already received in aligned rxctl */
5940 	if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
5941 		goto gotpkt;
5942 
5943 	ASSERT(bus->rxbuf);
5944 	/* Set rxctl for frame (w/optional alignment) */
5945 	bus->rxctl = bus->rxbuf;
5946 	if (dhd_alignctl) {
5947 		bus->rxctl += firstread;
5948 		if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
5949 			bus->rxctl += (DHD_SDALIGN - pad);
5950 		bus->rxctl -= firstread;
5951 	}
5952 	ASSERT(bus->rxctl >= bus->rxbuf);
5953 
5954 	/* Copy the already-read portion over */
5955 	bcopy(hdr, bus->rxctl, firstread);
5956 	if (len <= firstread)
5957 		goto gotpkt;
5958 
5959 	/* Copy the full data pkt in gSPI case and process ioctl. */
5960 	if (bus->bus == SPI_BUS) {
5961 		bcopy(hdr, bus->rxctl, len);
5962 		goto gotpkt;
5963 	}
5964 
5965 	/* Raise rdlen to next SDIO block to avoid tail command */
5966 	rdlen = len - firstread;
5967 	if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
5968 		pad = bus->blocksize - (rdlen % bus->blocksize);
5969 		if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
5970 		    ((len + pad) < bus->dhd->maxctl))
5971 			rdlen += pad;
5972 	} else if (rdlen % DHD_SDALIGN) {
5973 		rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
5974 	}
5975 
5976 	/* Satisfy length-alignment requirements */
5977 	if (forcealign && (rdlen & (ALIGNMENT - 1)))
5978 		rdlen = ROUNDUP(rdlen, ALIGNMENT);
5979 
5980 	/* Drop if the read is too big or it exceeds our maximum */
5981 	if ((rdlen + firstread) > bus->dhd->maxctl) {
5982 		DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
5983 		           __FUNCTION__, rdlen, bus->dhd->maxctl));
5984 		bus->dhd->rx_errors++;
5985 		dhdsdio_rxfail(bus, FALSE, FALSE);
5986 		goto done;
5987 	}
5988 
5989 	if ((len - doff) > bus->dhd->maxctl) {
5990 		DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
5991 		           __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
5992 		bus->dhd->rx_errors++; bus->rx_toolong++;
5993 		dhdsdio_rxfail(bus, FALSE, FALSE);
5994 		goto done;
5995 	}
5996 
5997 	/* Read remainder of frame body into the rxctl buffer */
5998 	sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
5999 	                            (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
6000 	bus->f2rxdata++;
6001 	ASSERT(sdret != BCME_PENDING);
6002 
6003 	/* Control frame failures need retransmission */
6004 	if (sdret < 0) {
6005 		DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
6006 		bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
6007 		dhdsdio_rxfail(bus, TRUE, TRUE);
6008 		goto done;
6009 	}
6010 
6011 gotpkt:
6012 
6013 #ifdef DHD_DEBUG
6014 	if (DHD_BYTES_ON() && DHD_CTL_ON()) {
6015 		prhex("RxCtrl", bus->rxctl, len);
6016 	}
6017 #endif // endif
6018 
6019 	/* Point to valid data and indicate its length */
6020 	bus->rxctl += doff;
6021 	bus->rxlen = len - doff;
6022 
6023 done:
6024 	/* Awake any waiters */
6025 	dhd_os_ioctl_resp_wake(bus->dhd);
6026 }
6027 int
6028 dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
6029 	void **pkt, uint32 *pkt_count);
6030 
6031 static uint8
dhdsdio_rxglom(dhd_bus_t * bus,uint8 rxseq)6032 dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
6033 {
6034 	uint16 dlen, totlen;
6035 	uint8 *dptr, num = 0;
6036 
6037 	uint16 sublen, check;
6038 	void *pfirst, *plast, *pnext;
6039 	void * list_tail[DHD_MAX_IFS] = { NULL };
6040 	void * list_head[DHD_MAX_IFS] = { NULL };
6041 	uint8 idx;
6042 	osl_t *osh = bus->dhd->osh;
6043 
6044 	int errcode;
6045 	uint8 chan, seq, doff, sfdoff;
6046 	uint8 txmax;
6047 	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
6048 	uint reorder_info_len;
6049 
6050 	int ifidx = 0;
6051 	bool usechain = bus->use_rxchain;
6052 
6053 	/* If packets, issue read(s) and send up packet chain */
6054 	/* Return sequence numbers consumed? */
6055 
6056 	DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
6057 
6058 	/* If there's a descriptor, generate the packet chain */
6059 	if (bus->glomd) {
6060 		dhd_os_sdlock_rxq(bus->dhd);
6061 
6062 		pfirst = plast = pnext = NULL;
6063 		dlen = (uint16)PKTLEN(osh, bus->glomd);
6064 		dptr = PKTDATA(osh, bus->glomd);
6065 		if (!dlen || (dlen & 1)) {
6066 			DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
6067 			           __FUNCTION__, dlen));
6068 			dlen = 0;
6069 		}
6070 
6071 		for (totlen = num = 0; dlen; num++) {
6072 			/* Get (and move past) next length */
6073 			sublen = ltoh16_ua(dptr);
6074 			dlen -= sizeof(uint16);
6075 			dptr += sizeof(uint16);
6076 			if ((sublen < SDPCM_HDRLEN) ||
6077 			    ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
6078 				DHD_ERROR(("%s: descriptor len %d bad: %d\n",
6079 				           __FUNCTION__, num, sublen));
6080 				pnext = NULL;
6081 				break;
6082 			}
6083 			if (sublen % DHD_SDALIGN) {
6084 				DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
6085 				           __FUNCTION__, sublen, DHD_SDALIGN));
6086 				usechain = FALSE;
6087 			}
6088 			totlen += sublen;
6089 
6090 			/* For last frame, adjust read len so total is a block multiple */
6091 			if (!dlen) {
6092 				sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
6093 				totlen = ROUNDUP(totlen, bus->blocksize);
6094 			}
6095 
6096 			/* Allocate/chain packet for next subframe */
6097 			if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
6098 				DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
6099 				           __FUNCTION__, num, sublen));
6100 				break;
6101 			}
6102 			ASSERT(!PKTLINK(pnext));
6103 			if (!pfirst) {
6104 				ASSERT(!plast);
6105 				pfirst = plast = pnext;
6106 			} else {
6107 				ASSERT(plast);
6108 				PKTSETNEXT(osh, plast, pnext);
6109 				plast = pnext;
6110 			}
6111 
6112 			/* Adhere to start alignment requirements */
6113 			PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
6114 		}
6115 
6116 		/* If all allocations succeeded, save packet chain in bus structure */
6117 		if (pnext) {
6118 			DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
6119 			          __FUNCTION__, totlen, num));
6120 			if (DHD_GLOM_ON() && bus->nextlen) {
6121 				if (totlen != bus->nextlen) {
6122 					DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
6123 					          "rxseq %d\n", __FUNCTION__, bus->nextlen,
6124 					          totlen, rxseq));
6125 				}
6126 			}
6127 			bus->glom = pfirst;
6128 			pfirst = pnext = NULL;
6129 		} else {
6130 			if (pfirst)
6131 				PKTFREE(osh, pfirst, FALSE);
6132 			bus->glom = NULL;
6133 			num = 0;
6134 		}
6135 
6136 		/* Done with descriptor packet */
6137 		PKTFREE(osh, bus->glomd, FALSE);
6138 		bus->glomd = NULL;
6139 		bus->nextlen = 0;
6140 
6141 		dhd_os_sdunlock_rxq(bus->dhd);
6142 	}
6143 
6144 	/* Ok -- either we just generated a packet chain, or had one from before */
6145 	if (bus->glom) {
6146 		if (DHD_GLOM_ON()) {
6147 			DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
6148 			for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
6149 				DHD_GLOM(("    %p: %p len 0x%04x (%d)\n",
6150 				          pnext, (uint8*)PKTDATA(osh, pnext),
6151 				          PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
6152 			}
6153 		}
6154 
6155 		pfirst = bus->glom;
6156 		dlen = (uint16)pkttotlen(osh, pfirst);
6157 
6158 		/* Do an SDIO read for the superframe.  Configurable iovar to
6159 		 * read directly into the chained packet, or allocate a large
6160 		 * packet and and copy into the chain.
6161 		 */
6162 		if (usechain) {
6163 			errcode = dhd_bcmsdh_recv_buf(bus,
6164 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
6165 			                              F2SYNC, (uint8*)PKTDATA(osh, pfirst),
6166 			                              dlen, pfirst, NULL, NULL);
6167 		} else if (bus->dataptr) {
6168 			errcode = dhd_bcmsdh_recv_buf(bus,
6169 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
6170 			                              F2SYNC, bus->dataptr,
6171 			                              dlen, NULL, NULL, NULL);
6172 			sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
6173 			if (sublen != dlen) {
6174 				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
6175 				           __FUNCTION__, dlen, sublen));
6176 				errcode = -1;
6177 			}
6178 			pnext = NULL;
6179 			BCM_REFERENCE(pnext);
6180 		} else {
6181 			DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
6182 			errcode = -1;
6183 		}
6184 		bus->f2rxdata++;
6185 		ASSERT(errcode != BCME_PENDING);
6186 
6187 		/* On failure, kill the superframe, allow a couple retries */
6188 		if (errcode < 0) {
6189 			DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
6190 			           __FUNCTION__, dlen, errcode));
6191 			bus->dhd->rx_errors++;
6192 
6193 			if (bus->glomerr++ < 3) {
6194 				dhdsdio_rxfail(bus, TRUE, TRUE);
6195 			} else {
6196 				bus->glomerr = 0;
6197 				dhdsdio_rxfail(bus, TRUE, FALSE);
6198 				dhd_os_sdlock_rxq(bus->dhd);
6199 				PKTFREE(osh, bus->glom, FALSE);
6200 				dhd_os_sdunlock_rxq(bus->dhd);
6201 				bus->rxglomfail++;
6202 				bus->glom = NULL;
6203 			}
6204 			return 0;
6205 		}
6206 
6207 #ifdef DHD_DEBUG
6208 		if (DHD_GLOM_ON()) {
6209 			prhex("SUPERFRAME", PKTDATA(osh, pfirst),
6210 			      MIN(PKTLEN(osh, pfirst), 48));
6211 		}
6212 #endif // endif
6213 
6214 		/* Validate the superframe header */
6215 		dptr = (uint8 *)PKTDATA(osh, pfirst);
6216 		sublen = ltoh16_ua(dptr);
6217 		check = ltoh16_ua(dptr + sizeof(uint16));
6218 
6219 		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6220 		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
6221 		bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
6222 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
6223 			DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
6224 			          __FUNCTION__, bus->nextlen, seq));
6225 			bus->nextlen = 0;
6226 		}
6227 		doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6228 		txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6229 
6230 		errcode = 0;
6231 		if ((uint16)~(sublen^check)) {
6232 			DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
6233 			           __FUNCTION__, sublen, check));
6234 			errcode = -1;
6235 		} else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
6236 			DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
6237 			           __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
6238 			errcode = -1;
6239 		} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
6240 			DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
6241 			           SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
6242 			errcode = -1;
6243 		} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
6244 			DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
6245 			errcode = -1;
6246 		} else if ((doff < SDPCM_HDRLEN) ||
6247 		           (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
6248 			DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
6249 				__FUNCTION__, doff, sublen, PKTLEN(osh, pfirst),
6250 				SDPCM_HDRLEN));
6251 			errcode = -1;
6252 		}
6253 
6254 		/* Check sequence number of superframe SW header */
6255 		if (rxseq != seq) {
6256 			DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
6257 			          __FUNCTION__, seq, rxseq));
6258 			bus->rx_badseq++;
6259 			rxseq = seq;
6260 		}
6261 
6262 		/* Check window for sanity */
6263 		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
6264 			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
6265 			           __FUNCTION__, txmax, bus->tx_seq));
6266 			txmax = bus->tx_max;
6267 		}
6268 		bus->tx_max = txmax;
6269 
6270 		/* Remove superframe header, remember offset */
6271 		PKTPULL(osh, pfirst, doff);
6272 		sfdoff = doff;
6273 
6274 		/* Validate all the subframe headers */
6275 		for (num = 0, pnext = pfirst; pnext && !errcode;
6276 		     num++, pnext = PKTNEXT(osh, pnext)) {
6277 			dptr = (uint8 *)PKTDATA(osh, pnext);
6278 			dlen = (uint16)PKTLEN(osh, pnext);
6279 			sublen = ltoh16_ua(dptr);
6280 			check = ltoh16_ua(dptr + sizeof(uint16));
6281 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6282 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6283 #ifdef DHD_DEBUG
6284 			if (DHD_GLOM_ON()) {
6285 				prhex("subframe", dptr, 32);
6286 			}
6287 #endif // endif
6288 
6289 			if ((uint16)~(sublen^check)) {
6290 				DHD_ERROR(("%s (subframe %d): HW hdr error: "
6291 				           "len/check 0x%04x/0x%04x\n",
6292 				           __FUNCTION__, num, sublen, check));
6293 				errcode = -1;
6294 			} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
6295 				DHD_ERROR(("%s (subframe %d): length mismatch: "
6296 				           "len 0x%04x, expect 0x%04x\n",
6297 				           __FUNCTION__, num, sublen, dlen));
6298 				errcode = -1;
6299 			} else if ((chan != SDPCM_DATA_CHANNEL) &&
6300 			           (chan != SDPCM_EVENT_CHANNEL)) {
6301 				DHD_ERROR(("%s (subframe %d): bad channel %d\n",
6302 				           __FUNCTION__, num, chan));
6303 				errcode = -1;
6304 			} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
6305 				DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
6306 				           __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
6307 				errcode = -1;
6308 			}
6309 		}
6310 
6311 		if (errcode) {
6312 			/* Terminate frame on error, request a couple retries */
6313 			if (bus->glomerr++ < 3) {
6314 				/* Restore superframe header space */
6315 				PKTPUSH(osh, pfirst, sfdoff);
6316 				dhdsdio_rxfail(bus, TRUE, TRUE);
6317 			} else {
6318 				bus->glomerr = 0;
6319 				dhdsdio_rxfail(bus, TRUE, FALSE);
6320 				dhd_os_sdlock_rxq(bus->dhd);
6321 				PKTFREE(osh, bus->glom, FALSE);
6322 				dhd_os_sdunlock_rxq(bus->dhd);
6323 				bus->rxglomfail++;
6324 				bus->glom = NULL;
6325 			}
6326 			bus->nextlen = 0;
6327 			return 0;
6328 		}
6329 
6330 		/* Basic SD framing looks ok - process each packet (header) */
6331 		bus->glom = NULL;
6332 		plast = NULL;
6333 
6334 		dhd_os_sdlock_rxq(bus->dhd);
6335 		for (num = 0; pfirst; rxseq++, pfirst = pnext) {
6336 			pnext = PKTNEXT(osh, pfirst);
6337 			PKTSETNEXT(osh, pfirst, NULL);
6338 
6339 			dptr = (uint8 *)PKTDATA(osh, pfirst);
6340 			sublen = ltoh16_ua(dptr);
6341 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6342 			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
6343 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6344 
6345 			DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
6346 			          __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
6347 			          PKTLEN(osh, pfirst), sublen, chan, seq));
6348 
6349 			ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
6350 
6351 			if (rxseq != seq) {
6352 				DHD_GLOM(("%s: rx_seq %d, expected %d\n",
6353 				          __FUNCTION__, seq, rxseq));
6354 				bus->rx_badseq++;
6355 				rxseq = seq;
6356 			}
6357 
6358 #ifdef DHD_DEBUG
6359 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
6360 				prhex("Rx Subframe Data", dptr, dlen);
6361 			}
6362 #endif // endif
6363 
6364 			PKTSETLEN(osh, pfirst, sublen);
6365 			PKTPULL(osh, pfirst, doff);
6366 
6367 			reorder_info_len = sizeof(reorder_info_buf);
6368 
6369 			if (PKTLEN(osh, pfirst) == 0) {
6370 				PKTFREE(bus->dhd->osh, pfirst, FALSE);
6371 				continue;
6372 			} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf,
6373 				&reorder_info_len) != 0) {
6374 				DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
6375 				bus->dhd->rx_errors++;
6376 				PKTFREE(osh, pfirst, FALSE);
6377 				continue;
6378 			}
6379 			if (reorder_info_len) {
6380 				uint32 free_buf_count;
6381 				void *ppfirst;
6382 
6383 				ppfirst = pfirst;
6384 				/* Reordering info from the firmware */
6385 				dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf,
6386 					reorder_info_len, &ppfirst, &free_buf_count);
6387 
6388 				if (free_buf_count == 0) {
6389 					continue;
6390 				} else {
6391 					void *temp;
6392 
6393 					/*  go to the end of the chain and attach the pnext there */
6394 					temp = ppfirst;
6395 					while (PKTNEXT(osh, temp) != NULL) {
6396 						temp = PKTNEXT(osh, temp);
6397 					}
6398 					pfirst = temp;
6399 					if (list_tail[ifidx] == NULL)
6400 						list_head[ifidx] = ppfirst;
6401 					else
6402 						PKTSETNEXT(osh, list_tail[ifidx], ppfirst);
6403 					list_tail[ifidx] = pfirst;
6404 				}
6405 
6406 				num += (uint8)free_buf_count;
6407 			} else {
6408 				/* this packet will go up, link back into chain and count it */
6409 
6410 				if (list_tail[ifidx] == NULL) {
6411 					list_head[ifidx] = list_tail[ifidx] = pfirst;
6412 				} else {
6413 					PKTSETNEXT(osh, list_tail[ifidx], pfirst);
6414 					list_tail[ifidx] = pfirst;
6415 				}
6416 				num++;
6417 			}
6418 #ifdef DHD_DEBUG
6419 			if (DHD_GLOM_ON()) {
6420 				DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
6421 				          __FUNCTION__, num, pfirst,
6422 				          PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
6423 				          PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
6424 				prhex("", (uint8 *)PKTDATA(osh, pfirst),
6425 				      MIN(PKTLEN(osh, pfirst), 32));
6426 			}
6427 #endif /* DHD_DEBUG */
6428 		}
6429 		dhd_os_sdunlock_rxq(bus->dhd);
6430 
6431 		for (idx = 0; idx < DHD_MAX_IFS; idx++) {
6432 			if (list_head[idx]) {
6433 				void *temp;
6434 				uint8 cnt = 0;
6435 				temp = list_head[idx];
6436 				do {
6437 					temp = PKTNEXT(osh, temp);
6438 					cnt++;
6439 				} while (temp);
6440 				if (cnt) {
6441 					dhd_os_sdunlock(bus->dhd);
6442 					dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
6443 					dhd_os_sdlock(bus->dhd);
6444 				}
6445 			}
6446 		}
6447 		bus->rxglomframes++;
6448 		bus->rxglompkts += num;
6449 	}
6450 	return num;
6451 }
6452 
6453 /* Return TRUE if there may be more frames to read */
6454 static uint
dhdsdio_readframes(dhd_bus_t * bus,uint maxframes,bool * finished)6455 dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
6456 {
6457 	osl_t *osh = bus->dhd->osh;
6458 	bcmsdh_info_t *sdh = bus->sdh;
6459 
6460 	uint16 len, check;	/* Extracted hardware header fields */
6461 	uint8 chan, seq, doff;	/* Extracted software header fields */
6462 	uint8 fcbits;		/* Extracted fcbits from software header */
6463 	uint8 delta;
6464 
6465 	void *pkt;	/* Packet for event or data frames */
6466 	uint16 pad;	/* Number of pad bytes to read */
6467 	uint16 rdlen;	/* Total number of bytes to read */
6468 	uint8 rxseq;	/* Next sequence number to expect */
6469 	uint rxleft = 0;	/* Remaining number of frames allowed */
6470 	int sdret;	/* Return code from bcmsdh calls */
6471 	uint8 txmax;	/* Maximum tx sequence offered */
6472 #ifdef BCMSPI
6473 	uint32 dstatus = 0;	/* gSPI device status bits of */
6474 #endif /* BCMSPI */
6475 	bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
6476 	uint8 *rxbuf;
6477 	int ifidx = 0;
6478 	uint rxcount = 0; /* Total frames read */
6479 	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
6480 	uint reorder_info_len;
6481 	uint pkt_count;
6482 
6483 #if defined(DHD_DEBUG) || defined(SDTEST)
6484 	bool sdtest = FALSE;	/* To limit message spew from test mode */
6485 #endif // endif
6486 
6487 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
6488 	bus->readframes = TRUE;
6489 
6490 	if (!KSO_ENAB(bus)) {
6491 		DHD_ERROR(("%s: KSO off\n", __FUNCTION__));
6492 		bus->readframes = FALSE;
6493 		return 0;
6494 	}
6495 
6496 	ASSERT(maxframes);
6497 
6498 #ifdef SDTEST
6499 	/* Allow pktgen to override maxframes */
6500 	if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
6501 		maxframes = bus->pktgen_count;
6502 		sdtest = TRUE;
6503 	}
6504 #endif // endif
6505 
6506 	/* Not finished unless we encounter no more frames indication */
6507 	*finished = FALSE;
6508 
6509 #ifdef BCMSPI
6510 	/* Get pktlen from gSPI device F0 reg. */
6511 	if (bus->bus == SPI_BUS) {
6512 		/* Peek in dstatus bits and find out size to do rx-read. */
6513 		dstatus = bcmsdh_get_dstatus(bus->sdh);
6514 		if (dstatus == 0)
6515 			DHD_ERROR(("%s:ZERO spi dstatus, a case observed in PR61352 hit !!!\n",
6516 			           __FUNCTION__));
6517 
6518 		DHD_TRACE(("Device status from regread = 0x%x\n", dstatus));
6519 		DHD_TRACE(("Device status from bit-reconstruction = 0x%x\n",
6520 		          bcmsdh_get_dstatus((void *)bus->sdh)));
6521 
6522 		if ((dstatus & STATUS_F2_PKT_AVAILABLE) && (((dstatus & STATUS_UNDERFLOW)) == 0)) {
6523 			bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
6524 			                STATUS_F2_PKT_LEN_SHIFT);
6525 			/* '0' size with pkt-available interrupt is eqvt to 2048 bytes */
6526 			bus->nextlen = (bus->nextlen == 0) ? SPI_MAX_PKT_LEN : bus->nextlen;
6527 			if (bus->dwordmode)
6528 				bus->nextlen = bus->nextlen << 2;
6529 			DHD_TRACE(("Entering %s: length to be read from gSPI = %d\n",
6530 			          __FUNCTION__, bus->nextlen));
6531 		} else {
6532 			if (dstatus & STATUS_F2_PKT_AVAILABLE)
6533 				DHD_ERROR(("Underflow during %s.\n", __FUNCTION__));
6534 			else
6535 				DHD_ERROR(("False pkt-available intr.\n"));
6536 			*finished = TRUE;
6537 			return (maxframes - rxleft);
6538 		}
6539 	}
6540 #endif /* BCMSPI */
6541 
6542 	for (rxseq = bus->rx_seq, rxleft = maxframes;
6543 	     !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
6544 	     rxseq++, rxleft--) {
6545 #ifdef DHDTCPACK_SUP_DBG
6546 		if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_DELAYTX) {
6547 			if (bus->dotxinrx == FALSE)
6548 				DHD_ERROR(("%s %d: dotxinrx FALSE with tcpack_sub_mode %d\n",
6549 					__FUNCTION__, __LINE__, bus->dhd->tcpack_sup_mode));
6550 		}
6551 #ifdef DEBUG_COUNTER
6552 		else if (pktq_mlen(&bus->txq, ~bus->flowcontrol) > 0) {
6553 			tack_tbl.cnt[bus->dotxinrx ? 6 : 7]++;
6554 		}
6555 #endif /* DEBUG_COUNTER */
6556 #endif /* DHDTCPACK_SUP_DBG */
6557 		/* tx more to improve rx performance */
6558 		if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
6559 			dhdsdio_sendpendctl(bus);
6560 		} else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
6561 			!bus->fcstate && DATAOK(bus) &&
6562 			(pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
6563 			dhdsdio_sendfromq(bus, dhd_txbound);
6564 #ifdef DHDTCPACK_SUPPRESS
6565 			/* In TCPACK_SUP_DELAYTX mode, do txinrx only if
6566 			 * 1. Any DATA packet to TX
6567 			 * 2. TCPACK to TCPDATA PSH packets.
6568 			 * in bus txq.
6569 			 */
6570 			bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ?
6571 				FALSE : TRUE;
6572 #endif // endif
6573 		}
6574 
6575 		/* Handle glomming separately */
6576 		if (bus->glom || bus->glomd) {
6577 			uint8 cnt;
6578 			DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
6579 			          __FUNCTION__, bus->glomd, bus->glom));
6580 			cnt = dhdsdio_rxglom(bus, rxseq);
6581 			DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
6582 			rxseq += cnt - 1;
6583 			rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
6584 			continue;
6585 		}
6586 
6587 		/* Try doing single read if we can */
6588 		if (dhd_readahead && bus->nextlen) {
6589 			uint16 nextlen = bus->nextlen;
6590 			bus->nextlen = 0;
6591 
6592 			if (bus->bus == SPI_BUS) {
6593 				rdlen = len = nextlen;
6594 			} else {
6595 				rdlen = len = nextlen << 4;
6596 
6597 				/* Pad read to blocksize for efficiency */
6598 				if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
6599 					pad = bus->blocksize - (rdlen % bus->blocksize);
6600 					if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
6601 						((rdlen + pad + firstread) < MAX_RX_DATASZ))
6602 						rdlen += pad;
6603 				} else if (rdlen % DHD_SDALIGN) {
6604 					rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
6605 				}
6606 			}
6607 
6608 			/* We use bus->rxctl buffer in WinXP for initial control pkt receives.
6609 			 * Later we use buffer-poll for data as well as control packets.
6610 			 * This is required because dhd receives full frame in gSPI unlike SDIO.
6611 			 * After the frame is received we have to distinguish whether it is data
6612 			 * or non-data frame.
6613 			 */
6614 			/* Allocate a packet buffer */
6615 			dhd_os_sdlock_rxq(bus->dhd);
6616 			if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
6617 				if (bus->bus == SPI_BUS) {
6618 					bus->usebufpool = FALSE;
6619 					bus->rxctl = bus->rxbuf;
6620 					if (dhd_alignctl) {
6621 						bus->rxctl += firstread;
6622 						if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
6623 							bus->rxctl += (DHD_SDALIGN - pad);
6624 						bus->rxctl -= firstread;
6625 					}
6626 					ASSERT(bus->rxctl >= bus->rxbuf);
6627 					rxbuf = bus->rxctl;
6628 					/* Read the entire frame */
6629 					sdret = dhd_bcmsdh_recv_buf(bus,
6630 					                            bcmsdh_cur_sbwad(sdh),
6631 					                            SDIO_FUNC_2,
6632 					                            F2SYNC, rxbuf, rdlen,
6633 					                            NULL, NULL, NULL);
6634 					bus->f2rxdata++;
6635 					ASSERT(sdret != BCME_PENDING);
6636 
6637 #ifdef BCMSPI
6638 					if (bcmsdh_get_dstatus((void *)bus->sdh) &
6639 					                STATUS_UNDERFLOW) {
6640 						bus->nextlen = 0;
6641 						*finished = TRUE;
6642 						DHD_ERROR(("%s: read %d control bytes failed "
6643 						           "due to spi underflow\n",
6644 						           __FUNCTION__, rdlen));
6645 						/* dhd.rx_ctlerrs is higher level */
6646 						bus->rxc_errors++;
6647 						dhd_os_sdunlock_rxq(bus->dhd);
6648 						continue;
6649 					}
6650 #endif /* BCMSPI */
6651 
6652 					/* Control frame failures need retransmission */
6653 					if (sdret < 0) {
6654 						DHD_ERROR(("%s: read %d control bytes failed: %d\n",
6655 						   __FUNCTION__, rdlen, sdret));
6656 						/* dhd.rx_ctlerrs is higher level */
6657 						bus->rxc_errors++;
6658 						dhd_os_sdunlock_rxq(bus->dhd);
6659 						dhdsdio_rxfail(bus, TRUE,
6660 						    (bus->bus == SPI_BUS) ? FALSE : TRUE);
6661 						continue;
6662 					}
6663 				} else {
6664 					/* Give up on data, request rtx of events */
6665 					DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
6666 					           "expected rxseq %d\n",
6667 					           __FUNCTION__, len, rdlen, rxseq));
6668 					/* Just go try again w/normal header read */
6669 					dhd_os_sdunlock_rxq(bus->dhd);
6670 					continue;
6671 				}
6672 			} else {
6673 				if (bus->bus == SPI_BUS)
6674 					bus->usebufpool = TRUE;
6675 
6676 				ASSERT(!PKTLINK(pkt));
6677 				PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
6678 				rxbuf = (uint8 *)PKTDATA(osh, pkt);
6679 				/* Read the entire frame */
6680 				sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
6681 				                            SDIO_FUNC_2,
6682 				                            F2SYNC, rxbuf, rdlen,
6683 				                            pkt, NULL, NULL);
6684 				bus->f2rxdata++;
6685 				ASSERT(sdret != BCME_PENDING);
6686 #ifdef BCMSPI
6687 				if (bcmsdh_get_dstatus((void *)bus->sdh) & STATUS_UNDERFLOW) {
6688 					bus->nextlen = 0;
6689 					*finished = TRUE;
6690 					DHD_ERROR(("%s (nextlen): read %d bytes failed due "
6691 					           "to spi underflow\n",
6692 					           __FUNCTION__, rdlen));
6693 					PKTFREE(bus->dhd->osh, pkt, FALSE);
6694 					bus->dhd->rx_errors++;
6695 					dhd_os_sdunlock_rxq(bus->dhd);
6696 					continue;
6697 				}
6698 #endif /* BCMSPI */
6699 
6700 				if (sdret < 0) {
6701 					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
6702 					   __FUNCTION__, rdlen, sdret));
6703 					PKTFREE(bus->dhd->osh, pkt, FALSE);
6704 					bus->dhd->rx_errors++;
6705 					dhd_os_sdunlock_rxq(bus->dhd);
6706 					/* Force retry w/normal header read.  Don't attempt NAK for
6707 					 * gSPI
6708 					 */
6709 					dhdsdio_rxfail(bus, TRUE,
6710 					      (bus->bus == SPI_BUS) ? FALSE : TRUE);
6711 					continue;
6712 				}
6713 			}
6714 			dhd_os_sdunlock_rxq(bus->dhd);
6715 
6716 			/* Now check the header */
6717 			bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
6718 
6719 			/* Extract hardware header fields */
6720 			len = ltoh16_ua(bus->rxhdr);
6721 			check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
6722 
6723 			/* All zeros means readahead info was bad */
6724 			if (!(len|check)) {
6725 				DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
6726 				           __FUNCTION__));
6727 				dhd_os_sdlock_rxq(bus->dhd);
6728 				PKTFREE2();
6729 				dhd_os_sdunlock_rxq(bus->dhd);
6730 				GSPI_PR55150_BAILOUT;
6731 				continue;
6732 			}
6733 
6734 			/* Validate check bytes */
6735 			if ((uint16)~(len^check)) {
6736 				DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
6737 				           " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
6738 				           len, check));
6739 				dhd_os_sdlock_rxq(bus->dhd);
6740 				PKTFREE2();
6741 				dhd_os_sdunlock_rxq(bus->dhd);
6742 				bus->rx_badhdr++;
6743 				dhdsdio_rxfail(bus, FALSE, FALSE);
6744 				GSPI_PR55150_BAILOUT;
6745 				continue;
6746 			}
6747 
6748 			/* Validate frame length */
6749 			if (len < SDPCM_HDRLEN) {
6750 				DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
6751 				           __FUNCTION__, len));
6752 				dhd_os_sdlock_rxq(bus->dhd);
6753 				PKTFREE2();
6754 				dhd_os_sdunlock_rxq(bus->dhd);
6755 				GSPI_PR55150_BAILOUT;
6756 				continue;
6757 			}
6758 
6759 			/* Check for consistency with readahead info */
6760 #ifdef BCMSPI
6761 			if (bus->bus == SPI_BUS) {
6762 				if (bus->dwordmode) {
6763 					uint16 spilen;
6764 					spilen = ROUNDUP(len, 4);
6765 					len_consistent = (nextlen != spilen);
6766 				} else
6767 					len_consistent = (nextlen != len);
6768 			} else
6769 #endif  /* BCMSPI */
6770 				len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
6771 			if (len_consistent) {
6772 				/* Mismatch, force retry w/normal header (may be >4K) */
6773 				DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
6774 				           "expected rxseq %d\n",
6775 				           __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
6776 				dhd_os_sdlock_rxq(bus->dhd);
6777 				PKTFREE2();
6778 				dhd_os_sdunlock_rxq(bus->dhd);
6779 				dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
6780 				GSPI_PR55150_BAILOUT;
6781 				continue;
6782 			}
6783 
6784 			/* Extract software header fields */
6785 			chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6786 			seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6787 			doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6788 			txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6789 
6790 #ifdef BCMSPI
6791 			/* Save the readahead length if there is one */
6792 			if (bus->bus == SPI_BUS) {
6793 				/* Use reconstructed dstatus bits and find out readahead size */
6794 				dstatus = bcmsdh_get_dstatus((void *)bus->sdh);
6795 				DHD_INFO(("Device status from bit-reconstruction = 0x%x\n",
6796 				bcmsdh_get_dstatus((void *)bus->sdh)));
6797 				if (dstatus & STATUS_F2_PKT_AVAILABLE) {
6798 					bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
6799 					                STATUS_F2_PKT_LEN_SHIFT);
6800 					bus->nextlen = (bus->nextlen == 0) ?
6801 					           SPI_MAX_PKT_LEN : bus->nextlen;
6802 					if (bus->dwordmode)
6803 						bus->nextlen = bus->nextlen << 2;
6804 					DHD_INFO(("readahead len from gSPI = %d \n",
6805 					           bus->nextlen));
6806 					bus->dhd->rx_readahead_cnt ++;
6807 				} else {
6808 					bus->nextlen = 0;
6809 					*finished = TRUE;
6810 				}
6811 			} else {
6812 #endif /* BCMSPI */
6813 				bus->nextlen =
6814 				         bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
6815 				if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
6816 					DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
6817 					          " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
6818 					          seq));
6819 					bus->nextlen = 0;
6820 				}
6821 
6822 				bus->dhd->rx_readahead_cnt ++;
6823 #ifdef BCMSPI
6824 			}
6825 #endif /* BCMSPI */
6826 			/* Handle Flow Control */
6827 			fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6828 
6829 			delta = 0;
6830 			if (~bus->flowcontrol & fcbits) {
6831 				bus->fc_xoff++;
6832 				delta = 1;
6833 			}
6834 			if (bus->flowcontrol & ~fcbits) {
6835 				bus->fc_xon++;
6836 				delta = 1;
6837 			}
6838 
6839 			if (delta) {
6840 				bus->fc_rcvd++;
6841 				bus->flowcontrol = fcbits;
6842 			}
6843 
6844 			/* Check and update sequence number */
6845 			if (rxseq != seq) {
6846 				DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
6847 				          __FUNCTION__, seq, rxseq));
6848 				bus->rx_badseq++;
6849 				rxseq = seq;
6850 			}
6851 
6852 			/* Check window for sanity */
6853 			if ((uint8)(txmax - bus->tx_seq) > 0x70) {
6854 #ifdef BCMSPI
6855 				if ((bus->bus == SPI_BUS) && !(dstatus & STATUS_F2_RX_READY)) {
6856 					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
6857 						__FUNCTION__, txmax, bus->tx_seq));
6858 					txmax = bus->tx_seq + 2;
6859 				} else {
6860 #endif /* BCMSPI */
6861 					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
6862 						__FUNCTION__, txmax, bus->tx_seq));
6863 					txmax = bus->tx_max;
6864 #ifdef BCMSPI
6865 				}
6866 #endif /* BCMSPI */
6867 			}
6868 			bus->tx_max = txmax;
6869 
6870 #ifdef DHD_DEBUG
6871 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
6872 				prhex("Rx Data", rxbuf, len);
6873 			} else if (DHD_HDRS_ON()) {
6874 				prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
6875 			}
6876 #endif // endif
6877 
6878 			if (chan == SDPCM_CONTROL_CHANNEL) {
6879 				if (bus->bus == SPI_BUS) {
6880 					dhdsdio_read_control(bus, rxbuf, len, doff);
6881 					if (bus->usebufpool) {
6882 						dhd_os_sdlock_rxq(bus->dhd);
6883 						PKTFREE(bus->dhd->osh, pkt, FALSE);
6884 						dhd_os_sdunlock_rxq(bus->dhd);
6885 					}
6886 					continue;
6887 				} else {
6888 					DHD_ERROR(("%s (nextlen): readahead on control"
6889 					           " packet %d?\n", __FUNCTION__, seq));
6890 					/* Force retry w/normal header read */
6891 					bus->nextlen = 0;
6892 					dhdsdio_rxfail(bus, FALSE, TRUE);
6893 					dhd_os_sdlock_rxq(bus->dhd);
6894 					PKTFREE2();
6895 					dhd_os_sdunlock_rxq(bus->dhd);
6896 					continue;
6897 				}
6898 			}
6899 
6900 			if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
6901 				DHD_ERROR(("Received %d bytes on %d channel. Running out of "
6902 				           "rx pktbuf's or not yet malloced.\n", len, chan));
6903 				continue;
6904 			}
6905 
6906 			/* Validate data offset */
6907 			if ((doff < SDPCM_HDRLEN) || (doff > len)) {
6908 				DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
6909 				           __FUNCTION__, doff, len, SDPCM_HDRLEN));
6910 				dhd_os_sdlock_rxq(bus->dhd);
6911 				PKTFREE2();
6912 				dhd_os_sdunlock_rxq(bus->dhd);
6913 				ASSERT(0);
6914 				dhdsdio_rxfail(bus, FALSE, FALSE);
6915 				continue;
6916 			}
6917 
6918 			/* All done with this one -- now deliver the packet */
6919 			goto deliver;
6920 		}
6921 		/* gSPI frames should not be handled in fractions */
6922 		if (bus->bus == SPI_BUS) {
6923 			break;
6924 		}
6925 
6926 		/* Read frame header (hardware and software) */
6927 		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
6928 		                            bus->rxhdr, firstread, NULL, NULL, NULL);
6929 		bus->f2rxhdrs++;
6930 		ASSERT(sdret != BCME_PENDING);
6931 
6932 		if (sdret < 0) {
6933 			DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
6934 			bus->rx_hdrfail++;
6935 			dhdsdio_rxfail(bus, TRUE, TRUE);
6936 			continue;
6937 		}
6938 
6939 #ifdef DHD_DEBUG
6940 		if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
6941 			prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
6942 		}
6943 #endif // endif
6944 
6945 		/* Extract hardware header fields */
6946 		len = ltoh16_ua(bus->rxhdr);
6947 		check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
6948 
6949 		/* All zeros means no more frames */
6950 		if (!(len|check)) {
6951 			*finished = TRUE;
6952 			break;
6953 		}
6954 
6955 		/* Validate check bytes */
6956 		if ((uint16)~(len^check)) {
6957 			DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
6958 			           __FUNCTION__, len, check));
6959 			bus->rx_badhdr++;
6960 			dhdsdio_rxfail(bus, FALSE, FALSE);
6961 			continue;
6962 		}
6963 
6964 		/* Validate frame length */
6965 		if (len < SDPCM_HDRLEN) {
6966 			DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len));
6967 			continue;
6968 		}
6969 
6970 		/* Extract software header fields */
6971 		chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6972 		seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6973 		doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6974 		txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6975 
6976 		/* Validate data offset */
6977 		if ((doff < SDPCM_HDRLEN) || (doff > len)) {
6978 			DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
6979 			           __FUNCTION__, doff, len, SDPCM_HDRLEN, seq));
6980 			bus->rx_badhdr++;
6981 			ASSERT(0);
6982 			dhdsdio_rxfail(bus, FALSE, FALSE);
6983 			continue;
6984 		}
6985 
6986 		/* Save the readahead length if there is one */
6987 		bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
6988 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
6989 			DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
6990 			          __FUNCTION__, bus->nextlen, seq));
6991 			bus->nextlen = 0;
6992 		}
6993 
6994 		/* Handle Flow Control */
6995 		fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
6996 
6997 		delta = 0;
6998 		if (~bus->flowcontrol & fcbits) {
6999 			bus->fc_xoff++;
7000 			delta = 1;
7001 		}
7002 		if (bus->flowcontrol & ~fcbits) {
7003 			bus->fc_xon++;
7004 			delta = 1;
7005 		}
7006 
7007 		if (delta) {
7008 			bus->fc_rcvd++;
7009 			bus->flowcontrol = fcbits;
7010 		}
7011 
7012 		/* Check and update sequence number */
7013 		if (rxseq != seq) {
7014 			DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq));
7015 			bus->rx_badseq++;
7016 			rxseq = seq;
7017 		}
7018 
7019 		/* Check window for sanity */
7020 		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
7021 			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
7022 			           __FUNCTION__, txmax, bus->tx_seq));
7023 			txmax = bus->tx_max;
7024 		}
7025 		bus->tx_max = txmax;
7026 
7027 		/* Call a separate function for control frames */
7028 		if (chan == SDPCM_CONTROL_CHANNEL) {
7029 			dhdsdio_read_control(bus, bus->rxhdr, len, doff);
7030 			continue;
7031 		}
7032 
7033 		ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) ||
7034 		       (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL));
7035 
7036 		/* Length to read */
7037 		rdlen = (len > firstread) ? (len - firstread) : 0;
7038 
7039 		/* May pad read to blocksize for efficiency */
7040 		if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
7041 			pad = bus->blocksize - (rdlen % bus->blocksize);
7042 			if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
7043 			    ((rdlen + pad + firstread) < MAX_RX_DATASZ))
7044 				rdlen += pad;
7045 		} else if (rdlen % DHD_SDALIGN) {
7046 			rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
7047 		}
7048 
7049 		/* Satisfy length-alignment requirements */
7050 		if (forcealign && (rdlen & (ALIGNMENT - 1)))
7051 			rdlen = ROUNDUP(rdlen, ALIGNMENT);
7052 
7053 		if ((rdlen + firstread) > MAX_RX_DATASZ) {
7054 			/* Too long -- skip this frame */
7055 			DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen));
7056 			bus->dhd->rx_errors++; bus->rx_toolong++;
7057 			dhdsdio_rxfail(bus, FALSE, FALSE);
7058 			continue;
7059 		}
7060 
7061 		dhd_os_sdlock_rxq(bus->dhd);
7062 		if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) {
7063 			/* Give up on data, request rtx of events */
7064 			DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n",
7065 			           __FUNCTION__, rdlen, chan));
7066 			bus->dhd->rx_dropped++;
7067 			dhd_os_sdunlock_rxq(bus->dhd);
7068 			dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan));
7069 			continue;
7070 		}
7071 		dhd_os_sdunlock_rxq(bus->dhd);
7072 
7073 		ASSERT(!PKTLINK(pkt));
7074 
7075 		/* Leave room for what we already read, and align remainder */
7076 		ASSERT(firstread < (PKTLEN(osh, pkt)));
7077 		PKTPULL(osh, pkt, firstread);
7078 		PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
7079 
7080 		/* Read the remaining frame data */
7081 		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
7082 		                            ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL);
7083 		bus->f2rxdata++;
7084 		ASSERT(sdret != BCME_PENDING);
7085 
7086 		if (sdret < 0) {
7087 			DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen,
7088 			           ((chan == SDPCM_EVENT_CHANNEL) ? "event" :
7089 			            ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret));
7090 			dhd_os_sdlock_rxq(bus->dhd);
7091 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7092 			dhd_os_sdunlock_rxq(bus->dhd);
7093 			bus->dhd->rx_errors++;
7094 			dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan));
7095 			continue;
7096 		}
7097 
7098 		/* Copy the already-read portion */
7099 		PKTPUSH(osh, pkt, firstread);
7100 		bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread);
7101 
7102 #ifdef DHD_DEBUG
7103 		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
7104 			prhex("Rx Data", PKTDATA(osh, pkt), len);
7105 		}
7106 #endif // endif
7107 
7108 deliver:
7109 		/* Save superframe descriptor and allocate packet frame */
7110 		if (chan == SDPCM_GLOM_CHANNEL) {
7111 			if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
7112 				DHD_GLOM(("%s: got glom descriptor, %d bytes:\n",
7113 				          __FUNCTION__, len));
7114 #ifdef DHD_DEBUG
7115 				if (DHD_GLOM_ON()) {
7116 					prhex("Glom Data", PKTDATA(osh, pkt), len);
7117 				}
7118 #endif // endif
7119 				PKTSETLEN(osh, pkt, len);
7120 				ASSERT(doff == SDPCM_HDRLEN);
7121 				PKTPULL(osh, pkt, SDPCM_HDRLEN);
7122 				bus->glomd = pkt;
7123 			} else {
7124 				DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__));
7125 				dhdsdio_rxfail(bus, FALSE, FALSE);
7126 			}
7127 			continue;
7128 		}
7129 
7130 		/* Fill in packet len and prio, deliver upward */
7131 		PKTSETLEN(osh, pkt, len);
7132 		PKTPULL(osh, pkt, doff);
7133 
7134 #ifdef SDTEST
7135 		/* Test channel packets are processed separately */
7136 		if (chan == SDPCM_TEST_CHANNEL) {
7137 			dhdsdio_testrcv(bus, pkt, seq);
7138 			continue;
7139 		}
7140 #endif /* SDTEST */
7141 
7142 #if defined(BCMSPI)
7143 	if ((chan == SDPCM_EVENT_CHANNEL) && (bus->sdpcmrev >= 17 && bus->sdpcmrev <= 22)) {
7144 #else
7145 	if (PKTLEN(osh, pkt) == 0) {
7146 #endif /* BCMSPI */
7147 			dhd_os_sdlock_rxq(bus->dhd);
7148 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7149 			dhd_os_sdunlock_rxq(bus->dhd);
7150 			continue;
7151 		} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt, reorder_info_buf,
7152 			&reorder_info_len) != 0) {
7153 			DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
7154 			dhd_os_sdlock_rxq(bus->dhd);
7155 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7156 			dhd_os_sdunlock_rxq(bus->dhd);
7157 			bus->dhd->rx_errors++;
7158 			continue;
7159 		}
7160 
7161 		if (reorder_info_len) {
7162 			/* Reordering info from the firmware */
7163 			dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len,
7164 				&pkt, &pkt_count);
7165 			if (pkt_count == 0)
7166 				continue;
7167 		} else {
7168 			pkt_count = 1;
7169 		}
7170 
7171 		/* Unlock during rx call */
7172 		dhd_os_sdunlock(bus->dhd);
7173 		dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
7174 		dhd_os_sdlock(bus->dhd);
7175 	}
7176 	rxcount = maxframes - rxleft;
7177 #ifdef DHD_DEBUG
7178 	/* Message if we hit the limit */
7179 	if (!rxleft && !sdtest)
7180 		DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
7181 	else
7182 #endif /* DHD_DEBUG */
7183 	DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
7184 	/* Back off rxseq if awaiting rtx, update rx_seq */
7185 	if (bus->rxskip)
7186 		rxseq--;
7187 	bus->rx_seq = rxseq;
7188 
7189 	if (bus->reqbussleep)
7190 	{
7191 	    dhdsdio_bussleep(bus, TRUE);
7192 		bus->reqbussleep = FALSE;
7193 	}
7194 	bus->readframes = FALSE;
7195 
7196 	return rxcount;
7197 }
7198 
7199 static uint32
7200 dhdsdio_hostmail(dhd_bus_t *bus, uint32 *hmbd)
7201 {
7202 	sdpcmd_regs_t *regs = bus->regs;
7203 	uint32 intstatus = 0;
7204 	uint32 hmb_data;
7205 	uint8 fcbits;
7206 	uint retries = 0;
7207 
7208 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7209 
7210 	/* Read mailbox data and ack that we did so */
7211 	R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
7212 	if (retries <= retry_limit)
7213 		W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
7214 	bus->f1regdata += 2;
7215 
7216 	/* Dongle recomposed rx frames, accept them again */
7217 	if (hmb_data & HMB_DATA_NAKHANDLED) {
7218 		DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq));
7219 		if (!bus->rxskip) {
7220 			DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__));
7221 		}
7222 		bus->rxskip = FALSE;
7223 		intstatus |= FRAME_AVAIL_MASK(bus);
7224 	}
7225 
7226 	/*
7227 	 * DEVREADY does not occur with gSPI.
7228 	 */
7229 	if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
7230 		bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT;
7231 		if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
7232 			DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n",
7233 			           bus->sdpcm_ver, SDPCM_PROT_VERSION));
7234 		else
7235 			DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
7236 #ifndef BCMSPI
7237 		/* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */
7238 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
7239 		    (bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1)) {
7240 			uint32 val;
7241 
7242 			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
7243 			val &= ~CC_XMTDATAAVAIL_MODE;
7244 			val |= CC_XMTDATAAVAIL_CTRL;
7245 			W_REG(bus->dhd->osh, &bus->regs->corecontrol, val);
7246 
7247 			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
7248 		}
7249 #endif /* BCMSPI */
7250 
7251 #ifdef DHD_DEBUG
7252 		/* Retrieve console state address now that firmware should have updated it */
7253 		{
7254 			sdpcm_shared_t shared;
7255 			if (dhdsdio_readshared(bus, &shared) == 0)
7256 				bus->console_addr = shared.console_addr;
7257 			}
7258 #endif /* DHD_DEBUG */
7259 	}
7260 
7261 	/*
7262 	 * Flow Control has been moved into the RX headers and this out of band
7263 	 * method isn't used any more.  Leave this here for possibly remaining backward
7264 	 * compatible with older dongles
7265 	 */
7266 	if (hmb_data & HMB_DATA_FC) {
7267 		fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT;
7268 
7269 		if (fcbits & ~bus->flowcontrol)
7270 			bus->fc_xoff++;
7271 		if (bus->flowcontrol & ~fcbits)
7272 			bus->fc_xon++;
7273 
7274 		bus->fc_rcvd++;
7275 		bus->flowcontrol = fcbits;
7276 	}
7277 
7278 	/* At least print a message if FW halted */
7279 	if (hmb_data & HMB_DATA_FWHALT) {
7280 		DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n"));
7281 		dhdsdio_checkdied(bus, NULL, 0);
7282 		DHD_ERROR(("Not doing bus down untill memdump done \n"));
7283 	}
7284 
7285 	/* Shouldn't be any others */
7286 	if (hmb_data & ~(HMB_DATA_DEVREADY |
7287 	                 HMB_DATA_FWHALT |
7288 	                 HMB_DATA_NAKHANDLED |
7289 	                 HMB_DATA_FC |
7290 	                 HMB_DATA_FWREADY |
7291 	                 HMB_DATA_FCDATA_MASK |
7292 	                 HMB_DATA_VERSION_MASK)) {
7293 		DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
7294 	}
7295 
7296 	if (hmbd) {
7297 		*hmbd = hmb_data;
7298 	}
7299 
7300 	return intstatus;
7301 }
7302 
7303 static bool
7304 dhdsdio_dpc(dhd_bus_t *bus)
7305 {
7306 	bcmsdh_info_t *sdh = bus->sdh;
7307 	sdpcmd_regs_t *regs = bus->regs;
7308 	uint32 intstatus, newstatus = 0;
7309 	uint retries = 0;
7310 	uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
7311 	uint txlimit = dhd_txbound; /* Tx frames to send before resched */
7312 	uint framecnt = 0;		  /* Temporary counter of tx/rx frames */
7313 	bool rxdone = TRUE;		  /* Flag for no more read data */
7314 	bool resched = FALSE;	  /* Flag indicating resched wanted */
7315 	unsigned long flags;
7316 #ifdef DEBUG_DPC_THREAD_WATCHDOG
7317 	bool is_resched_by_readframe = FALSE;
7318 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
7319 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7320 
7321 	dhd_os_sdlock(bus->dhd);
7322 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
7323 	if (bus->dhd->busstate == DHD_BUS_DOWN) {
7324 		DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
7325 		bus->intstatus = 0;
7326 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
7327 		dhd_os_sdunlock(bus->dhd);
7328 		return 0;
7329 	}
7330 
7331 	DHD_BUS_BUSY_SET_IN_DPC(bus->dhd);
7332 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
7333 
7334 	/* Start with leftover status bits */
7335 	intstatus = bus->intstatus;
7336 
7337 	if (!SLPAUTO_ENAB(bus) && !KSO_ENAB(bus)) {
7338 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
7339 		goto exit;
7340 	}
7341 
7342 	/* If waiting for HTAVAIL, check status */
7343 	if (!SLPAUTO_ENAB(bus) && (bus->clkstate == CLK_PENDING)) {
7344 		int err;
7345 		uint8 clkctl, devctl = 0;
7346 
7347 #ifdef DHD_DEBUG
7348 		/* Check for inconsistent device control */
7349 		devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
7350 		if (err) {
7351 			DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
7352 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7353 			bus->dhd->busstate = DHD_BUS_DOWN;
7354 		} else {
7355 			ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
7356 		}
7357 #endif /* DHD_DEBUG */
7358 
7359 		/* Read CSR, if clock on switch to AVAIL, else ignore */
7360 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
7361 		if (err) {
7362 			DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
7363 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7364 			bus->dhd->busstate = DHD_BUS_DOWN;
7365 		}
7366 
7367 		DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl));
7368 
7369 		if (SBSDIO_HTAV(clkctl)) {
7370 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
7371 			if (err) {
7372 				DHD_ERROR(("%s: error reading DEVCTL: %d\n",
7373 				           __FUNCTION__, err));
7374 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7375 				bus->dhd->busstate = DHD_BUS_DOWN;
7376 			}
7377 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
7378 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
7379 			if (err) {
7380 				DHD_ERROR(("%s: error writing DEVCTL: %d\n",
7381 				           __FUNCTION__, err));
7382 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7383 				bus->dhd->busstate = DHD_BUS_DOWN;
7384 			}
7385 			bus->clkstate = CLK_AVAIL;
7386 		} else {
7387 			goto clkwait;
7388 		}
7389 	}
7390 
7391 	BUS_WAKE(bus);
7392 
7393 	/* Make sure backplane clock is on */
7394 	dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
7395 	if (bus->clkstate != CLK_AVAIL)
7396 		goto clkwait;
7397 
7398 	/* Pending interrupt indicates new device status */
7399 	if (bus->ipend) {
7400 		bus->ipend = FALSE;
7401 #if defined(BT_OVER_SDIO)
7402 	bcmsdh_btsdio_process_f3_intr();
7403 #endif /* defined (BT_OVER_SDIO) */
7404 
7405 		R_SDREG(newstatus, &regs->intstatus, retries);
7406 		bus->f1regdata++;
7407 		if (bcmsdh_regfail(bus->sdh))
7408 			newstatus = 0;
7409 		newstatus &= bus->hostintmask;
7410 		bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
7411 		if (newstatus) {
7412 			bus->f1regdata++;
7413 #ifndef BCMSPI
7414 			if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) &&
7415 				(newstatus == I_XMTDATA_AVAIL)) {
7416 			} else
7417 #endif /* BCMSPI */
7418 				W_SDREG(newstatus, &regs->intstatus, retries);
7419 		}
7420 	}
7421 
7422 	/* Merge new bits with previous */
7423 	intstatus |= newstatus;
7424 	bus->intstatus = 0;
7425 
7426 	/* Handle flow-control change: read new state in case our ack
7427 	 * crossed another change interrupt.  If change still set, assume
7428 	 * FC ON for safety, let next loop through do the debounce.
7429 	 */
7430 	if (intstatus & I_HMB_FC_CHANGE) {
7431 		intstatus &= ~I_HMB_FC_CHANGE;
7432 		W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
7433 		R_SDREG(newstatus, &regs->intstatus, retries);
7434 		bus->f1regdata += 2;
7435 		bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
7436 		intstatus |= (newstatus & bus->hostintmask);
7437 	}
7438 
7439 	/* Handle host mailbox indication */
7440 	if (intstatus & I_HMB_HOST_INT) {
7441 		uint32 hmbdata = 0;
7442 
7443 		intstatus &= ~I_HMB_HOST_INT;
7444 		intstatus |= dhdsdio_hostmail(bus, &hmbdata);
7445 
7446 #ifdef DHD_ULP
7447 		/* ULP prototyping. Redowload fw on oob interupt */
7448 
7449 		/* all the writes after this point CAN use cached sbwad value */
7450 		bcmsdh_force_sbwad_calc(bus->sdh, FALSE);
7451 
7452 		if (dhd_ulp_pre_redownload_check(bus->dhd, bus->sdh, hmbdata)) {
7453 			if (dhd_bus_ulp_reinit_fw(bus) < 0) {
7454 				DHD_ERROR(("%s:%d FW redownload failed\n",
7455 					__FUNCTION__, __LINE__));
7456 				goto exit;
7457 			}
7458 		}
7459 #endif // endif
7460 
7461 	}
7462 
7463 #ifdef DHD_UCODE_DOWNLOAD
7464 exit_ucode:
7465 #endif /* DHD_UCODE_DOWNLOAD */
7466 
7467 	/* Just being here means nothing more to do for chipactive */
7468 	if (intstatus & I_CHIPACTIVE) {
7469 		/* ASSERT(bus->clkstate == CLK_AVAIL); */
7470 		intstatus &= ~I_CHIPACTIVE;
7471 	}
7472 
7473 	/* Handle host mailbox indication */
7474 	if (intstatus & I_HMB_HOST_INT) {
7475 		intstatus &= ~I_HMB_HOST_INT;
7476 		intstatus |= dhdsdio_hostmail(bus, NULL);
7477 	}
7478 
7479 	/* Generally don't ask for these, can get CRC errors... */
7480 	if (intstatus & I_WR_OOSYNC) {
7481 		DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
7482 		intstatus &= ~I_WR_OOSYNC;
7483 	}
7484 
7485 	if (intstatus & I_RD_OOSYNC) {
7486 		DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
7487 		intstatus &= ~I_RD_OOSYNC;
7488 	}
7489 
7490 	if (intstatus & I_SBINT) {
7491 		DHD_ERROR(("Dongle reports SBINT\n"));
7492 		intstatus &= ~I_SBINT;
7493 	}
7494 
7495 	/* Would be active due to wake-wlan in gSPI */
7496 	if (intstatus & I_CHIPACTIVE) {
7497 		DHD_INFO(("Dongle reports CHIPACTIVE\n"));
7498 		intstatus &= ~I_CHIPACTIVE;
7499 	}
7500 
7501 	if (intstatus & I_HMB_FC_STATE) {
7502 		DHD_INFO(("Dongle reports HMB_FC_STATE\n"));
7503 		intstatus &= ~I_HMB_FC_STATE;
7504 	}
7505 
7506 	/* Ignore frame indications if rxskip is set */
7507 	if (bus->rxskip) {
7508 		intstatus &= ~FRAME_AVAIL_MASK(bus);
7509 	}
7510 
7511 	/* On frame indication, read available frames */
7512 	if (PKT_AVAILABLE(bus, intstatus)) {
7513 
7514 			framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
7515 			if (rxdone || bus->rxskip)
7516 				intstatus  &= ~FRAME_AVAIL_MASK(bus);
7517 			rxlimit -= MIN(framecnt, rxlimit);
7518 	}
7519 
7520 	/* Keep still-pending events for next scheduling */
7521 	bus->intstatus = intstatus;
7522 
7523 clkwait:
7524 	/* Re-enable interrupts to detect new device events (mailbox, rx frame)
7525 	 * or clock availability.  (Allows tx loop to check ipend if desired.)
7526 	 * (Unless register access seems hosed, as we may not be able to ACK...)
7527 	 */
7528 	if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
7529 		DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
7530 		          __FUNCTION__, rxdone, framecnt));
7531 		bus->intdis = FALSE;
7532 #if defined(OOB_INTR_ONLY)
7533 		bcmsdh_oob_intr_set(bus->sdh, TRUE);
7534 #endif /* defined(OOB_INTR_ONLY) */
7535 		bcmsdh_intr_enable(sdh);
7536 #ifdef BCMSPI_ANDROID
7537 		if (*dhd_spi_lockcount == 0)
7538 			bcmsdh_oob_intr_set(bus->sdh, TRUE);
7539 #endif /* BCMSPI_ANDROID */
7540 	}
7541 
7542 #if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
7543 	/* In case of SW-OOB(using edge trigger),
7544 	 * Check interrupt status in the dongle again after enable irq on the host.
7545 	 * and rechedule dpc if interrupt is pended in the dongle.
7546 	 * There is a chance to miss OOB interrupt while irq is disabled on the host.
7547 	 * No need to do this with HW-OOB(level trigger)
7548 	 */
7549 	R_SDREG(newstatus, &regs->intstatus, retries);
7550 	if (bcmsdh_regfail(bus->sdh))
7551 		newstatus = 0;
7552 	if (newstatus & bus->hostintmask) {
7553 		bus->ipend = TRUE;
7554 		resched = TRUE;
7555 	}
7556 #endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */
7557 
7558 #ifdef PROP_TXSTATUS
7559 	dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
7560 #endif // endif
7561 
7562 	if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
7563 		dhdsdio_sendpendctl(bus);
7564 
7565 	/* Send queued frames (limit 1 if rx may still be pending) */
7566 	else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
7567 	    pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
7568 
7569 #ifdef DHD_ULP
7570 		if (dhd_ulp_f2_ready(bus->dhd, bus->sdh)) {
7571 #endif /* DHD_ULP */
7572 			framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
7573 			framecnt = dhdsdio_sendfromq(bus, framecnt);
7574 			txlimit -= framecnt;
7575 #ifdef DHD_ULP
7576 		} else {
7577 			/* In other transient states like DHD_ULP_, after the states are
7578 			* DHD_ULP_F2ENAB_CLEARING and DHD_ULP_F2ENAB_SETTING,
7579 			* dpc is scheduled after steady-state and dhdsdio_sendfromq() will
7580 			* execute again
7581 			*/
7582 		}
7583 #endif /* DHD_ULP */
7584 	}
7585 	/* Resched the DPC if ctrl cmd is pending on bus credit */
7586 	if (bus->ctrl_frame_stat)
7587 		resched = TRUE;
7588 
7589 	/* Resched if events or tx frames are pending, else await next interrupt */
7590 	/* On failed register access, all bets are off: no resched or interrupts */
7591 	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
7592 		if ((bus->sih && bus->sih->buscorerev >= 12) && !(dhdsdio_sleepcsr_get(bus) &
7593 			SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
7594 			/* Bus failed because of KSO */
7595 			DHD_ERROR(("%s: Bus failed due to KSO\n", __FUNCTION__));
7596 			bus->kso = FALSE;
7597 		} else {
7598 			DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
7599 				__FUNCTION__));
7600 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7601 			bus->dhd->busstate = DHD_BUS_DOWN;
7602 			bus->intstatus = 0;
7603 		}
7604 	} else if (bus->clkstate == CLK_PENDING) {
7605 		/* Awaiting I_CHIPACTIVE; don't resched */
7606 	} else if (bus->intstatus || bus->ipend ||
7607 	           (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
7608 			PKT_AVAILABLE(bus, bus->intstatus)) {  /* Read multiple frames */
7609 		resched = TRUE;
7610 	}
7611 
7612 	bus->dpc_sched = resched;
7613 
7614 	/* If we're done for now, turn off clock request. */
7615 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING) &&
7616 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
7617 		bus->activity = FALSE;
7618 		dhdsdio_bussleep(bus, TRUE);
7619 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
7620 	}
7621 
7622 exit:
7623 
7624 	if (!resched && dhd_dpcpoll) {
7625 		if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) {
7626 			resched = TRUE;
7627 #ifdef DEBUG_DPC_THREAD_WATCHDOG
7628 			is_resched_by_readframe = TRUE;
7629 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
7630 		}
7631 	}
7632 
7633 	dhd_os_sdunlock(bus->dhd);
7634 #ifdef DEBUG_DPC_THREAD_WATCHDOG
7635 	if (bus->dhd->dhd_bug_on) {
7636 		DHD_INFO(("%s: resched = %d ctrl_frame_stat = %d intstatus 0x%08x"
7637 			" ipend = %d pktq_mlen = %d is_resched_by_readframe = %d \n",
7638 			__FUNCTION__, resched, bus->ctrl_frame_stat,
7639 			bus->intstatus, bus->ipend,
7640 			pktq_mlen(&bus->txq, ~bus->flowcontrol), is_resched_by_readframe));
7641 
7642 			bus->dhd->dhd_bug_on = FALSE;
7643 	}
7644 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
7645 
7646 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
7647 	DHD_BUS_BUSY_CLEAR_IN_DPC(bus->dhd);
7648 	dhd_os_busbusy_wake(bus->dhd);
7649 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
7650 
7651 	return resched;
7652 }
7653 
7654 bool
7655 dhd_bus_dpc(struct dhd_bus *bus)
7656 {
7657 	bool resched;
7658 
7659 	/* Call the DPC directly. */
7660 	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
7661 	resched = dhdsdio_dpc(bus);
7662 
7663 	return resched;
7664 }
7665 
7666 void
7667 dhdsdio_isr(void *arg)
7668 {
7669 	dhd_bus_t *bus = (dhd_bus_t*)arg;
7670 	bcmsdh_info_t *sdh;
7671 
7672 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7673 
7674 	if (!bus) {
7675 		DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
7676 		return;
7677 	}
7678 	sdh = bus->sdh;
7679 
7680 	if (bus->dhd->busstate == DHD_BUS_DOWN) {
7681 		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
7682 		return;
7683 	}
7684 
7685 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7686 
7687 	/* Count the interrupt call */
7688 	bus->intrcount++;
7689 	bus->ipend = TRUE;
7690 
7691 	/* Shouldn't get this interrupt if we're sleeping? */
7692 	if (!SLPAUTO_ENAB(bus)) {
7693 		if (bus->sleeping) {
7694 			DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
7695 			return;
7696 		} else if (!KSO_ENAB(bus)) {
7697 			DHD_ERROR(("ISR in devsleep 1\n"));
7698 		}
7699 	}
7700 
7701 	/* Disable additional interrupts (is this needed now)? */
7702 	if (bus->intr) {
7703 		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
7704 	} else {
7705 		DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
7706 	}
7707 
7708 #ifdef BCMSPI_ANDROID
7709 	bcmsdh_oob_intr_set(bus->sdh, FALSE);
7710 #endif /* BCMSPI_ANDROID */
7711 	bcmsdh_intr_disable(sdh);
7712 	bus->intdis = TRUE;
7713 
7714 #if defined(SDIO_ISR_THREAD)
7715 	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
7716 	DHD_OS_WAKE_LOCK(bus->dhd);
7717 	dhdsdio_dpc(bus);
7718 	DHD_OS_WAKE_UNLOCK(bus->dhd);
7719 #else
7720 	bus->dpc_sched = TRUE;
7721 	dhd_sched_dpc(bus->dhd);
7722 #endif /* defined(SDIO_ISR_THREAD) */
7723 
7724 }
7725 
7726 #ifdef SDTEST
7727 static void
7728 dhdsdio_pktgen_init(dhd_bus_t *bus)
7729 {
7730 	/* Default to specified length, or full range */
7731 	if (dhd_pktgen_len) {
7732 		bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN);
7733 		bus->pktgen_minlen = bus->pktgen_maxlen;
7734 	} else {
7735 		bus->pktgen_maxlen = MAX_PKTGEN_LEN;
7736 		bus->pktgen_minlen = 0;
7737 	}
7738 	bus->pktgen_len = (uint16)bus->pktgen_minlen;
7739 
7740 	/* Default to per-watchdog burst with 10s print time */
7741 	bus->pktgen_freq = 1;
7742 	bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0;
7743 	bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
7744 
7745 	/* Default to echo mode */
7746 	bus->pktgen_mode = DHD_PKTGEN_ECHO;
7747 	bus->pktgen_stop = 1;
7748 }
7749 
7750 static void
7751 dhdsdio_pktgen(dhd_bus_t *bus)
7752 {
7753 	void *pkt;
7754 	uint8 *data;
7755 	uint pktcount;
7756 	uint fillbyte;
7757 	osl_t *osh = bus->dhd->osh;
7758 	uint16 len;
7759 	ulong time_lapse;
7760 	uint sent_pkts;
7761 	uint rcvd_pkts;
7762 
7763 	/* Display current count if appropriate */
7764 	if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
7765 		bus->pktgen_ptick = 0;
7766 		printf("%s: send attempts %d, rcvd %d, errors %d\n",
7767 		       __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
7768 
7769 		/* Print throughput stats only for constant length packet runs */
7770 		if (bus->pktgen_minlen == bus->pktgen_maxlen) {
7771 			time_lapse = jiffies - bus->pktgen_prev_time;
7772 			bus->pktgen_prev_time = jiffies;
7773 			sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent;
7774 			bus->pktgen_prev_sent = bus->pktgen_sent;
7775 			rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd;
7776 			bus->pktgen_prev_rcvd = bus->pktgen_rcvd;
7777 
7778 			printf("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n",
7779 			  __FUNCTION__,
7780 			  (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8,
7781 			  (rcvd_pkts * bus->pktgen_len  / jiffies_to_msecs(time_lapse)) * 8);
7782 		}
7783 	}
7784 
7785 	/* For recv mode, just make sure dongle has started sending */
7786 	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
7787 		if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) {
7788 			bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING;
7789 			dhdsdio_sdtest_set(bus, bus->pktgen_total);
7790 		}
7791 		return;
7792 	}
7793 
7794 	/* Otherwise, generate or request the specified number of packets */
7795 	for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
7796 		/* Stop if total has been reached */
7797 		if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) {
7798 			bus->pktgen_count = 0;
7799 			break;
7800 		}
7801 
7802 		/* Allocate an appropriate-sized packet */
7803 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
7804 			len = SDPCM_TEST_PKT_CNT_FLD_LEN;
7805 		} else {
7806 			len = bus->pktgen_len;
7807 		}
7808 		if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
7809 		                   TRUE))) {;
7810 			DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
7811 			break;
7812 		}
7813 		PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
7814 		data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
7815 
7816 		/* Write test header cmd and extra based on mode */
7817 		switch (bus->pktgen_mode) {
7818 		case DHD_PKTGEN_ECHO:
7819 			*data++ = SDPCM_TEST_ECHOREQ;
7820 			*data++ = (uint8)bus->pktgen_sent;
7821 			break;
7822 
7823 		case DHD_PKTGEN_SEND:
7824 			*data++ = SDPCM_TEST_DISCARD;
7825 			*data++ = (uint8)bus->pktgen_sent;
7826 			break;
7827 
7828 		case DHD_PKTGEN_RXBURST:
7829 			*data++ = SDPCM_TEST_BURST;
7830 			*data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */
7831 			break;
7832 
7833 		default:
7834 			DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode));
7835 			PKTFREE(osh, pkt, TRUE);
7836 			bus->pktgen_count = 0;
7837 			return;
7838 		}
7839 
7840 		/* Write test header length field */
7841 		*data++ = (bus->pktgen_len >> 0);
7842 		*data++ = (bus->pktgen_len >> 8);
7843 
7844 		/* Write frame count in a 4 byte field adjucent to SDPCM test header for
7845 		 * burst mode
7846 		 */
7847 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
7848 			*data++ = (uint8)(bus->pktgen_count >> 0);
7849 			*data++ = (uint8)(bus->pktgen_count >> 8);
7850 			*data++ = (uint8)(bus->pktgen_count >> 16);
7851 			*data++ = (uint8)(bus->pktgen_count >> 24);
7852 		} else {
7853 
7854 			/* Then fill in the remainder -- N/A for burst */
7855 			for (fillbyte = 0; fillbyte < len; fillbyte++)
7856 				*data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent);
7857 		}
7858 
7859 #ifdef DHD_DEBUG
7860 		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
7861 			data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
7862 			prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
7863 		}
7864 #endif // endif
7865 
7866 		/* Send it */
7867 		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) {
7868 			bus->pktgen_fail++;
7869 			if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail)
7870 				bus->pktgen_count = 0;
7871 		}
7872 		bus->pktgen_sent++;
7873 
7874 		/* Bump length if not fixed, wrap at max */
7875 		if (++bus->pktgen_len > bus->pktgen_maxlen)
7876 			bus->pktgen_len = (uint16)bus->pktgen_minlen;
7877 
7878 		/* Special case for burst mode: just send one request! */
7879 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
7880 			break;
7881 	}
7882 }
7883 
7884 static void
7885 dhdsdio_sdtest_set(dhd_bus_t *bus, uint count)
7886 {
7887 	void *pkt;
7888 	uint8 *data;
7889 	osl_t *osh = bus->dhd->osh;
7890 
7891 	/* Allocate the packet */
7892 	if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
7893 		SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) {
7894 		DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
7895 		return;
7896 	}
7897 	PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
7898 		SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN);
7899 	data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
7900 
7901 	/* Fill in the test header */
7902 	*data++ = SDPCM_TEST_SEND;
7903 	*data++ = (count > 0)?TRUE:FALSE;
7904 	*data++ = (bus->pktgen_maxlen >> 0);
7905 	*data++ = (bus->pktgen_maxlen >> 8);
7906 	*data++ = (uint8)(count >> 0);
7907 	*data++ = (uint8)(count >> 8);
7908 	*data++ = (uint8)(count >> 16);
7909 	*data++ = (uint8)(count >> 24);
7910 
7911 	/* Send it */
7912 	if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK)
7913 		bus->pktgen_fail++;
7914 }
7915 
7916 static void
7917 dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
7918 {
7919 	osl_t *osh = bus->dhd->osh;
7920 	uint8 *data;
7921 	uint pktlen;
7922 
7923 	uint8 cmd;
7924 	uint8 extra;
7925 	uint16 len;
7926 	uint16 offset;
7927 
7928 	/* Check for min length */
7929 	if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) {
7930 		DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen));
7931 		PKTFREE(osh, pkt, FALSE);
7932 		return;
7933 	}
7934 
7935 	/* Extract header fields */
7936 	data = PKTDATA(osh, pkt);
7937 	cmd = *data++;
7938 	extra = *data++;
7939 	len = *data++; len += *data++ << 8;
7940 	DHD_TRACE(("%s:cmd:%d, xtra:%d,len:%d\n", __FUNCTION__, cmd, extra, len));
7941 	/* Check length for relevant commands */
7942 	if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) {
7943 		if (pktlen != len + SDPCM_TEST_HDRLEN) {
7944 			DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d"
7945 			           " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
7946 			PKTFREE(osh, pkt, FALSE);
7947 			return;
7948 		}
7949 	}
7950 
7951 	/* Process as per command */
7952 	switch (cmd) {
7953 	case SDPCM_TEST_ECHOREQ:
7954 		/* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
7955 		*(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP;
7956 		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) == BCME_OK) {
7957 			bus->pktgen_sent++;
7958 		} else {
7959 			bus->pktgen_fail++;
7960 			PKTFREE(osh, pkt, FALSE);
7961 		}
7962 		bus->pktgen_rcvd++;
7963 		break;
7964 
7965 	case SDPCM_TEST_ECHORSP:
7966 		if (bus->ext_loop) {
7967 			PKTFREE(osh, pkt, FALSE);
7968 			bus->pktgen_rcvd++;
7969 			break;
7970 		}
7971 
7972 		for (offset = 0; offset < len; offset++, data++) {
7973 			if (*data != SDPCM_TEST_FILL(offset, extra)) {
7974 				DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: "
7975 				           "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
7976 				           offset, len, SDPCM_TEST_FILL(offset, extra), *data));
7977 				break;
7978 			}
7979 		}
7980 		PKTFREE(osh, pkt, FALSE);
7981 		bus->pktgen_rcvd++;
7982 		break;
7983 
7984 	case SDPCM_TEST_DISCARD:
7985 		{
7986 			int i = 0;
7987 			uint8 *prn = data;
7988 			uint8 testval = extra;
7989 			for (i = 0; i < len; i++) {
7990 				if (*prn != testval) {
7991 					DHD_ERROR(("DIErr@Pkt#:%d,Ix:%d, expected:0x%x, got:0x%x\n",
7992 						i, bus->pktgen_rcvd_rcvsession, testval, *prn));
7993 					prn++; testval++;
7994 				}
7995 			}
7996 		}
7997 		PKTFREE(osh, pkt, FALSE);
7998 		bus->pktgen_rcvd++;
7999 		break;
8000 
8001 	case SDPCM_TEST_BURST:
8002 	case SDPCM_TEST_SEND:
8003 	default:
8004 		DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
8005 		          " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
8006 		PKTFREE(osh, pkt, FALSE);
8007 		break;
8008 	}
8009 
8010 	/* For recv mode, stop at limit (and tell dongle to stop sending) */
8011 	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
8012 		if (bus->pktgen_rcv_state != PKTGEN_RCV_IDLE) {
8013 			bus->pktgen_rcvd_rcvsession++;
8014 
8015 			if (bus->pktgen_total &&
8016 				(bus->pktgen_rcvd_rcvsession >= bus->pktgen_total)) {
8017 			bus->pktgen_count = 0;
8018 			DHD_ERROR(("Pktgen:rcv test complete!\n"));
8019 			bus->pktgen_rcv_state = PKTGEN_RCV_IDLE;
8020 			dhdsdio_sdtest_set(bus, FALSE);
8021 				bus->pktgen_rcvd_rcvsession = 0;
8022 			}
8023 		}
8024 	}
8025 }
8026 #endif /* SDTEST */
8027 
8028 int dhd_bus_oob_intr_register(dhd_pub_t *dhdp)
8029 {
8030 	int err = 0;
8031 
8032 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8033 	err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus);
8034 #endif // endif
8035 	return err;
8036 }
8037 
8038 void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
8039 {
8040 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8041 	bcmsdh_oob_intr_unregister(dhdp->bus->sdh);
8042 #endif // endif
8043 }
8044 
8045 void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
8046 {
8047 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8048 	bcmsdh_oob_intr_set(dhdp->bus->sdh, enable);
8049 #endif // endif
8050 }
8051 
8052 void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
8053 {
8054 	bcmsdh_dev_pm_stay_awake(dhdpub->bus->sdh);
8055 }
8056 
8057 void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub)
8058 {
8059 	bcmsdh_dev_relax(dhdpub->bus->sdh);
8060 }
8061 
8062 bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub)
8063 {
8064 	bool enabled = FALSE;
8065 
8066 	enabled = bcmsdh_dev_pm_enabled(dhdpub->bus->sdh);
8067 	return enabled;
8068 }
8069 
8070 extern bool
8071 dhd_bus_watchdog(dhd_pub_t *dhdp)
8072 {
8073 	dhd_bus_t *bus;
8074 	unsigned long flags;
8075 
8076 	DHD_TIMER(("%s: Enter\n", __FUNCTION__));
8077 
8078 	bus = dhdp->bus;
8079 
8080 	if (bus->dhd->dongle_reset)
8081 		return FALSE;
8082 
8083 	if (bus->dhd->hang_was_sent) {
8084 		dhd_os_wd_timer(bus->dhd, 0);
8085 		return FALSE;
8086 	}
8087 
8088 	/* Ignore the timer if simulating bus down */
8089 	if (!SLPAUTO_ENAB(bus) && bus->sleeping)
8090 		return FALSE;
8091 
8092 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
8093 	if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp) ||
8094 			DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp)) {
8095 		DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8096 		return FALSE;
8097 	}
8098 	DHD_BUS_BUSY_SET_IN_WD(dhdp);
8099 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8100 
8101 	dhd_os_sdlock(bus->dhd);
8102 
8103 	/* Poll period: check device if appropriate. */
8104 	if (!SLPAUTO_ENAB(bus) && (bus->poll && (++bus->polltick >= bus->pollrate))) {
8105 		uint32 intstatus = 0;
8106 
8107 		/* Reset poll tick */
8108 		bus->polltick = 0;
8109 
8110 		/* Check device if no interrupts */
8111 		if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
8112 
8113 #ifndef BCMSPI
8114 			if (!bus->dpc_sched) {
8115 				uint8 devpend;
8116 				devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
8117 				                          SDIOD_CCCR_INTPEND, NULL);
8118 				intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
8119 			}
8120 #else
8121 			if (!bus->dpc_sched) {
8122 				uint32 devpend;
8123 				devpend = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0,
8124 					SPID_STATUS_REG, NULL);
8125 				intstatus = devpend & STATUS_F2_PKT_AVAILABLE;
8126 			}
8127 #endif /* !BCMSPI */
8128 
8129 			/* If there is something, make like the ISR and schedule the DPC */
8130 			if (intstatus) {
8131 				bus->pollcnt++;
8132 				bus->ipend = TRUE;
8133 				if (bus->intr) {
8134 					bcmsdh_intr_disable(bus->sdh);
8135 				}
8136 				bus->dpc_sched = TRUE;
8137 				dhd_sched_dpc(bus->dhd);
8138 			}
8139 		}
8140 
8141 		/* Update interrupt tracking */
8142 		bus->lastintrs = bus->intrcount;
8143 	}
8144 
8145 #ifdef DHD_DEBUG
8146 	/* Poll for console output periodically */
8147 	if (dhdp->busstate == DHD_BUS_DATA && dhdp->dhd_console_ms != 0) {
8148 		bus->console.count += dhd_watchdog_ms;
8149 		if (bus->console.count >= dhdp->dhd_console_ms) {
8150 			bus->console.count -= dhdp->dhd_console_ms;
8151 			/* Make sure backplane clock is on */
8152 			if (SLPAUTO_ENAB(bus))
8153 				dhdsdio_bussleep(bus, FALSE);
8154 			else
8155 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8156 		if (dhdsdio_readconsole(bus) < 0)
8157 				dhdp->dhd_console_ms = 0;	/* On error, stop trying */
8158 		}
8159 	}
8160 #endif /* DHD_DEBUG */
8161 
8162 #ifdef SDTEST
8163 	/* Generate packets if configured */
8164 	if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
8165 		/* Make sure backplane clock is on */
8166 		if (SLPAUTO_ENAB(bus))
8167 			dhdsdio_bussleep(bus, FALSE);
8168 		else
8169 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8170 		bus->pktgen_tick = 0;
8171 		dhdsdio_pktgen(bus);
8172 	}
8173 #endif // endif
8174 
8175 	/* On idle timeout clear activity flag and/or turn off clock */
8176 #ifdef DHD_USE_IDLECOUNT
8177 	if (bus->activity)
8178 		bus->activity = FALSE;
8179 	else {
8180 		bus->idlecount++;
8181 
8182 		/*
8183 		 * If the condition to switch off the clock is reached And if
8184 		 * BT is inactive (in case of BT_OVER_SDIO build) turn off clk.
8185 		 *
8186 		 * Consider the following case, DHD is configured with
8187 		 * 1) idletime == DHD_IDLE_IMMEDIATE
8188 		 * 2) BT is the last user of the clock
8189 		 * We cannot disable the clock from __dhdsdio_clk_disable
8190 		 * since WLAN might be using it. If WLAN is active then
8191 		 * from the respective function/context after doing the job
8192 		 * the clk is turned off.
8193 		 * But if WLAN is actually inactive then the watchdog should
8194 		 * disable the clock. So the condition check below should be
8195 		 * bus->idletime != 0 instead of idletime == 0
8196 		 */
8197 		if ((bus->idletime != 0) && (bus->idlecount >= bus->idletime) &&
8198 			NO_OTHER_ACTIVE_BUS_USER(bus)) {
8199 			DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
8200 			if (SLPAUTO_ENAB(bus)) {
8201 				if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
8202 					dhd_os_wd_timer(bus->dhd, 0);
8203 			} else
8204 				dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8205 
8206 			bus->idlecount = 0;
8207 		}
8208 	}
8209 #else
8210 	if ((bus->idletime != 0) && (bus->clkstate == CLK_AVAIL) &&
8211 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8212 		if (++bus->idlecount >= bus->idletime) {
8213 			bus->idlecount = 0;
8214 			if (bus->activity) {
8215 				bus->activity = FALSE;
8216 #if !defined(OEM_ANDROID)
8217 			} else {
8218 #endif // endif
8219 				if (SLPAUTO_ENAB(bus)) {
8220 					if (!bus->readframes)
8221 						dhdsdio_bussleep(bus, TRUE);
8222 					else
8223 						bus->reqbussleep = TRUE;
8224 				} else {
8225 					dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8226 				}
8227 			}
8228 		}
8229 	}
8230 #endif /* DHD_USE_IDLECOUNT */
8231 
8232 	dhd_os_sdunlock(bus->dhd);
8233 
8234 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
8235 	DHD_BUS_BUSY_CLEAR_IN_WD(dhdp);
8236 	dhd_os_busbusy_wake(dhdp);
8237 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8238 
8239 	return bus->ipend;
8240 }
8241 
8242 extern int
8243 dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
8244 {
8245 	dhd_bus_t *bus = dhdp->bus;
8246 	uint32 addr, val;
8247 	int rv;
8248 	void *pkt;
8249 
8250 	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
8251 	if (bus->console_addr == 0)
8252 		return BCME_UNSUPPORTED;
8253 
8254 	/* Exclusive bus access */
8255 	dhd_os_sdlock(bus->dhd);
8256 
8257 	/* Don't allow input if dongle is in reset */
8258 	if (bus->dhd->dongle_reset) {
8259 		dhd_os_sdunlock(bus->dhd);
8260 		return BCME_NOTREADY;
8261 	}
8262 
8263 	/* Request clock to allow SDIO accesses */
8264 	BUS_WAKE(bus);
8265 	/* No pend allowed since txpkt is called later, ht clk has to be on */
8266 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8267 
8268 	/* Zero cbuf_index */
8269 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx);
8270 	val = htol32(0);
8271 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
8272 		goto done;
8273 
8274 	/* Write message into cbuf */
8275 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf);
8276 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
8277 		goto done;
8278 
8279 	/* Write length into vcons_in */
8280 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, vcons_in);
8281 	val = htol32(msglen);
8282 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
8283 		goto done;
8284 
8285 	/* Bump dongle by sending an empty packet on the event channel.
8286 	 * sdpcm_sendup (RX) checks for virtual console input.
8287 	 */
8288 	if ((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL)
8289 		rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
8290 
8291 done:
8292 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
8293 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8294 		bus->activity = FALSE;
8295 		dhdsdio_bussleep(bus, TRUE);
8296 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8297 	}
8298 
8299 	dhd_os_sdunlock(bus->dhd);
8300 
8301 	return rv;
8302 }
8303 
8304 #if defined(DHD_DEBUG) && !defined(BCMSDIOLITE) && !defined(BCMSPI)
8305 static void
8306 dhd_dump_cis(uint fn, uint8 *cis)
8307 {
8308 	uint byte, tag, tdata;
8309 	DHD_INFO(("Function %d CIS:\n", fn));
8310 
8311 	for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
8312 		if ((byte % 16) == 0)
8313 			DHD_INFO(("    "));
8314 		DHD_INFO(("%02x ", cis[byte]));
8315 		if ((byte % 16) == 15)
8316 			DHD_INFO(("\n"));
8317 		if (!tdata--) {
8318 			tag = cis[byte];
8319 			if (tag == 0xff)
8320 				break;
8321 			else if (!tag)
8322 				tdata = 0;
8323 			else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
8324 				tdata = cis[byte + 1] + 1;
8325 			else
8326 				DHD_INFO(("]"));
8327 		}
8328 	}
8329 	if ((byte % 16) != 15)
8330 		DHD_INFO(("\n"));
8331 }
8332 #endif /* DHD_DEBUG */
8333 
8334 static bool
8335 dhdsdio_chipmatch(uint16 chipid)
8336 {
8337 	if (chipid == BCM4335_CHIP_ID)
8338 		return TRUE;
8339 	if (chipid == BCM4339_CHIP_ID)
8340 		return TRUE;
8341 	if (BCM4345_CHIP(chipid))
8342 		return TRUE;
8343 	if (chipid == BCM4350_CHIP_ID)
8344 		return TRUE;
8345 	if (chipid == BCM4354_CHIP_ID)
8346 		return TRUE;
8347 	if (chipid == BCM4358_CHIP_ID)
8348 		return TRUE;
8349 	if (chipid == BCM43430_CHIP_ID)
8350 		return TRUE;
8351 	if (chipid == BCM43018_CHIP_ID)
8352 		return TRUE;
8353 	if (BCM4349_CHIP(chipid))
8354 		return TRUE;
8355 	if (chipid == BCM4373_CHIP_ID)
8356 		return TRUE;
8357 	if (chipid == BCM4364_CHIP_ID)
8358 			return TRUE;
8359 
8360 	if (chipid == BCM43012_CHIP_ID)
8361 		return TRUE;
8362 
8363 	if (chipid == BCM43014_CHIP_ID)
8364 		return TRUE;
8365 
8366 	if (chipid == BCM4369_CHIP_ID)
8367 		return TRUE;
8368 #ifdef CHIPS_CUSTOMER_HW6
8369 	if (BCM4378_CHIP(chipid)) {
8370 		return TRUE;
8371 	}
8372 #endif /* CHIPS_CUSTOMER_HW6 */
8373 	if (chipid == BCM4362_CHIP_ID)
8374 		return TRUE;
8375 	if (chipid == BCM43751_CHIP_ID)
8376 		return TRUE;
8377 	if (chipid == CYW55500_CHIP_ID)
8378 		return TRUE;
8379 	if (chipid == CYW55560_CHIP_ID)
8380 		return TRUE;
8381 	return FALSE;
8382 }
8383 
8384 static void *
8385 dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
8386 	uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
8387 {
8388 	int ret;
8389 	dhd_bus_t *bus;
8390 
8391 #if defined(MULTIPLE_SUPPLICANT)
8392 	if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
8393 		DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
8394 	} else {
8395 		DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
8396 	}
8397 	mutex_lock(&_dhd_sdio_mutex_lock_);
8398 #endif // endif
8399 
8400 	/* Init global variables at run-time, not as part of the declaration.
8401 	 * This is required to support init/de-init of the driver. Initialization
8402 	 * of globals as part of the declaration results in non-deterministic
8403 	 * behavior since the value of the globals may be different on the
8404 	 * first time that the driver is initialized vs subsequent initializations.
8405 	 */
8406 	dhd_txbound = DHD_TXBOUND;
8407 	dhd_rxbound = DHD_RXBOUND;
8408 #ifdef BCMSPI
8409 	dhd_alignctl = FALSE;
8410 #else
8411 	dhd_alignctl = TRUE;
8412 #endif /* BCMSPI */
8413 	sd1idle = TRUE;
8414 	dhd_readahead = TRUE;
8415 	retrydata = FALSE;
8416 
8417 #ifdef DISABLE_FLOW_CONTROL
8418 	dhd_doflow = FALSE;
8419 #endif /* DISABLE_FLOW_CONTROL */
8420 	dhd_dongle_ramsize = 0;
8421 	dhd_txminmax = DHD_TXMINMAX;
8422 
8423 #ifdef BCMSPI
8424 	forcealign = FALSE;
8425 #else
8426 	forcealign = TRUE;
8427 #endif /* !BCMSPI */
8428 
8429 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
8430 	DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
8431 
8432 	/* We make assumptions about address window mappings */
8433 	ASSERT((uintptr)regsva == si_enum_base(devid));
8434 
8435 	/* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
8436 	 * means early parse could fail, so here we should get either an ID
8437 	 * we recognize OR (-1) indicating we must request power first.
8438 	 */
8439 	/* Check the Vendor ID */
8440 	switch (venid) {
8441 		case 0x0000:
8442 		case VENDOR_BROADCOM:
8443 			break;
8444 		default:
8445 			DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
8446 			           __FUNCTION__, venid));
8447 			goto forcereturn;
8448 	}
8449 
8450 	/* Check the Device ID and make sure it's one that we support */
8451 	switch (devid) {
8452 		case 0:
8453 			DHD_INFO(("%s: allow device id 0, will check chip internals\n",
8454 			          __FUNCTION__));
8455 			break;
8456 
8457 		default:
8458 			DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
8459 			           __FUNCTION__, venid, devid));
8460 			goto forcereturn;
8461 	}
8462 
8463 	if (osh == NULL) {
8464 #if defined(BCMSPI) && (defined(BCMPCISPIHOST) || defined(BCMSDIOH_SPI))
8465 		/* bcmsdh_probe() calls drvinfo.probe() that is this function with osh as NULL */
8466 		if (!(osh = osl_attach(sdh, DHD_BUS, TRUE))) {
8467 			DHD_ERROR(("%s: osl_attach failed!\n", __FUNCTION__));
8468 			goto forcereturn;
8469 		}
8470 #else
8471 		DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__));
8472 		goto forcereturn;
8473 #endif /* BCMSPI && (defined(BCMPCISPIHOST) || defined(BCMSDIOH_SPI)) */
8474 	}
8475 
8476 	/* Allocate private bus interface state */
8477 	if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
8478 		DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
8479 		goto fail;
8480 	}
8481 	bzero(bus, sizeof(dhd_bus_t));
8482 	bus->sdh = sdh;
8483 	bus->cl_devid = (uint16)devid;
8484 	bus->bus = DHD_BUS;
8485 	bus->bus_num = bus_no;
8486 	bus->slot_num = slot;
8487 	bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
8488 	bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */
8489 #ifdef BT_OVER_SDIO
8490 	bus->bt_use_count = 0;
8491 #endif // endif
8492 
8493 #if defined(SUPPORT_P2P_GO_PS)
8494 	init_waitqueue_head(&bus->bus_sleep);
8495 #endif /* LINUX && SUPPORT_P2P_GO_PS */
8496 
8497 	/* attempt to attach to the dongle */
8498 	if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
8499 		DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__));
8500 		goto fail;
8501 	}
8502 
8503 	/* Attach to the dhd/OS/network interface */
8504 	if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) {
8505 		DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
8506 		goto fail;
8507 	}
8508 
8509 	/* Allocate buffers */
8510 	if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
8511 		DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
8512 		goto fail;
8513 	}
8514 
8515 	if (!(dhdsdio_probe_init(bus, osh, sdh))) {
8516 		DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__));
8517 		goto fail;
8518 	}
8519 
8520 	if (bus->intr) {
8521 		/* Register interrupt callback, but mask it (not operational yet). */
8522 		DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
8523 		bcmsdh_intr_disable(sdh);
8524 		if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
8525 			DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
8526 			           __FUNCTION__, ret));
8527 			goto fail;
8528 		}
8529 		DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
8530 	} else {
8531 		DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
8532 		           __FUNCTION__));
8533 	}
8534 
8535 	DHD_INFO(("%s: completed!!\n", __FUNCTION__));
8536 
8537 	/* if firmware path present try to download and bring up bus */
8538 	bus->dhd->hang_report  = TRUE;
8539 	if (dhd_download_fw_on_driverload) {
8540 		if ((ret = dhd_bus_start(bus->dhd)) != 0) {
8541 			DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__));
8542 #if !defined(OEM_ANDROID) || defined(BCMQT)
8543 			if (ret == BCME_NOTUP)
8544 #endif /* !OEM_ANDROID || defined(BCMQT) */
8545 				goto fail;
8546 		}
8547 	}
8548 	else {
8549 		/* Set random MAC address during boot time */
8550 		get_random_bytes(&bus->dhd->mac.octet[3], 3);
8551 		/* Adding BRCM OUI */
8552 		bus->dhd->mac.octet[0] = 0;
8553 		bus->dhd->mac.octet[1] = 0x90;
8554 		bus->dhd->mac.octet[2] = 0x4C;
8555 	}
8556 #if defined(BT_OVER_SDIO)
8557 	/* At this point Regulators are turned on and iconditionaly sdio bus is started
8558 	 * based upon dhd_download_fw_on_driverload check, so
8559 	 * increase the bus user count, this count will only be disabled inside
8560 	 * dhd_register_if() function if flag dhd_download_fw_on_driverload is set to false,
8561 	 * i.e FW download during insmod is not needed, otherwise it will not be decremented
8562 	 * so that WALN will always hold the bus untill rmmod is done.
8563 	 */
8564 	dhdsdio_bus_usr_cnt_inc(bus->dhd);
8565 #endif /* BT_OVER_SDIO */
8566 
8567 	/* Ok, have the per-port tell the stack we're open for business */
8568 	if (dhd_attach_net(bus->dhd, TRUE) != 0)
8569 	{
8570 		DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
8571 		goto fail;
8572 	}
8573 
8574 #ifdef BCMHOST_XTAL_PU_TIME_MOD
8575 	bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11);
8576 	bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001);
8577 #endif /* BCMHOST_XTAL_PU_TIME_MOD */
8578 
8579 #if defined(MULTIPLE_SUPPLICANT)
8580 	mutex_unlock(&_dhd_sdio_mutex_lock_);
8581 	DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
8582 #endif // endif
8583 
8584 	return bus;
8585 
8586 fail:
8587 	dhdsdio_release(bus, osh);
8588 
8589 forcereturn:
8590 #if defined(MULTIPLE_SUPPLICANT)
8591 	mutex_unlock(&_dhd_sdio_mutex_lock_);
8592 	DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
8593 #endif // endif
8594 
8595 	return NULL;
8596 }
8597 
8598 static bool
8599 dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
8600                      uint16 devid)
8601 {
8602 #ifdef BCMSPI
8603 	uint32 spidreg = 0;
8604 #else
8605 	uint8 clkctl = 0;
8606 	uint8 cardcap = 0;
8607 #endif /* BCMSPI */
8608 	uint fn, numfn;
8609 	uint8 *cis[SDIOD_MAX_IOFUNCS];
8610 	int32 value;
8611 	int32 size;
8612 	int err = 0;
8613 	hs_addrs_t bl_hs_addrs = {NULL, NULL};
8614 
8615 	BCM_REFERENCE(value);
8616 	bus->alp_only = TRUE;
8617 	bus->sih = NULL;
8618 
8619 #ifdef BCMSPI
8620 	spidreg = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_RESET_BP, NULL);
8621 	if (spidreg & SPID_SECURE_MODE) {
8622 		DHD_INFO(("Security related features are present\n"));
8623 		bus->secureboot = TRUE;
8624 	}
8625 	if (spidreg & SPID_CHIPID_PRESENT) {
8626 		DHD_INFO(("Chip ID is present in SPI core\n"));
8627 		bus->chipidpresent = true;
8628 	}
8629 #else
8630 	cardcap = dhdsdio_devcap_get(bus);
8631 	if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_SECURE_MODE) {
8632 		DHD_INFO(("Security related features are present\n"));
8633 		bus->secureboot = TRUE;
8634 	}
8635 	if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_CHIPID_PRESENT) {
8636 		DHD_INFO(("Chip ID is present in SDIO core\n"));
8637 		bus->chipidpresent = true;
8638 	}
8639 #endif /* BCMSPI */
8640 
8641 	if (bus->secureboot) {
8642 		/* Should not do any backplane access before bootloader is ready */
8643 		dhdsdio_dongle_host_get_handshake_address(bus, &bl_hs_addrs);
8644 		err = dhdsdio_wait_bootloader_ready(bus, &bl_hs_addrs);
8645 		if (err) {
8646 			DHD_ERROR(("Bootloader ready timeout\n"));
8647 			goto fail;
8648 		}
8649 	}
8650 
8651 	if (bus->chipidpresent) {
8652 		/* Get SDIO core base address */
8653 		bus->regs = si_get_sdio_addrbase(sdh);
8654 	}
8655 
8656 	/* Return the window to backplane enumeration space for core access */
8657 	if (dhdsdio_set_siaddr_window(bus, si_enum_base(devid))) {
8658 		DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
8659 	}
8660 
8661 #if defined(DHD_DEBUG) && !defined(CUSTOMER_HW4_DEBUG)
8662 	if (bus->chipidpresent) {
8663 		DHD_ERROR(("F1 signature read @0x%lx=0x%4x\n",
8664 			(unsigned long)&bus->regs->chipid, R_REG(osh, &bus->regs->chipid)));
8665 	} else {
8666 		DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n",
8667 			bcmsdh_reg_read(bus->sdh, si_enum_base(devid), 4)));
8668 	}
8669 #endif /* DHD_DEBUG && !CUSTOMER_HW4_DEBUG */
8670 
8671 #ifndef BCMSPI	/* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */
8672 
8673 	/* Force PLL off until si_attach() programs PLL control regs */
8674 
8675 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err);
8676 	if (!err)
8677 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
8678 
8679 	if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
8680 		DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
8681 				err, DHD_INIT_CLKCTL1, clkctl));
8682 		goto fail;
8683 	}
8684 
8685 #endif /* !BCMSPI */
8686 #ifdef BCMSPI
8687 	/* internally func is hardcoded to 1 as gSPI has cis on F1 only */
8688 	fn = 0;
8689 	value = F0_BLOCK_SIZE;
8690 	/* Get block size from sd */
8691 	if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32),
8692 			&size, sizeof(int32), FALSE) != BCME_OK) {
8693 		size = 0;
8694 		DHD_ERROR(("%s: fail on fn %d %s get\n",
8695 				__FUNCTION__, fn, "sd_blocksize"));
8696 	} else {
8697 		DHD_INFO(("%s: Initial value for fn %d %s is %d\n",
8698 				__FUNCTION__, fn, "sd_blocksize", size));
8699 	}
8700 	if (size != 0 && size < value) {
8701 		value = size;
8702 	}
8703 	value = fn << 16 | value;
8704 	if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &value,
8705 			sizeof(value), TRUE) != BCME_OK) {
8706 		bus->blocksize = 0;
8707 		DHD_ERROR(("%s: fail on fn %d %s set\n", __FUNCTION__,
8708 				fn, "sd_blocksize"));
8709 	}
8710 	BCM_REFERENCE(cis);
8711 	BCM_REFERENCE(numfn);
8712 #else
8713 	numfn = bcmsdh_query_iofnum(sdh);
8714 	ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
8715 
8716 	/* Make sure ALP is available before trying to read CIS */
8717 	SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
8718 			SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
8719 			!SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
8720 
8721 	/* Now request ALP be put on the bus */
8722 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
8723 			DHD_INIT_CLKCTL2, &err);
8724 	OSL_DELAY(65);
8725 #ifndef BCMSDIOLITE
8726 	for (fn = 0; fn <= numfn; fn++) {
8727 		if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
8728 			DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn));
8729 			break;
8730 		}
8731 		bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
8732 
8733 		if ((err = bcmsdh_cis_read(sdh, fn, cis[fn],
8734 				SBSDIO_CIS_SIZE_LIMIT))) {
8735 			DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err));
8736 			MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
8737 			break;
8738 		}
8739 
8740 		/* Reading the F1, F2 and F3 max blocksize values from CIS
8741 		 * and writing into the F1, F2 and F3	block size registers.
8742 		 * There is no max block size register value available for F0 in CIS register.
8743 		 * So, setting default value for F0 block size as 32 (which was set earlier
8744 		 * in iovar). IOVAR takes only one arguement.
8745 		 * So, we are passing the function number alongwith the value (fn<<16)
8746 		 */
8747 		if (!fn)
8748 			value = F0_BLOCK_SIZE;
8749 		else
8750 			value = (cis[fn][25]<<8) | cis[fn][24] | (fn<<16);
8751 		/* Get block size from sd */
8752 		if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32),
8753 				&size, sizeof(int32), FALSE) != BCME_OK) {
8754 			size = 0;
8755 			DHD_ERROR(("%s: fail on fn %d %s get\n",
8756 					__FUNCTION__, fn, "sd_blocksize"));
8757 		} else {
8758 			DHD_INFO(("%s: Initial value for fn %d %s is %d\n",
8759 					__FUNCTION__, fn, "sd_blocksize", size));
8760 		}
8761 		if (size != 0 && size < value) {
8762 			value = size;
8763 		}
8764 		value = fn << 16 | value;
8765 		if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &value,
8766 				sizeof(value), TRUE) != BCME_OK) {
8767 			bus->blocksize = 0;
8768 			DHD_ERROR(("%s: fail on fn %d %s set\n", __FUNCTION__,
8769 					fn, "sd_blocksize"));
8770 		}
8771 
8772 		/* F2 blocksize value can be taken in order of precedence of
8773 		 *	insmod argument
8774 		 *	build flag variable
8775 		 *	CIS tuple
8776 		 *	default parameter
8777 		 */
8778 		if (fn == F2_BLOCK) {
8779 			if (!sd_f2_blocksize) {
8780 #ifdef CUSTOM_SDIO_F2_BLKSIZE
8781 				sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE;
8782 #else
8783 				sd_f2_blocksize = ((uint16)value ? (uint16)value :
8784 						DEFAULT_SDIO_F2_BLKSIZE);
8785 #endif /* CUSTOM_SDIO_F2_BLKSIZE */
8786 			}
8787 
8788 			value = (fn << SDIO_FUNC_BLOCK_SIZE_SHIFT) | sd_f2_blocksize;
8789 			if (bcmsdh_iovar_op(sdh, "sd_blocksize",
8790 					NULL, 0, &value, sizeof(fn), TRUE) != BCME_OK) {
8791 				DHD_ERROR(("%s: Set F2 Block size error\n",
8792 						__FUNCTION__));
8793 				goto fail;
8794 			}
8795 		}
8796 
8797 #ifdef DHD_DEBUG
8798 		if (DHD_INFO_ON()) {
8799 			dhd_dump_cis(fn, cis[fn]);
8800 		}
8801 #endif /* DHD_DEBUG */
8802 	}
8803 	while (fn-- > 0) {
8804 		ASSERT(cis[fn]);
8805 		MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
8806 	}
8807 #else
8808 	BCM_REFERENCE(cis);
8809 	BCM_REFERENCE(fn);
8810 #endif /* !BCMSDIOLITE */
8811 #endif /* !BCMSPI */
8812 	if (err) {
8813 		DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n"));
8814 		goto fail;
8815 	}
8816 
8817 	/* si_attach() will provide an SI handle and scan the backplane */
8818 	if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
8819 	                           &bus->vars, &bus->varsz))) {
8820 		DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
8821 		goto fail;
8822 	}
8823 
8824 #ifdef DHD_DEBUG
8825 	DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n",
8826 		bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg));
8827 #endif /* DHD_DEBUG */
8828 
8829 #ifdef DHD_MAP_CHIP_FIRMWARE_PATH
8830     bus->chipmodule = sd_chip_module;
8831 #endif /* DHD_MAP_CHIP_FIRMWARE_PATH */
8832 
8833 	bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
8834 
8835 	if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
8836 		DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
8837 		           __FUNCTION__, bus->sih->chip));
8838 		goto fail;
8839 	}
8840 
8841 	if (bus->sih->buscorerev >= 12)
8842 		dhdsdio_clk_kso_init(bus);
8843 	else
8844 		bus->kso = TRUE;
8845 
8846 	si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
8847 
8848 	/* Get info on the ARM and SOCRAM cores... */
8849 	if (!DHD_NOPMU(bus)) {
8850 		if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
8851 		    (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
8852 		    (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
8853 			bus->armrev = si_corerev(bus->sih);
8854 		} else {
8855 			DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
8856 			goto fail;
8857 		}
8858 
8859 		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
8860 			if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
8861 				DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
8862 				goto fail;
8863 			}
8864 		} else {
8865 			/* cr4 has a different way to find the RAM size from TCM's */
8866 			if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
8867 				DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
8868 				goto fail;
8869 			}
8870 			/* also populate base address */
8871 			switch ((uint16)bus->sih->chip) {
8872 			case BCM4335_CHIP_ID:
8873 			case BCM4339_CHIP_ID:
8874 				bus->dongle_ram_base = CR4_4335_RAM_BASE;
8875 				break;
8876 			case BCM4350_CHIP_ID:
8877 			case BCM4354_CHIP_ID:
8878 			case BCM4358_CHIP_ID:
8879 				bus->dongle_ram_base = CR4_4350_RAM_BASE;
8880 				break;
8881 			case BCM4360_CHIP_ID:
8882 				bus->dongle_ram_base = CR4_4360_RAM_BASE;
8883 				break;
8884 			CASE_BCM4345_CHIP:
8885 				bus->dongle_ram_base = (bus->sih->chiprev < 6)  /* from 4345C0 */
8886 					? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
8887 				break;
8888 			case BCM4349_CHIP_GRPID:
8889 				/* RAM based changed from 4349c0(revid=9) onwards */
8890 				bus->dongle_ram_base = ((bus->sih->chiprev < 9) ?
8891 					CR4_4349_RAM_BASE: CR4_4349_RAM_BASE_FROM_REV_9);
8892 				break;
8893 			case BCM4373_CHIP_ID:
8894 				bus->dongle_ram_base = CR4_4373_RAM_BASE;
8895 				/* Updating F2 Block size to 256 for 4373 to fix TX Transmit
8896 				 * Underflow issue during Bi-Directional Traffic
8897 				 */
8898 				{
8899 					uint fn = 2;
8900 					fn = fn << SDIO_FUNC_BLOCK_SIZE_SHIFT | F2_BLOCK_SIZE_256;
8901 					if (bcmsdh_iovar_op(sdh, "sd_blocksize",
8902 						NULL, 0, &fn, sizeof(fn), TRUE) != BCME_OK) {
8903 						DHD_ERROR(("%s: Set F2 Block size error\n",
8904 						__FUNCTION__));
8905 						goto fail;
8906 					}
8907 				}
8908 				break;
8909 			case BCM4364_CHIP_ID:
8910 				bus->dongle_ram_base = CR4_4364_RAM_BASE;
8911 				break;
8912 			case BCM4362_CHIP_ID:
8913 				bus->dongle_ram_base = CR4_4362_RAM_BASE;
8914 				break;
8915 			case BCM43751_CHIP_ID:
8916 				bus->dongle_ram_base = CR4_43751_RAM_BASE;
8917 				break;
8918 			case BCM4369_CHIP_ID:
8919 				bus->dongle_ram_base = CR4_4369_RAM_BASE;
8920 				break;
8921 			case CYW55500_CHIP_ID:
8922 				bus->dongle_ram_base = CR4_55500_RAM_BASE;
8923 				break;
8924 			case CYW55560_CHIP_ID:
8925 				bus->dongle_ram_base = CR4_55560_RAM_BASE;
8926 				break;
8927 #ifdef CHIPS_CUSTOMER_HW6
8928 			case BCM4378_CHIP_GRPID:
8929 				bus->dongle_ram_base = CR4_4378_RAM_BASE;
8930 				break;
8931 #endif /* CHIPS_CUSTOMER_HW6 */
8932 			default:
8933 				bus->dongle_ram_base = 0;
8934 				DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
8935 				           __FUNCTION__, bus->dongle_ram_base));
8936 			}
8937 		}
8938 
8939 		/* 55560, Dedicated space for TCAM patching and TRX Hader at RAMBASE */
8940 		/* TCAM Patching - 2048[2K], TRX Header - 32Bytes */
8941 		if (bus->sih->chip == CYW55500_CHIP_ID) {
8942 			bus->orig_ramsize -= (CR4_55500_TCAM_SZ + CR4_55500_TRX_HDR_SZ);
8943 		} else if (bus->sih->chip == CYW55560_CHIP_ID) {
8944 			bus->orig_ramsize -= (CR4_55560_TCAM_SZ + CR4_55560_TRX_HDR_SZ);
8945 		}
8946 
8947 		bus->ramsize = bus->orig_ramsize;
8948 		if (dhd_dongle_ramsize)
8949 			dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
8950 
8951 		DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
8952 		           bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
8953 
8954 		bus->srmemsize = si_socram_srmem_size(bus->sih);
8955 	}
8956 
8957 	/* ...but normally deal with the SDPCMDEV core */
8958 #ifdef BCMSDIOLITE
8959 	if (!(bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0))) {
8960 		DHD_ERROR(("%s: failed to find Chip Common core!\n", __FUNCTION__));
8961 		goto fail;
8962 	}
8963 #else
8964 	if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
8965 	    !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
8966 		DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
8967 		goto fail;
8968 	}
8969 #endif // endif
8970 	bus->sdpcmrev = si_corerev(bus->sih);
8971 
8972 	/* Set core control so an SDIO reset does a backplane reset */
8973 	OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
8974 #ifndef BCMSPI
8975 	bus->rxint_mode = SDIO_DEVICE_HMB_RXINT;
8976 
8977 	if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
8978 		(bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1))
8979 	{
8980 		uint32 val;
8981 
8982 		val = R_REG(osh, &bus->regs->corecontrol);
8983 		val &= ~CC_XMTDATAAVAIL_MODE;
8984 		val |= CC_XMTDATAAVAIL_CTRL;
8985 		W_REG(osh, &bus->regs->corecontrol, val);
8986 	}
8987 #endif /* BCMSPI */
8988 
8989 	pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
8990 
8991 	/* Locate an appropriately-aligned portion of hdrbuf */
8992 	bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN);
8993 
8994 	/* Set the poll and/or interrupt flags */
8995 	bus->intr = (bool)dhd_intr;
8996 	if ((bus->poll = (bool)dhd_poll))
8997 		bus->pollrate = 1;
8998 
8999 	/* Setting default Glom size */
9000 	bus->txglomsize = SDPCM_DEFGLOM_SIZE;
9001 
9002 	return TRUE;
9003 
9004 fail:
9005 	if (bus->sih != NULL) {
9006 		si_detach(bus->sih);
9007 		bus->sih = NULL;
9008 	}
9009 	return FALSE;
9010 }
9011 
9012 static bool
9013 dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
9014 {
9015 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9016 
9017 	if (bus->dhd->maxctl) {
9018 		bus->rxblen = ROUNDUP((bus->dhd->maxctl+SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
9019 		if (!(bus->rxbuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxblen))) {
9020 			DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
9021 			           __FUNCTION__, bus->rxblen));
9022 			goto fail;
9023 		}
9024 	}
9025 	/* Allocate buffer to receive glomed packet */
9026 	if (!(bus->databuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
9027 		DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
9028 			__FUNCTION__, MAX_DATA_BUF));
9029 		/* release rxbuf which was already located as above */
9030 		if (!bus->rxblen)
9031 			DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen);
9032 		goto fail;
9033 	}
9034 
9035 #ifdef DHD_SDIO_MEM_BUF
9036     bus->membuf = MALLOC(osh, MAX_MEM_BUF);
9037     if (bus->membuf == NULL) {
9038         DHD_ERROR(("%s: MALLOC of %d-byte membuf failed\n", __FUNCTION__, MAX_MEM_BUF));
9039         if (bus->databuf) {
9040         #ifndef CONFIG_DHD_USE_STATIC_BUF
9041             MFREE(osh, bus->databuf, MAX_DATA_BUF);
9042         #endif /* CONFIG_DHD_USE_STATIC_BUF */
9043             bus->databuf = NULL;
9044         }
9045         if (!bus->rxblen)
9046             DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen);
9047         goto fail;
9048     }
9049     memset(bus->membuf, 0, MAX_MEM_BUF);
9050 #endif /* DHD_SDIO_MEM_BUF */
9051 
9052 	/* Align the buffer */
9053 	if ((uintptr)bus->databuf % DHD_SDALIGN)
9054 		bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
9055 	else
9056 		bus->dataptr = bus->databuf;
9057 
9058 	return TRUE;
9059 
9060 fail:
9061 	return FALSE;
9062 }
9063 
9064 static bool
9065 dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
9066 {
9067 	int32 fnum;
9068 
9069 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9070 
9071 	bus->_srenab = FALSE;
9072 
9073 #ifdef SDTEST
9074 	dhdsdio_pktgen_init(bus);
9075 #endif /* SDTEST */
9076 
9077 #ifndef BCMSPI
9078 	/* Disable F2 to clear any intermediate frame state on the dongle */
9079 	bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
9080 #endif /* !BCMSPI */
9081 
9082 	DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
9083 	bus->dhd->busstate = DHD_BUS_DOWN;
9084 	bus->sleeping = FALSE;
9085 	bus->rxflow = FALSE;
9086 	bus->prev_rxlim_hit = 0;
9087 
9088 #ifndef BCMSPI
9089 	/* Done with backplane-dependent accesses, can drop clock... */
9090 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
9091 #endif /* !BCMSPI */
9092 
9093 	/* ...and initialize clock/power states */
9094 	bus->clkstate = CLK_SDONLY;
9095 	bus->idletime = (int32)dhd_idletime;
9096 	bus->idleclock = DHD_IDLE_ACTIVE;
9097 
9098 	/* Query the SD clock speed */
9099 	if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
9100 	                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
9101 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"));
9102 		bus->sd_divisor = -1;
9103 	} else {
9104 		DHD_INFO(("%s: Initial value for %s is %d\n",
9105 		          __FUNCTION__, "sd_divisor", bus->sd_divisor));
9106 	}
9107 
9108 	/* Query the SD bus mode */
9109 	if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
9110 	                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
9111 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode"));
9112 		bus->sd_mode = -1;
9113 	} else {
9114 		DHD_INFO(("%s: Initial value for %s is %d\n",
9115 		          __FUNCTION__, "sd_mode", bus->sd_mode));
9116 	}
9117 
9118 	/* Query the F2 block size, set roundup accordingly */
9119 	fnum = 2;
9120 	if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
9121 	                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
9122 		bus->blocksize = 0;
9123 		DHD_ERROR(("%s: fail on fn %d %s get\n", __FUNCTION__, fnum, "sd_blocksize"));
9124 	} else {
9125 		DHD_INFO(("%s: Initial value for fn %d %s is %d\n",
9126 		          __FUNCTION__, fnum, "sd_blocksize", bus->blocksize));
9127 
9128 		dhdsdio_tune_fifoparam(bus);
9129 	}
9130 	bus->roundup = MIN(max_roundup, bus->blocksize);
9131 
9132 #ifdef DHDENABLE_TAILPAD
9133 	if (bus->pad_pkt)
9134 		PKTFREE(osh, bus->pad_pkt, FALSE);
9135 	bus->pad_pkt = PKTGET(osh, SDIO_MAX_BLOCK_SIZE, FALSE);
9136 	if (bus->pad_pkt == NULL)
9137 		DHD_ERROR(("failed to allocate padding packet\n"));
9138 	else {
9139 		int alignment_offset = 0;
9140 		uintptr pktprt = (uintptr)PKTDATA(osh, bus->pad_pkt);
9141 		if (!(pktprt&1) && (pktprt = (pktprt % DHD_SDALIGN)))
9142 			PKTPUSH(osh, bus->pad_pkt, alignment_offset);
9143 		PKTSETNEXT(osh, bus->pad_pkt, NULL);
9144 	}
9145 #endif /* DHDENABLE_TAILPAD */
9146 
9147 	/* Query if bus module supports packet chaining, default to use if supported */
9148 	if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
9149 	                    &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) {
9150 		bus->sd_rxchain = FALSE;
9151 	} else {
9152 		DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
9153 		          __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")));
9154 	}
9155 	bus->use_rxchain = (bool)bus->sd_rxchain;
9156 	bus->txinrx_thres = CUSTOM_TXINRX_THRES;
9157 	/* TX first in dhdsdio_readframes() */
9158 	bus->dotxinrx = TRUE;
9159 
9160 	return TRUE;
9161 }
9162 
9163 int
9164 dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
9165                           char *pfw_path, char *pnv_path)
9166 {
9167 	int ret;
9168 
9169 	bus->fw_path = pfw_path;
9170 	bus->nv_path = pnv_path;
9171 
9172 	ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
9173 
9174 #if defined(BCMSPI) && defined(GSPI_DWORD_MODE)
9175 	/* Enable the dwordmode in gSPI before first F2 transaction */
9176 	if (((bus->sih->chip == BCM4329_CHIP_ID) && (bus->sih->chiprev > 1)) ||
9177 		(bus->sih->chip == BCM43430_CHIP_ID)) {
9178 			bcmsdh_dwordmode(bus->sdh, TRUE);
9179 			bus->dwordmode = TRUE;
9180 			DHD_INFO(("DHD:SPI DWORD mode enabled\n"));
9181 	}
9182 #endif /* defined(BCMSPI) && defined(GSPI_DWORD_MODE) */
9183 
9184 	return ret;
9185 }
9186 
9187 static int
9188 dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
9189 {
9190 	int ret;
9191 
9192 #if defined(SUPPORT_MULTIPLE_REVISION)
9193 	if (concate_revision(bus, bus->fw_path, bus->nv_path) != 0) {
9194 		DHD_ERROR(("%s: fail to concatnate revison \n",
9195 			__FUNCTION__));
9196 		return BCME_BADARG;
9197 	}
9198 #endif /* SUPPORT_MULTIPLE_REVISION */
9199 
9200 #if defined(DHD_BLOB_EXISTENCE_CHECK)
9201 	dhd_set_blob_support(bus->dhd, bus->fw_path);
9202 #endif /* DHD_BLOB_EXISTENCE_CHECK */
9203 
9204 	DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
9205 		__FUNCTION__, bus->fw_path, bus->nv_path));
9206 	DHD_OS_WAKE_LOCK(bus->dhd);
9207 
9208 	/* Download the firmware */
9209 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
9210 
9211 	ret = _dhdsdio_download_firmware(bus);
9212 
9213 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
9214 
9215 	DHD_OS_WAKE_UNLOCK(bus->dhd);
9216 	return ret;
9217 }
9218 
9219 /* Detach and free everything */
9220 static void
9221 dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
9222 {
9223 	bool dongle_isolation = FALSE;
9224 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9225 
9226 	if (bus) {
9227 		ASSERT(osh);
9228 
9229 		if (bus->dhd) {
9230 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
9231 			debugger_close();
9232 #endif /* DEBUGGER || DHD_DSCOPE */
9233 			dongle_isolation = bus->dhd->dongle_isolation;
9234 			dhd_detach(bus->dhd);
9235 		}
9236 
9237 		/* De-register interrupt handler */
9238 		bcmsdh_intr_disable(bus->sdh);
9239 		bcmsdh_intr_dereg(bus->sdh);
9240 
9241 		if (bus->dhd) {
9242 			dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
9243 			dhd_free(bus->dhd);
9244 			bus->dhd = NULL;
9245 		}
9246 
9247 		dhdsdio_release_malloc(bus, osh);
9248 
9249 #ifdef DHD_DEBUG
9250 		if (bus->console.buf != NULL)
9251 			MFREE(osh, bus->console.buf, bus->console.bufsize);
9252 #endif // endif
9253 
9254 #ifdef DHDENABLE_TAILPAD
9255 		if (bus->pad_pkt)
9256 			PKTFREE(osh, bus->pad_pkt, FALSE);
9257 #endif /* DHDENABLE_TAILPAD */
9258 
9259 		MFREE(osh, bus, sizeof(dhd_bus_t));
9260 	}
9261 
9262 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
9263 }
9264 
9265 static void
9266 dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
9267 {
9268 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9269 
9270 	if (bus->dhd && bus->dhd->dongle_reset)
9271 		return;
9272 
9273 	if (bus->rxbuf) {
9274 #ifndef CONFIG_DHD_USE_STATIC_BUF
9275 		MFREE(osh, bus->rxbuf, bus->rxblen);
9276 #endif // endif
9277 		bus->rxctl = bus->rxbuf = NULL;
9278 		bus->rxlen = 0;
9279 	}
9280 
9281 	if (bus->databuf) {
9282 #ifndef CONFIG_DHD_USE_STATIC_BUF
9283 		MFREE(osh, bus->databuf, MAX_DATA_BUF);
9284 #endif // endif
9285 		bus->databuf = NULL;
9286 	}
9287 
9288 #ifdef DHD_SDIO_MEM_BUF
9289 	if (bus->membuf) {
9290 		MFREE(osh, bus->membuf, MAX_MEM_BUF);
9291 		bus->membuf = NULL;
9292 	}
9293 #endif /* DHD_SDIO_MEM_BUF */
9294 
9295 	if (bus->vars && bus->varsz) {
9296 		MFREE(osh, bus->vars, bus->varsz);
9297 		bus->vars = NULL;
9298 	}
9299 
9300 }
9301 
9302 static void
9303 dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
9304 {
9305 #if !defined(BCMLXSDMMC)
9306 	int32 bcmerror = BCME_ERROR;
9307 #endif // endif
9308 
9309 	DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
9310 		bus->dhd, bus->dhd->dongle_reset));
9311 
9312 	if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
9313 		return;
9314 
9315 	if (bus->sih) {
9316 		/* In Win10, system will be BSOD if using "sysprep" to do OS image */
9317 		/* Skip this will not cause the BSOD. */
9318 #if !defined(BCMLXSDMMC)
9319 		if (bus->dhd) {
9320 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
9321 		}
9322 		if (KSO_ENAB(bus) && (dongle_isolation == FALSE)) {
9323 			if (bus->secureboot) {
9324 				/*
9325 				 * CYW555x0 - As part of watchdog reset, ARM gets
9326 				 * reset and bootloader starts from fresh,
9327 				 * So, pre wd reset sequcnce defined to make
9328 				 * sure H2D regs are initialized to zero
9329 				 */
9330 				if ((bcmerror =
9331 					dhdsdio_dongle_host_pre_wd_reset_sequence(bus)))
9332 				{
9333 					DHD_ERROR(("%s: error %d pre wd reset seq.\n",
9334 						__FUNCTION__, bcmerror));
9335 				}
9336 			}
9337 
9338 			if (bus->chipidpresent) {
9339 				/*
9340 				 * Configure registers to trigger WLAN reset on
9341 				 * "SDIO Soft Reset", and set RES bit to trigger SDIO as
9342 				 * well as WLAN reset (instead of using PMU/CC Watchdog register)
9343 				 */
9344 				uint8 cardctl;
9345 				cardctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
9346 						SDIOD_CCCR_BRCM_CARDCTL, &bcmerror);
9347 				cardctl |= SDIOD_CCCR_BRCM_WLANRST_ONF0ABORT;
9348 				if (!bcmerror) {
9349 					bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0,
9350 							SDIOD_CCCR_BRCM_CARDCTL, cardctl,
9351 							&bcmerror);
9352 				}
9353 				if (!bcmerror) {
9354 					bcmerror = bcmsdh_abort(bus->sdh, SDIO_FUNC_0 | 0x8);
9355 					DHD_ERROR(("%s: Set WLANRST in cardctl error %d\n",
9356 							__FUNCTION__, bcmerror));
9357 				}
9358 			} else {
9359 				si_watchdog(bus->sih, 4);
9360 			}
9361 
9362 		}
9363 #endif /* !defined(BCMLXSDMMC) */
9364 		if (bus->dhd) {
9365 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
9366 		}
9367 		si_detach(bus->sih);
9368 		bus->sih = NULL;
9369 		if (bus->vars && bus->varsz)
9370 			MFREE(osh, bus->vars, bus->varsz);
9371 		bus->vars = NULL;
9372 	}
9373 
9374 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
9375 }
9376 
9377 static void
9378 dhdsdio_disconnect(void *ptr)
9379 {
9380 	dhd_bus_t *bus = (dhd_bus_t *)ptr;
9381 
9382 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9383 
9384 #if defined(MULTIPLE_SUPPLICANT)
9385 	if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
9386 		DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
9387 	} else {
9388 		DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
9389 	}
9390 	mutex_lock(&_dhd_sdio_mutex_lock_);
9391 #endif // endif
9392 
9393 	if (bus) {
9394 		ASSERT(bus->dhd);
9395 		/* Advertise bus cleanup during rmmod */
9396 		dhdsdio_advertise_bus_cleanup(bus->dhd);
9397 		dhdsdio_release(bus, bus->dhd->osh);
9398 	}
9399 
9400 #if defined(MULTIPLE_SUPPLICANT)
9401 	mutex_unlock(&_dhd_sdio_mutex_lock_);
9402 	DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
9403 #endif /* LINUX */
9404 
9405 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
9406 }
9407 
9408 static int
9409 dhdsdio_suspend(void *context)
9410 {
9411 	int ret = 0;
9412 #ifdef SUPPORT_P2P_GO_PS
9413 	int wait_time = 0;
9414 #endif /* SUPPORT_P2P_GO_PS */
9415 
9416 	dhd_bus_t *bus = (dhd_bus_t*)context;
9417 	unsigned long flags;
9418 
9419 	DHD_ERROR(("%s Enter\n", __FUNCTION__));
9420 	if (bus->dhd == NULL) {
9421 		DHD_ERROR(("bus not inited\n"));
9422 		return BCME_ERROR;
9423 	}
9424 	if (bus->dhd->prot == NULL) {
9425 		DHD_ERROR(("prot is not inited\n"));
9426 		return BCME_ERROR;
9427 	}
9428 
9429 	if (bus->dhd->up == FALSE) {
9430 		return BCME_OK;
9431 	}
9432 
9433 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
9434 	if (bus->dhd->busstate != DHD_BUS_DATA && bus->dhd->busstate != DHD_BUS_SUSPEND) {
9435 		DHD_ERROR(("not in a readystate to LPBK  is not inited\n"));
9436 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
9437 		return BCME_ERROR;
9438 	}
9439 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
9440 	if (bus->dhd->dongle_reset) {
9441 		DHD_ERROR(("Dongle is in reset state.\n"));
9442 		return -EIO;
9443 	}
9444 
9445 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
9446 	/* stop all interface network queue. */
9447 	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
9448 	bus->dhd->busstate = DHD_BUS_SUSPEND;
9449 	if (DHD_BUS_BUSY_CHECK_IN_TX(bus->dhd)) {
9450 		DHD_ERROR(("Tx Request is not ended\n"));
9451 		bus->dhd->busstate = DHD_BUS_DATA;
9452 		/* resume all interface network queue. */
9453 		dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
9454 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
9455 		return -EBUSY;
9456 	}
9457 	DHD_BUS_BUSY_SET_SUSPEND_IN_PROGRESS(bus->dhd);
9458 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
9459 
9460 #ifdef SUPPORT_P2P_GO_PS
9461 	if (bus->idletime > 0) {
9462 		wait_time = msecs_to_jiffies(bus->idletime * dhd_watchdog_ms);
9463 	}
9464 #endif /* SUPPORT_P2P_GO_PS */
9465 	ret = dhd_os_check_wakelock(bus->dhd);
9466 #ifdef SUPPORT_P2P_GO_PS
9467 	if ((!ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) {
9468 		if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) {
9469 			if (!bus->sleeping) {
9470 				ret = 1;
9471 			}
9472 		}
9473 	}
9474 #endif /* SUPPORT_P2P_GO_PS */
9475 
9476 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
9477 	if (ret) {
9478 		bus->dhd->busstate = DHD_BUS_DATA;
9479 		/* resume all interface network queue. */
9480 		dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
9481 	}
9482 	DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd);
9483 	dhd_os_busbusy_wake(bus->dhd);
9484 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
9485 	return ret;
9486 }
9487 
9488 static int
9489 dhdsdio_resume(void *context)
9490 {
9491 	dhd_bus_t *bus = (dhd_bus_t*)context;
9492 	ulong flags;
9493 
9494 	DHD_ERROR(("%s Enter\n", __FUNCTION__));
9495 
9496 	if (bus->dhd->up == FALSE) {
9497 		return BCME_OK;
9498 	}
9499 
9500 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
9501 	DHD_BUS_BUSY_SET_RESUME_IN_PROGRESS(bus->dhd);
9502 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
9503 
9504 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
9505 	if (dhd_os_check_if_up(bus->dhd))
9506 		bcmsdh_oob_intr_set(bus->sdh, TRUE);
9507 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
9508 
9509 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
9510 	DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd);
9511 	bus->dhd->busstate = DHD_BUS_DATA;
9512 	dhd_os_busbusy_wake(bus->dhd);
9513 	/* resume all interface network queue. */
9514 	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
9515 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
9516 
9517 	return 0;
9518 }
9519 
9520 /* Register/Unregister functions are called by the main DHD entry
9521  * point (e.g. module insertion) to link with the bus driver, in
9522  * order to look for or await the device.
9523  */
9524 
9525 static bcmsdh_driver_t dhd_sdio = {
9526 	dhdsdio_probe,
9527 	dhdsdio_disconnect,
9528 	dhdsdio_suspend,
9529 	dhdsdio_resume
9530 };
9531 
9532 int
9533 dhd_bus_register(void)
9534 {
9535 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9536 
9537 	return bcmsdh_register(&dhd_sdio);
9538 }
9539 
9540 void
9541 dhd_bus_unregister(void)
9542 {
9543 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9544 
9545 	bcmsdh_unregister();
9546 }
9547 
9548 #if defined(BCMLXSDMMC)
9549 /* Register a dummy SDIO client driver in order to be notified of new SDIO device */
9550 int dhd_bus_reg_sdio_notify(void* semaphore)
9551 {
9552 	return bcmsdh_reg_sdio_notify(semaphore);
9553 }
9554 
9555 void dhd_bus_unreg_sdio_notify(void)
9556 {
9557 	bcmsdh_unreg_sdio_notify();
9558 }
9559 #endif /* defined(BCMLXSDMMC) */
9560 
9561 static int
9562 dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
9563 {
9564 	int bcmerror = -1;
9565 	int offset = 0;
9566 	int len;
9567 	void *image = NULL;
9568 	uint8 *memblock = NULL, *memptr;
9569 	uint memblock_size = MEMBLOCK;
9570 	struct trx_header *trx_hdr;
9571 	bool trx_chk = TRUE;
9572 #ifdef DHD_DEBUG_DOWNLOADTIME
9573 	unsigned long initial_jiffies = 0;
9574 	uint firmware_sz = 0;
9575 #endif // endif
9576 
9577 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
9578 
9579 	image = dhd_os_open_image1(bus->dhd, pfw_path);
9580 	if (image == NULL) {
9581 		DHD_ERROR(("%s: Failed to open fw file !\n", __FUNCTION__));
9582 		goto err;
9583 	}
9584 
9585 	/* Update the dongle image download block size depending on the F1 block size */
9586 	if (sd_f1_blocksize == 512)
9587 		memblock_size = MAX_MEMBLOCK;
9588 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
9589 	if (memblock == NULL) {
9590 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
9591 			memblock_size));
9592 		goto err;
9593 	}
9594 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
9595 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
9596 
9597 #ifdef DHD_DEBUG_DOWNLOADTIME
9598 	initial_jiffies = jiffies;
9599 #endif // endif
9600 
9601 	/* Download image */
9602 	while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) {
9603 		if (len < 0) {
9604 			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
9605 			bcmerror = BCME_ERROR;
9606 			goto err;
9607 		}
9608 		/* check if CR4 */
9609 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
9610 			/* if address is 0, store the reset instruction to be written in 0 */
9611 
9612 			if (offset == 0) {
9613 				bus->resetinstr = *(((uint32*)memptr));
9614 				/* Add start of RAM address to the address given by user */
9615 				offset += bus->dongle_ram_base;
9616 			}
9617 		}
9618 
9619 		/* Check for trx file */
9620 		if (trx_chk && (len >= sizeof(struct trx_header))) {
9621 			trx_chk = FALSE;
9622 			trx_hdr = (struct trx_header *)memptr;
9623 			if (trx_hdr->magic == TRX_MAGIC) {
9624 				/* CYW555x0, we need to write TRX header at RAMSTART */
9625 				offset -= sizeof(struct trx_header);
9626 			}
9627 		}
9628 
9629 		bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
9630 		if (bcmerror) {
9631 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
9632 			        __FUNCTION__, bcmerror, memblock_size, offset));
9633 			goto err;
9634 		}
9635 
9636 		offset += memblock_size;
9637 #ifdef DHD_DEBUG_DOWNLOADTIME
9638 		firmware_sz += len;
9639 #endif // endif
9640 	}
9641 
9642 #ifdef DHD_DEBUG_DOWNLOADTIME
9643 	DHD_ERROR(("Firmware download time for %u bytes: %u ms\n",
9644 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
9645 #endif // endif
9646 
9647 err:
9648 	if (memblock)
9649 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
9650 
9651 	if (image)
9652 		dhd_os_close_image1(bus->dhd, image);
9653 
9654 	return bcmerror;
9655 }
9656 
9657 #ifdef DHD_UCODE_DOWNLOAD
9658 /* Currently supported only for the chips in which ucode RAM is AXI addressable */
9659 static uint32
9660 dhdsdio_ucode_base(struct dhd_bus *bus)
9661 {
9662 	uint32 ucode_base = 0;
9663 
9664 	switch ((uint16)bus->sih->chip) {
9665 	case BCM43012_CHIP_ID:
9666 		ucode_base = 0xE8020000;
9667 		break;
9668 	default:
9669 		DHD_ERROR(("%s: Unsupported!\n", __func__));
9670 		break;
9671 	}
9672 
9673 	return ucode_base;
9674 }
9675 
9676 static int
9677 dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path)
9678 {
9679 	int bcmerror = -1;
9680 	int offset = 0;
9681 	int len;
9682 	uint32 ucode_base;
9683 	void *image = NULL;
9684 	uint8 *memblock = NULL, *memptr;
9685 	uint memblock_size = MEMBLOCK;
9686 #ifdef DHD_DEBUG_DOWNLOADTIME
9687 	unsigned long initial_jiffies = 0;
9688 	uint firmware_sz = 0;
9689 #endif // endif
9690 
9691 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, ucode_path));
9692 
9693 	ucode_base = dhdsdio_ucode_base(bus);
9694 
9695 	image = dhd_os_open_image1(bus->dhd, ucode_path);
9696 	if (image == NULL)
9697 		goto err;
9698 
9699 	/* Update the dongle image download block size depending on the F1 block size */
9700 	if (sd_f1_blocksize == 512)
9701 		memblock_size = MAX_MEMBLOCK;
9702 
9703 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
9704 	if (memblock == NULL) {
9705 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
9706 			memblock_size));
9707 		goto err;
9708 	}
9709 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
9710 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
9711 
9712 #ifdef DHD_DEBUG_DOWNLOADTIME
9713 	initial_jiffies = jiffies;
9714 #endif // endif
9715 
9716 	/* Download image */
9717 	while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) {
9718 		if (len < 0) {
9719 			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
9720 			bcmerror = BCME_ERROR;
9721 			goto err;
9722 		}
9723 
9724 		bcmerror = dhdsdio_membytes(bus, TRUE, (ucode_base + offset), memptr, len);
9725 		if (bcmerror) {
9726 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
9727 			        __FUNCTION__, bcmerror, memblock_size, offset));
9728 			goto err;
9729 		}
9730 
9731 		offset += memblock_size;
9732 #ifdef DHD_DEBUG_DOWNLOADTIME
9733 		firmware_sz += len;
9734 #endif // endif
9735 	}
9736 
9737 #ifdef DHD_DEBUG_DOWNLOADTIME
9738 	DHD_ERROR(("ucode download time for %u bytes: %u ms\n",
9739 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
9740 #endif // endif
9741 
9742 err:
9743 	if (memblock)
9744 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
9745 
9746 	if (image)
9747 		dhd_os_close_image1(bus->dhd, image);
9748 
9749 	return bcmerror;
9750 } /* dhdsdio_download_ucode_file */
9751 
9752 void
9753 dhd_bus_ucode_download(struct dhd_bus *bus)
9754 {
9755 	uint32 shaddr = 0, shdata = 0;
9756 
9757 	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
9758 	dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&shdata, 4);
9759 
9760 	DHD_TRACE(("%s: shdata:[0x%08x :0x%08x]\n", __func__, shaddr, shdata));
9761 
9762 	if (shdata == UCODE_DOWNLOAD_REQUEST)
9763 	{
9764 		DHD_ERROR(("%s: Received ucode download request!\n", __func__));
9765 
9766 		/* Download the ucode */
9767 		if (!dhd_get_ucode_path(bus->dhd)) {
9768 			DHD_ERROR(("%s: bus->uc_path not set!\n", __func__));
9769 			return;
9770 		}
9771 		dhdsdio_download_ucode_file(bus, dhd_get_ucode_path(bus->dhd));
9772 
9773 		DHD_ERROR(("%s: Ucode downloaded successfully!\n", __func__));
9774 
9775 		shdata = UCODE_DOWNLOAD_COMPLETE;
9776 		dhdsdio_membytes(bus, TRUE, shaddr, (uint8 *)&shdata, 4);
9777 	}
9778 }
9779 
9780 #endif /* DHD_UCODE_DOWNLOAD */
9781 
9782 static int
9783 dhdsdio_download_nvram(struct dhd_bus *bus)
9784 {
9785 	int bcmerror = -1;
9786 	uint len;
9787 	void * image = NULL;
9788 	char * memblock = NULL;
9789 	char *bufp;
9790 	char *pnv_path;
9791 	bool nvram_file_exists;
9792 
9793 	pnv_path = bus->nv_path;
9794 
9795 	nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
9796 
9797 	/* For Get nvram from UEFI */
9798 	if (nvram_file_exists)
9799 		image = dhd_os_open_image1(bus->dhd, pnv_path);
9800 
9801 	memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE);
9802 	if (memblock == NULL) {
9803 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
9804 		           __FUNCTION__, MAX_NVRAMBUF_SIZE));
9805 		goto err;
9806 	}
9807 
9808 	/* For Get nvram from image or UEFI (when image == NULL ) */
9809 	len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image);
9810 
9811 	if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
9812 		bufp = (char *)memblock;
9813 		bufp[len] = 0;
9814 		len = process_nvram_vars(bufp, len);
9815 		if (len % 4) {
9816 			len += 4 - (len % 4);
9817 		}
9818 		bufp += len;
9819 		*bufp++ = 0;
9820 		if (len)
9821 			bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
9822 		if (bcmerror) {
9823 			DHD_ERROR(("%s: error downloading vars: %d\n",
9824 			           __FUNCTION__, bcmerror));
9825 		}
9826 	} else {
9827 		DHD_ERROR(("%s: error reading nvram file: %d\n",
9828 		           __FUNCTION__, len));
9829 		bcmerror = BCME_SDIO_ERROR;
9830 	}
9831 
9832 err:
9833 	if (memblock)
9834 		MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
9835 
9836 	if (image)
9837 		dhd_os_close_image1(bus->dhd, image);
9838 
9839 	return bcmerror;
9840 }
9841 
9842 static int
9843 _dhdsdio_download_firmware(struct dhd_bus *bus)
9844 {
9845 	int bcmerror = -1;
9846 
9847 	bool embed = FALSE;	/* download embedded firmware */
9848 	bool dlok = FALSE;	/* download firmware succeeded */
9849 
9850 	/* Out immediately if no image to download */
9851 	if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
9852 		return bcmerror;
9853 	}
9854 
9855 	/* Keep arm in reset */
9856 	if (dhdsdio_download_state(bus, TRUE)) {
9857 		DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
9858 		goto err;
9859 	}
9860 
9861 	/* External image takes precedence if specified */
9862 	if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
9863 		if (dhdsdio_download_code_file(bus, bus->fw_path)) {
9864 			DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
9865 			goto err;
9866 		} else {
9867 			embed = FALSE;
9868 			dlok = TRUE;
9869 		}
9870 	}
9871 
9872 	BCM_REFERENCE(embed);
9873 	if (!dlok) {
9874 		DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
9875 		goto err;
9876 	}
9877 
9878 	/* External nvram takes precedence if specified */
9879 	if (dhdsdio_download_nvram(bus)) {
9880 		DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
9881 		goto err;
9882 	}
9883 
9884 	/* Take arm out of reset */
9885 	if (dhdsdio_download_state(bus, FALSE)) {
9886 		DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
9887 		goto err;
9888 	}
9889 
9890 	bcmerror = 0;
9891 
9892 err:
9893 	return bcmerror;
9894 }
9895 
9896 static int
9897 dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
9898 	void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle)
9899 {
9900 	int status;
9901 
9902 	if (!KSO_ENAB(bus)) {
9903 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
9904 		return BCME_NODEVICE;
9905 	}
9906 
9907 	status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete_fn, handle);
9908 
9909 	return status;
9910 }
9911 
9912 static int
9913 dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
9914 	void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle, int max_retry)
9915 {
9916 	int ret;
9917 	int i = 0;
9918 	int retries = 0;
9919 	bcmsdh_info_t *sdh;
9920 
9921 	if (!KSO_ENAB(bus)) {
9922 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
9923 		return BCME_NODEVICE;
9924 	}
9925 
9926 	sdh = bus->sdh;
9927 	do {
9928 		if (fn == 2)
9929 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_CHIP_CTRL_DATA, 0x80, NULL);
9930 
9931 		ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,
9932 			pkt, complete_fn, handle);
9933 
9934 		bus->f2txdata++;
9935 		ASSERT(ret != BCME_PENDING);
9936 
9937 		if (ret == BCME_NODEVICE) {
9938 			DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__));
9939 		} else if (ret < 0) {
9940 			/* On failure, abort the command and terminate the frame */
9941 			DHD_ERROR(("%s: sdio error %d, abort command and terminate frame.\n",
9942 				__FUNCTION__, ret));
9943 			bus->tx_sderrs++;
9944 			bus->f1regdata++;
9945 			bus->dhd->tx_errors++;
9946 			bcmsdh_abort(sdh, SDIO_FUNC_2);
9947 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
9948 				SFC_WF_TERM, NULL);
9949 			for (i = 0; i < READ_FRM_CNT_RETRIES; i++) {
9950 				uint8 hi, lo;
9951 				hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI,
9952 					NULL);
9953 				lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO,
9954 					NULL);
9955 				bus->f1regdata += 2;
9956 				if ((hi == 0) && (lo == 0))
9957 					break;
9958 			}
9959 		}
9960 	} while ((ret < 0) && retrydata && ++retries < max_retry);
9961 
9962 	return ret;
9963 }
9964 
9965 uint8
9966 dhd_bus_is_ioready(struct dhd_bus *bus)
9967 {
9968 	uint8 enable;
9969 	bcmsdh_info_t *sdh;
9970 	ASSERT(bus);
9971 	ASSERT(bus->sih != NULL);
9972 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
9973 	sdh = bus->sdh;
9974 	return (enable == bcmsdh_cfg_read(sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL));
9975 }
9976 
9977 uint
9978 dhd_bus_chip(struct dhd_bus *bus)
9979 {
9980 	ASSERT(bus->sih != NULL);
9981 	return bus->sih->chip;
9982 }
9983 
9984 uint
9985 dhd_bus_chiprev(struct dhd_bus *bus)
9986 {
9987 	ASSERT(bus);
9988 	ASSERT(bus->sih != NULL);
9989 	return bus->sih->chiprev;
9990 }
9991 
9992 void *
9993 dhd_bus_pub(struct dhd_bus *bus)
9994 {
9995 	return bus->dhd;
9996 }
9997 
9998 void *
9999 dhd_bus_sih(struct dhd_bus *bus)
10000 {
10001 	return (void *)bus->sih;
10002 }
10003 
10004 void *
10005 dhd_bus_txq(struct dhd_bus *bus)
10006 {
10007 	return &bus->txq;
10008 }
10009 
10010 uint
10011 dhd_bus_hdrlen(struct dhd_bus *bus)
10012 {
10013 	return (bus->txglom_enable) ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
10014 }
10015 
10016 void
10017 dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val)
10018 {
10019 	bus->dotxinrx = val;
10020 }
10021 
10022 /*
10023  *  dhdsdio_advertise_bus_cleanup advertises that clean up is under progress
10024  * to other bus user contexts like Tx, Rx, IOVAR, WD etc and it waits for other contexts
10025  * to gracefully exit. All the bus usage contexts before marking busstate as busy, will check for
10026  * whether the busstate is DHD_BUS_DOWN or DHD_BUS_DOWN_IN_PROGRESS, if so
10027  * they will exit from there itself without marking dhd_bus_busy_state as BUSY.
10028  */
10029 static void
10030 dhdsdio_advertise_bus_cleanup(dhd_pub_t	 *dhdp)
10031 {
10032 	unsigned long flags;
10033 	int timeleft;
10034 
10035 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
10036 	dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS;
10037 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
10038 
10039 	timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
10040 	if ((timeleft == 0) || (timeleft == 1)) {
10041 		DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
10042 				__FUNCTION__, dhdp->dhd_bus_busy_state));
10043 		ASSERT(0);
10044 	}
10045 
10046 	return;
10047 }
10048 
10049 int
10050 dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
10051 {
10052 	int bcmerror = 0;
10053 	dhd_bus_t *bus;
10054 	unsigned long flags;
10055 
10056 	bus = dhdp->bus;
10057 
10058 	if (flag == TRUE) {
10059 		if (!bus->dhd->dongle_reset) {
10060 			DHD_ERROR(("%s: == Power OFF ==\n", __FUNCTION__));
10061 			dhdsdio_advertise_bus_cleanup(bus->dhd);
10062 			dhd_os_sdlock(dhdp);
10063 			dhd_os_wd_timer(dhdp, 0);
10064 #if defined(OEM_ANDROID)
10065 #if !defined(IGNORE_ETH0_DOWN)
10066 			/* Force flow control as protection when stop come before ifconfig_down */
10067 			dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
10068 #endif /* !defined(IGNORE_ETH0_DOWN) */
10069 #endif /* OEM_ANDROID */
10070 			/* Expect app to have torn down any connection before calling */
10071 			/* Stop the bus, disable F2 */
10072 			dhd_bus_stop(bus, FALSE);
10073 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
10074 			/* Clean up any pending IRQ */
10075 			dhd_enable_oob_intr(bus, FALSE);
10076 			bcmsdh_oob_intr_set(bus->sdh, FALSE);
10077 			bcmsdh_oob_intr_unregister(bus->sdh);
10078 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
10079 
10080 			/* Clean tx/rx buffer pointers, detach from the dongle */
10081 			dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
10082 
10083 			bus->dhd->dongle_reset = TRUE;
10084 			DHD_ERROR(("%s: making dhdpub up FALSE\n", __FUNCTION__));
10085 			bus->dhd->up = FALSE;
10086 			dhd_txglom_enable(dhdp, FALSE);
10087 			dhd_os_sdunlock(dhdp);
10088 
10089 			DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10090 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
10091 			bus->dhd->busstate = DHD_BUS_DOWN;
10092 			DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10093 
10094 			DHD_TRACE(("%s:  WLAN OFF DONE\n", __FUNCTION__));
10095 			/* App can now remove power from device */
10096 		} else
10097 			bcmerror = BCME_SDIO_ERROR;
10098 	} else {
10099 		/* App must have restored power to device before calling */
10100 
10101 		DHD_ERROR(("\n\n%s: == Power ON ==\n", __FUNCTION__));
10102 
10103 		if (bus->dhd->dongle_reset) {
10104 			/* Turn on WLAN */
10105 			dhd_os_sdlock(dhdp);
10106 			/* Reset SD client -- required if devreset is called
10107 			* via 'dhd devreset' iovar
10108 			*/
10109 			bcmsdh_reset(bus->sdh);
10110 			/* Attempt to re-attach & download */
10111 			if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
10112 				(uint32 *)(uintptr)si_enum_base(bus->cl_devid),
10113 				bus->cl_devid)) {
10114 
10115 				DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10116 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
10117 				bus->dhd->busstate = DHD_BUS_DOWN;
10118 				DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10119 
10120 				/* Attempt to download binary to the dongle */
10121 				if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
10122 				    dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) {
10123 
10124 					/* Re-init bus, enable F2 transfer */
10125 					bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
10126 					if (bcmerror == BCME_OK) {
10127 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
10128 						dhd_enable_oob_intr(bus, TRUE);
10129 						bcmsdh_oob_intr_register(bus->sdh,
10130 							dhdsdio_isr, bus);
10131 						bcmsdh_oob_intr_set(bus->sdh, TRUE);
10132 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
10133 
10134 						bus->dhd->dongle_reset = FALSE;
10135 						bus->dhd->up = TRUE;
10136 
10137 #if defined(OEM_ANDROID) && !defined(IGNORE_ETH0_DOWN)
10138 						/* Restore flow control  */
10139 						dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
10140 #endif /* defined(OEM_ANDROID) &&  (!defined(IGNORE_ETH0_DOWN)) */
10141 						dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
10142 
10143 						DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
10144 					} else {
10145 						dhd_bus_stop(bus, FALSE);
10146 						dhdsdio_release_dongle(bus, bus->dhd->osh,
10147 							TRUE, FALSE);
10148 					}
10149 				} else {
10150 					DHD_ERROR(("%s Failed to download binary to the dongle\n",
10151 						__FUNCTION__));
10152 					if (bus->sih != NULL) {
10153 						si_detach(bus->sih);
10154 						bus->sih = NULL;
10155 					}
10156 					bcmerror = BCME_SDIO_ERROR;
10157 				}
10158 			} else {
10159 				bcmerror = BCME_SDIO_ERROR;
10160 			}
10161 
10162 			dhd_os_sdunlock(dhdp);
10163 		} else {
10164 			DHD_INFO(("%s called when dongle is not in reset\n",
10165 				__FUNCTION__));
10166 #if defined(OEM_ANDROID)
10167 			DHD_INFO(("Will call dhd_bus_start instead\n"));
10168 			dhd_bus_resume(dhdp, 1);
10169 			if ((bcmerror = dhd_bus_start(dhdp)) != 0)
10170 				DHD_ERROR(("%s: dhd_bus_start fail with %d\n",
10171 					__FUNCTION__, bcmerror));
10172 #endif /* defined(OEM_ANDROID) */
10173 		}
10174 	}
10175 	return bcmerror;
10176 }
10177 
10178 int dhd_bus_suspend(dhd_pub_t *dhdpub)
10179 {
10180 	return bcmsdh_stop(dhdpub->bus->sdh);
10181 }
10182 
10183 int dhd_bus_resume(dhd_pub_t *dhdpub, int stage)
10184 {
10185 	return bcmsdh_start(dhdpub->bus->sdh, stage);
10186 }
10187 
10188 /* Get Chip ID version */
10189 uint dhd_bus_chip_id(dhd_pub_t *dhdp)
10190 {
10191 	dhd_bus_t *bus = dhdp->bus;
10192 
10193 	return  bus->sih->chip;
10194 }
10195 
10196 /* Get Chip Rev ID version */
10197 uint dhd_bus_chiprev_id(dhd_pub_t *dhdp)
10198 {
10199 	dhd_bus_t *bus = dhdp->bus;
10200 
10201 	return bus->sih->chiprev;
10202 }
10203 
10204 #ifdef DHD_MAP_CHIP_FIRMWARE_PATH
10205 /* Get Chip Module ID */
10206 uint dhd_bus_chipmodule_id(dhd_pub_t *dhdp)
10207 {
10208 	dhd_bus_t *bus = dhdp->bus;
10209 
10210 	return bus->chipmodule;
10211 }
10212 #endif /* DHD_MAP_CHIP_FIRMWARE_PATH */
10213 
10214 /* Get Chip Pkg ID version */
10215 uint dhd_bus_chippkg_id(dhd_pub_t *dhdp)
10216 {
10217 	dhd_bus_t *bus = dhdp->bus;
10218 
10219 	return bus->sih->chippkg;
10220 }
10221 
10222 int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num, uint32 *slot_num)
10223 {
10224 	*bus_type = bus->bus;
10225 	*bus_num = bus->bus_num;
10226 	*slot_num = bus->slot_num;
10227 	return 0;
10228 }
10229 
10230 int
10231 dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size)
10232 {
10233 	dhd_bus_t *bus;
10234 
10235 	bus = dhdp->bus;
10236 	return dhdsdio_membytes(bus, set, address, data, size);
10237 }
10238 
10239 #if defined(SUPPORT_MULTIPLE_REVISION)
10240 static int
10241 concate_revision_bcm4335(dhd_bus_t *bus, char *fw_path, char *nv_path)
10242 {
10243 
10244 	uint chipver;
10245 #if defined(SUPPORT_MULTIPLE_CHIPS)
10246 	char chipver_tag[10] = "_4335";
10247 #else
10248 	char chipver_tag[4] = {0, };
10249 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
10250 
10251 	DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__));
10252 	if (bus->sih->chip != BCM4335_CHIP_ID) {
10253 		DHD_ERROR(("%s:Chip is not BCM4335\n", __FUNCTION__));
10254 		return -1;
10255 	}
10256 	chipver = bus->sih->chiprev;
10257 	DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
10258 	if (chipver == 0x0) {
10259 		DHD_ERROR(("----- CHIP bcm4335_A0 -----\n"));
10260 		strcat(chipver_tag, "_a0");
10261 	} else if (chipver == 0x1) {
10262 		DHD_ERROR(("----- CHIP bcm4335_B0 -----\n"));
10263 #if defined(SUPPORT_MULTIPLE_CHIPS)
10264 		strcat(chipver_tag, "_b0");
10265 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
10266 	}
10267 
10268 	strcat(fw_path, chipver_tag);
10269 	strcat(nv_path, chipver_tag);
10270 	return 0;
10271 }
10272 
10273 static int
10274 concate_revision_bcm4339(dhd_bus_t *bus, char *fw_path, char *nv_path)
10275 {
10276 
10277 	uint chipver;
10278 #if defined(SUPPORT_MULTIPLE_CHIPS)
10279 	char chipver_tag[10] = "_4339";
10280 #else
10281 	char chipver_tag[4] = {0, };
10282 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
10283 
10284 	DHD_TRACE(("%s: BCM4339 Multiple Revision Check\n", __FUNCTION__));
10285 	if (bus->sih->chip != BCM4339_CHIP_ID) {
10286 		DHD_ERROR(("%s:Chip is not BCM4339\n", __FUNCTION__));
10287 		return -1;
10288 	}
10289 	chipver = bus->sih->chiprev;
10290 	DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
10291 	if (chipver == 0x1) {
10292 		DHD_ERROR(("----- CHIP bcm4339_A0 -----\n"));
10293 		strcat(chipver_tag, "_a0");
10294 	} else {
10295 		DHD_ERROR(("----- CHIP bcm4339 unknown revision %d -----\n",
10296 			chipver));
10297 	}
10298 
10299 	strcat(fw_path, chipver_tag);
10300 	strcat(nv_path, chipver_tag);
10301 	return 0;
10302 }
10303 
10304 static int concate_revision_bcm4350(dhd_bus_t *bus, char *fw_path, char *nv_path)
10305 {
10306 	uint32 chip_ver;
10307 #if defined(SUPPORT_MULTIPLE_CHIPS)
10308 	char chipver_tag[10] = {0, };
10309 #else
10310 	char chipver_tag[4] = {0, };
10311 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
10312 	chip_ver = bus->sih->chiprev;
10313 
10314 #if defined(SUPPORT_MULTIPLE_CHIPS)
10315 	if (chip_ver == 3)
10316 		strcat(chipver_tag, "_4354");
10317 	else
10318 		strcat(chipver_tag, "_4350");
10319 #endif // endif
10320 
10321 	if (chip_ver == 3) {
10322 		DHD_ERROR(("----- CHIP 4354 A0 -----\n"));
10323 		strcat(chipver_tag, "_a0");
10324 	} else {
10325 		DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
10326 	}
10327 
10328 	strcat(fw_path, chipver_tag);
10329 	strcat(nv_path, chipver_tag);
10330 	return 0;
10331 }
10332 
10333 static int concate_revision_bcm4354(dhd_bus_t *bus, char *fw_path, char *nv_path)
10334 {
10335 	uint32 chip_ver;
10336 #if defined(SUPPORT_MULTIPLE_CHIPS)
10337 	char chipver_tag[10] = "_4354";
10338 #else
10339 	char chipver_tag[4] = {0, };
10340 #endif /* SUPPORT_MULTIPLE_CHIPS */
10341 
10342 	chip_ver = bus->sih->chiprev;
10343 	if (chip_ver == 1) {
10344 		DHD_ERROR(("----- CHIP 4354 A1 -----\n"));
10345 		strcat(chipver_tag, "_a1");
10346 	} else {
10347 		DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
10348 	}
10349 
10350 	strcat(fw_path, chipver_tag);
10351 	strcat(nv_path, chipver_tag);
10352 
10353 	return 0;
10354 }
10355 
10356 static int
10357 concate_revision_bcm43454(dhd_bus_t *bus, char *fw_path, char *nv_path)
10358 {
10359 	char chipver_tag[10] = {0, };
10360 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
10361 	int base_system_rev_for_nv = 0;
10362 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
10363 
10364 	DHD_TRACE(("%s: BCM43454 Multiple Revision Check\n", __FUNCTION__));
10365 	if (bus->sih->chip != BCM43454_CHIP_ID) {
10366 		DHD_ERROR(("%s:Chip is not BCM43454!\n", __FUNCTION__));
10367 		return -1;
10368 	}
10369 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
10370 	base_system_rev_for_nv = dhd_get_system_rev();
10371 	if (base_system_rev_for_nv > 0) {
10372 		DHD_ERROR(("----- Board Rev  [%d] -----\n", base_system_rev_for_nv));
10373 		sprintf(chipver_tag, "_r%02d", base_system_rev_for_nv);
10374 	}
10375 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
10376 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW
10377 	DHD_ERROR(("----- Rev [%d] Fot MULTIPLE Board. -----\n", system_hw_rev));
10378 	if ((system_hw_rev >= 8) && (system_hw_rev <= 11)) {
10379 		DHD_ERROR(("This HW is Rev 08 ~ 11. this is For FD-HW\n"));
10380 		strcat(chipver_tag, "_FD");
10381 	}
10382 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
10383 
10384 	strcat(nv_path, chipver_tag);
10385 	return 0;
10386 }
10387 
10388 int
10389 concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path)
10390 {
10391 	int res = 0;
10392 
10393 	if (!bus || !bus->sih) {
10394 		DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
10395 		return -1;
10396 	}
10397 
10398 	switch (bus->sih->chip) {
10399 	case BCM4335_CHIP_ID:
10400 		res = concate_revision_bcm4335(bus, fw_path, nv_path);
10401 
10402 		break;
10403 	case BCM4339_CHIP_ID:
10404 		res = concate_revision_bcm4339(bus, fw_path, nv_path);
10405 		break;
10406 	case BCM4350_CHIP_ID:
10407 		res = concate_revision_bcm4350(bus, fw_path, nv_path);
10408 		break;
10409 	case BCM4354_CHIP_ID:
10410 		res = concate_revision_bcm4354(bus, fw_path, nv_path);
10411 		break;
10412 	case BCM43454_CHIP_ID:
10413 		res = concate_revision_bcm43454(bus, fw_path, nv_path);
10414 		break;
10415 
10416 	default:
10417 		DHD_ERROR(("REVISION SPECIFIC feature is not required\n"));
10418 		return res;
10419 	}
10420 
10421 	if (res == 0) {
10422 	}
10423 	return res;
10424 }
10425 #endif /* SUPPORT_MULTIPLE_REVISION */
10426 
10427 void
10428 dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path)
10429 {
10430 	bus->fw_path = pfw_path;
10431 	bus->nv_path = pnv_path;
10432 }
10433 
10434 int
10435 dhd_enableOOB(dhd_pub_t *dhd, bool sleep)
10436 {
10437 	dhd_bus_t *bus = dhd->bus;
10438 	sdpcmd_regs_t *regs = bus->regs;
10439 	uint retries = 0;
10440 
10441 	if (sleep) {
10442 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
10443 		/* Tell device to start using OOB wakeup */
10444 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
10445 		if (retries > retry_limit) {
10446 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
10447 			return BCME_BUSY;
10448 		}
10449 		/* Turn off our contribution to the HT clock request */
10450 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
10451 	} else {
10452 		/* Make sure the controller has the bus up */
10453 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
10454 
10455 		/* Send misc interrupt to indicate OOB not needed */
10456 		W_SDREG(0, &regs->tosbmailboxdata, retries);
10457 		if (retries <= retry_limit)
10458 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
10459 
10460 		if (retries > retry_limit)
10461 			DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
10462 
10463 		/* Make sure we have SD bus access */
10464 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
10465 	}
10466 	return BCME_OK;
10467 }
10468 
10469 void
10470 dhd_bus_pktq_flush(dhd_pub_t *dhdp)
10471 {
10472 	dhd_bus_t *bus = dhdp->bus;
10473 	bool wlfc_enabled = FALSE;
10474 
10475 #ifdef PROP_TXSTATUS
10476 	wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED);
10477 #endif // endif
10478 	if (!wlfc_enabled) {
10479 #ifdef DHDTCPACK_SUPPRESS
10480 		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
10481 		 * when there is a newly coming packet from network stack.
10482 		 */
10483 		dhd_tcpack_info_tbl_clean(bus->dhd);
10484 #endif /* DHDTCPACK_SUPPRESS */
10485 		/* Clear the data packet queues */
10486 		pktq_flush(dhdp->osh, &bus->txq, TRUE);
10487 	}
10488 }
10489 
10490 #ifdef BCMSDIO
10491 int
10492 dhd_sr_config(dhd_pub_t *dhd, bool on)
10493 {
10494 	dhd_bus_t *bus = dhd->bus;
10495 
10496 	if (!bus->_srenab)
10497 		return -1;
10498 
10499 	return dhdsdio_clk_devsleep_iovar(bus, on);
10500 }
10501 
10502 uint16
10503 dhd_get_chipid(dhd_pub_t *dhd)
10504 {
10505 	dhd_bus_t *bus = dhd->bus;
10506 
10507 	if (bus && bus->sih)
10508 		return (uint16)bus->sih->chip;
10509 	else
10510 		return 0;
10511 }
10512 #endif /* BCMSDIO */
10513 
10514 #ifdef DEBUGGER
10515 static uint32
10516 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr)
10517 {
10518 	uint32 rval;
10519 
10520 	dhd_os_sdlock(bus->dhd);
10521 
10522 	BUS_WAKE(bus);
10523 
10524 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
10525 
10526 	rval = bcmsdh_reg_read(bus->sdh, addr, 4);
10527 
10528 	dhd_os_sdunlock(bus->dhd);
10529 
10530 	return rval;
10531 }
10532 
10533 static void
10534 dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val)
10535 {
10536 	dhd_os_sdlock(bus->dhd);
10537 
10538 	BUS_WAKE(bus);
10539 
10540 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
10541 
10542 	bcmsdh_reg_write(bus->sdh, addr, 4, val);
10543 
10544 	dhd_os_sdunlock(bus->dhd);
10545 }
10546 
10547 #endif /* DEBUGGER */
10548 
10549 #if defined(BT_OVER_SDIO)
10550 uint8 dhd_bus_cfg_read(void *h, uint fun_num, uint32 addr, int *err)
10551 {
10552 	uint8 intrd;
10553 	dhd_pub_t *dhdp = (dhd_pub_t *)h;
10554 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
10555 
10556 	dhd_os_sdlock(bus->dhd);
10557 
10558 	intrd = bcmsdh_cfg_read(bus->sdh, fun_num, addr, err);
10559 
10560 	dhd_os_sdunlock(bus->dhd);
10561 
10562 	return intrd;
10563 } EXPORT_SYMBOL(dhd_bus_cfg_read);
10564 
10565 void dhd_bus_cfg_write(void *h, uint fun_num, uint32 addr, uint8 val, int *err)
10566 {
10567 	dhd_pub_t *dhdp = (dhd_pub_t *)h;
10568 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
10569 
10570 	dhd_os_sdlock(bus->dhd);
10571 
10572 	bcmsdh_cfg_write(bus->sdh, fun_num, addr, val, err);
10573 
10574 	dhd_os_sdunlock(bus->dhd);
10575 
10576 } EXPORT_SYMBOL(dhd_bus_cfg_write);
10577 
10578 static int
10579 extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value)
10580 {
10581 	char field [8];
10582 
10583 	strncpy(field, line + start_pos, num_chars);
10584 	field [num_chars] = '\0';
10585 
10586 	return (sscanf (field, "%hX", value) == 1);
10587 }
10588 
10589 static int
10590 read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode, uint16 * hi_addr,
10591 	uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes)
10592 {
10593 	int		str_len;
10594 	uint16	num_data_bytes, addr, data_pos, type, w, i;
10595 	uint32	abs_base_addr32 = 0;
10596 	*num_bytes = 0;
10597 
10598 	while (!*num_bytes)
10599 	{
10600 		str_len = dhd_os_gets_image(bus->dhd, line, BTFW_MAX_STR_LEN, file);
10601 
10602 		DHD_TRACE(("%s: Len :0x%x  %s\n", __FUNCTION__, str_len, line));
10603 
10604 		if (str_len == 0) {
10605 			break;
10606 		} else if (str_len > 9) {
10607 			extract_hex_field(line, 1, 2, &num_data_bytes);
10608 			extract_hex_field(line, 3, 4, &addr);
10609 			extract_hex_field(line, 7, 2, &type);
10610 
10611 			data_pos = 9;
10612 			for (i = 0; i < num_data_bytes; i++) {
10613 				extract_hex_field(line, data_pos, 2, &w);
10614 				data_bytes [i] = (uint8)(w & 0x00FF);
10615 				data_pos += 2;
10616 			}
10617 
10618 			if (type == BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS) {
10619 				*hi_addr = (data_bytes [0] << 8) | data_bytes [1];
10620 				*addr_mode = BTFW_ADDR_MODE_EXTENDED;
10621 			} else if (type == BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS) {
10622 				*hi_addr = (data_bytes [0] << 8) | data_bytes [1];
10623 				*addr_mode = BTFW_ADDR_MODE_SEGMENT;
10624 			} else if (type == BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS) {
10625 				abs_base_addr32 = (data_bytes [0] << 24) | (data_bytes [1] << 16) |
10626 					(data_bytes [2] << 8) | data_bytes [3];
10627 				*addr_mode = BTFW_ADDR_MODE_LINEAR32;
10628 			} else if (type == BTFW_HEX_LINE_TYPE_DATA) {
10629 				*dest_addr = addr;
10630 				if (*addr_mode == BTFW_ADDR_MODE_EXTENDED)
10631 					*dest_addr += (*hi_addr << 16);
10632 				else if (*addr_mode == BTFW_ADDR_MODE_SEGMENT)
10633 					*dest_addr += (*hi_addr << 4);
10634 				else if (*addr_mode == BTFW_ADDR_MODE_LINEAR32)
10635 					*dest_addr += abs_base_addr32;
10636 				*num_bytes = num_data_bytes;
10637 			}
10638 		}
10639 	}
10640 	return (*num_bytes > 0);
10641 }
10642 
10643 static int
10644 _dhdsdio_download_btfw(struct dhd_bus *bus)
10645 {
10646 	int	bcm_error = -1;
10647 	void	*image = NULL;
10648 	uint8	*mem_blk = NULL, *mem_ptr = NULL, *data_ptr = NULL;
10649 
10650 	uint32 offset_addr = 0, offset_len = 0, bytes_to_write = 0;
10651 
10652 	char	*line = NULL;
10653 	uint32	dest_addr = 0, num_bytes;
10654 	uint16	hiAddress = 0;
10655 	uint32	start_addr, start_data, end_addr, end_data, i, index, pad,
10656 	bt2wlan_pwrup_adr;
10657 
10658 	int	addr_mode		= BTFW_ADDR_MODE_EXTENDED;
10659 
10660 	/* Out immediately if no image to download */
10661 	if ((bus->btfw_path == NULL) || (bus->btfw_path[0] == '\0')) {
10662 		return 0;
10663 	}
10664 
10665 	image = dhd_os_open_image1(bus->dhd, bus->btfw_path);
10666 	if (image == NULL)
10667 		goto err;
10668 
10669 	mem_ptr = mem_blk = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN);
10670 	if (mem_blk == NULL) {
10671 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10672 			BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN));
10673 		goto err;
10674 	}
10675 	if ((uint32)(uintptr)mem_blk % DHD_SDALIGN)
10676 		mem_ptr += (DHD_SDALIGN - ((uint32)(uintptr)mem_blk % DHD_SDALIGN));
10677 
10678 	data_ptr = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE - 8);
10679 	if (data_ptr == NULL) {
10680 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10681 			BTFW_DOWNLOAD_BLK_SIZE - 8));
10682 		goto err;
10683 	}
10684 	/* Write to BT register to hold WLAN wake high during BT FW download */
10685 	bt2wlan_pwrup_adr = BTMEM_OFFSET + BT2WLAN_PWRUP_ADDR;
10686 	bcmsdh_reg_write(bus->sdh, bt2wlan_pwrup_adr, 4, BT2WLAN_PWRUP_WAKE);
10687 	/*
10688 	  * Wait for at least 2msec for the clock to be ready/Available.
10689 	  */
10690 	OSL_DELAY(2000);
10691 
10692 	line = MALLOC(bus->dhd->osh, BTFW_MAX_STR_LEN);
10693 	if (line == NULL) {
10694 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
10695 			__FUNCTION__, BTFW_MAX_STR_LEN));
10696 		goto err;
10697 	}
10698 	memset(line, 0, BTFW_MAX_STR_LEN);
10699 
10700 	while (read_more_btbytes (bus, image, line, &addr_mode, &hiAddress, &dest_addr,
10701 		data_ptr, &num_bytes)) {
10702 
10703 		DHD_TRACE(("read %d bytes at address %08X\n", num_bytes, dest_addr));
10704 
10705 		start_addr = BTMEM_OFFSET + dest_addr;
10706 		index = 0;
10707 
10708 		/* Make sure the start address is 4 byte aligned to avoid alignment issues
10709 		 * with SD host controllers
10710 		 */
10711 		if (!ISALIGNED(start_addr, 4)) {
10712 			pad = start_addr % 4;
10713 			start_addr = ROUNDDN(start_addr, 4);
10714 			start_data = bcmsdh_reg_read(bus->sdh, start_addr, 4);
10715 			for (i = 0; i < pad; i++, index++) {
10716 			    mem_ptr[index] = (uint8)((uint8 *)&start_data)[i];
10717 			}
10718 		}
10719 		bcopy(data_ptr, &(mem_ptr[index]), num_bytes);
10720 		index += num_bytes;
10721 
10722 		/* Make sure the length is multiple of 4bytes to avoid alignment issues
10723 		 * with SD host controllers
10724 		 */
10725 		end_addr = start_addr + index;
10726 		if (!ISALIGNED(end_addr, 4)) {
10727 			end_addr = ROUNDDN(end_addr, 4);
10728 			end_data = bcmsdh_reg_read(bus->sdh, end_addr, 4);
10729 			for (i = (index % 4); i < 4; i++, index++) {
10730 				mem_ptr[index] = (uint8)((uint8 *)&end_data)[i];
10731 			}
10732 		}
10733 
10734 		offset_addr = start_addr & 0xFFF;
10735 		offset_len =  offset_addr + index;
10736 		if (offset_len <= 0x1000) {
10737 			bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr, index);
10738 			if (bcm_error) {
10739 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10740 				__FUNCTION__, bcm_error, num_bytes, start_addr));
10741 				goto err;
10742 			}
10743 		}
10744 		else {
10745 			bytes_to_write = 0x1000 - offset_addr;
10746 			bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr,
10747 				bytes_to_write);
10748 			if (bcm_error) {
10749 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10750 				__FUNCTION__, bcm_error, num_bytes, start_addr));
10751 				goto err;
10752 			}
10753 
10754 			OSL_DELAY(10000);
10755 
10756 			bcm_error = dhdsdio_membytes(bus, TRUE, (start_addr + bytes_to_write),
10757 				(mem_ptr + bytes_to_write), (index - bytes_to_write));
10758 			if (bcm_error) {
10759 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10760 					__FUNCTION__, bcm_error, num_bytes, start_addr));
10761 				goto err;
10762 			}
10763 		}
10764 		memset(line, 0, BTFW_MAX_STR_LEN);
10765 	}
10766 
10767 	bcm_error = 0;
10768 err:
10769 	if (mem_blk)
10770 		MFREE(bus->dhd->osh, mem_blk, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN);
10771 
10772 	if (data_ptr)
10773 		MFREE(bus->dhd->osh, data_ptr, BTFW_DOWNLOAD_BLK_SIZE - 8);
10774 
10775 	if (line)
10776 		MFREE(bus->dhd->osh, line, BTFW_MAX_STR_LEN);
10777 
10778 	if (image)
10779 		dhd_os_close_image1(bus->dhd, image);
10780 
10781 	return bcm_error;
10782 }
10783 
10784 static int
10785 dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh)
10786 {
10787 	int ret;
10788 
10789 	DHD_TRACE(("%s: btfw path=%s\n",
10790 		__FUNCTION__, bus->btfw_path));
10791 	DHD_OS_WAKE_LOCK(bus->dhd);
10792 	dhd_os_sdlock(bus->dhd);
10793 
10794 	/* Download the firmware */
10795 	ret = _dhdsdio_download_btfw(bus);
10796 
10797 	dhd_os_sdunlock(bus->dhd);
10798 	DHD_OS_WAKE_UNLOCK(bus->dhd);
10799 
10800 	return ret;
10801 }
10802 
10803 int
10804 dhd_bus_download_btfw(struct dhd_bus *bus, osl_t *osh,
10805                           char *pbtfw_path)
10806 {
10807 	int ret;
10808 
10809 	bus->btfw_path = pbtfw_path;
10810 
10811 	ret = dhdsdio_download_btfw(bus, osh, bus->sdh);
10812 
10813 	return ret;
10814 }
10815 #endif /* defined (BT_OVER_SDIO) */
10816 
10817 void
10818 dhd_bus_dump_trap_info(dhd_bus_t *bus, struct bcmstrbuf *strbuf)
10819 {
10820 	trap_t *tr = &bus->dhd->last_trap_info;
10821 
10822 	bcm_bprintf(strbuf,
10823 		"Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
10824 		"lp 0x%x, rpc 0x%x Trap offset 0x%x, "
10825 		"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
10826 		"r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
10827 		ltoh32(tr->type), ltoh32(tr->epc), ltoh32(tr->cpsr), ltoh32(tr->spsr),
10828 		ltoh32(tr->r13), ltoh32(tr->r14), ltoh32(tr->pc),
10829 		ltoh32(bus->dongle_trap_addr),
10830 		ltoh32(tr->r0), ltoh32(tr->r1), ltoh32(tr->r2), ltoh32(tr->r3),
10831 		ltoh32(tr->r4), ltoh32(tr->r5), ltoh32(tr->r6), ltoh32(tr->r7));
10832 
10833 }
10834 
10835 static int
10836 dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len)
10837 {
10838 	int ret = -1;
10839 
10840 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(((dhd_bus_t*)bus)->sdh),
10841 		SDIO_FUNC_2, F2SYNC, frame, len, NULL, NULL, NULL, TXRETRIES);
10842 
10843 	if (ret == BCME_OK)
10844 		((dhd_bus_t*)bus)->tx_seq = (((dhd_bus_t*)bus)->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
10845 
10846 	return ret;
10847 }
10848 
10849 /* Function to set the min res mask depending on the chip ID used */
10850 bool
10851 dhd_bus_set_default_min_res_mask(struct dhd_bus *bus)
10852 {
10853 	if ((bus == NULL) || (bus->sih == NULL)) {
10854 		DHD_ERROR(("%s(): Invalid Arguments \r\n", __FUNCTION__));
10855 		return FALSE;
10856 	}
10857 
10858 	switch (bus->sih->chip) {
10859 	case BCM4339_CHIP_ID:
10860 		bcmsdh_reg_write(bus->sdh, SI_ENUM_BASE(bus->sih) + 0x618, 4, 0x3fcaf377);
10861 		if (bcmsdh_regfail(bus->sdh)) {
10862 			DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
10863 			return FALSE;
10864 		}
10865 		break;
10866 
10867 	case BCM43012_CHIP_ID:
10868 		bcmsdh_reg_write(bus->sdh,
10869 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(pmuregs_t, min_res_mask)),
10870 			4, DEFAULT_43012_MIN_RES_MASK);
10871 		if (bcmsdh_regfail(bus->sdh)) {
10872 			DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
10873 			return FALSE;
10874 		}
10875 		break;
10876 
10877 	default:
10878 		DHD_ERROR(("%s: Unhandled chip id\n", __FUNCTION__));
10879 		return FALSE;
10880 	}
10881 
10882 	return TRUE;
10883 }
10884 
10885 /* Function to reset PMU registers */
10886 void
10887 dhd_bus_pmu_reg_reset(dhd_pub_t *dhdp)
10888 {
10889 	struct dhd_bus *bus = dhdp->bus;
10890 	bcmsdh_reg_write(bus->sdh, si_get_pmu_reg_addr(bus->sih,
10891 		OFFSETOF(pmuregs_t, swscratch)), 4, 0x0);
10892 	if (bcmsdh_regfail(bus->sdh)) {
10893 		DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
10894 	}
10895 }
10896 
10897 #ifdef DHD_ULP
10898 
10899 /* Function to disable console messages on entering ULP mode */
10900 void
10901 dhd_bus_ulp_disable_console(dhd_pub_t *dhdp)
10902 {
10903 #ifdef DHD_DEBUG
10904 	DHD_ERROR(("Flushing and disabling console messages\n"));
10905 
10906 	/* Save the console print interval */
10907 	dhd_ulp_save_console_interval(dhdp);
10908 
10909 	/* Flush the console buffer before disabling */
10910 	dhdsdio_readconsole(dhdp->bus);
10911 	dhdp->dhd_console_ms = 0;
10912 #endif /* DHD_DEBUG */
10913 }
10914 
10915 /* Function for redownloading firmaware */
10916 static int
10917 dhd_bus_ulp_reinit_fw(dhd_bus_t *bus)
10918 {
10919 	int bcmerror = 0;
10920 
10921 	/* After firmware redownload tx/rx seq are reset accordingly these values are
10922 	reset on DHD side tx_max is initially set to 4, which later is updated by FW
10923 	*/
10924 	bus->tx_seq = bus->rx_seq = 0;
10925 	bus->tx_max = 4;
10926 
10927 	if (dhd_bus_download_firmware(bus, bus->dhd->osh,
10928 		bus->fw_path, bus->nv_path) >= 0) {
10929 
10930 		/* Re-init bus, enable F2 transfer */
10931 		bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
10932 		if (bcmerror == BCME_OK) {
10933 			bus->dhd->up = TRUE;
10934 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
10935 
10936 			dhd_ulp_set_ulp_state(bus->dhd, DHD_ULP_READY);
10937 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
10938 			dhd_enable_oob_intr(bus, TRUE);
10939 			bcmsdh_oob_intr_set(bus->sdh, TRUE);
10940 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
10941 #ifdef DHD_DEBUG
10942 		/* Re-enable the console messages on FW redownload to default value */
10943 		dhd_ulp_restore_console_interval(bus->dhd);
10944 #endif /* DHD_DEBUG */
10945 		} else {
10946 			DHD_ERROR(("bus init failed\n"));
10947 			dhd_bus_stop(bus, FALSE);
10948 			dhdsdio_release_dongle(bus, bus->dhd->osh,
10949 				TRUE, FALSE);
10950 		}
10951 	} else
10952 		bcmerror = BCME_SDIO_ERROR;
10953 
10954 	return bcmerror;
10955 }
10956 #endif /* DHD_ULP */
10957 
10958 int
10959 dhd_bus_readwrite_bp_addr(dhd_pub_t *dhdp, uint addr, uint size, uint* data, bool read)
10960 {
10961 	int bcmerror = 0;
10962 	struct dhd_bus *bus = dhdp->bus;
10963 
10964 	if (read) {
10965 		*data = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
10966 	} else {
10967 		bcmsdh_reg_write(bus->sdh, addr, size, *data);
10968 	}
10969 
10970 	if (bcmsdh_regfail(bus->sdh))
10971 		bcmerror = BCME_SDIO_ERROR;
10972 
10973 	return bcmerror;
10974 }
10975 
10976 int dhd_get_idletime(dhd_pub_t *dhd)
10977 {
10978 	return dhd->bus->idletime;
10979 }
10980 
10981 #ifdef DHD_WAKE_STATUS
10982 wake_counts_t*
10983 dhd_bus_get_wakecount(dhd_pub_t *dhd)
10984 {
10985 	return &dhd->bus->wake_counts;
10986 }
10987 int
10988 dhd_bus_get_bus_wake(dhd_pub_t *dhd)
10989 {
10990 	return bcmsdh_set_get_wake(dhd->bus->sdh, 0);
10991 }
10992 #endif /* DHD_WAKE_STATUS */
10993