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