xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * DHD Bus Module for SDIO
3  *
4  * Copyright (C) 2020, Broadcom.
5  *
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  *
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  *
20  *
21  * <<Broadcom-WL-IPTag/Open:>>
22  *
23  * $Id$
24  */
25 
26 #include <typedefs.h>
27 #include <osl.h>
28 #include <bcmsdh.h>
29 
30 #ifdef BCMEMBEDIMAGE
31 #include BCMEMBEDIMAGE
32 #endif /* BCMEMBEDIMAGE */
33 
34 #include <bcmdefs.h>
35 #include <bcmutils.h>
36 #include <bcmendian.h>
37 #include <bcmdevs.h>
38 #include <bcmdevs_legacy.h>    /* need to still support chips no longer in trunk firmware */
39 
40 #include <siutils.h>
41 #include <hndpmu.h>
42 #include <hndsoc.h>
43 #include <bcmsdpcm.h>
44 #include <hnd_armtrap.h>
45 #include <hnd_cons.h>
46 #include <sbchipc.h>
47 #include <sbhnddma.h>
48 #if defined(DHD_SPROM)
49 #include <bcmsrom.h>
50 #endif /* defined(DHD_SPROM) */
51 
52 #include <sdio.h>
53 #ifdef BCMSPI
54 #include <spid.h>
55 #endif /* BCMSPI */
56 #include <sbsdio.h>
57 #include <sbsdpcmdev.h>
58 #include <bcmsdpcm.h>
59 #include <bcmsdbus.h>
60 
61 #include <ethernet.h>
62 #include <802.1d.h>
63 #include <802.11.h>
64 
65 #include <dngl_stats.h>
66 #include <dhd.h>
67 #include <dhd_bus.h>
68 #include <dhd_proto.h>
69 #include <dhd_dbg.h>
70 #include <dhdioctl.h>
71 #include <sdiovar.h>
72 #include <dhd_config.h>
73 #ifdef DHD_PKTDUMP_TOFW
74 #include <dhd_linux_pktdump.h>
75 #endif
76 #include <linux/mmc/sdio_func.h>
77 #include <dhd_linux.h>
78 #include <linux/mmc/host.h>
79 #include "bcmsdh_sdmmc.h"
80 
81 #ifdef PROP_TXSTATUS
82 #include <dhd_wlfc.h>
83 #endif
84 #ifdef DHDTCPACK_SUPPRESS
85 #include <dhd_ip.h>
86 #endif /* DHDTCPACK_SUPPRESS */
87 
88 #ifdef BT_OVER_SDIO
89 #include <dhd_bt_interface.h>
90 #endif /* BT_OVER_SDIO */
91 
92 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
93 #include <debugger.h>
94 #endif /* DEBUGGER || DHD_DSCOPE */
95 
96 bool dhd_mp_halting(dhd_pub_t *dhdp);
97 extern void bcmsdh_waitfor_iodrain(void *sdh);
98 extern void bcmsdh_reject_ioreqs(void *sdh, bool reject);
99 extern bool  bcmsdh_fatal_error(void *sdh);
100 static int dhdsdio_suspend(void *context);
101 static int dhdsdio_resume(void *context);
102 
103 #ifndef DHDSDIO_MEM_DUMP_FNAME
104 #define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
105 #endif
106 
107 #define QLEN		(1024) /* bulk rx and tx queue lengths */
108 #define FCHI		(QLEN - 10)
109 #define FCLOW		(FCHI / 2)
110 #define PRIOMASK	7 	/* XXX FixMe: should come from elsewhere...
111 				 * MAXPRIO?  PKTQ_MAX_PREC? WLC? Other?
112 				 */
113 
114 #define TXRETRIES	2	/* # of retries for tx frames */
115 #define READ_FRM_CNT_RETRIES	3
116 #ifndef DHD_RXBOUND
117 #define DHD_RXBOUND	50	/* Default for max rx frames in one scheduling */
118 #endif
119 
120 #ifndef DHD_TXBOUND
121 #define DHD_TXBOUND	20	/* Default for max tx frames in one scheduling */
122 #endif
123 
124 #define DHD_TXMINMAX	1	/* Max tx frames if rx still pending */
125 
126 #define MEMBLOCK	2048		/* Block size used for downloading of dongle image */
127 #define MAX_MEMBLOCK  (32 * 1024)	/* Block size used for downloading of dongle image */
128 
129 #define MAX_DATA_BUF	(64 * 1024)	/* Must be large enough to hold biggest possible glom */
130 #define MAX_MEM_BUF	4096
131 
132 #ifndef DHD_FIRSTREAD
133 #define DHD_FIRSTREAD   32
134 #endif
135 #if !ISPOWEROF2(DHD_FIRSTREAD)
136 #error DHD_FIRSTREAD is not a power of 2!
137 #endif
138 
139 /* Total length of frame header for dongle protocol */
140 #define SDPCM_HDRLEN	(SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
141 #define SDPCM_HDRLEN_TXGLOM	(SDPCM_HDRLEN + SDPCM_HWEXT_LEN)
142 #define MAX_TX_PKTCHAIN_CNT	SDPCM_MAXGLOM_SIZE
143 
144 #ifdef SDTEST
145 #define SDPCM_RESERVE	(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
146 #else
147 #define SDPCM_RESERVE	(SDPCM_HDRLEN + DHD_SDALIGN)
148 #endif
149 
150 /* Space for header read, limit for data packets */
151 #ifndef MAX_HDR_READ
152 #define MAX_HDR_READ	32
153 #endif
154 #if !ISPOWEROF2(MAX_HDR_READ)
155 #error MAX_HDR_READ is not a power of 2!
156 #endif
157 
158 #define MAX_RX_DATASZ	2048	/* XXX Should be based on PKTGET limits? */
159 
160 /* Maximum milliseconds to wait for F2 to come up */
161 #ifdef BCMQT
162 #define DHD_WAIT_F2RDY  30000
163 #else
164 #define DHD_WAIT_F2RDY	3000
165 #endif /* BCMQT */
166 
167 /* Maximum usec to wait for HTAVAIL to come up */
168 #ifdef BCMQT
169 #define DHD_WAIT_HTAVAIL	10000000
170 #else
171 #define DHD_WAIT_HTAVAIL	10000
172 #endif /* BCMQT */
173 
174 /* Bump up limit on waiting for HT to account for first startup;
175  * if the image is doing a CRC calculation before programming the PMU
176  * for HT availability, it could take a couple hundred ms more, so
177  * max out at a 1 second (1000000us).
178  */
179 #if (PMU_MAX_TRANSITION_DLY <= 1000000)
180 #undef PMU_MAX_TRANSITION_DLY
181 #ifdef NO_EXT32K
182 #define PMU_MAX_TRANSITION_DLY (1000000*5)
183 #else
184 #define PMU_MAX_TRANSITION_DLY 1000000
185 #endif
186 #endif // endif
187 
188 /* hooks for limiting threshold custom tx num in rx processing */
189 #define DEFAULT_TXINRX_THRES    0
190 #ifndef CUSTOM_TXINRX_THRES
191 #define CUSTOM_TXINRX_THRES     DEFAULT_TXINRX_THRES
192 #endif
193 
194 /* Value for ChipClockCSR during initial setup */
195 #define DHD_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
196 #define DHD_INIT_CLKCTL2	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
197 
198 /* Flags for SDH calls */
199 #define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
200 /* XXX #define F2ASYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED | SDIO_REQ_ASYNC) */
201 
202 /* Packet free applicable unconditionally for sdio and sdspi.  Conditional if
203  * bufpool was present for gspi bus.
204  */
205 #define PKTFREE2()		if ((bus->bus != SPI_BUS) || bus->usebufpool) \
206 					PKTFREE(bus->dhd->osh, pkt, FALSE);
207 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
208 
209 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW
210 extern unsigned int system_hw_rev;
211 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
212 
213 /* Device console log buffer state */
214 #define CONSOLE_LINE_MAX	192
215 #define CONSOLE_BUFFER_MAX	8192
216 typedef struct dhd_console {
217 	uint		count;			/* Poll interval msec counter */
218 	uint		log_addr;		/* Log struct address (fixed) */
219 	hnd_log_t	log;			/* Log struct (host copy) */
220 	uint		bufsize;		/* Size of log buffer */
221 	uint8		*buf;			/* Log buffer (host copy) */
222 	uint		last;			/* Last buffer read index */
223 } dhd_console_t;
224 
225 #define	REMAP_ENAB(bus)			((bus)->remap)
226 #define	REMAP_ISADDR(bus, a)		(((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
227 #define	KSO_ENAB(bus)			((bus)->kso)
228 #define	SR_ENAB(bus)			((bus)->_srenab)
229 #define	SLPAUTO_ENAB(bus)		((SR_ENAB(bus)) && ((bus)->_slpauto))
230 
231 #define	MIN_RSRC_SR			0x3
232 #define	CORE_CAPEXT_ADDR_OFFSET		(0x64c)
233 #define	CORE_CAPEXT_SR_SUPPORTED_MASK	(1 << 1)
234 #define RCTL_MACPHY_DISABLE_MASK	(1 << 26)
235 #define RCTL_LOGIC_DISABLE_MASK		(1 << 27)
236 
237 #define	OOB_WAKEUP_ENAB(bus)		((bus)->_oobwakeup)
238 #define	GPIO_DEV_SRSTATE		16	/* Host gpio17 mapped to device gpio0 SR state */
239 #define	GPIO_DEV_SRSTATE_TIMEOUT	320000	/* 320ms */
240 #define	GPIO_DEV_WAKEUP			17	/* Host gpio17 mapped to device gpio1 wakeup */
241 #define	CC_CHIPCTRL2_GPIO1_WAKEUP	(1  << 0)
242 #define	CC_CHIPCTRL3_SR_ENG_ENABLE	(1  << 2)
243 #define OVERFLOW_BLKSZ512_WM		96
244 #define OVERFLOW_BLKSZ512_MES		80
245 
246 #define CC_PMUCC3	(0x3)
247 
248 #ifdef DHD_UCODE_DOWNLOAD
249 /* Ucode host download related macros */
250 #define UCODE_DOWNLOAD_REQUEST  0xCAFECAFE
251 #define UCODE_DOWNLOAD_COMPLETE 0xABCDABCD
252 #endif /* DHD_UCODE_DOWNLOAD */
253 
254 #if defined(BT_OVER_SDIO)
255 #define BTMEM_OFFSET			0x19000000
256 /* BIT0 => WLAN Power UP and BIT1=> WLAN Wake */
257 #define BT2WLAN_PWRUP_WAKE		0x03
258 #define BT2WLAN_PWRUP_ADDR		0x640894	/* This address is specific to 43012B0 */
259 
260 #define BTFW_MAX_STR_LEN		600
261 #define BTFW_DOWNLOAD_BLK_SIZE		(BTFW_MAX_STR_LEN/2 + 8)
262 
263 #define BTFW_ADDR_MODE_UNKNOWN		0
264 #define BTFW_ADDR_MODE_EXTENDED		1
265 #define BTFW_ADDR_MODE_SEGMENT		2
266 #define BTFW_ADDR_MODE_LINEAR32		3
267 
268 #define BTFW_HEX_LINE_TYPE_DATA				0
269 #define BTFW_HEX_LINE_TYPE_END_OF_DATA			1
270 #define BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS	2
271 #define BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS		4
272 #define BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS	5
273 
274 #endif /* defined (BT_OVER_SDIO) */
275 
276 /* Private data for SDIO bus interaction */
277 typedef struct dhd_bus {
278 	dhd_pub_t	*dhd;
279 
280 	bcmsdh_info_t	*sdh;			/* Handle for BCMSDH calls */
281 	si_t		*sih;			/* Handle for SI calls */
282 	char		*vars;			/* Variables (from CIS and/or other) */
283 	uint		varsz;			/* Size of variables buffer */
284 	uint32		sbaddr;			/* Current SB window pointer (-1, invalid) */
285 
286 	sdpcmd_regs_t	*regs;			/* Registers for SDIO core */
287 	uint		sdpcmrev;		/* SDIO core revision */
288 	uint		armrev;			/* CPU core revision */
289 	uint		ramrev;			/* SOCRAM core revision */
290 	uint32		ramsize;		/* Size of RAM in SOCRAM (bytes) */
291 	uint32		orig_ramsize;		/* Size of RAM in SOCRAM (bytes) */
292 	uint32		srmemsize;		/* Size of SRMEM */
293 
294 	uint32		bus;			/* gSPI or SDIO bus */
295 	uint32		bus_num;		/* bus number */
296 	uint32		slot_num;		/* slot ID */
297 	uint32		hostintmask;	/* Copy of Host Interrupt Mask */
298 	uint32		intstatus;		/* Intstatus bits (events) pending */
299 	bool		dpc_sched;		/* Indicates DPC schedule (intrpt rcvd) */
300 	bool		fcstate;		/* State of dongle flow-control */
301 
302 	uint16		cl_devid;		/* cached devid for dhdsdio_probe_attach() */
303 	char		*fw_path;		/* module_param: path to firmware image */
304 	char		*nv_path;		/* module_param: path to nvram vars file */
305 
306 	uint		blocksize;		/* Block size of SDIO transfers */
307 	uint		roundup;		/* Max roundup limit */
308 
309 	struct pktq	txq;			/* Queue length used for flow-control */
310 	uint8		flowcontrol;		/* per prio flow control bitmask */
311 	uint8		tx_seq;			/* Transmit sequence number (next) */
312 	uint8		tx_max;			/* Maximum transmit sequence allowed */
313 
314 #ifdef DYNAMIC_MAX_HDR_READ
315 	uint8		*hdrbufp;
316 #else
317 	uint8		hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
318 #endif
319 	uint8		*rxhdr;			/* Header of current rx frame (in hdrbuf) */
320 	uint16		nextlen;		/* Next Read Len from last header */
321 	uint8		rx_seq;			/* Receive sequence number (expected) */
322 	bool		rxskip;			/* Skip receive (awaiting NAK ACK) */
323 
324 	void		*glomd;			/* Packet containing glomming descriptor */
325 	void		*glom;			/* Packet chain for glommed superframe */
326 	uint		glomerr;		/* Glom packet read errors */
327 
328 	uint8		*rxbuf;			/* Buffer for receiving control packets */
329 	uint		rxblen;			/* Allocated length of rxbuf */
330 	uint8		*rxctl;			/* Aligned pointer into rxbuf */
331 	uint8		*databuf;		/* Buffer for receiving big glom packet */
332 	uint8		*dataptr;		/* Aligned pointer into databuf */
333 	uint		rxlen;			/* Length of valid data in buffer */
334 
335 	uint8		sdpcm_ver;		/* Bus protocol reported by dongle */
336 
337 	bool		intr;			/* Use interrupts */
338 	bool		poll;			/* Use polling */
339 	bool		ipend;			/* Device interrupt is pending */
340 	bool		intdis;			/* Interrupts disabled by isr */
341 	uint 		intrcount;		/* Count of device interrupt callbacks */
342 	uint		lastintrs;		/* Count as of last watchdog timer */
343 	uint		spurious;		/* Count of spurious interrupts */
344 	uint		pollrate;		/* Ticks between device polls */
345 	uint		polltick;		/* Tick counter */
346 	uint		pollcnt;		/* Count of active polls */
347 
348 	dhd_console_t	console;		/* Console output polling support */
349 	uint		console_addr;		/* Console address from shared struct */
350 
351 	uint		regfails;		/* Count of R_REG/W_REG failures */
352 
353 	uint		clkstate;		/* State of sd and backplane clock(s) */
354 	bool		activity;		/* Activity flag for clock down */
355 	int32		idletime;		/* Control for activity timeout */
356 	int32		idlecount;		/* Activity timeout counter */
357 	int32		idleclock;		/* How to set bus driver when idle */
358 	int32		sd_divisor;		/* Speed control to bus driver */
359 	int32		sd_mode;		/* Mode control to bus driver */
360 	int32		sd_rxchain;		/* If bcmsdh api accepts PKT chains */
361 	bool		use_rxchain;		/* If dhd should use PKT chains */
362 	bool		sleeping;		/* Is SDIO bus sleeping? */
363 #if defined(LINUX) && defined(SUPPORT_P2P_GO_PS)
364 	wait_queue_head_t bus_sleep;
365 #endif /* LINUX && SUPPORT_P2P_GO_PS */
366 	bool		ctrl_wait;
367 	wait_queue_head_t ctrl_tx_wait;
368 	uint		rxflow_mode;		/* Rx flow control mode */
369 	bool		rxflow;			/* Is rx flow control on */
370 	uint		prev_rxlim_hit;		/* Is prev rx limit exceeded (per dpc schedule) */
371 #ifdef BCMINTERNAL
372 	bool		_nopmu;			/* No PMU (FPGA), don't try it */
373 	bool		clockpoll;		/* Force clock polling (no chipactive interrupt) */
374 #endif
375 	bool		alp_only;		/* Don't use HT clock (ALP only) */
376 	/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
377 	bool		usebufpool;
378 	int32		txinrx_thres;	/* num of in-queued pkts */
379 	int32		dotxinrx;	/* tx first in dhdsdio_readframes */
380 #ifdef BCMSDIO_RXLIM_POST
381 	bool		rxlim_en;
382 	uint32		rxlim_addr;
383 #endif /* BCMSDIO_RXLIM_POST */
384 #ifdef SDTEST
385 	/* external loopback */
386 	bool		ext_loop;
387 	uint8		loopid;
388 
389 	/* pktgen configuration */
390 	uint		pktgen_freq;		/* Ticks between bursts */
391 	uint		pktgen_count;		/* Packets to send each burst */
392 	uint		pktgen_print;		/* Bursts between count displays */
393 	uint		pktgen_total;		/* Stop after this many */
394 	uint		pktgen_minlen;		/* Minimum packet data len */
395 	uint		pktgen_maxlen;		/* Maximum packet data len */
396 	uint		pktgen_mode;		/* Configured mode: tx, rx, or echo */
397 	uint		pktgen_stop;		/* Number of tx failures causing stop */
398 
399 	/* active pktgen fields */
400 	uint		pktgen_tick;		/* Tick counter for bursts */
401 	uint		pktgen_ptick;		/* Burst counter for printing */
402 	uint		pktgen_sent;		/* Number of test packets generated */
403 	uint		pktgen_rcvd;		/* Number of test packets received */
404 	uint		pktgen_prev_time;	/* Time at which previous stats where printed */
405 	uint		pktgen_prev_sent;	/* Number of test packets generated when
406 						 * previous stats were printed
407 						 */
408 	uint		pktgen_prev_rcvd;	/* Number of test packets received when
409 						 * previous stats were printed
410 						 */
411 	uint		pktgen_fail;		/* Number of failed send attempts */
412 	uint16		pktgen_len;		/* Length of next packet to send */
413 #define PKTGEN_RCV_IDLE     (0)
414 #define PKTGEN_RCV_ONGOING  (1)
415 	uint16		pktgen_rcv_state;		/* receive state */
416 	uint		pktgen_rcvd_rcvsession;	/* test pkts rcvd per rcv session. */
417 #endif /* SDTEST */
418 
419 	/* Some additional counters */
420 	uint		tx_sderrs;		/* Count of tx attempts with sd errors */
421 	uint		fcqueued;		/* Tx packets that got queued */
422 	uint		rxrtx;			/* Count of rtx requests (NAK to dongle) */
423 	uint		rx_toolong;		/* Receive frames too long to receive */
424 	uint		rxc_errors;		/* SDIO errors when reading control frames */
425 	uint		rx_hdrfail;		/* SDIO errors on header reads */
426 	uint		rx_badhdr;		/* Bad received headers (roosync?) */
427 	uint		rx_badseq;		/* Mismatched rx sequence number */
428 	uint		fc_rcvd;		/* Number of flow-control events received */
429 	uint		fc_xoff;		/* Number which turned on flow-control */
430 	uint		fc_xon;			/* Number which turned off flow-control */
431 	uint		rxglomfail;		/* Failed deglom attempts */
432 	uint		rxglomframes;		/* Number of glom frames (superframes) */
433 	uint		rxglompkts;		/* Number of packets from glom frames */
434 	uint		f2rxhdrs;		/* Number of header reads */
435 	uint		f2rxdata;		/* Number of frame data reads */
436 	uint		f2txdata;		/* Number of f2 frame writes */
437 	uint		f1regdata;		/* Number of f1 register accesses */
438 	wake_counts_t	wake_counts;		/* Wake up counter */
439 #ifdef BCMSPI
440 	bool		dwordmode;
441 #endif /* BCMSPI */
442 #ifdef DHDENABLE_TAILPAD
443 	uint		tx_tailpad_chain;	/* Number of tail padding by chaining pad_pkt */
444 	uint		tx_tailpad_pktget;	/* Number of tail padding by new PKTGET */
445 #endif /* DHDENABLE_TAILPAD */
446 #ifdef BCMINTERNAL
447 	uint		tx_deferred;		/* Tx calls queued while event pending */
448 #endif
449 	uint8		*ctrl_frame_buf;
450 	uint32		ctrl_frame_len;
451 	bool		ctrl_frame_stat;
452 #ifndef BCMSPI
453 	uint32		rxint_mode;	/* rx interrupt mode */
454 #endif /* BCMSPI */
455 	bool		remap;		/* Contiguous 1MB RAM: 512K socram + 512K devram
456 					 * Available with socram rev 16
457 					 * Remap region not DMA-able
458 					 */
459 	bool		kso;
460 	bool		_slpauto;
461 	bool		_oobwakeup;
462 	bool		_srenab;
463 	bool        readframes;
464 	bool        reqbussleep;
465 	uint32		resetinstr;
466 	uint32		dongle_ram_base;
467 
468 	void		*glom_pkt_arr[SDPCM_MAXGLOM_SIZE];	/* Array of pkts for glomming */
469 	uint32		txglom_cnt;	/* Number of pkts in the glom array */
470 	uint32		txglom_total_len;	/* Total length of pkts in glom array */
471 	bool		txglom_enable;	/* Flag to indicate whether tx glom is enabled/disabled */
472 	uint32		txglomsize;	/* Glom size limitation */
473 #ifdef DHDENABLE_TAILPAD
474 	void		*pad_pkt;
475 #endif /* DHDENABLE_TAILPAD */
476 	uint32		dongle_trap_addr; /* device trap addr location in device memory */
477 #if defined(BT_OVER_SDIO)
478 	char		*btfw_path;	/* module_param: path to BT firmware image */
479 	uint32		bt_use_count; /* Counter that tracks whether BT is using the bus */
480 #endif /* defined (BT_OVER_SDIO) */
481 	uint		txglomframes;	/* Number of tx glom frames (superframes) */
482 	uint		txglompkts;		/* Number of packets from tx glom frames */
483 #ifdef PKT_STATICS
484 	struct pkt_statics tx_statics;
485 #endif
486 	uint8		*membuf;		/* Buffer for dhdsdio_membytes */
487 #ifdef CONSOLE_DPC
488 	char		cons_cmd[16];
489 #endif
490 } dhd_bus_t;
491 
492 /*
493  * Whenever DHD_IDLE_IMMEDIATE condition is handled, we have to now check if
494  * BT is active too. Instead of adding #ifdef code in all the places, we thought
495  * of adding one macro check as part of the if condition that checks for DHD_IDLE_IMMEDIATE
496  * In case of non BT over SDIO builds, this macro will always return TRUE. In case
497  * of the builds where BT_OVER_SDIO is enabled, it will expand to a condition check
498  * that checks if bt_use_count is zero. So this macro will return equate to 1 if
499  * bt_use_count is 0, indicating that there are no active users and if bt_use_count
500  * is non zero it would return 0 there by preventing the caller from executing the
501  * sleep calls.
502  */
503 #ifdef BT_OVER_SDIO
504 #define NO_OTHER_ACTIVE_BUS_USER(bus)		(bus->bt_use_count == 0)
505 #else
506 #define NO_OTHER_ACTIVE_BUS_USER(bus)		(1)
507 #endif /* BT_OVER_SDIO */
508 
509 /* clkstate */
510 #define CLK_NONE	0
511 #define CLK_SDONLY	1
512 #define CLK_PENDING	2	/* Not used yet */
513 #define CLK_AVAIL	3
514 
515 #ifdef BCMINTERNAL
516 #define DHD_NOPMU(dhd)	((dhd)->_nopmu)
517 #else
518 #define DHD_NOPMU(dhd)	(FALSE)
519 #endif
520 
521 #if defined(BCMSDIOH_STD)
522 #define BLK_64_MAXTXGLOM 20
523 #endif /* BCMSDIOH_STD */
524 
525 #ifdef DHD_DEBUG
526 static int qcount[NUMPRIO];
527 static int tx_packets[NUMPRIO];
528 #endif /* DHD_DEBUG */
529 
530 /* Deferred transmit */
531 const uint dhd_deferred_tx = 1;
532 
533 extern uint dhd_watchdog_ms;
534 #ifndef NDIS
535 extern uint sd_f1_blocksize;
536 #endif /* !NDIS */
537 
538 #ifdef BCMSPI_ANDROID
539 extern uint *dhd_spi_lockcount;
540 #endif /* BCMSPI_ANDROID */
541 
542 extern void dhd_os_wd_timer(void *bus, uint wdtick);
543 int dhd_enableOOB(dhd_pub_t *dhd, bool sleep);
544 
545 #ifdef DHD_PM_CONTROL_FROM_FILE
546 extern bool g_pm_control;
547 #endif /* DHD_PM_CONTROL_FROM_FILE */
548 
549 /* Tx/Rx bounds */
550 uint dhd_txbound;
551 uint dhd_rxbound;
552 uint dhd_txminmax = DHD_TXMINMAX;
553 
554 /* override the RAM size if possible */
555 #define DONGLE_MIN_RAMSIZE (128 *1024)
556 int dhd_dongle_ramsize;
557 
558 uint dhd_doflow = TRUE;
559 uint dhd_dpcpoll = FALSE;
560 
561 #ifdef linux
562 module_param(dhd_doflow, uint, 0644);
563 module_param(dhd_dpcpoll, uint, 0644);
564 #endif
565 
566 static bool dhd_alignctl;
567 
568 static bool sd1idle;
569 
570 static bool retrydata;
571 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
572 
573 #ifndef BCMINTERNAL
574 #ifdef BCMSPI
575 /* At a watermark around 8 the spid hits underflow error. */
576 static uint watermark = 32;
577 static uint mesbusyctrl = 0;
578 #else
579 static uint watermark = 8;
580 static uint mesbusyctrl = 0;
581 #endif /* BCMSPI */
582 #ifdef DYNAMIC_MAX_HDR_READ
583 uint firstread = DHD_FIRSTREAD;
584 #else
585 static const uint firstread = DHD_FIRSTREAD;
586 #endif
587 #else /* BCMINTERNAL */
588 /* PR47410: low watermark to avoid F2 hang after SD clock stops */
589 /* PR48178: read to (not through) bus burst to avoid F2 underflow */
590 #ifdef BCMSPI
591 static uint watermark = 32;
592 static uint mesbusyctrl = 0;
593 #else
594 static uint watermark = 8;
595 static uint mesbusyctrl = 0;
596 #endif /* BCMSPI */
597 static uint firstread = DHD_FIRSTREAD;
598 /* Additional knobs in case we need them */
599 static bool tstoph = FALSE;
600 static bool checkfifo = FALSE;
601 uint dhd_anychip = 0;
602 #endif /* BCMINTERNAL */
603 
604 /* Retry count for register access failures */
605 static const uint retry_limit = 2;
606 
607 /* Force even SD lengths (some host controllers mess up on odd bytes) */
608 static bool forcealign;
609 
610 #if defined(DEBUGGER)
611 static uint32 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr);
612 static void dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val);
613 
614 /** the debugger layer will call back into this (bus) layer to read/write dongle memory */
615 static struct dhd_dbg_bus_ops_s  bus_ops = {
616 	.read_u16 = NULL,
617 	.read_u32 = dhd_sdio_reg_read,
618 	.write_u32 = dhd_sdio_reg_write,
619 };
620 #endif /* DEBUGGER */
621 
622 #define ALIGNMENT  4
623 
624 #if (defined(OOB_INTR_ONLY) && defined(HW_OOB)) || defined(FORCE_WOWLAN)
625 extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
626 #endif
627 
628 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
629 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
630 #endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
631 #define PKTALIGN(osh, p, len, align)					\
632 	do {								\
633 		uintptr datalign;						\
634 		datalign = (uintptr)PKTDATA((osh), (p));		\
635 		datalign = ROUNDUP(datalign, (align)) - datalign;	\
636 		ASSERT(datalign < (align));				\
637 		ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign));	\
638 		if (datalign)						\
639 			PKTPULL((osh), (p), (uint)datalign);			\
640 		PKTSETLEN((osh), (p), (len));				\
641 	} while (0)
642 
643 /* Limit on rounding up frames */
644 static const uint max_roundup = 512;
645 
646 /* Try doing readahead */
647 static bool dhd_readahead;
648 
649 #if defined(BCMSDIOH_TXGLOM_EXT)
650 bool
dhdsdio_is_dataok(dhd_bus_t * bus)651 dhdsdio_is_dataok(dhd_bus_t *bus) {
652 	return (((uint8)(bus->tx_max - bus->tx_seq) - bus->dhd->conf->tx_max_offset > 1) && \
653 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0));
654 }
655 
656 uint8
dhdsdio_get_databufcnt(dhd_bus_t * bus)657 dhdsdio_get_databufcnt(dhd_bus_t *bus) {
658 	return ((uint8)(bus->tx_max - bus->tx_seq) - 1 - bus->dhd->conf->tx_max_offset);
659 }
660 #endif
661 
662 /* To check if there's window offered */
663 #if defined(BCMSDIOH_TXGLOM_EXT)
664 #define DATAOK(bus) dhdsdio_is_dataok(bus)
665 #else
666 #define DATAOK(bus) \
667 	(((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
668 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
669 #endif
670 
671 /* To check if there's window offered for ctrl frame */
672 #define TXCTLOK(bus) \
673 	(((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
674 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
675 
676 /* Number of pkts available in dongle for data RX */
677 #if defined(BCMSDIOH_TXGLOM_EXT)
678 #define DATABUFCNT(bus) dhdsdio_get_databufcnt(bus)
679 #else
680 #define DATABUFCNT(bus) \
681 	((uint8)(bus->tx_max - bus->tx_seq) - 1)
682 #endif
683 
684 /* Macros to get register read/write status */
685 /* NOTE: these assume a local dhdsdio_bus_t *bus! */
686 /* XXX Need to replace these with something better. */
687 #define R_SDREG(regvar, regaddr, retryvar) \
688 do { \
689 	retryvar = 0; \
690 	do { \
691 		regvar = R_REG(bus->dhd->osh, regaddr); \
692 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
693 	if (retryvar) { \
694 		bus->regfails += (retryvar-1); \
695 		if (retryvar > retry_limit) { \
696 			DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
697 			           __FUNCTION__, __LINE__)); \
698 			regvar = 0; \
699 		} \
700 	} \
701 } while (0)
702 
703 #define W_SDREG(regval, regaddr, retryvar) \
704 do { \
705 	retryvar = 0; \
706 	do { \
707 		W_REG(bus->dhd->osh, regaddr, regval); \
708 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
709 	if (retryvar) { \
710 		bus->regfails += (retryvar-1); \
711 		if (retryvar > retry_limit) \
712 			DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
713 			           __FUNCTION__, __LINE__)); \
714 	} \
715 } while (0)
716 
717 #define BUS_WAKE(bus) \
718 	do { \
719 		bus->idlecount = 0; \
720 		if ((bus)->sleeping) \
721 			dhdsdio_bussleep((bus), FALSE); \
722 	} while (0);
723 
724 /*
725  * pktavail interrupts from dongle to host can be managed in 3 different ways
726  * whenever there is a packet available in dongle to transmit to host.
727  *
728  * Mode 0:	Dongle writes the software host mailbox and host is interrupted.
729  * Mode 1:	(sdiod core rev >= 4)
730  *		Device sets a new bit in the intstatus whenever there is a packet
731  *		available in fifo.  Host can't clear this specific status bit until all the
732  *		packets are read from the FIFO.  No need to ack dongle intstatus.
733  * Mode 2:	(sdiod core rev >= 4)
734  *		Device sets a bit in the intstatus, and host acks this by writing
735  *		one to this bit.  Dongle won't generate anymore packet interrupts
736  *		until host reads all the packets from the dongle and reads a zero to
737  *		figure that there are no more packets.  No need to disable host ints.
738  *		Need to ack the intstatus.
739  */
740 
741 #define SDIO_DEVICE_HMB_RXINT		0	/* default old way */
742 #define SDIO_DEVICE_RXDATAINT_MODE_0	1	/* from sdiod rev 4 */
743 #define SDIO_DEVICE_RXDATAINT_MODE_1	2	/* from sdiod rev 4 */
744 
745 #ifdef BCMSPI
746 
747 #define FRAME_AVAIL_MASK(bus) I_HMB_FRAME_IND
748 
749 #define DHD_BUS			SPI_BUS
750 
751 /* check packet-available-interrupt in piggybacked dstatus */
752 #define PKT_AVAILABLE(bus, intstatus)	(bcmsdh_get_dstatus(bus->sdh) & STATUS_F2_PKT_AVAILABLE)
753 
754 #define HOSTINTMASK		(I_HMB_FC_CHANGE | I_HMB_HOST_INT)
755 
756 #define GSPI_PR55150_BAILOUT									\
757 do {												\
758 	uint32 dstatussw = bcmsdh_get_dstatus((void *)bus->sdh);				\
759 	uint32 dstatushw = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL);	\
760 	uint32 intstatuserr = 0;								\
761 	uint retries = 0;									\
762 												\
763 	R_SDREG(intstatuserr, &bus->regs->intstatus, retries);					\
764 	printf("dstatussw = 0x%x, dstatushw = 0x%x, intstatus = 0x%x\n",			\
765 	        dstatussw, dstatushw, intstatuserr); 						\
766 												\
767 	bus->nextlen = 0;									\
768 	*finished = TRUE;									\
769 } while (0)
770 
771 #else /* BCMSDIO */
772 
773 #define FRAME_AVAIL_MASK(bus) 	\
774 	((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL)
775 
776 #define DHD_BUS			SDIO_BUS
777 
778 #define PKT_AVAILABLE(bus, intstatus)	((intstatus) & (FRAME_AVAIL_MASK(bus)))
779 
780 #define HOSTINTMASK		(I_HMB_SW_MASK | I_CHIPACTIVE)
781 
782 #define GSPI_PR55150_BAILOUT
783 
784 #endif /* BCMSPI */
785 
786 #ifdef SDTEST
787 static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
788 static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count);
789 #endif
790 
791 static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size);
792 #ifdef DHD_DEBUG
793 static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror);
794 #endif /* DHD_DEBUG */
795 
796 #if defined(DHD_FW_COREDUMP)
797 static int dhdsdio_mem_dump(dhd_bus_t *bus);
798 static int dhdsdio_get_mem_dump(dhd_bus_t *bus);
799 #endif /* DHD_FW_COREDUMP */
800 static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap);
801 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
802 
803 static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
804 static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
805 static void dhdsdio_disconnect(void *ptr);
806 static bool dhdsdio_chipmatch(uint16 chipid);
807 static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
808                                  void * regsva, uint16  devid);
809 static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
810 static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
811 static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation,
812 	bool reset_flag);
813 
814 static void dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size);
815 static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
816 	uint8 *buf, uint nbytes,
817 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
818 static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
819 	uint8 *buf, uint nbytes,
820 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry);
821 static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt);
822 static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
823 	int prev_chain_total_len, bool last_chained_pkt,
824 	int *pad_pkt_len, void **new_pkt
825 #if defined(BCMSDIOH_TXGLOM_EXT)
826 	, int first_frame
827 #endif
828 );
829 static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt);
830 
831 static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh);
832 static int _dhdsdio_download_firmware(dhd_bus_t *bus);
833 
834 #ifdef DHD_UCODE_DOWNLOAD
835 static int dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path);
836 #endif /* DHD_UCODE_DOWNLOAD */
837 static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path);
838 static int dhdsdio_download_nvram(dhd_bus_t *bus);
839 #ifdef BCMEMBEDIMAGE
840 static int dhdsdio_download_code_array(dhd_bus_t *bus);
841 #endif
842 static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep);
843 static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok);
844 static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus);
845 static bool dhdsdio_dpc(dhd_bus_t *bus);
846 static int dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len);
847 static int dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode);
848 static int dhdsdio_sdclk(dhd_bus_t *bus, bool on);
849 static void dhdsdio_advertise_bus_cleanup(dhd_pub_t *dhdp);
850 static void dhdsdio_advertise_bus_remove(dhd_pub_t *dhdp);
851 
852 #if defined(BT_OVER_SDIO)
853 static int extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value);
854 static int read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode,
855 	uint16 * hi_addr, uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes);
856 static int dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh);
857 static int _dhdsdio_download_btfw(struct dhd_bus *bus);
858 #endif /* defined (BT_OVER_SDIO) */
859 
860 #ifdef DHD_WAKE_STATUS
861 int bcmsdh_get_total_wake(bcmsdh_info_t *bcmsdh);
862 int bcmsdh_set_get_wake(bcmsdh_info_t *bcmsdh, int flag);
863 #endif /* DHD_WAKE_STATUS */
864 
865 /*
866  * PR 114233: [4335] Sdio 3.0 overflow due to spur mode PLL change
867  */
868 static void
dhdsdio_tune_fifoparam(struct dhd_bus * bus)869 dhdsdio_tune_fifoparam(struct dhd_bus *bus)
870 {
871 	int err;
872 	uint8 devctl, wm, mes;
873 
874 	if (bus->sih->buscorerev >= 15) {
875 		/* See .ppt in PR for these recommended values */
876 		if (bus->blocksize == 512) {
877 			wm = OVERFLOW_BLKSZ512_WM;
878 			mes = OVERFLOW_BLKSZ512_MES;
879 		} else {
880 			mes = bus->blocksize/4;
881 			wm = bus->blocksize/4;
882 		}
883 
884 		/* XXX: Need to set watermark since SBSDIO_WATERMARK could be overwritten
885 		 based on watermark value in other place. Refer to SWDHD-17.
886 		*/
887 		watermark = wm;
888 		mesbusyctrl = mes;
889 	} else {
890 		DHD_INFO(("skip fifotune: SdioRev(%d) is lower than minimal requested ver\n",
891 			bus->sih->buscorerev));
892 		return;
893 	}
894 
895 	/* Update watermark */
896 	if (wm > 0) {
897 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err);
898 
899 		devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
900 		devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
901 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
902 	}
903 
904 	/* Update MES */
905 	if (mes > 0) {
906 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
907 			(mes | SBSDIO_MESBUSYCTRL_ENAB), &err);
908 	}
909 
910 	DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n",
911 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err),
912 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err),
913 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err)));
914 }
915 
916 static void
dhd_dongle_setramsize(struct dhd_bus * bus,int mem_size)917 dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size)
918 {
919 	int32 min_size =  DONGLE_MIN_RAMSIZE;
920 	/* Restrict the ramsize to user specified limit */
921 	DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
922 		dhd_dongle_ramsize, min_size));
923 	if ((dhd_dongle_ramsize > min_size) &&
924 		(dhd_dongle_ramsize < (int32)bus->orig_ramsize))
925 		bus->ramsize = dhd_dongle_ramsize;
926 }
927 
928 static int
dhdsdio_set_siaddr_window(dhd_bus_t * bus,uint32 address)929 dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
930 {
931 	int err = 0;
932 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
933 	                 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
934 	if (!err)
935 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
936 		                 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
937 	if (!err)
938 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
939 		                 (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
940 	return err;
941 }
942 
943 #ifdef BCMSPI
944 static void
dhdsdio_wkwlan(dhd_bus_t * bus,bool on)945 dhdsdio_wkwlan(dhd_bus_t *bus, bool on)
946 {
947 	int err;
948 	uint32 regdata;
949 	bcmsdh_info_t *sdh = bus->sdh;
950 
951 	/* XXX: sdiod cores have SPI as a block, PCMCIA doesn't have the gspi core */
952 	/* XXX: may be we don't even need this check at all */
953 	if (bus->sih->buscoretype == SDIOD_CORE_ID) {
954 		/* wake up wlan function :WAKE_UP goes as ht_avail_request and alp_avail_request */
955 		regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL);
956 		DHD_INFO(("F0 REG0 rd = 0x%x\n", regdata));
957 
958 		if (on == TRUE)
959 			regdata |= WAKE_UP;
960 		else
961 			regdata &= ~WAKE_UP;
962 
963 		bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err);
964 	}
965 }
966 #endif /* BCMSPI */
967 
968 #ifdef USE_OOB_GPIO1
969 static int
dhdsdio_oobwakeup_init(dhd_bus_t * bus)970 dhdsdio_oobwakeup_init(dhd_bus_t *bus)
971 {
972 	uint32 val, addr, data;
973 
974 	bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP);
975 
976 	addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
977 	data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
978 
979 	/* Set device for gpio1 wakeup */
980 	bcmsdh_reg_write(bus->sdh, addr, 4, 2);
981 	val = bcmsdh_reg_read(bus->sdh, data, 4);
982 	val |= CC_CHIPCTRL2_GPIO1_WAKEUP;
983 	bcmsdh_reg_write(bus->sdh, data, 4, val);
984 
985 	bus->_oobwakeup = TRUE;
986 
987 	return 0;
988 }
989 #endif /* USE_OOB_GPIO1 */
990 
991 #ifndef BCMSPI
992 /*
993  * Query if FW is in SR mode
994  */
995 static bool
dhdsdio_sr_cap(dhd_bus_t * bus)996 dhdsdio_sr_cap(dhd_bus_t *bus)
997 {
998 	bool cap = FALSE;
999 	uint32  core_capext, addr, data;
1000 
1001 	if (bus->sih->chip == BCM43430_CHIP_ID ||
1002 		bus->sih->chip == BCM43018_CHIP_ID) {
1003 		/* check if fw initialized sr engine */
1004 		addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, sr_control1);
1005 		if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0)
1006 			cap = TRUE;
1007 
1008 		return cap;
1009 	}
1010 	if (
1011 #ifdef UNRELEASEDCHIP
1012 		(bus->sih->chip == BCM4347_CHIP_ID) ||
1013 		(bus->sih->chip == BCM4357_CHIP_ID) ||
1014 		(bus->sih->chip == BCM4361_CHIP_ID) ||
1015 #endif
1016 		0) {
1017 			core_capext = FALSE;
1018 	} else if ((bus->sih->chip == BCM4330_CHIP_ID) ||
1019 		(bus->sih->chip == BCM43362_CHIP_ID) ||
1020 		(BCM4347_CHIP(bus->sih->chip))) {
1021 			core_capext = FALSE;
1022 	} else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
1023 		(bus->sih->chip == BCM4339_CHIP_ID) ||
1024 		BCM4345_CHIP(bus->sih->chip) ||
1025 		(bus->sih->chip == BCM4354_CHIP_ID) ||
1026 		(bus->sih->chip == BCM4358_CHIP_ID) ||
1027 		(bus->sih->chip == BCM43569_CHIP_ID) ||
1028 		(bus->sih->chip == BCM4371_CHIP_ID) ||
1029 		(BCM4349_CHIP(bus->sih->chip))		||
1030 		(bus->sih->chip == BCM4350_CHIP_ID) ||
1031 		(bus->sih->chip == BCM4362_CHIP_ID) ||
1032 		(bus->sih->chip == BCM43012_CHIP_ID) ||
1033 		(bus->sih->chip == BCM43013_CHIP_ID) ||
1034 		(bus->sih->chip == BCM43014_CHIP_ID) ||
1035 		(bus->sih->chip == BCM43751_CHIP_ID) ||
1036 		(bus->sih->chip == BCM43752_CHIP_ID)) {
1037 		core_capext = TRUE;
1038 	} else {
1039 		/* XXX: For AOB, CORE_CAPEXT_ADDR is moved to PMU core */
1040 		core_capext = bcmsdh_reg_read(bus->sdh,
1041 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, core_cap_ext)),
1042 			4);
1043 
1044 		core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
1045 	}
1046 	if (!(core_capext))
1047 		return FALSE;
1048 
1049 	if ((bus->sih->chip == BCM4335_CHIP_ID) ||
1050 		(bus->sih->chip == BCM4339_CHIP_ID) ||
1051 		BCM4345_CHIP(bus->sih->chip) ||
1052 		(bus->sih->chip == BCM4354_CHIP_ID) ||
1053 		(bus->sih->chip == BCM4358_CHIP_ID) ||
1054 		(bus->sih->chip == BCM43569_CHIP_ID) ||
1055 		(bus->sih->chip == BCM4371_CHIP_ID) ||
1056 		(bus->sih->chip == BCM4350_CHIP_ID)) {
1057 		uint32 enabval = 0;
1058 		addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
1059 		data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
1060 		/* XXX: assuming the dongle doesn't change chipcontrol_addr, because
1061 		* if that happens, the chipcontrol_data read will be wrong. So we need
1062 		* to make sure the dongle and host will not access chipcontrol_addr
1063 		* simultaneously at this point.
1064 		*/
1065 		bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3);
1066 		enabval = bcmsdh_reg_read(bus->sdh, data, 4);
1067 
1068 		if ((bus->sih->chip == BCM4350_CHIP_ID) ||
1069 			BCM4345_CHIP(bus->sih->chip) ||
1070 			(bus->sih->chip == BCM4354_CHIP_ID) ||
1071 			(bus->sih->chip == BCM4358_CHIP_ID) ||
1072 			(bus->sih->chip == BCM43569_CHIP_ID) ||
1073 			(bus->sih->chip == BCM4371_CHIP_ID))
1074 			enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
1075 
1076 		/* XXX: not checking the CC_PMUCC3_SRCC_SR_ENG_ENAB bit [val 4], but
1077 		* will check the whole register to be non-zero so that, sleep sequence
1078 		* can be also checked without enabling SR.
1079 		*/
1080 		if (enabval)
1081 			cap = TRUE;
1082 	} else {
1083 		data = bcmsdh_reg_read(bus->sdh,
1084 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, retention_ctl)),
1085 			4);
1086 		if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
1087 			cap = TRUE;
1088 	}
1089 
1090 	return cap;
1091 }
1092 
1093 static int
dhdsdio_sr_init(dhd_bus_t * bus)1094 dhdsdio_sr_init(dhd_bus_t *bus)
1095 {
1096 	uint8 val;
1097 	int err = 0;
1098 
1099 	if (bus->sih->chip == BCM43012_CHIP_ID ||
1100 		bus->sih->chip == BCM43013_CHIP_ID ||
1101 		bus->sih->chip == BCM43014_CHIP_ID) {
1102 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1103 		val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
1104 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1105 			1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT, &err);
1106 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1107 	} else {
1108 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1109 		val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
1110 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1111 			1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
1112 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1113 	}
1114 
1115 #ifdef USE_CMD14
1116 	/* Add CMD14 Support */
1117 	dhdsdio_devcap_set(bus,
1118 		(SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT));
1119 #endif /* USE_CMD14 */
1120 
1121 	if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
1122 		CHIPID(bus->sih->chip) == BCM43018_CHIP_ID ||
1123 		CHIPID(bus->sih->chip) == BCM4339_CHIP_ID ||
1124 		CHIPID(bus->sih->chip) == BCM4362_CHIP_ID ||
1125 		CHIPID(bus->sih->chip) == BCM43012_CHIP_ID ||
1126 		CHIPID(bus->sih->chip) == BCM43013_CHIP_ID ||
1127 		CHIPID(bus->sih->chip) == BCM43014_CHIP_ID ||
1128 		CHIPID(bus->sih->chip) == BCM43751_CHIP_ID ||
1129 		CHIPID(bus->sih->chip) == BCM43752_CHIP_ID)
1130 			dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
1131 
1132 	if (bus->sih->chip == BCM43012_CHIP_ID ||
1133 		bus->sih->chip == BCM43013_CHIP_ID ||
1134 		bus->sih->chip == BCM43014_CHIP_ID) {
1135 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
1136 			SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_HT_AVAIL_REQ, &err);
1137 	} else {
1138 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
1139 			SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
1140 	}
1141 	bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
1142 
1143 	bus->_srenab = TRUE;
1144 
1145 	return 0;
1146 }
1147 #endif /* BCMSPI */
1148 
1149 /*
1150  * FIX: Be sure KSO bit is enabled
1151  * Currently, it's defaulting to 0 which should be 1.
1152  */
1153 static int
dhdsdio_clk_kso_init(dhd_bus_t * bus)1154 dhdsdio_clk_kso_init(dhd_bus_t *bus)
1155 {
1156 	uint8 val;
1157 	int err = 0;
1158 
1159 	/* set flag */
1160 	bus->kso = TRUE;
1161 
1162 	/*
1163 	 * Enable KeepSdioOn (KSO) bit for normal operation
1164 	 * Default is 0 (4334A0) so set it. Fixed in B0.
1165 	 */
1166 	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, NULL);
1167 	if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
1168 		val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
1169 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, val, &err);
1170 		if (err)
1171 			DHD_ERROR(("%s: SBSDIO_FUNC1_SLEEPCSR err: 0x%x\n", __FUNCTION__, err));
1172 	}
1173 
1174 	return 0;
1175 }
1176 
1177 #define KSO_DBG(x)
1178 /* XXX KSO set typically takes depending on resource up & number of
1179 * resources which were down. Max value is PMU_MAX_TRANSITION_DLY usec.
1180 * Currently the KSO attempt loop is such that, it waits
1181 * (KSO_WAIT_US [50usec] time + 2 SDIO operations) * MAX_KSO_ATTEMPTS.
1182 * So setting a value of maximum PMU_MAX_TRANSITION_DLY as wait time.,
1183 * to calculate MAX_KSO_ATTEMPTS.
1184 */
1185 #define KSO_WAIT_US 50
1186 #define KSO_WAIT_MS 1
1187 #define KSO_SLEEP_RETRY_COUNT 20
1188 #define KSO_WAKE_RETRY_COUNT 100
1189 #define ERROR_BCME_NODEVICE_MAX 1
1190 
1191 #define DEFAULT_MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
1192 #ifndef CUSTOM_MAX_KSO_ATTEMPTS
1193 #define CUSTOM_MAX_KSO_ATTEMPTS DEFAULT_MAX_KSO_ATTEMPTS
1194 #endif
1195 
1196 static int
dhdsdio_clk_kso_enab(dhd_bus_t * bus,bool on)1197 dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
1198 {
1199 	uint8 wr_val = 0, rd_val, cmp_val, bmask;
1200 	int err = 0;
1201 	int try_cnt = 0, try_max = CUSTOM_MAX_KSO_ATTEMPTS;
1202 	struct dhd_conf *conf = bus->dhd->conf;
1203 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
1204 	wifi_adapter_info_t *adapter = NULL;
1205 	uint32 bus_type = -1, bus_num = -1, slot_num = -1;
1206 #else
1207 	struct mmc_host *host;
1208 	struct sdioh_info *sd = (struct sdioh_info *)(bus->sdh->sdioh);
1209 	struct sdio_func *func = sd->func[SDIO_FUNC_0];
1210 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1211 
1212 	KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
1213 
1214 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
1215 	dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num);
1216 	adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
1217 	sdio_retune_crc_disable(adapter->sdio_func);
1218 	if (on)
1219 		sdio_retune_hold_now(adapter->sdio_func);
1220 #else
1221 	host = func->card->host;
1222 	mmc_retune_disable(host);
1223 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1224 
1225 	wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
1226 
1227 	/* XXX 1st KSO write goes to AOS wake up core if device is asleep  */
1228 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
1229 
1230 	/* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared.
1231 	 * So the further reads of KSO register could fail. Thereby just bailing out immediately
1232 	 * after clearing KSO bit, to avoid polling of KSO bit.
1233 	 */
1234 	if ((!on) && (bus->sih->chip == BCM43012_CHIP_ID ||
1235 		bus->sih->chip == BCM43013_CHIP_ID ||
1236 		bus->sih->chip == BCM43014_CHIP_ID)) {
1237 		goto exit;
1238 	}
1239 
1240 	if (on) {
1241 		/* XXX
1242 		 *  device WAKEUP through KSO:
1243 		 *  write bit 0 & read back until
1244 		 *  both bits 0(kso bit) & 1 (dev on status) are set
1245 		 */
1246 		cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |  SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
1247 		bmask = cmp_val;
1248 
1249 #if defined(NDIS)
1250 		/* XXX Windows Host controller hangs if chip still sleeps before read.
1251 		 * So during a wake we write 0x1 for 5 msec to guarantee that chip is a wake.
1252 		 */
1253 		for (int i = 0; i < KSO_WAKE_RETRY_COUNT; i++) {
1254 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR,
1255 				wr_val, &err);
1256 			OSL_DELAY(KSO_WAIT_US);
1257 		}
1258 
1259 		rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1260 		if (((rd_val & bmask) != cmp_val) || err) {
1261 			/* Sdio Bus Failure - Bus hang */
1262 			DHD_ERROR(("%s> op:%s, ERROR: SDIO Bus Hang, rd_val:%x, ERR:%x \n",
1263 				__FUNCTION__, "KSO_SET", rd_val, err));
1264 		}
1265 #else
1266 		OSL_SLEEP(3);
1267 #endif /* defined(NDIS) */
1268 
1269 	} else {
1270 		/* Put device to sleep, turn off  KSO  */
1271 		cmp_val = 0;
1272 		/* XXX only check for bit0, bit1(devon status) may not get cleared right away */
1273 		bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
1274 	}
1275 #if !defined(NDIS)
1276 	/* XXX We can't use polling in Windows since Windows Host controller
1277 	 * hangs if chip is a sleep during read or write.
1278 	 */
1279 
1280 	if (conf->kso_try_max)
1281 		try_max = conf->kso_try_max;
1282 	do {
1283 		/*
1284 		 *  XXX reliable KSO bit set/clr:
1285 		 *  the sdiod sleep write access appears to be is synced to PMU 32khz clk
1286 		 *  just one write attempt may fail,(same is with read ?)
1287 		 *  in any case, read it back until it matches written value
1288 		 */
1289 		rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1290 		if (((rd_val & bmask) == cmp_val) && !err)
1291 			break;
1292 
1293 		KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err));
1294 
1295 		if (((try_cnt + 1) % KSO_SLEEP_RETRY_COUNT) == 0) {
1296 			OSL_SLEEP(KSO_WAIT_MS);
1297 		} else
1298 			OSL_DELAY(KSO_WAIT_US);
1299 
1300 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
1301 	} while (try_cnt++ < try_max);
1302 
1303 #ifdef KSO_DEBUG
1304 	if (try_cnt > 0 && try_cnt <= 10)
1305 		conf->kso_try_array[0] += 1;
1306 	else if (try_cnt <= 50)
1307 		conf->kso_try_array[1] += 1;
1308 	else if (try_cnt <= 100)
1309 		conf->kso_try_array[2] += 1;
1310 	else if (try_cnt <= 200)
1311 		conf->kso_try_array[3] += 1;
1312 	else if (try_cnt <= 500)
1313 		conf->kso_try_array[4] += 1;
1314 	else if (try_cnt <= 1000)
1315 		conf->kso_try_array[5] += 1;
1316 	else if (try_cnt <= 2000)
1317 		conf->kso_try_array[6] += 1;
1318 	else if (try_cnt <= 5000)
1319 		conf->kso_try_array[7] += 1;
1320 	else if (try_cnt <= 10000)
1321 		conf->kso_try_array[8] += 1;
1322 	else
1323 		conf->kso_try_array[9] += 1;
1324 #endif
1325 	if (try_cnt > 2)
1326 		KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n",
1327 			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
1328 
1329 	if (try_cnt > try_max)  {
1330 		DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n",
1331 			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
1332 #ifdef KSO_DEBUG
1333 		{
1334 			int i;
1335 			printk(KERN_CONT DHD_LOG_PREFIXS);
1336 			for (i=0; i<10; i++) {
1337 				printk(KERN_CONT "[%d]: %d, ", i, conf->kso_try_array[i]);
1338 		 	}
1339 			printk("\n");
1340 		}
1341 #endif
1342 	}
1343 #endif /* !defined(NDIS) */
1344 
1345 exit:
1346 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
1347 	if (on)
1348 		sdio_retune_release(adapter->sdio_func);
1349 	sdio_retune_crc_enable(adapter->sdio_func);
1350 #else
1351 	mmc_retune_enable(host);
1352 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1353 
1354 	return err;
1355 }
1356 
1357 static int
dhdsdio_clk_kso_iovar(dhd_bus_t * bus,bool on)1358 dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bool on)
1359 {
1360 	int err = 0;
1361 
1362 	if (on == FALSE) {
1363 
1364 		BUS_WAKE(bus);
1365 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1366 
1367 		DHD_ERROR(("%s: KSO disable clk: 0x%x\n", __FUNCTION__,
1368 			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1369 			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1370 		dhdsdio_clk_kso_enab(bus, FALSE);
1371 	} else {
1372 		DHD_ERROR(("%s: KSO enable\n", __FUNCTION__));
1373 
1374 		/* Make sure we have SD bus access */
1375 		if (bus->clkstate == CLK_NONE) {
1376 			DHD_ERROR(("%s: Request SD clk\n", __FUNCTION__));
1377 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1378 		}
1379 
1380 		dhdsdio_clk_kso_enab(bus, TRUE);
1381 
1382 		DHD_ERROR(("%s: sleepcsr: 0x%x\n", __FUNCTION__,
1383 			dhdsdio_sleepcsr_get(bus)));
1384 	}
1385 
1386 	bus->kso = on;
1387 	BCM_REFERENCE(err);
1388 
1389 	return 0;
1390 }
1391 
1392 static uint8
dhdsdio_sleepcsr_get(dhd_bus_t * bus)1393 dhdsdio_sleepcsr_get(dhd_bus_t *bus)
1394 {
1395 	int err = 0;
1396 	uint8 val = 0;
1397 
1398 	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1399 	/* XXX: Propagate error */
1400 	if (err)
1401 		DHD_TRACE(("Failed to read SLEEPCSR: %d\n", err));
1402 
1403 	return val;
1404 }
1405 
1406 uint8
dhdsdio_devcap_get(dhd_bus_t * bus)1407 dhdsdio_devcap_get(dhd_bus_t *bus)
1408 {
1409 	return bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL);
1410 }
1411 
1412 static int
dhdsdio_devcap_set(dhd_bus_t * bus,uint8 cap)1413 dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap)
1414 {
1415 	int err = 0;
1416 
1417 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, cap, &err);
1418 	if (err)
1419 		DHD_ERROR(("%s: devcap set err: 0x%x\n", __FUNCTION__, err));
1420 
1421 	return 0;
1422 }
1423 
1424 static int
dhdsdio_clk_devsleep_iovar(dhd_bus_t * bus,bool on)1425 dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on)
1426 {
1427 	int err = 0, retry;
1428 	uint8 val;
1429 
1430 	retry = 0;
1431 	if (on == TRUE) {
1432 		/* Enter Sleep */
1433 
1434 		/* Be sure we request clk before going to sleep
1435 		 * so we can wake-up with clk request already set
1436 		 * else device can go back to sleep immediately
1437 		 */
1438 		if (!SLPAUTO_ENAB(bus))
1439 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1440 		else {
1441 			/* XXX: Check if Host cleared clock request
1442 			 * XXX: With CMD14, Host does not need to explicitly toggle clock requests
1443 			 * XXX: Just keep clock request active and use CMD14 to enter/exit sleep
1444 			 */
1445 			val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
1446 			if ((val & SBSDIO_CSR_MASK) == 0) {
1447 				DHD_ERROR(("%s: No clock before enter sleep:0x%x\n",
1448 					__FUNCTION__, val));
1449 
1450 				/* Reset clock request */
1451 				bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
1452 					SBSDIO_ALP_AVAIL_REQ, &err);
1453 				DHD_ERROR(("%s: clock before sleep:0x%x\n", __FUNCTION__,
1454 					bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1455 					SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1456 			}
1457 		}
1458 
1459 		DHD_TRACE(("%s: clk before sleep: 0x%x\n", __FUNCTION__,
1460 			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1461 			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1462 #ifdef USE_CMD14
1463 		err = bcmsdh_sleep(bus->sdh, TRUE);
1464 #else
1465 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) {
1466 			if (sd1idle) {
1467 				/* Change to SD1 mode */
1468 				dhdsdio_set_sdmode(bus, 1);
1469 			}
1470 		}
1471 
1472 		err = dhdsdio_clk_kso_enab(bus, FALSE);
1473 		if (OOB_WAKEUP_ENAB(bus))
1474 		{
1475 #if !defined(NDIS)
1476 			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE);  /* GPIO_1 is off */
1477 #endif /* !defined(NDIS) */
1478 		}
1479 #endif /* USE_CMD14 */
1480 
1481 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock != DHD_IDLE_ACTIVE)) {
1482 			DHD_TRACE(("%s: Turnoff SD clk\n", __FUNCTION__));
1483 			/* Now remove the SD clock */
1484 			err = dhdsdio_sdclk(bus, FALSE);
1485 		}
1486 	} else {
1487 		/* Exit Sleep */
1488 		/* Make sure we have SD bus access */
1489 		if (bus->clkstate == CLK_NONE) {
1490 			DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__));
1491 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1492 		}
1493 #ifdef USE_CMD14
1494 		err = bcmsdh_sleep(bus->sdh, FALSE);
1495 		if (SLPAUTO_ENAB(bus) && (err != 0)) {
1496 			/* XXX: CMD14 exit sleep is failing somehow
1497 			 * XXX: Is Host out of sync with device?
1498 			 * XXX: Try toggling the reverse
1499 			 */
1500 			OSL_DELAY(10000);
1501 			DHD_TRACE(("%s: Resync device sleep\n", __FUNCTION__));
1502 
1503 			/* Toggle sleep to resync with host and device */
1504 			err = bcmsdh_sleep(bus->sdh, TRUE);
1505 			OSL_DELAY(10000);
1506 			err = bcmsdh_sleep(bus->sdh, FALSE);
1507 
1508 			/* XXX: Ugly hack for host-device out-of-sync while testing
1509 			 * XXX: Need to root-cause
1510 			 */
1511 			if (err) {
1512 				/* XXX: Host and device out-of-sync */
1513 				OSL_DELAY(10000);
1514 				DHD_ERROR(("%s: CMD14 exit failed again!\n", __FUNCTION__));
1515 
1516 				/* Toggle sleep to resync with host and device */
1517 				err = bcmsdh_sleep(bus->sdh, TRUE);
1518 				OSL_DELAY(10000);
1519 				err = bcmsdh_sleep(bus->sdh, FALSE);
1520 				if (err) {
1521 					/* XXX: Give up and assumed it has exited sleep
1522 					 * XXX: Device probably dead at this point
1523 					 * XXX: So far only happens with SR
1524 					 */
1525 					DHD_ERROR(("%s: CMD14 exit failed twice!\n", __FUNCTION__));
1526 					DHD_ERROR(("%s: FATAL: Device non-response!\n",
1527 						__FUNCTION__));
1528 					err = 0;
1529 				}
1530 			}
1531 		}
1532 #else
1533 		if (OOB_WAKEUP_ENAB(bus))
1534 		{
1535 #if !defined(NDIS)
1536 			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE);  /* GPIO_1 is on */
1537 #endif /* !defined(NDIS) */
1538 		}
1539 		/* PR 101351: sdiod_aos sleep followed by immediate wakeup
1540 		 *    before sdiod_aos takes over has a problem.
1541 		 * Set KSO after ExitSleep.
1542 		 */
1543 		do {
1544 			err = dhdsdio_clk_kso_enab(bus, TRUE);
1545 			if (err)
1546 				OSL_SLEEP(10);
1547 		} while ((err != 0) && (++retry < 3));
1548 
1549 		if (err != 0) {
1550 			DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry));
1551 #ifndef BT_OVER_SDIO
1552 			err = 0; /* continue anyway */
1553 #endif /* BT_OVER_SDIO */
1554 		}
1555 
1556 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) {
1557 			dhdsdio_set_sdmode(bus, bus->sd_mode);
1558 		}
1559 #endif /* !USE_CMD14 */
1560 
1561 		if (err == 0) {
1562 			uint8 csr;
1563 
1564 			/* Wait for device ready during transition to wake-up */
1565 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1566 				(((csr = dhdsdio_sleepcsr_get(bus)) &
1567 				SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) !=
1568 				(SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000));
1569 
1570 			DHD_TRACE(("%s: ExitSleep sleepcsr: 0x%x\n", __FUNCTION__, csr));
1571 
1572 			if (!(csr & SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) {
1573 				DHD_ERROR(("%s:ERROR: ExitSleep device NOT Ready! 0x%x\n",
1574 					__FUNCTION__, csr));
1575 				err = BCME_NODEVICE;
1576 			}
1577 
1578 			/* PR 101351: sdiod_aos sleep followed by immediate wakeup
1579 			 *    before sdiod_aos takes over has a problem.
1580 			 */
1581 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1582 				(((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1583 				SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) !=
1584 				(SBSDIO_HT_AVAIL)), (DHD_WAIT_HTAVAIL));
1585 
1586 			DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr));
1587 			if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) {
1588 				DHD_ERROR(("%s:ERROR: device NOT Ready! 0x%x\n",
1589 					__FUNCTION__, csr));
1590 				err = BCME_NODEVICE;
1591 			}
1592 		}
1593 	}
1594 
1595 	/* Update if successful */
1596 	if (err == 0)
1597 		bus->kso = on ? FALSE : TRUE;
1598 	else {
1599 		DHD_ERROR(("%s: Sleep request failed: kso:%d on:%d err:%d\n",
1600 			__FUNCTION__, bus->kso, on, err));
1601 		if (!on && retry > 2)
1602 			bus->kso = FALSE;
1603 	}
1604 
1605 	return err;
1606 }
1607 
1608 /* Turn backplane clock on or off */
1609 static int
dhdsdio_htclk(dhd_bus_t * bus,bool on,bool pendok)1610 dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
1611 {
1612 #define HT_AVAIL_ERROR_MAX 10
1613 	static int ht_avail_error = 0;
1614 	int err;
1615 	uint8 clkctl, clkreq, devctl;
1616 	bcmsdh_info_t *sdh;
1617 
1618 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1619 
1620 	clkctl = 0;
1621 	sdh = bus->sdh;
1622 
1623 #ifdef BCMINTERNAL
1624 	if (DHD_NOPMU(bus)) {
1625 		/* There is no PMU present, so just fake the clock state... */
1626 		bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
1627 		return BCME_OK;
1628 	}
1629 
1630 	if (bus->clockpoll)
1631 		pendok = FALSE;
1632 #endif /* BCMINTERNAL */
1633 
1634 	if (!KSO_ENAB(bus))
1635 		return BCME_OK;
1636 
1637 	if (SLPAUTO_ENAB(bus)) {
1638 		bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
1639 		return BCME_OK;
1640 	}
1641 
1642 	if (on) {
1643 		/* Request HT Avail */
1644 		clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
1645 
1646 #ifdef BCMSPI
1647 		dhdsdio_wkwlan(bus, TRUE);
1648 #endif /* BCMSPI */
1649 
1650 		/* XXX Should be able to early-exit if pendok && PENDING */
1651 
1652 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1653 		if (err) {
1654 			ht_avail_error++;
1655 			if (ht_avail_error < HT_AVAIL_ERROR_MAX) {
1656 				DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
1657 			}
1658 
1659 #ifdef OEM_ANDROID
1660 			else if (ht_avail_error == HT_AVAIL_ERROR_MAX) {
1661 				bus->dhd->hang_reason = HANG_REASON_HT_AVAIL_ERROR;
1662 				dhd_os_send_hang_message(bus->dhd);
1663 			}
1664 #endif /* OEM_ANDROID */
1665 			return BCME_ERROR;
1666 		} else {
1667 			ht_avail_error = 0;
1668 		}
1669 
1670 		/* Check current status */
1671 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
1672 		if (err) {
1673 			DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
1674 			return BCME_ERROR;
1675 		}
1676 
1677 #if !defined(OOB_INTR_ONLY)
1678 		/* Go to pending and await interrupt if appropriate */
1679 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
1680 			/* Allow only clock-available interrupt */
1681 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1682 			if (err) {
1683 				DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
1684 				           __FUNCTION__, err));
1685 				return BCME_ERROR;
1686 			}
1687 
1688 			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
1689 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1690 			DHD_INFO(("CLKCTL: set PENDING\n"));
1691 			bus->clkstate = CLK_PENDING;
1692 			return BCME_OK;
1693 		} else
1694 #endif /* !defined (OOB_INTR_ONLY) */
1695 		{
1696 			if (bus->clkstate == CLK_PENDING) {
1697 				/* Cancel CA-only interrupt filter */
1698 				devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1699 				devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1700 				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1701 			}
1702 		}
1703 #ifndef BCMSDIOLITE
1704 		/* Otherwise, wait here (polling) for HT Avail */
1705 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1706 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1707 				((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
1708 			                                    SBSDIO_FUNC1_CHIPCLKCSR, &err)),
1709 			          !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
1710 		}
1711 		if (err) {
1712 			DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
1713 			return BCME_ERROR;
1714 		}
1715 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1716 			DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
1717 			           __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
1718 			return BCME_ERROR;
1719 		}
1720 #endif /* BCMSDIOLITE */
1721 		/* Mark clock available */
1722 		bus->clkstate = CLK_AVAIL;
1723 		DHD_INFO(("CLKCTL: turned ON\n"));
1724 
1725 #if defined(DHD_DEBUG)
1726 		if (bus->alp_only == TRUE) {
1727 #if !defined(BCMLXSDMMC)
1728 			/* XXX For the SDMMC Driver stack, if DHD was unloaded,
1729 			 * the chip is not completely reset, so in this case,
1730 			 * the PMU may already be programmed to allow HT clock.
1731 			 */
1732 			if (!SBSDIO_ALPONLY(clkctl)) {
1733 				DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
1734 			}
1735 #endif /* !defined(BCMLXSDMMC) */
1736 		} else {
1737 			if (SBSDIO_ALPONLY(clkctl)) {
1738 				DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
1739 			}
1740 		}
1741 #endif /* defined (DHD_DEBUG) */
1742 
1743 		bus->activity = TRUE;
1744 #ifdef DHD_USE_IDLECOUNT
1745 		bus->idlecount = 0;
1746 #endif /* DHD_USE_IDLECOUNT */
1747 	} else {
1748 		clkreq = 0;
1749 
1750 		if (bus->clkstate == CLK_PENDING) {
1751 			/* Cancel CA-only interrupt filter */
1752 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1753 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1754 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1755 		}
1756 
1757 		bus->clkstate = CLK_SDONLY;
1758 		if (!SR_ENAB(bus)) {
1759 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1760 			DHD_INFO(("CLKCTL: turned OFF\n"));
1761 			if (err) {
1762 				DHD_ERROR(("%s: Failed access turning clock off: %d\n",
1763 				           __FUNCTION__, err));
1764 				return BCME_ERROR;
1765 			}
1766 		}
1767 #ifdef BCMSPI
1768 			dhdsdio_wkwlan(bus, FALSE);
1769 #endif /* BCMSPI */
1770 	}
1771 	return BCME_OK;
1772 }
1773 
1774 /* Change SD1/SD4 bus mode */
1775 static int
dhdsdio_set_sdmode(dhd_bus_t * bus,int32 sd_mode)1776 dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode)
1777 {
1778 	int err;
1779 
1780 	err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
1781 		&sd_mode, sizeof(sd_mode), TRUE);
1782 	if (err) {
1783 		DHD_ERROR(("%s: error changing sd_mode: %d\n",
1784 			__FUNCTION__, err));
1785 		return BCME_ERROR;
1786 	}
1787 	return BCME_OK;
1788 }
1789 
1790 /* Change idle/active SD state */
1791 static int
dhdsdio_sdclk(dhd_bus_t * bus,bool on)1792 dhdsdio_sdclk(dhd_bus_t *bus, bool on)
1793 {
1794 #ifndef BCMSPI
1795 	int err;
1796 	int32 iovalue;
1797 
1798 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1799 
1800 	if (on) {
1801 		if (bus->idleclock == DHD_IDLE_STOP) {
1802 			/* Turn on clock and restore mode */
1803 			iovalue = 1;
1804 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
1805 			                      &iovalue, sizeof(iovalue), TRUE);
1806 			if (err) {
1807 				DHD_ERROR(("%s: error enabling sd_clock: %d\n",
1808 				           __FUNCTION__, err));
1809 				return BCME_ERROR;
1810 			}
1811 
1812 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
1813 			/* Restore clock speed */
1814 			iovalue = bus->sd_divisor;
1815 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
1816 			                      &iovalue, sizeof(iovalue), TRUE);
1817 			if (err) {
1818 				DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
1819 				           __FUNCTION__, err));
1820 				return BCME_ERROR;
1821 			}
1822 		}
1823 		bus->clkstate = CLK_SDONLY;
1824 	} else {
1825 		/* Stop or slow the SD clock itself */
1826 		if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
1827 			DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
1828 			           __FUNCTION__, bus->sd_divisor, bus->sd_mode));
1829 			return BCME_ERROR;
1830 		}
1831 		if (bus->idleclock == DHD_IDLE_STOP) {
1832 			iovalue = 0;
1833 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
1834 			                      &iovalue, sizeof(iovalue), TRUE);
1835 			if (err) {
1836 				DHD_ERROR(("%s: error disabling sd_clock: %d\n",
1837 				           __FUNCTION__, err));
1838 				return BCME_ERROR;
1839 			}
1840 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
1841 			/* Set divisor to idle value */
1842 			iovalue = bus->idleclock;
1843 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
1844 			                      &iovalue, sizeof(iovalue), TRUE);
1845 			if (err) {
1846 				DHD_ERROR(("%s: error changing sd_divisor: %d\n",
1847 				           __FUNCTION__, err));
1848 				return BCME_ERROR;
1849 			}
1850 		}
1851 		bus->clkstate = CLK_NONE;
1852 	}
1853 #endif /* BCMSPI */
1854 
1855 	return BCME_OK;
1856 }
1857 
1858 /* Transition SD and backplane clock readiness */
1859 static int
dhdsdio_clkctl(dhd_bus_t * bus,uint target,bool pendok)1860 dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
1861 {
1862 	int ret = BCME_OK;
1863 #ifdef DHD_DEBUG
1864 	uint oldstate = bus->clkstate;
1865 #endif /* DHD_DEBUG */
1866 
1867 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1868 
1869 	/* Early exit if we're already there */
1870 	if (bus->clkstate == target) {
1871 		if (target == CLK_AVAIL) {
1872 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1873 			bus->activity = TRUE;
1874 #ifdef DHD_USE_IDLECOUNT
1875 			bus->idlecount = 0;
1876 #endif /* DHD_USE_IDLECOUNT */
1877 		}
1878 		return ret;
1879 	}
1880 
1881 	switch (target) {
1882 	case CLK_AVAIL:
1883 		/* Make sure SD clock is available */
1884 		if (bus->clkstate == CLK_NONE)
1885 			dhdsdio_sdclk(bus, TRUE);
1886 		/* Now request HT Avail on the backplane */
1887 		ret = dhdsdio_htclk(bus, TRUE, pendok);
1888 		if (ret == BCME_OK) {
1889 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1890 		bus->activity = TRUE;
1891 #ifdef DHD_USE_IDLECOUNT
1892 			bus->idlecount = 0;
1893 #endif /* DHD_USE_IDLECOUNT */
1894 		}
1895 		break;
1896 
1897 	case CLK_SDONLY:
1898 
1899 #ifdef BT_OVER_SDIO
1900 		/*
1901 		 * If the request is to switch off Back plane clock,
1902 		 * confirm that BT is inactive before doing so.
1903 		 * If this call had come from Non Watchdog context any way
1904 		 * the Watchdog would switch off the clock again when
1905 		 * nothing is to be done & Bt has finished using the bus.
1906 		 */
1907 		if (bus->bt_use_count != 0) {
1908 			DHD_INFO(("%s(): Req CLK_SDONLY, BT is active %d not switching off \r\n",
1909 				__FUNCTION__, bus->bt_use_count));
1910 			ret = BCME_OK;
1911 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1912 			break;
1913 		}
1914 
1915 		DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n",
1916 			__FUNCTION__));
1917 #endif /* BT_OVER_SDIO */
1918 
1919 		/* Remove HT request, or bring up SD clock */
1920 		if (bus->clkstate == CLK_NONE)
1921 			ret = dhdsdio_sdclk(bus, TRUE);
1922 		else if (bus->clkstate == CLK_AVAIL)
1923 			ret = dhdsdio_htclk(bus, FALSE, FALSE);
1924 		else
1925 			DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
1926 			           bus->clkstate, target));
1927 		if (ret == BCME_OK) {
1928 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1929 		}
1930 		break;
1931 
1932 	case CLK_NONE:
1933 
1934 #ifdef BT_OVER_SDIO
1935 		/*
1936 		 * If the request is to switch off Back plane clock,
1937 		 * confirm that BT is inactive before doing so.
1938 		 * If this call had come from Non Watchdog context any way
1939 		 * the Watchdog would switch off the clock again when
1940 		 * nothing is to be done & Bt has finished using the bus.
1941 		 */
1942 		if (bus->bt_use_count != 0) {
1943 			DHD_INFO(("%s(): Request CLK_NONE BT is active %d not switching off \r\n",
1944 				__FUNCTION__, bus->bt_use_count));
1945 			ret = BCME_OK;
1946 			break;
1947 		}
1948 
1949 		DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n",
1950 			__FUNCTION__));
1951 #endif /* BT_OVER_SDIO */
1952 
1953 		/* Make sure to remove HT request */
1954 		if (bus->clkstate == CLK_AVAIL)
1955 			ret = dhdsdio_htclk(bus, FALSE, FALSE);
1956 		/* Now remove the SD clock */
1957 		ret = dhdsdio_sdclk(bus, FALSE);
1958 #ifdef DHD_DEBUG
1959 		if (bus->dhd->dhd_console_ms == 0)
1960 #endif /* DHD_DEBUG */
1961 		if (bus->poll == 0)
1962 			dhd_os_wd_timer(bus->dhd, 0);
1963 		break;
1964 	}
1965 #ifdef DHD_DEBUG
1966 	DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
1967 #endif /* DHD_DEBUG */
1968 
1969 	return ret;
1970 }
1971 
1972 static int
dhdsdio_bussleep(dhd_bus_t * bus,bool sleep)1973 dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
1974 {
1975 	int err = 0;
1976 	bcmsdh_info_t *sdh = bus->sdh;
1977 	sdpcmd_regs_t *regs = bus->regs;
1978 	uint retries = 0;
1979 #if defined(BCMSDIOH_STD)
1980 	uint32 sd3_tuning_disable = FALSE;
1981 #endif /* BCMSDIOH_STD */
1982 
1983 	DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
1984 	         (sleep ? "SLEEP" : "WAKE"),
1985 	          (bus->sleeping ? "SLEEP" : "WAKE")));
1986 
1987 	if (bus->dhd->hang_was_sent)
1988 		return BCME_ERROR;
1989 
1990 	/* Done if we're already in the requested state */
1991 	if (sleep == bus->sleeping)
1992 		return BCME_OK;
1993 
1994 	/* Going to sleep: set the alarm and turn off the lights... */
1995 	if (sleep) {
1996 		/* Don't sleep if something is pending */
1997 #ifdef DHD_USE_IDLECOUNT
1998 		if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq) ||
1999 			bus->readframes || bus->ctrl_frame_stat)
2000 #else
2001 		if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq))
2002 #endif /* DHD_USE_IDLECOUNT */
2003 			return BCME_BUSY;
2004 
2005 #ifdef BT_OVER_SDIO
2006 		/*
2007 		 * The following is the assumption based on which the hook is placed.
2008 		 * From WLAN driver, either from the active contexts OR from the Watchdog contexts
2009 		 * we will be attempting to Go to Sleep. AT that moment if we see that BT is still
2010 		 * actively using the bus, we will return BCME_BUSY from here, but the bus->sleeping
2011 		 * state would not have changed. So the caller can then schedule the Watchdog again
2012 		 * which will come and attempt to sleep at a later point.
2013 		 *
2014 		 * In case if BT is the only one and is the last user, we don't switch off the clock
2015 		 * immediately, we allow the WLAN to decide when to sleep i.e from the watchdog.
2016 		 * Now if the watchdog becomes active and attempts to switch off the clock and if
2017 		 * another WLAN context is active they are any way serialized with sdlock.
2018 		 */
2019 		if (bus->bt_use_count != 0) {
2020 			DHD_INFO(("%s(): Cannot sleep BT is active \r\n", __FUNCTION__));
2021 			return BCME_BUSY;
2022 		}
2023 #endif /* !BT_OVER_SDIO */
2024 
2025 		/* XXX Is it an error to sleep when not in data state? */
2026 
2027 		if (!SLPAUTO_ENAB(bus)) {
2028 			/* Disable SDIO interrupts (no longer interested) */
2029 			bcmsdh_intr_disable(bus->sdh);
2030 
2031 			/* Make sure the controller has the bus up */
2032 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2033 
2034 			/* Tell device to start using OOB wakeup */
2035 			W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
2036 			if (retries > retry_limit)
2037 				DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
2038 
2039 			/* Turn off our contribution to the HT clock request */
2040 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
2041 
2042 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
2043 				SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
2044 
2045 			/* Isolate the bus */
2046 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
2047 					SBSDIO_DEVCTL_PADS_ISO, NULL);
2048 		} else {
2049 #ifdef FORCE_SWOOB_ENABLE
2050 			/* Tell device to start using OOB wakeup */
2051 			W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
2052 			if (retries > retry_limit)
2053 				DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
2054 #endif
2055 			/* Leave interrupts enabled since device can exit sleep and
2056 			 * interrupt host
2057 			 */
2058 			err = dhdsdio_clk_devsleep_iovar(bus, TRUE /* sleep */);
2059 		}
2060 
2061 		/* Change state */
2062 		bus->sleeping = TRUE;
2063 #if defined(BCMSDIOH_STD)
2064 		sd3_tuning_disable = TRUE;
2065 		err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0,
2066 			&sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE);
2067 #endif /* BCMSDIOH_STD */
2068 #if defined(LINUX) && defined(SUPPORT_P2P_GO_PS)
2069 		wake_up(&bus->bus_sleep);
2070 #endif /* LINUX && SUPPORT_P2P_GO_PS */
2071 		/* XXX Should be able to turn off clock and power */
2072 		/* XXX Make sure GPIO interrupt input is enabled */
2073 	} else {
2074 		/* Waking up: bus power up is ok, set local state */
2075 
2076 		if (!SLPAUTO_ENAB(bus)) {
2077 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, &err);
2078 
2079 			/* Force pad isolation off if possible (in case power never toggled) */
2080 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
2081 
2082 			/* XXX Make sure GPIO interrupt input is disabled */
2083 			/* XXX Should be able to turn on power and clock */
2084 
2085 			/* Make sure the controller has the bus up */
2086 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2087 
2088 			/* Send misc interrupt to indicate OOB not needed */
2089 			W_SDREG(0, &regs->tosbmailboxdata, retries);
2090 			if (retries <= retry_limit)
2091 				W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
2092 
2093 			if (retries > retry_limit)
2094 				DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
2095 
2096 			/* Make sure we have SD bus access */
2097 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
2098 
2099 			/* Enable interrupts again */
2100 			if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
2101 				bus->intdis = FALSE;
2102 				bcmsdh_intr_enable(bus->sdh);
2103 			}
2104 		} else {
2105 			err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */);
2106 #ifdef FORCE_SWOOB_ENABLE
2107 			/* Send misc interrupt to indicate OOB not needed */
2108 			W_SDREG(0, &regs->tosbmailboxdata, retries);
2109 			if (retries <= retry_limit)
2110 				W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
2111 #endif
2112 #ifdef BT_OVER_SDIO
2113 			if (err < 0) {
2114 				struct net_device *net = NULL;
2115 				dhd_pub_t *dhd = bus->dhd;
2116 				net = dhd_idx2net(dhd, 0);
2117 				if (net != NULL) {
2118 					DHD_ERROR(("<< WIFI HANG by KSO Enabled failure\n"));
2119 					dhd_os_sdunlock(dhd);
2120 					net_os_send_hang_message(net);
2121 					dhd_os_sdlock(dhd);
2122 				} else {
2123 					DHD_ERROR(("<< WIFI HANG Fail because net is NULL\n"));
2124 				}
2125 			}
2126 #endif /* BT_OVER_SDIO */
2127 		}
2128 
2129 		if (err == 0) {
2130 			/* Change state */
2131 			bus->sleeping = FALSE;
2132 #if defined(BCMSDIOH_STD)
2133 			sd3_tuning_disable = FALSE;
2134 			err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0,
2135 				&sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE);
2136 #endif /* BCMSDIOH_STD */
2137 		}
2138 	}
2139 
2140 	return err;
2141 }
2142 
2143 #ifdef BT_OVER_SDIO
2144 /*
2145  * Call this function to Get the Clock running.
2146  * Assumes that the caller holds the sdlock.
2147  * bus - Pointer to the dhd_bus handle
2148  * can_wait - TRUE if the caller can wait until the clock becomes ready
2149  *            FALSE if the caller cannot wait
2150  */
__dhdsdio_clk_enable(struct dhd_bus * bus,bus_owner_t owner,int can_wait)2151 int __dhdsdio_clk_enable(struct dhd_bus *bus, bus_owner_t owner, int can_wait)
2152 {
2153 	int ret = BCME_ERROR;
2154 
2155 	BCM_REFERENCE(owner);
2156 
2157 	bus->bt_use_count++;
2158 
2159 	/*
2160 	 * We can call BUS_WAKE, clkctl multiple times, both of the items
2161 	 * have states and if its already ON, no new configuration is done
2162 	 */
2163 
2164 	/* Wake up the Dongle FW from SR */
2165 	BUS_WAKE(bus);
2166 
2167 	/*
2168 	 * Make sure back plane ht clk is on
2169 	 * CLK_AVAIL - Turn On both SD & HT clock
2170 	 */
2171 	ret = dhdsdio_clkctl(bus, CLK_AVAIL, can_wait);
2172 
2173 	DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__,
2174 		bus->bt_use_count));
2175 	return ret;
2176 }
2177 
2178 /*
2179  * Call this function to relinquish the Clock.
2180  * Assumes that the caller holds the sdlock.
2181  * bus - Pointer to the dhd_bus handle
2182  * can_wait - TRUE if the caller can wait until the clock becomes ready
2183  *            FALSE if the caller cannot wait
2184  */
__dhdsdio_clk_disable(struct dhd_bus * bus,bus_owner_t owner,int can_wait)2185 int __dhdsdio_clk_disable(struct dhd_bus *bus, bus_owner_t owner, int can_wait)
2186 {
2187 	int ret = BCME_ERROR;
2188 
2189 	BCM_REFERENCE(owner);
2190 	BCM_REFERENCE(can_wait);
2191 
2192 	if (bus->bt_use_count == 0) {
2193 		DHD_ERROR(("%s(): Clocks are already turned off \r\n",
2194 			__FUNCTION__));
2195 		return ret;
2196 	}
2197 
2198 	bus->bt_use_count--;
2199 
2200 	/*
2201 	 * When the SDIO Bus is shared between BT & WLAN, we turn Off the clock
2202 	 * once the last user has relinqushed the same. But there are two schemes
2203 	 * in that too. We consider WLAN as the  bus master (even if its not
2204 	 * active). Even when the WLAN is OFF the DHD Watchdog is active.
2205 	 * So this Bus Watchdog is the context whill put the Bus to sleep.
2206 	 * Refer dhd_bus_watchdog function
2207 	 */
2208 
2209 	ret = BCME_OK;
2210 	DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__,
2211 		bus->bt_use_count));
2212 	return ret;
2213 }
2214 
dhdsdio_reset_bt_use_count(struct dhd_bus * bus)2215 void dhdsdio_reset_bt_use_count(struct dhd_bus *bus)
2216 {
2217 	/* reset bt use count */
2218 	bus->bt_use_count = 0;
2219 }
2220 #endif /* BT_OVER_SDIO */
2221 
2222 #ifdef USE_DYNAMIC_F2_BLKSIZE
dhdsdio_func_blocksize(dhd_pub_t * dhd,int function_num,int block_size)2223 int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
2224 {
2225 	int func_blk_size = function_num;
2226 	int bcmerr = 0;
2227 	int result;
2228 
2229 	bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size,
2230 		sizeof(int), &result, sizeof(int), IOV_GET);
2231 
2232 	if (bcmerr != BCME_OK) {
2233 		DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num));
2234 		return BCME_ERROR;
2235 	}
2236 
2237 	if (result != block_size) {
2238 		DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n",
2239 			__FUNCTION__, function_num, result, block_size));
2240 		func_blk_size = function_num << 16 | block_size;
2241 		bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL,
2242 			0, &func_blk_size, sizeof(int32), IOV_SET);
2243 		if (bcmerr != BCME_OK) {
2244 			DHD_ERROR(("%s: Set F2 Block size error\n", __FUNCTION__));
2245 			return BCME_ERROR;
2246 		}
2247 	}
2248 
2249 	return BCME_OK;
2250 }
2251 #endif /* USE_DYNAMIC_F2_BLKSIZE */
2252 
2253 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) || defined(FORCE_WOWLAN)
2254 void
dhd_enable_oob_intr(struct dhd_bus * bus,bool enable)2255 dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
2256 {
2257 #if defined(BCMSPI_ANDROID)
2258 	bcmsdh_intr_enable(bus->sdh);
2259 #elif defined(HW_OOB) || defined(FORCE_WOWLAN)
2260 	bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
2261 #else
2262 	sdpcmd_regs_t *regs = bus->regs;
2263 	uint retries = 0;
2264 
2265 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2266 	if (enable == TRUE) {
2267 
2268 		/* Tell device to start using OOB wakeup */
2269 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
2270 		if (retries > retry_limit)
2271 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
2272 
2273 	} else {
2274 		/* Send misc interrupt to indicate OOB not needed */
2275 		W_SDREG(0, &regs->tosbmailboxdata, retries);
2276 		if (retries <= retry_limit)
2277 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
2278 	}
2279 
2280 	/* Turn off our contribution to the HT clock request */
2281 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
2282 #endif /* !defined(HW_OOB) */
2283 }
2284 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
2285 
2286 int
dhd_bus_txdata(struct dhd_bus * bus,void * pkt)2287 dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
2288 {
2289 	int ret = BCME_ERROR;
2290 	osl_t *osh;
2291 	uint datalen, prec;
2292 
2293 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2294 
2295 	osh = bus->dhd->osh;
2296 	datalen = PKTLEN(osh, pkt);
2297 
2298 #ifdef SDTEST
2299 	/* Push the test header if doing loopback */
2300 	if (bus->ext_loop) {
2301 		uint8* data;
2302 		PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
2303 		data = PKTDATA(osh, pkt);
2304 		*data++ = SDPCM_TEST_ECHOREQ;
2305 		*data++ = (uint8)bus->loopid++;
2306 		*data++ = (datalen >> 0);
2307 		*data++ = (datalen >> 8);
2308 		datalen += SDPCM_TEST_HDRLEN;
2309 	}
2310 #else /* SDTEST */
2311 	BCM_REFERENCE(datalen);
2312 #endif /* SDTEST */
2313 
2314 	prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
2315 
2316 	/* move from dhdsdio_sendfromq(), try to orphan skb early */
2317 	if (bus->dhd->conf->orphan_move == 1)
2318 		PKTORPHAN(pkt, bus->dhd->conf->tsq);
2319 
2320 	/* Check for existing queue, current flow-control, pending event, or pending clock */
2321 	if (dhd_deferred_tx || bus->fcstate || pktq_n_pkts_tot(&bus->txq) || bus->dpc_sched ||
2322 	    (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
2323 	    (bus->clkstate != CLK_AVAIL)) {
2324 		bool deq_ret;
2325 		int pkq_len = 0;
2326 
2327 		DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
2328 			pktq_n_pkts_tot(&bus->txq)));
2329 #ifdef BCMINTERNAL
2330 		if (!bus->fcstate)
2331 			bus->tx_deferred++;
2332 #endif /* BCMINTERNAL */
2333 		bus->fcqueued++;
2334 
2335 		/* Priority based enq */
2336 		dhd_os_sdlock_txq(bus->dhd);
2337 		deq_ret = dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec);
2338 		dhd_os_sdunlock_txq(bus->dhd);
2339 
2340 		if (!deq_ret) {
2341 #ifdef PROP_TXSTATUS
2342 			if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) == 0)
2343 #endif /* PROP_TXSTATUS */
2344 			{
2345 #ifdef DHDTCPACK_SUPPRESS
2346 				if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
2347 					DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using\n",
2348 						__FUNCTION__, __LINE__));
2349 					dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
2350 				}
2351 #endif /* DHDTCPACK_SUPPRESS */
2352 				dhd_txcomplete(bus->dhd, pkt, FALSE);
2353 				PKTFREE(osh, pkt, TRUE);	/* XXX update counter */
2354 			}
2355 			ret = BCME_NORESOURCE;
2356 		} else
2357 			ret = BCME_OK;
2358 
2359 		/* XXX Possible race since check and action are not locked? */
2360 		if (dhd_doflow) {
2361 			dhd_os_sdlock_txq(bus->dhd);
2362 			pkq_len = pktq_n_pkts_tot(&bus->txq);
2363 			dhd_os_sdunlock_txq(bus->dhd);
2364 		}
2365 		if (dhd_doflow && pkq_len >= FCHI) {
2366 			bool wlfc_enabled = FALSE;
2367 #ifdef PROP_TXSTATUS
2368 			wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) !=
2369 				WLFC_UNSUPPORTED);
2370 #endif
2371 			if (!wlfc_enabled && dhd_doflow) {
2372 				dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
2373 			}
2374 		}
2375 
2376 #ifdef DHD_DEBUG
2377 		dhd_os_sdlock_txq(bus->dhd);
2378 		if (pktqprec_n_pkts(&bus->txq, prec) > qcount[prec])
2379 			qcount[prec] = pktqprec_n_pkts(&bus->txq, prec);
2380 		dhd_os_sdunlock_txq(bus->dhd);
2381 #endif
2382 
2383 		/* Schedule DPC if needed to send queued packet(s) */
2384 		/* XXX Also here, since other deferral conditions may no longer hold? */
2385 		if (dhd_deferred_tx && !bus->dpc_sched) {
2386 			if (bus->dhd->conf->deferred_tx_len) {
2387 				if(dhd_os_wd_timer_enabled(bus->dhd) == FALSE) {
2388 					bus->dpc_sched = TRUE;
2389 					dhd_sched_dpc(bus->dhd);
2390 				}
2391 				if(pktq_n_pkts_tot(&bus->txq) >= bus->dhd->conf->deferred_tx_len &&
2392 						dhd_os_wd_timer_enabled(bus->dhd) == FALSE) {
2393 					bus->dpc_sched = TRUE;
2394 					dhd_sched_dpc(bus->dhd);
2395 				}
2396 			} else {
2397 				bus->dpc_sched = TRUE;
2398 				dhd_sched_dpc(bus->dhd);
2399 			}
2400 		}
2401 	} else {
2402 		int chan = SDPCM_DATA_CHANNEL;
2403 
2404 #ifdef SDTEST
2405 		chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL);
2406 #endif
2407 		/* Lock: we're about to use shared data/code (and SDIO) */
2408 		dhd_os_sdlock(bus->dhd);
2409 
2410 		/* Otherwise, send it now */
2411 		BUS_WAKE(bus);
2412 		/* Make sure back plane ht clk is on, no pending allowed */
2413 		dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
2414 
2415 		ret = dhdsdio_txpkt(bus, chan, &pkt, 1, TRUE);
2416 
2417 		if (ret != BCME_OK)
2418 			bus->dhd->tx_errors++;
2419 		else
2420 			bus->dhd->dstats.tx_bytes += datalen;
2421 
2422 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
2423 				NO_OTHER_ACTIVE_BUS_USER(bus)) {
2424 			bus->activity = FALSE;
2425 			dhdsdio_bussleep(bus, TRUE);
2426 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
2427 		}
2428 
2429 		dhd_os_sdunlock(bus->dhd);
2430 	}
2431 
2432 	return ret;
2433 }
2434 
2435 /* align packet data pointer and packet length to n-byte boundary, process packet headers,
2436  * a new packet may be allocated if there is not enough head and/or tail from for padding.
2437  * the caller is responsible for updating the glom size in the head packet (when glom is
2438  * used)
2439  *
2440  * pad_pkt_len: returns the length of extra padding needed from the padding packet, this parameter
2441  * is taken in tx glom mode only
2442  *
2443  * new_pkt: out, pointer of the new packet allocated due to insufficient head room for alignment
2444  * padding, NULL if not needed, the caller is responsible for freeing the new packet
2445  *
2446  * return: positive value - length of the packet, including head and tail padding
2447  *		   negative value - errors
2448  */
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,int first_frame)2449 static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
2450 	int prev_chain_total_len, bool last_chained_pkt,
2451 	int *pad_pkt_len, void **new_pkt
2452 #if defined(BCMSDIOH_TXGLOM_EXT)
2453 	, int first_frame
2454 #endif
2455 )
2456 {
2457 	osl_t *osh;
2458 	uint8 *frame;
2459 	int pkt_len;
2460 	int modulo;
2461 	int head_padding;
2462 	int tail_padding = 0;
2463 	uint32 swheader;
2464 	uint32 swhdr_offset;
2465 	bool alloc_new_pkt = FALSE;
2466 	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
2467 #ifdef PKT_STATICS
2468 	uint16 len;
2469 #endif
2470 
2471 	*new_pkt = NULL;
2472 	osh = bus->dhd->osh;
2473 
2474 #ifdef DHDTCPACK_SUPPRESS
2475 	if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
2476 		DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
2477 			__FUNCTION__, __LINE__));
2478 		dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
2479 	}
2480 #endif /* DHDTCPACK_SUPPRESS */
2481 
2482 	/* Add space for the SDPCM hardware/software headers */
2483 	PKTPUSH(osh, pkt, sdpcm_hdrlen);
2484 	ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
2485 
2486 	frame = (uint8*)PKTDATA(osh, pkt);
2487 	pkt_len = (uint16)PKTLEN(osh, pkt);
2488 
2489 #ifdef PKT_STATICS
2490 	len = (uint16)PKTLEN(osh, pkt);
2491 	switch(chan) {
2492 		case SDPCM_CONTROL_CHANNEL:
2493 			bus->tx_statics.ctrl_count++;
2494 			bus->tx_statics.ctrl_size += len;
2495 			break;
2496 		case SDPCM_DATA_CHANNEL:
2497 			bus->tx_statics.data_count++;
2498 			bus->tx_statics.data_size += len;
2499 			break;
2500 		case SDPCM_GLOM_CHANNEL:
2501 			bus->tx_statics.glom_count++;
2502 			bus->tx_statics.glom_size += len;
2503 			break;
2504 		case SDPCM_EVENT_CHANNEL:
2505 			bus->tx_statics.event_count++;
2506 			bus->tx_statics.event_size += len;
2507 			break;
2508 		case SDPCM_TEST_CHANNEL:
2509 			bus->tx_statics.test_count++;
2510 			bus->tx_statics.test_size += len;
2511 			break;
2512 
2513 		default:
2514 			break;
2515 	}
2516 #endif /* PKT_STATICS */
2517 #ifdef DHD_DEBUG
2518 	if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets))
2519 		tx_packets[PKTPRIO(pkt)]++;
2520 #endif /* DHD_DEBUG */
2521 
2522 	/* align the data pointer, allocate a new packet if there is not enough space (new
2523 	 * packet data pointer will be aligned thus no padding will be needed)
2524 	 */
2525 	head_padding = (uintptr)frame % DHD_SDALIGN;
2526 	if (PKTHEADROOM(osh, pkt) < head_padding) {
2527 		head_padding = 0;
2528 		alloc_new_pkt = TRUE;
2529 	} else {
2530 		uint cur_chain_total_len;
2531 		int chain_tail_padding = 0;
2532 
2533 		/* All packets need to be aligned by DHD_SDALIGN */
2534 		modulo = (pkt_len + head_padding) % DHD_SDALIGN;
2535 		tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
2536 
2537 		/* Total pkt chain length needs to be aligned by block size,
2538 		 * unless it is a single pkt chain with total length less than one block size,
2539 		 * which we prefer sending by byte mode.
2540 		 *
2541 		 * Do the chain alignment here if
2542 		 * 1. This is the last pkt of the chain of multiple pkts or a single pkt.
2543 		 * 2-1. This chain is of multiple pkts, or
2544 		 * 2-2. This is a single pkt whose size is longer than one block size.
2545 		 */
2546 		cur_chain_total_len = prev_chain_total_len +
2547 			(head_padding + pkt_len + tail_padding);
2548 		if (last_chained_pkt && bus->blocksize != 0 &&
2549 			(cur_chain_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
2550 			modulo = cur_chain_total_len % bus->blocksize;
2551 			chain_tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
2552 		}
2553 
2554 #ifdef DHDENABLE_TAILPAD
2555 		if (PKTTAILROOM(osh, pkt) < tail_padding) {
2556 			/* We don't have tail room to align by DHD_SDALIGN */
2557 			alloc_new_pkt = TRUE;
2558 			bus->tx_tailpad_pktget++;
2559 		} else if (PKTTAILROOM(osh, pkt) < tail_padding + chain_tail_padding) {
2560 			/* We have tail room for tail_padding of this pkt itself, but not for
2561 			 * total pkt chain alignment by block size.
2562 			 * Use the padding packet to avoid memory copy if applicable,
2563 			 * otherwise, just allocate a new pkt.
2564 			 */
2565 			if (bus->pad_pkt) {
2566 				*pad_pkt_len = chain_tail_padding;
2567 				bus->tx_tailpad_chain++;
2568 			} else {
2569 				alloc_new_pkt = TRUE;
2570 				bus->tx_tailpad_pktget++;
2571 			}
2572 		} else
2573 		/* This last pkt's tailroom is sufficient to hold both tail_padding
2574 		 * of the pkt itself and chain_tail_padding of total pkt chain
2575 		 */
2576 #endif /* DHDENABLE_TAILPAD */
2577 		tail_padding += chain_tail_padding;
2578 	}
2579 
2580 	DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n",
2581 		__FUNCTION__, pkt_len, head_padding, tail_padding, *pad_pkt_len));
2582 
2583 	if (alloc_new_pkt) {
2584 		void *tmp_pkt;
2585 		int newpkt_size;
2586 		int cur_total_len;
2587 
2588 		ASSERT(*pad_pkt_len == 0);
2589 
2590 		DHD_INFO(("%s allocating new packet for padding\n", __FUNCTION__));
2591 
2592 		/* head pointer is aligned now, no padding needed */
2593 		head_padding = 0;
2594 
2595 		/* update the tail padding as it depends on the head padding, since a new packet is
2596 		 * allocated, the head padding is non longer needed and packet length is chagned
2597 		 */
2598 
2599 		cur_total_len = prev_chain_total_len + pkt_len;
2600 		if (last_chained_pkt && bus->blocksize != 0 &&
2601 			(cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
2602 			modulo = cur_total_len % bus->blocksize;
2603 			tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
2604 		} else {
2605 			modulo = pkt_len % DHD_SDALIGN;
2606 			tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
2607 		}
2608 
2609 		newpkt_size = PKTLEN(osh, pkt) + bus->blocksize + DHD_SDALIGN;
2610 		bus->dhd->tx_realloc++;
2611 		tmp_pkt = PKTGET(osh, newpkt_size, TRUE);
2612 		if (tmp_pkt == NULL) {
2613 			DHD_ERROR(("failed to alloc new %d byte packet\n", newpkt_size));
2614 			return BCME_NOMEM;
2615 		}
2616 		PKTALIGN(osh, tmp_pkt, PKTLEN(osh, pkt), DHD_SDALIGN);
2617 		bcopy(PKTDATA(osh, pkt), PKTDATA(osh, tmp_pkt), PKTLEN(osh, pkt));
2618 		*new_pkt = tmp_pkt;
2619 		pkt = tmp_pkt;
2620 	}
2621 
2622 	if (head_padding)
2623 		PKTPUSH(osh, pkt, head_padding);
2624 
2625 	frame = (uint8*)PKTDATA(osh, pkt);
2626 	bzero(frame, head_padding + sdpcm_hdrlen);
2627 	pkt_len = (uint16)PKTLEN(osh, pkt);
2628 
2629 	/* the header has the followming format
2630 	 * 4-byte HW frame tag: length, ~length (for glom this is the total length)
2631 	 *
2632 	 * 8-byte HW extesion flags (glom mode only) as the following:
2633 	 *			2-byte packet length, excluding HW tag and padding
2634 	 *			2-byte frame channel and frame flags (e.g. next frame following)
2635 	 *			2-byte header length
2636 	 *			2-byte tail padding size
2637 	 *
2638 	 * 8-byte SW frame tags as the following
2639 	 *			4-byte flags: host tx seq, channel, data offset
2640 	 *			4-byte flags: TBD
2641 	 */
2642 
2643 	swhdr_offset = SDPCM_FRAMETAG_LEN;
2644 
2645 	/* hardware frame tag:
2646 	 *
2647 	 * in tx-glom mode, dongle only checks the hardware frame tag in the first
2648 	 * packet and sees it as the total lenght of the glom (including tail padding),
2649 	 * for each packet in the glom, the packet length needs to be updated, (see
2650 	 * below PKTSETLEN)
2651 	 *
2652 	 * in non tx-glom mode, PKTLEN still need to include tail padding as to be
2653 	 * referred to in sdioh_request_buffer(). The tail length will be excluded in
2654 	 * dhdsdio_txpkt_postprocess().
2655 	 */
2656 #if defined(BCMSDIOH_TXGLOM_EXT)
2657 	if (bus->dhd->conf->txglom_bucket_size)
2658 		tail_padding = 0;
2659 #endif
2660 	*(uint16*)frame = (uint16)htol16(pkt_len);
2661 	*(((uint16*)frame) + 1) = (uint16)htol16(~pkt_len);
2662 	pkt_len += tail_padding;
2663 
2664 	/* hardware extesion flags */
2665 	if (bus->txglom_enable) {
2666 		uint32 hwheader1;
2667 		uint32 hwheader2;
2668 #ifdef BCMSDIOH_TXGLOM_EXT
2669 		uint32 act_len = pkt_len - tail_padding;
2670 		uint32 real_pad = 0;
2671 		if(bus->dhd->conf->txglom_ext && !last_chained_pkt) {
2672 			tail_padding = 0;
2673 			if(first_frame == 0) {
2674 				// first pkt, add pad to bucket size - recv offset
2675 				pkt_len = bus->dhd->conf->txglom_bucket_size - TXGLOM_RECV_OFFSET;
2676 			} else {
2677 				// add pad to bucket size
2678 				pkt_len = bus->dhd->conf->txglom_bucket_size;
2679 			}
2680 			swhdr_offset += SDPCM_HWEXT_LEN;
2681 			hwheader1 = (act_len - SDPCM_FRAMETAG_LEN) | (last_chained_pkt << 24);
2682 			hwheader2 = (pkt_len - act_len) << 16;
2683 			htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
2684 			htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
2685 			real_pad = pkt_len - act_len;
2686 
2687 			if (PKTTAILROOM(osh, pkt) < real_pad) {
2688 				DHD_INFO(("%s : insufficient tailroom %d for %d real_pad\n",
2689 					__func__, (int)PKTTAILROOM(osh, pkt), real_pad));
2690 				if (PKTPADTAILROOM(osh, pkt, real_pad)) {
2691 					DHD_ERROR(("CHK1: padding error size %d\n", real_pad));
2692 				} else
2693 					frame = (uint8 *)PKTDATA(osh, pkt);
2694 			}
2695 		} else
2696 #endif
2697 		{
2698 			swhdr_offset += SDPCM_HWEXT_LEN;
2699 			hwheader1 = (pkt_len - SDPCM_FRAMETAG_LEN - tail_padding) |
2700 				(last_chained_pkt << 24);
2701 			hwheader2 = (tail_padding) << 16;
2702 			htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
2703 			htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
2704 		}
2705 	}
2706 	PKTSETLEN((osh), (pkt), (pkt_len));
2707 
2708 	/* software frame tags */
2709 	swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
2710 		| (txseq % SDPCM_SEQUENCE_WRAP) |
2711 		(((head_padding + sdpcm_hdrlen) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
2712 	htol32_ua_store(swheader, frame + swhdr_offset);
2713 	htol32_ua_store(0, frame + swhdr_offset + sizeof(swheader));
2714 
2715 	return pkt_len;
2716 }
2717 
dhdsdio_txpkt_postprocess(dhd_bus_t * bus,void * pkt)2718 static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt)
2719 {
2720 	osl_t *osh;
2721 	uint8 *frame;
2722 	int data_offset;
2723 	int tail_padding;
2724 	int swhdr_offset = SDPCM_FRAMETAG_LEN + (bus->txglom_enable ? SDPCM_HWEXT_LEN : 0);
2725 
2726 	(void)osh;
2727 	osh = bus->dhd->osh;
2728 
2729 	/* restore pkt buffer pointer, but keeps the header pushed by dhd_prot_hdrpush */
2730 	frame = (uint8*)PKTDATA(osh, pkt);
2731 
2732 	DHD_INFO(("%s PKTLEN before postprocess %d",
2733 		__FUNCTION__, PKTLEN(osh, pkt)));
2734 
2735 	/* PKTLEN still includes tail_padding, so exclude it.
2736 	 * We shall have head_padding + original pkt_len for PKTLEN afterwards.
2737 	 */
2738 	if (bus->txglom_enable) {
2739 		/* txglom pkts have tail_padding length in HW ext header */
2740 		tail_padding = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16;
2741 		PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - tail_padding);
2742 		DHD_INFO((" txglom pkt: tail_padding %d PKTLEN %d\n",
2743 			tail_padding, PKTLEN(osh, pkt)));
2744 	} else {
2745 		/* non-txglom pkts have head_padding + original pkt length in HW frame tag.
2746 		 * We cannot refer to this field for txglom pkts as the first pkt of the chain will
2747 		 * have the field for the total length of the chain.
2748 		 */
2749 		PKTSETLEN(osh, pkt, *(uint16*)frame);
2750 		DHD_INFO((" non-txglom pkt: HW frame tag len %d after PKTLEN %d\n",
2751 			*(uint16*)frame, PKTLEN(osh, pkt)));
2752 	}
2753 
2754 	data_offset = ltoh32_ua(frame + swhdr_offset);
2755 	data_offset = (data_offset & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT;
2756 	/* Get rid of sdpcm header + head_padding */
2757 	PKTPULL(osh, pkt, data_offset);
2758 
2759 	DHD_INFO(("%s data_offset %d, PKTLEN %d\n",
2760 		__FUNCTION__, data_offset, PKTLEN(osh, pkt)));
2761 
2762 	return BCME_OK;
2763 }
2764 
dhdsdio_txpkt(dhd_bus_t * bus,uint chan,void ** pkts,int num_pkt,bool free_pkt)2765 static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt)
2766 {
2767 	int i;
2768 	int ret = 0;
2769 	osl_t *osh;
2770 	bcmsdh_info_t *sdh;
2771 	void *pkt = NULL;
2772 	void *pkt_chain;
2773 	int total_len = 0;
2774 	void *head_pkt = NULL;
2775 	void *prev_pkt = NULL;
2776 	int pad_pkt_len = 0;
2777 	int new_pkt_num = 0;
2778 	void *new_pkts[MAX_TX_PKTCHAIN_CNT];
2779 	bool wlfc_enabled = FALSE;
2780 
2781 	if (bus->dhd->dongle_reset)
2782 		return BCME_NOTREADY;
2783 
2784 	if (num_pkt <= 0)
2785 		return BCME_BADARG;
2786 
2787 	sdh = bus->sdh;
2788 	osh = bus->dhd->osh;
2789 	/* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */
2790 	new_pkts[0] = NULL;
2791 
2792 	for (i = 0; i < num_pkt; i++) {
2793 		int pkt_len;
2794 		bool last_pkt;
2795 		void *new_pkt = NULL;
2796 
2797 		pkt = pkts[i];
2798 		ASSERT(pkt);
2799 		last_pkt = (i == num_pkt - 1);
2800 		pkt_len = dhdsdio_txpkt_preprocess(bus, pkt, chan, bus->tx_seq + i,
2801 			total_len, last_pkt, &pad_pkt_len, &new_pkt
2802 #if defined(BCMSDIOH_TXGLOM_EXT)
2803 			, i
2804 #endif
2805 		);
2806 		if (pkt_len <= 0)
2807 			goto done;
2808 		if (new_pkt) {
2809 			pkt = new_pkt;
2810 			new_pkts[new_pkt_num++] = new_pkt;
2811 		}
2812 		total_len += pkt_len;
2813 
2814 		PKTSETNEXT(osh, pkt, NULL);
2815 		/* insert the packet into the list */
2816 		head_pkt ? PKTSETNEXT(osh, prev_pkt, pkt) : (head_pkt = pkt);
2817 		prev_pkt = pkt;
2818 
2819 	}
2820 
2821 	/* Update the HW frame tag (total length) in the first pkt of the glom */
2822 	if (bus->txglom_enable) {
2823 		uint8 *frame;
2824 
2825 		total_len += pad_pkt_len;
2826 		frame = (uint8*)PKTDATA(osh, head_pkt);
2827 		*(uint16*)frame = (uint16)htol16(total_len);
2828 		*(((uint16*)frame) + 1) = (uint16)htol16(~total_len);
2829 
2830 	}
2831 
2832 #ifdef DHDENABLE_TAILPAD
2833 	/* if a padding packet if needed, insert it to the end of the link list */
2834 	if (pad_pkt_len) {
2835 		PKTSETLEN(osh, bus->pad_pkt, pad_pkt_len);
2836 		PKTSETNEXT(osh, pkt, bus->pad_pkt);
2837 	}
2838 #endif /* DHDENABLE_TAILPAD */
2839 
2840 	/* dhd_bcmsdh_send_buf ignores the buffer pointer if he packet
2841 	 * parameter is not NULL, for non packet chian we pass NULL pkt pointer
2842 	 * so it will take the aligned length and buffer pointer.
2843 	 */
2844 	pkt_chain = PKTNEXT(osh, head_pkt) ? head_pkt : NULL;
2845 #ifdef TPUT_MONITOR
2846 	if ((bus->dhd->conf->data_drop_mode == TXPKT_DROP) && (total_len > 500))
2847 		ret = BCME_OK;
2848 	else
2849 #endif
2850 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
2851 		PKTDATA(osh, head_pkt), total_len, pkt_chain, NULL, NULL, TXRETRIES);
2852 	if (ret == BCME_OK)
2853 		bus->tx_seq = (bus->tx_seq + num_pkt) % SDPCM_SEQUENCE_WRAP;
2854 
2855 	/* if a padding packet was needed, remove it from the link list as it not a data pkt */
2856 	if (pad_pkt_len && pkt)
2857 		PKTSETNEXT(osh, pkt, NULL);
2858 
2859 done:
2860 	pkt = head_pkt;
2861 	while (pkt) {
2862 		void *pkt_next = PKTNEXT(osh, pkt);
2863 		PKTSETNEXT(osh, pkt, NULL);
2864 		dhdsdio_txpkt_postprocess(bus, pkt);
2865 		pkt = pkt_next;
2866 	}
2867 
2868 	/* new packets might be allocated due to insufficient room for padding, but we
2869 	 * still have to indicate the original packets to upper layer
2870 	 */
2871 	for (i = 0; i < num_pkt; i++) {
2872 		pkt = pkts[i];
2873 		wlfc_enabled = FALSE;
2874 #ifdef PROP_TXSTATUS
2875 		if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt))) {
2876 			wlfc_enabled = (dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0) !=
2877 				WLFC_UNSUPPORTED);
2878 		}
2879 #endif /* PROP_TXSTATUS */
2880 		if (!wlfc_enabled) {
2881 			PKTSETNEXT(osh, pkt, NULL);
2882 			dhd_txcomplete(bus->dhd, pkt, ret != 0);
2883 			if (free_pkt)
2884 				PKTFREE(osh, pkt, TRUE);
2885 		}
2886 	}
2887 
2888 	for (i = 0; i < new_pkt_num; i++)
2889 		PKTFREE(osh, new_pkts[i], TRUE);
2890 
2891 	return ret;
2892 }
2893 
2894 static uint
dhdsdio_sendfromq(dhd_bus_t * bus,uint maxframes)2895 dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
2896 {
2897 	uint cnt = 0;
2898 	uint8 tx_prec_map;
2899 	uint16 txpktqlen = 0;
2900 	uint32 intstatus = 0;
2901 	uint retries = 0;
2902 	osl_t *osh;
2903 	dhd_pub_t *dhd = bus->dhd;
2904 	sdpcmd_regs_t *regs = bus->regs;
2905 #if defined(DHD_LOSSLESS_ROAMING) || defined(DHD_PKTDUMP_TOFW)
2906 	uint8 *pktdata;
2907 	struct ether_header *eh;
2908 #ifdef BDC
2909 	struct bdc_header *bdc_header;
2910 	uint8 data_offset;
2911 #endif
2912 #endif /* DHD_LOSSLESS_ROAMING */
2913 
2914 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2915 
2916 	if (!KSO_ENAB(bus)) {
2917 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
2918 		return BCME_NODEVICE;
2919 	}
2920 
2921 	osh = dhd->osh;
2922 	tx_prec_map = ~bus->flowcontrol;
2923 #ifdef DHD_LOSSLESS_ROAMING
2924 	tx_prec_map &= dhd->dequeue_prec_map;
2925 #endif /* DHD_LOSSLESS_ROAMING */
2926 	for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) {
2927 		int i;
2928 		int num_pkt = 1;
2929 		void *pkts[MAX_TX_PKTCHAIN_CNT];
2930 		int prec_out;
2931 		uint datalen = 0;
2932 
2933 		dhd_os_sdlock_txq(bus->dhd);
2934 		if (bus->txglom_enable) {
2935 			uint32 glomlimit = (uint32)bus->txglomsize;
2936 #if defined(BCMSDIOH_STD)
2937 			if (bus->blocksize == 64) {
2938 				glomlimit = MIN((uint32)bus->txglomsize, BLK_64_MAXTXGLOM);
2939 			}
2940 #endif /* BCMSDIOH_STD */
2941 			num_pkt = MIN((uint32)DATABUFCNT(bus), glomlimit);
2942 			num_pkt = MIN(num_pkt, ARRAYSIZE(pkts));
2943 		}
2944 		num_pkt = MIN(num_pkt, pktq_mlen(&bus->txq, tx_prec_map));
2945 		for (i = 0; i < num_pkt; i++) {
2946 			pkts[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
2947 			if (!pkts[i]) {
2948 				DHD_ERROR(("%s: pktq_mlen non-zero when no pkt\n",
2949 					__FUNCTION__));
2950 				ASSERT(0);
2951 				break;
2952 			}
2953 #if defined(DHD_LOSSLESS_ROAMING) || defined(DHD_PKTDUMP_TOFW)
2954 			pktdata = (uint8 *)PKTDATA(osh, pkts[i]);
2955 #ifdef BDC
2956 			/* Skip BDC header */
2957 			bdc_header = (struct bdc_header *)pktdata;
2958 			data_offset = bdc_header->dataOffset;
2959 			pktdata += BDC_HEADER_LEN + (data_offset << 2);
2960 #endif
2961 			eh = (struct ether_header *)pktdata;
2962 #ifdef DHD_LOSSLESS_ROAMING
2963 			if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
2964 				uint8 prio = (uint8)PKTPRIO(pkts[i]);
2965 
2966 				/* Restore to original priority for 802.1X packet */
2967 				if (prio == PRIO_8021D_NC) {
2968 					PKTSETPRIO(pkts[i], dhd->prio_8021x);
2969 #ifdef BDC
2970 					/* Restore to original priority in BDC header */
2971 					bdc_header->priority =
2972 						(dhd->prio_8021x & BDC_PRIORITY_MASK);
2973 #endif
2974 				}
2975 			}
2976 #endif /* DHD_LOSSLESS_ROAMING */
2977 #ifdef DHD_PKTDUMP_TOFW
2978 			dhd_dump_pkt(bus->dhd, BDC_GET_IF_IDX(bdc_header), pktdata,
2979 				(uint32)PKTLEN(bus->dhd->osh, pkts[i]), TRUE, NULL, NULL);
2980 #endif
2981 #endif /* DHD_LOSSLESS_ROAMING || DHD_8021X_DUMP */
2982 			if (!bus->dhd->conf->orphan_move)
2983 				PKTORPHAN(pkts[i], bus->dhd->conf->tsq);
2984 			datalen += PKTLEN(osh, pkts[i]);
2985 		}
2986 		dhd_os_sdunlock_txq(bus->dhd);
2987 
2988 		if (i == 0)
2989 			break;
2990 		if (dhdsdio_txpkt(bus, SDPCM_DATA_CHANNEL, pkts, i, TRUE) != BCME_OK)
2991 			dhd->tx_errors++;
2992 		else {
2993 			dhd->dstats.tx_bytes += datalen;
2994 			bus->txglomframes++;
2995 			bus->txglompkts += num_pkt;
2996 #ifdef PKT_STATICS
2997 			bus->tx_statics.glom_cnt_us[num_pkt-1] =
2998 				(bus->tx_statics.glom_cnt[num_pkt-1]*bus->tx_statics.glom_cnt_us[num_pkt-1]
2999 				+ bcmsdh_get_spend_time(bus->sdh))/(bus->tx_statics.glom_cnt[num_pkt-1] + 1);
3000 #endif
3001 		}
3002 		cnt += i;
3003 #ifdef PKT_STATICS
3004 		if (num_pkt) {
3005 			bus->tx_statics.glom_cnt[num_pkt-1]++;
3006 			if (num_pkt > bus->tx_statics.glom_max)
3007 				bus->tx_statics.glom_max = num_pkt;
3008 		}
3009 #endif
3010 
3011 		/* In poll mode, need to check for other events */
3012 		if (!bus->intr && cnt)
3013 		{
3014 			/* Check device status, signal pending interrupt */
3015 			R_SDREG(intstatus, &regs->intstatus, retries);
3016 			bus->f2txdata++;
3017 			if (bcmsdh_regfail(bus->sdh))
3018 				break;
3019 			if (intstatus & bus->hostintmask)
3020 				bus->ipend = TRUE;
3021 		}
3022 
3023 	}
3024 
3025 	if (dhd_doflow) {
3026 		dhd_os_sdlock_txq(bus->dhd);
3027 		txpktqlen = pktq_n_pkts_tot(&bus->txq);
3028 		dhd_os_sdunlock_txq(bus->dhd);
3029 	}
3030 
3031 	/* Do flow-control if needed */
3032 	if (dhd->up && (dhd->busstate == DHD_BUS_DATA) && (txpktqlen < FCLOW)) {
3033 		bool wlfc_enabled = FALSE;
3034 #ifdef PROP_TXSTATUS
3035 		wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED);
3036 #endif
3037 		if (!wlfc_enabled && dhd_doflow && dhd->txoff) {
3038 			dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
3039 		}
3040 	}
3041 
3042 	return cnt;
3043 }
3044 
3045 static void
dhdsdio_sendpendctl(dhd_bus_t * bus)3046 dhdsdio_sendpendctl(dhd_bus_t *bus)
3047 {
3048 	bcmsdh_info_t *sdh = bus->sdh;
3049 	int ret;
3050 	uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN;
3051 
3052 	if (bus->txglom_enable)
3053 		frame_seq += SDPCM_HWEXT_LEN;
3054 
3055 	if (*frame_seq != bus->tx_seq) {
3056 		DHD_INFO(("%s IOCTL frame seq lag detected!"
3057 			" frm_seq:%d != bus->tx_seq:%d, corrected\n",
3058 			__FUNCTION__, *frame_seq, bus->tx_seq));
3059 		*frame_seq = bus->tx_seq;
3060 	}
3061 
3062 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
3063 		(uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len,
3064 		NULL, NULL, NULL, 1);
3065 	if (ret == BCME_OK)
3066 		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
3067 
3068 	bus->ctrl_frame_stat = FALSE;
3069 	dhd_wait_event_wakeup(bus->dhd);
3070 }
3071 
3072 int
dhd_bus_txctl(struct dhd_bus * bus,uchar * msg,uint msglen)3073 dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
3074 {
3075 	static int err_nodevice = 0;
3076 	uint8 *frame;
3077 	uint16 len;
3078 	uint32 swheader;
3079 	uint8 doff = 0;
3080 	int ret = -1;
3081 	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
3082 
3083 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
3084 
3085 	if (bus->dhd->dongle_reset)
3086 		return -EIO;
3087 
3088 	/* Back the pointer to make a room for bus header */
3089 	frame = msg - sdpcm_hdrlen;
3090 	len = (msglen += sdpcm_hdrlen);
3091 
3092 	/* Add alignment padding (optional for ctl frames) */
3093 	if (dhd_alignctl) {
3094 		if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
3095 			frame -= doff;
3096 			len += doff;
3097 			msglen += doff;
3098 			bzero(frame, doff + sdpcm_hdrlen);
3099 		}
3100 		ASSERT(doff < DHD_SDALIGN);
3101 	}
3102 	doff += sdpcm_hdrlen;
3103 
3104 #ifndef BCMSPI
3105 	/* Round send length to next SDIO block */
3106 	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
3107 		uint16 pad = bus->blocksize - (len % bus->blocksize);
3108 		if ((pad <= bus->roundup) && (pad < bus->blocksize))
3109 			len += pad;
3110 	} else if (len % DHD_SDALIGN) {
3111 		len += DHD_SDALIGN - (len % DHD_SDALIGN);
3112 	}
3113 #endif /* BCMSPI */
3114 
3115 	/* Satisfy length-alignment requirements */
3116 	if (forcealign && (len & (ALIGNMENT - 1)))
3117 		len = ROUNDUP(len, ALIGNMENT);
3118 
3119 	ASSERT(ISALIGNED((uintptr)frame, 2));
3120 
3121 	/* Need to lock here to protect txseq and SDIO tx calls */
3122 	dhd_os_sdlock(bus->dhd);
3123 	if (bus->dhd->conf->txctl_tmo_fix > 0 && !TXCTLOK(bus)) {
3124 		bus->ctrl_wait = TRUE;
3125 		dhd_os_sdunlock(bus->dhd);
3126 		wait_event_interruptible_timeout(bus->ctrl_tx_wait, TXCTLOK(bus),
3127 			msecs_to_jiffies(bus->dhd->conf->txctl_tmo_fix));
3128 		dhd_os_sdlock(bus->dhd);
3129 		bus->ctrl_wait = FALSE;
3130 	}
3131 
3132 	BUS_WAKE(bus);
3133 
3134 	/* Make sure backplane clock is on */
3135 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
3136 
3137 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
3138 	*(uint16*)frame = htol16((uint16)msglen);
3139 	*(((uint16*)frame) + 1) = htol16(~msglen);
3140 
3141 	if (bus->txglom_enable) {
3142 		uint32 hwheader1, hwheader2;
3143 		/* Software tag: channel, sequence number, data offset */
3144 		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
3145 				| bus->tx_seq
3146 				| ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
3147 		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN);
3148 		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN
3149 			+ SDPCM_HWEXT_LEN + sizeof(swheader));
3150 
3151 		hwheader1 = (msglen - SDPCM_FRAMETAG_LEN) | (1 << 24);
3152 		hwheader2 = (len - (msglen)) << 16;
3153 		htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
3154 		htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
3155 
3156 		*(uint16*)frame = htol16(len);
3157 		*(((uint16*)frame) + 1) = htol16(~(len));
3158 	} else {
3159 		/* Software tag: channel, sequence number, data offset */
3160 		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
3161 		        | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
3162 		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
3163 		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
3164 	}
3165 
3166 	if (!TXCTLOK(bus))
3167 	{
3168 		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
3169 			__FUNCTION__, bus->tx_max, bus->tx_seq));
3170 		bus->ctrl_frame_stat = TRUE;
3171 		/* Send from dpc */
3172 		bus->ctrl_frame_buf = frame;
3173 		bus->ctrl_frame_len = len;
3174 
3175 #if defined(NDIS)
3176 		dhd_os_sdunlock(bus->dhd);
3177 		dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
3178 		dhd_os_sdlock(bus->dhd);
3179 #else
3180 		if (!bus->dpc_sched) {
3181 			bus->dpc_sched = TRUE;
3182 			dhd_sched_dpc(bus->dhd);
3183 		}
3184 		if (bus->ctrl_frame_stat) {
3185 			dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
3186 		}
3187 #endif /* NDIS */
3188 
3189 		if (bus->ctrl_frame_stat == FALSE) {
3190 			DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
3191 			ret = 0;
3192 		} else {
3193 			bus->dhd->txcnt_timeout++;
3194 			if (!bus->dhd->hang_was_sent) {
3195 #ifdef CUSTOMER_HW4_DEBUG
3196 				/* XXX Add Debug code for find root cause from CSP:565333 */
3197 				uint32 status, retry = 0;
3198 				R_SDREG(status, &bus->regs->intstatus, retry);
3199 				DHD_TRACE_HW4(("%s: txcnt_timeout, INT status=0x%08X\n",
3200 					__FUNCTION__, status));
3201 				DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n",
3202 					__FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate));
3203 #endif /* CUSTOMER_HW4_DEBUG */
3204 				DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
3205 					__FUNCTION__, bus->dhd->txcnt_timeout));
3206 #ifdef BCMSDIO_RXLIM_POST
3207 				DHD_ERROR(("%s: rxlim_en=%d, rxlim enable=%d, rxlim_addr=%d\n",
3208 					__FUNCTION__,
3209 					bus->dhd->conf->rxlim_en, bus->rxlim_en, bus->rxlim_addr));
3210 #endif /* BCMSDIO_RXLIM_POST */
3211 			}
3212 #ifdef DHD_FW_COREDUMP
3213 			/* Collect socram dump */
3214 			if ((bus->dhd->memdump_enabled) &&
3215 				(bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT)) {
3216 				/* collect core dump */
3217 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_TX;
3218 				dhd_os_sdunlock(bus->dhd);
3219 				dhd_bus_mem_dump(bus->dhd);
3220 				dhd_os_sdlock(bus->dhd);
3221 			}
3222 #endif /* DHD_FW_COREDUMP */
3223 			ret = -1;
3224 			bus->ctrl_frame_stat = FALSE;
3225 			goto done;
3226 		}
3227 	}
3228 
3229 	bus->dhd->txcnt_timeout = 0;
3230 	bus->ctrl_frame_stat = TRUE;
3231 
3232 	if (ret == -1) {
3233 #ifdef DHD_DEBUG
3234 		if (DHD_BYTES_ON() && DHD_CTL_ON()) {
3235 			prhex("Tx Frame", frame, len);
3236 		} else if (DHD_HDRS_ON()) {
3237 			prhex("TxHdr", frame, MIN(len, 16));
3238 		}
3239 #endif
3240 #ifdef PKT_STATICS
3241 		bus->tx_statics.ctrl_count++;
3242 		bus->tx_statics.ctrl_size += len;
3243 #endif
3244 		ret = dhd_bcmsdh_send_buffer(bus, frame, len);
3245 	}
3246 	bus->ctrl_frame_stat = FALSE;
3247 
3248 done:
3249 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
3250 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
3251 		bus->activity = FALSE;
3252 		dhdsdio_bussleep(bus, TRUE);
3253 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
3254 	}
3255 
3256 	dhd_os_sdunlock(bus->dhd);
3257 
3258 	/* XXX Need to validate return code (ranges) */
3259 	if (ret)
3260 		bus->dhd->tx_ctlerrs++;
3261 	else
3262 		bus->dhd->tx_ctlpkts++;
3263 
3264 	if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT) {
3265 #ifdef DHD_PM_CONTROL_FROM_FILE
3266 		if (g_pm_control == TRUE) {
3267 			return -BCME_ERROR;
3268 		} else {
3269 		return -ETIMEDOUT;
3270 		}
3271 #else
3272 		return -ETIMEDOUT;
3273 #endif /* DHD_PM_CONTROL_FROM_FILE */
3274 	}
3275 	if (ret == BCME_NODEVICE)
3276 		err_nodevice++;
3277 	else
3278 		err_nodevice = 0;
3279 
3280 	return ret ? err_nodevice >= ERROR_BCME_NODEVICE_MAX ? -ETIMEDOUT : -EIO : 0;
3281 }
3282 
3283 int
dhd_bus_rxctl(struct dhd_bus * bus,uchar * msg,uint msglen)3284 dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
3285 {
3286 	int timeleft;
3287 	uint rxlen = 0;
3288 	static uint cnt = 0;
3289 	uint max_rxcnt;
3290 
3291 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
3292 
3293 	if (bus->dhd->dongle_reset)
3294 		return -EIO;
3295 
3296 	/* Wait until control frame is available */
3297 	timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen);
3298 
3299 	dhd_os_sdlock(bus->dhd);
3300 	rxlen = bus->rxlen;
3301 	bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
3302 	bus->rxlen = 0;
3303 	dhd_os_sdunlock(bus->dhd);
3304 
3305 	if (bus->dhd->conf->ctrl_resched > 0 && !rxlen && timeleft == 0) {
3306 		cnt++;
3307 		if (cnt <= bus->dhd->conf->ctrl_resched) {
3308 			uint32 status, retry = 0;
3309 			R_SDREG(status, &bus->regs->intstatus, retry);
3310 			if ((status & I_HMB_HOST_INT) || PKT_AVAILABLE(bus, status)) {
3311 				DHD_ERROR(("%s: reschedule dhd_dpc, cnt=%d, status=0x%x\n",
3312 					__FUNCTION__, cnt, status));
3313 				bus->ipend = TRUE;
3314 				bus->dpc_sched = TRUE;
3315 				dhd_sched_dpc(bus->dhd);
3316 
3317 				/* Wait until control frame is available */
3318 				timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen);
3319 
3320 				dhd_os_sdlock(bus->dhd);
3321 				rxlen = bus->rxlen;
3322 				bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
3323 				bus->rxlen = 0;
3324 				dhd_os_sdunlock(bus->dhd);
3325 			}
3326 		}
3327 	} else {
3328 		cnt = 0;
3329 	}
3330 
3331 	if (rxlen) {
3332 		DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
3333 			__FUNCTION__, rxlen, msglen));
3334 	} else {
3335 		if (timeleft == 0) {
3336 #ifdef DHD_DEBUG
3337 			uint32 status, retry = 0;
3338 			R_SDREG(status, &bus->regs->intstatus, retry);
3339 			DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n",
3340 				__FUNCTION__, status));
3341 #else
3342 			DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
3343 #endif /* DHD_DEBUG */
3344 			if (!bus->dhd->dongle_trap_occured) {
3345 #ifdef DHD_FW_COREDUMP
3346 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT;
3347 #endif /* DHD_FW_COREDUMP */
3348 				dhd_os_sdlock(bus->dhd);
3349 				dhdsdio_checkdied(bus, NULL, 0);
3350 				dhd_os_sdunlock(bus->dhd);
3351 			}
3352 		} else {
3353 			DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
3354 			if (!bus->dhd->dongle_trap_occured) {
3355 #ifdef DHD_FW_COREDUMP
3356 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_UNKNOWN;
3357 #endif /* DHD_FW_COREDUMP */
3358 				dhd_os_sdlock(bus->dhd);
3359 				dhdsdio_checkdied(bus, NULL, 0);
3360 				dhd_os_sdunlock(bus->dhd);
3361 			}
3362 		}
3363 #ifdef DHD_FW_COREDUMP
3364 		/* Dump the ram image */
3365 		if (bus->dhd->memdump_enabled && !bus->dhd->dongle_trap_occured)
3366 			dhdsdio_mem_dump(bus);
3367 #endif /* DHD_FW_COREDUMP */
3368 	}
3369 	if (timeleft == 0) {
3370 		if (rxlen == 0)
3371 			bus->dhd->rxcnt_timeout++;
3372 		DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__,
3373 			bus->dhd->rxcnt_timeout, rxlen));
3374 #ifdef DHD_FW_COREDUMP
3375 		/* collect socram dump */
3376 		if (bus->dhd->memdump_enabled) {
3377 			bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_RX;
3378 			dhd_bus_mem_dump(bus->dhd);
3379 		}
3380 #endif /* DHD_FW_COREDUMP */
3381 	} else {
3382 		bus->dhd->rxcnt_timeout = 0;
3383 	}
3384 
3385 	if (rxlen)
3386 		bus->dhd->rx_ctlpkts++;
3387 	else
3388 		bus->dhd->rx_ctlerrs++;
3389 
3390 	if (bus->dhd->conf->rxcnt_timeout)
3391 		max_rxcnt = bus->dhd->conf->rxcnt_timeout;
3392 	else
3393 		max_rxcnt = MAX_CNTL_RX_TIMEOUT;
3394 	if (bus->dhd->rxcnt_timeout >= max_rxcnt) {
3395 #ifdef DHD_PM_CONTROL_FROM_FILE
3396 		if (g_pm_control == TRUE) {
3397 			return -BCME_ERROR;
3398 		} else {
3399 			return -ETIMEDOUT;
3400 		}
3401 #else
3402 		return -ETIMEDOUT;
3403 #endif /* DHD_PM_CONTROL_FROM_FILE */
3404 	}
3405 	if (bus->dhd->dongle_trap_occured)
3406 		return -EREMOTEIO;
3407 
3408 	return rxlen ? (int)rxlen : -EIO; /* XXX Returns EIO error  */
3409 }
3410 
3411 /* IOVar table */
3412 enum {
3413 	IOV_INTR = 1,
3414 	IOV_POLLRATE,
3415 	IOV_SDREG,
3416 	IOV_SBREG,
3417 	IOV_SDCIS,
3418 #ifdef DHD_BUS_MEM_ACCESS
3419 	IOV_MEMBYTES,
3420 #endif /* DHD_BUS_MEM_ACCESS */
3421 	IOV_RAMSIZE,
3422 	IOV_RAMSTART,
3423 #ifdef DHD_DEBUG
3424 	IOV_CHECKDIED,
3425 	IOV_SERIALCONS,
3426 #endif /* DHD_DEBUG */
3427 	IOV_SET_DOWNLOAD_STATE,
3428 	IOV_SOCRAM_STATE,
3429 	IOV_FORCEEVEN,
3430 	IOV_SDIOD_DRIVE,
3431 	IOV_READAHEAD,
3432 	IOV_SDRXCHAIN,
3433 	IOV_ALIGNCTL,
3434 	IOV_SDALIGN,
3435 	IOV_DEVRESET,
3436 	IOV_CPU,
3437 #if defined(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL)
3438 	IOV_WATERMARK,
3439 	IOV_MESBUSYCTRL,
3440 #endif /* USE_SDIOFIFO_IOVAR */
3441 #ifdef BCMINTERNAL
3442 	IOV_SDRESET,
3443 	IOV_SDABORT,
3444 	IOV_FIRSTREAD,
3445 	IOV_TSTOPH,
3446 	IOV_RETRYDATA,
3447 	IOV_CHECKFIFO,
3448 	IOV_DOFLOW,
3449 	IOV_SDF2,
3450 	IOV_CLOCKPOLL,
3451 	IOV_MAXRAMSIZE,
3452 	IOV_SIALL,
3453 #endif /* BCMINTERNAL */
3454 #ifdef SDTEST
3455 	IOV_PKTGEN,
3456 	IOV_EXTLOOP,
3457 #endif /* SDTEST */
3458 	IOV_SPROM,
3459 	IOV_TXBOUND,
3460 	IOV_RXBOUND,
3461 	IOV_TXMINMAX,
3462 	IOV_IDLETIME,
3463 	IOV_IDLECLOCK,
3464 	IOV_SD1IDLE,
3465 	IOV_SLEEP,
3466 	IOV_DONGLEISOLATION,
3467 	IOV_KSO,
3468 	IOV_DEVSLEEP,
3469 	IOV_DEVCAP,
3470 	IOV_VARS,
3471 #ifdef SOFTAP
3472 	IOV_FWPATH,
3473 #endif
3474 	IOV_TXGLOMSIZE,
3475 	IOV_TXGLOMMODE,
3476 	IOV_HANGREPORT,
3477 	IOV_TXINRX_THRES,
3478 	IOV_SDIO_SUSPEND
3479 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
3480 	IOV_GDB_SERVER,  /**< starts gdb server on given interface */
3481 #endif /* DEBUGGER || DHD_DSCOPE */
3482 };
3483 
3484 const bcm_iovar_t dhdsdio_iovars[] = {
3485 	{"intr",	IOV_INTR,	0, 0,	IOVT_BOOL,	0 },
3486 	{"sleep",	IOV_SLEEP,	0, 0,	IOVT_BOOL,	0 },
3487 	{"pollrate",	IOV_POLLRATE,	0, 0,	IOVT_UINT32,	0 },
3488 	{"idletime",	IOV_IDLETIME,	0, 0,	IOVT_INT32,	0 },
3489 	{"idleclock",	IOV_IDLECLOCK,	0, 0,	IOVT_INT32,	0 },
3490 	{"sd1idle",	IOV_SD1IDLE,	0, 0,	IOVT_BOOL,	0 },
3491 #ifdef DHD_BUS_MEM_ACCESS
3492 	{"membytes",	IOV_MEMBYTES,	0, 0,	IOVT_BUFFER,	2 * sizeof(int) },
3493 #endif /* DHD_BUS_MEM_ACCESS */
3494 	{"ramsize",	IOV_RAMSIZE,	0, 0,	IOVT_UINT32,	0 },
3495 	{"ramstart",	IOV_RAMSTART,	0, 0,	IOVT_UINT32,	0 },
3496 	{"dwnldstate",	IOV_SET_DOWNLOAD_STATE,	0, 0,	IOVT_BOOL,	0 },
3497 	{"socram_state",	IOV_SOCRAM_STATE,	0, 0,	IOVT_BOOL,	0 },
3498 	{"vars",	IOV_VARS,	0, 0,	IOVT_BUFFER,	0 },
3499 	{"sdiod_drive",	IOV_SDIOD_DRIVE, 0, 0,	IOVT_UINT32,	0 },
3500 	{"readahead",	IOV_READAHEAD,	0, 0,	IOVT_BOOL,	0 },
3501 	{"sdrxchain",	IOV_SDRXCHAIN,	0, 0,	IOVT_BOOL,	0 },
3502 	{"alignctl",	IOV_ALIGNCTL,	0, 0,	IOVT_BOOL,	0 },
3503 	{"sdalign",	IOV_SDALIGN,	0, 0,	IOVT_BOOL,	0 },
3504 	{"devreset",	IOV_DEVRESET,	0, 0,	IOVT_BOOL,	0 },
3505 #ifdef DHD_DEBUG
3506 	{"sdreg",	IOV_SDREG,	0, 0,	IOVT_BUFFER,	sizeof(sdreg_t) },
3507 	{"sbreg",	IOV_SBREG,	0, 0,	IOVT_BUFFER,	sizeof(sdreg_t) },
3508 	{"sd_cis",	IOV_SDCIS,	0, 0,	IOVT_BUFFER,	DHD_IOCTL_MAXLEN },
3509 	{"forcealign",	IOV_FORCEEVEN,	0, 0,	IOVT_BOOL,	0 },
3510 	{"txbound",	IOV_TXBOUND,	0, 0,	IOVT_UINT32,	0 },
3511 	{"rxbound",	IOV_RXBOUND,	0, 0,	IOVT_UINT32,	0 },
3512 	{"txminmax",	IOV_TXMINMAX,	0, 0,	IOVT_UINT32,	0 },
3513 	{"cpu",		IOV_CPU,	0, 0,	IOVT_BOOL,	0 },
3514 #ifdef DHD_DEBUG
3515 	{"checkdied",	IOV_CHECKDIED,	0, 0,	IOVT_BUFFER,	0 },
3516 	{"serial",	IOV_SERIALCONS,	0, 0,	IOVT_UINT32,	0 },
3517 #endif /* DHD_DEBUG  */
3518 #ifdef BCMINTERNAL
3519 	{"siregall",	IOV_SIALL,	0, 0,	IOVT_UINT32,	0 },
3520 #endif /* BCMINTERNAL */
3521 #endif /* DHD_DEBUG */
3522 #if defined(BCMINTERNAL) || defined(DHD_SPROM)
3523 	{"sprom",	IOV_SPROM,	0, 0,	IOVT_BUFFER,	2 * sizeof(int) },
3524 #endif /* BCMINTERNAL || DHD_SPROM */
3525 #ifdef SDTEST
3526 	{"extloop",	IOV_EXTLOOP,	0, 0,	IOVT_BOOL,	0 },
3527 	{"pktgen",	IOV_PKTGEN,	0, 0,	IOVT_BUFFER,	sizeof(dhd_pktgen_t) },
3528 #endif /* SDTEST */
3529 #if defined(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL)
3530 	{"watermark",	IOV_WATERMARK,	0, 0,	IOVT_UINT32,	0 },
3531 	{"mesbusyctrl",	IOV_MESBUSYCTRL,	0, 0,	IOVT_UINT32,	0 },
3532 #endif /* USE_SDIOFIFO_IOVAR */
3533 #ifdef BCMINTERNAL
3534 	{"firstread",	IOV_FIRSTREAD,	0, 0,	IOVT_UINT32,	0 }, /* INTERNAL */
3535 	{"tstoph",	IOV_TSTOPH,	0, 0,	IOVT_BOOL,	0 },
3536 	{"retrydata",	IOV_RETRYDATA,	0, 0,	IOVT_BOOL,	0 },
3537 	{"checkfifo",	IOV_CHECKFIFO,	0, 0,	IOVT_BOOL,	0 },
3538 	{"sdf2",	IOV_SDF2,	0, 0,	IOVT_UINT32,	0 },
3539 	{"sdreset",	IOV_SDRESET,	0, 0,	IOVT_VOID,	0 },
3540 	{"sdabort",	IOV_SDABORT,	0, 0,	IOVT_UINT32,	0 },
3541 	{"doflow",	IOV_DOFLOW,	0, 0,	IOVT_BOOL,	0 },
3542 	{"clockpoll",	IOV_CLOCKPOLL,	0, 0,	IOVT_BOOL,	0 },
3543 	{"maxsocram",	IOV_MAXRAMSIZE,	0, 0,	IOVT_UINT32,	0 },
3544 #ifdef DHD_DEBUG
3545 	{"serial",	IOV_SERIALCONS,	0, 0,	IOVT_UINT32,	0 },
3546 #endif /* DHD_DEBUG */
3547 #endif /* BCMINTERNAL */
3548 	{"devcap", IOV_DEVCAP,	0, 0,	IOVT_UINT32,	0 },
3549 	{"dngl_isolation", IOV_DONGLEISOLATION,	0, 0,	IOVT_UINT32,	0 },
3550 	{"kso",	IOV_KSO,	0, 0,	IOVT_UINT32,	0 },
3551 	{"devsleep", IOV_DEVSLEEP,	0, 0,	IOVT_UINT32,	0 },
3552 #ifdef SOFTAP
3553 	{"fwpath", IOV_FWPATH, 0, 0, IOVT_BUFFER, 0 },
3554 #endif
3555 	{"txglomsize", IOV_TXGLOMSIZE, 0, 0, IOVT_UINT32, 0 },
3556 	{"fw_hang_report", IOV_HANGREPORT, 0, 0, IOVT_BOOL, 0 },
3557 	{"txinrx_thres", IOV_TXINRX_THRES, 0, 0, IOVT_INT32, 0 },
3558 	{"sdio_suspend", IOV_SDIO_SUSPEND, 0, 0, IOVT_UINT32, 0 },
3559 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
3560 	{"gdb_server", IOV_GDB_SERVER,    0, 0,      IOVT_UINT32,    0 },
3561 #endif /* DEBUGGER || DHD_DSCOPE */
3562 	{NULL, 0, 0, 0, 0, 0 }
3563 };
3564 
3565 static void
dhd_dump_pct(struct bcmstrbuf * strbuf,char * desc,uint num,uint div)3566 dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
3567 {
3568 	uint q1, q2;
3569 
3570 	if (!div) {
3571 		bcm_bprintf(strbuf, "%s N/A", desc);
3572 	} else {
3573 		q1 = num / div;
3574 		q2 = (100 * (num - (q1 * div))) / div;
3575 		bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
3576 	}
3577 }
3578 
3579 void
dhd_bus_dump(dhd_pub_t * dhdp,struct bcmstrbuf * strbuf)3580 dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
3581 {
3582 	dhd_bus_t *bus = dhdp->bus;
3583 #if defined(DHD_WAKE_STATUS) && defined(DHD_WAKE_EVENT_STATUS)
3584 	int i;
3585 #endif
3586 
3587 	bcm_bprintf(strbuf, "Bus SDIO structure:\n");
3588 	bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
3589 	            bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
3590 	bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n",
3591 	            bus->fcstate, pktq_n_pkts_tot(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
3592 	            bus->rxlen, bus->rx_seq);
3593 	bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
3594 	            bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
3595 
3596 #ifdef DHD_WAKE_STATUS
3597 	bcm_bprintf(strbuf, "wake %u rxwake %u readctrlwake %u\n",
3598 		bcmsdh_get_total_wake(bus->sdh), bus->wake_counts.rxwake,
3599 		bus->wake_counts.rcwake);
3600 #ifdef DHD_WAKE_RX_STATUS
3601 	bcm_bprintf(strbuf, " unicast %u multicast %u broadcast %u arp %u\n",
3602 		bus->wake_counts.rx_ucast, bus->wake_counts.rx_mcast,
3603 		bus->wake_counts.rx_bcast, bus->wake_counts.rx_arp);
3604 	bcm_bprintf(strbuf, " multi4 %u multi6 %u icmp6 %u multiother %u\n",
3605 		bus->wake_counts.rx_multi_ipv4, bus->wake_counts.rx_multi_ipv6,
3606 		bus->wake_counts.rx_icmpv6, bus->wake_counts.rx_multi_other);
3607 	bcm_bprintf(strbuf, " icmp6_ra %u, icmp6_na %u, icmp6_ns %u\n",
3608 		bus->wake_counts.rx_icmpv6_ra, bus->wake_counts.rx_icmpv6_na,
3609 		bus->wake_counts.rx_icmpv6_ns);
3610 #endif /* DHD_WAKE_RX_STATUS */
3611 #ifdef DHD_WAKE_EVENT_STATUS
3612 	for (i = 0; i < WLC_E_LAST; i++)
3613 		if (bus->wake_counts.rc_event[i] != 0)
3614 			bcm_bprintf(strbuf, " %s = %u\n", bcmevent_get_name(i),
3615 				bus->wake_counts.rc_event[i]);
3616 	bcm_bprintf(strbuf, "\n");
3617 #endif /* DHD_WAKE_EVENT_STATUS */
3618 #endif /* DHD_WAKE_STATUS */
3619 
3620 	bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
3621 	            bus->pollrate, bus->pollcnt, bus->regfails);
3622 
3623 	bcm_bprintf(strbuf, "\nAdditional counters:\n");
3624 #ifdef DHDENABLE_TAILPAD
3625 	bcm_bprintf(strbuf, "tx_tailpad_chain %u tx_tailpad_pktget %u\n",
3626 	            bus->tx_tailpad_chain, bus->tx_tailpad_pktget);
3627 #endif /* DHDENABLE_TAILPAD */
3628 	bcm_bprintf(strbuf, "tx_sderrs %u fcqueued %u rxrtx %u rx_toolong %u rxc_errors %u\n",
3629 	            bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
3630 	            bus->rxc_errors);
3631 	bcm_bprintf(strbuf, "rx_hdrfail %u badhdr %u badseq %u\n",
3632 	            bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
3633 	bcm_bprintf(strbuf, "fc_rcvd %u, fc_xoff %u, fc_xon %u\n",
3634 	            bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
3635 	bcm_bprintf(strbuf, "rxglomfail %u, rxglomframes %u, rxglompkts %u\n",
3636 	            bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
3637 	bcm_bprintf(strbuf, "f2rx (hdrs/data) %u (%u/%u), f2tx %u f1regs %u\n",
3638 	            (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
3639 	            bus->f2txdata, bus->f1regdata);
3640 	{
3641 		dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
3642 		             (bus->f2rxhdrs + bus->f2rxdata));
3643 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
3644 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
3645 		             (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
3646 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
3647 		bcm_bprintf(strbuf, "\n");
3648 
3649 		dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
3650 		             bus->dhd->rx_packets);
3651 		dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
3652 		bcm_bprintf(strbuf, "\n");
3653 
3654 		dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
3655 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
3656 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
3657 		             (bus->f2txdata + bus->f1regdata));
3658 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
3659 		bcm_bprintf(strbuf, "\n");
3660 
3661 		dhd_dump_pct(strbuf, "Total: pkts/f2rw",
3662 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
3663 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
3664 		dhd_dump_pct(strbuf, ", pkts/f1sd",
3665 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
3666 		dhd_dump_pct(strbuf, ", pkts/sd",
3667 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
3668 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
3669 		dhd_dump_pct(strbuf, ", pkts/int",
3670 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
3671 		bcm_bprintf(strbuf, "\n\n");
3672 	}
3673 
3674 #ifdef SDTEST
3675 	/* XXX Add new stats, include pktq len */
3676 	if (bus->pktgen_count) {
3677 		bcm_bprintf(strbuf, "pktgen config and count:\n");
3678 		bcm_bprintf(strbuf, "freq %u count %u print %u total %u min %u len %u\n",
3679 		            bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
3680 		            bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
3681 		bcm_bprintf(strbuf, "send attempts %u rcvd %u fail %u\n",
3682 		            bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
3683 	}
3684 #endif /* SDTEST */
3685 #ifdef DHD_DEBUG
3686 	bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
3687 	            bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
3688 	bcm_bprintf(strbuf, "blocksize %u roundup %u\n", bus->blocksize, bus->roundup);
3689 #endif /* DHD_DEBUG */
3690 	bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
3691 	            bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
3692 #ifdef BCMINTERNAL
3693 	bcm_bprintf(strbuf, "tx_deferred %d, fc 0x%x\n", bus->tx_deferred, bus->flowcontrol);
3694 #ifdef DHD_DEBUG
3695 	{
3696 		int i;
3697 		bcm_bprintf(strbuf, "qcount: ");
3698 		for (i = 0; i < 8; i++)
3699 			bcm_bprintf(strbuf, " %d , ", qcount[i]);
3700 		bcm_bprintf(strbuf, "\n");
3701 		bcm_bprintf(strbuf, "tx_packets: ");
3702 		for (i = 0; i < 8; i++)
3703 			bcm_bprintf(strbuf, " %d , ", tx_packets[i]);
3704 		bcm_bprintf(strbuf, "\n");
3705 	}
3706 #endif /* DHD_DEBUG */
3707 #endif /* BCMINTERNAL */
3708 	dhd_dump_pct(strbuf, "Tx: glom pct", (100 * bus->txglompkts), bus->dhd->tx_packets);
3709 	dhd_dump_pct(strbuf, ", pkts/glom", bus->txglompkts, bus->txglomframes);
3710 	bcm_bprintf(strbuf, "\n");
3711 	bcm_bprintf(strbuf, "txglomframes %u, txglompkts %u\n", bus->txglomframes, bus->txglompkts);
3712 	bcm_bprintf(strbuf, "\n");
3713 }
3714 
3715 void
dhd_bus_clearcounts(dhd_pub_t * dhdp)3716 dhd_bus_clearcounts(dhd_pub_t *dhdp)
3717 {
3718 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
3719 
3720 	bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
3721 	bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
3722 	bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
3723 #ifdef DHDENABLE_TAILPAD
3724 	bus->tx_tailpad_chain = bus->tx_tailpad_pktget = 0;
3725 #endif /* DHDENABLE_TAILPAD */
3726 	bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
3727 	bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
3728 	bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
3729 #ifdef BCMINTERNAL
3730 	bus->tx_deferred = bus->flowcontrol = 0;
3731 #endif
3732 	bus->txglomframes = bus->txglompkts = 0;
3733 }
3734 
3735 #ifdef SDTEST
3736 static int
dhdsdio_pktgen_get(dhd_bus_t * bus,uint8 * arg)3737 dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
3738 {
3739 	dhd_pktgen_t pktgen;
3740 
3741 	pktgen.version = DHD_PKTGEN_VERSION;
3742 	pktgen.freq = bus->pktgen_freq;
3743 	pktgen.count = bus->pktgen_count;
3744 	pktgen.print = bus->pktgen_print;
3745 	pktgen.total = bus->pktgen_total;
3746 	pktgen.minlen = bus->pktgen_minlen;
3747 	pktgen.maxlen = bus->pktgen_maxlen;
3748 	pktgen.numsent = bus->pktgen_sent;
3749 	pktgen.numrcvd = bus->pktgen_rcvd;
3750 	pktgen.numfail = bus->pktgen_fail;
3751 	pktgen.mode = bus->pktgen_mode;
3752 	pktgen.stop = bus->pktgen_stop;
3753 
3754 	bcopy(&pktgen, arg, sizeof(pktgen));
3755 
3756 	return 0;
3757 }
3758 
3759 static int
dhdsdio_pktgen_set(dhd_bus_t * bus,uint8 * arg)3760 dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
3761 {
3762 	dhd_pktgen_t pktgen;
3763 	uint oldcnt, oldmode;
3764 
3765 	bcopy(arg, &pktgen, sizeof(pktgen));
3766 	if (pktgen.version != DHD_PKTGEN_VERSION)
3767 		return BCME_BADARG;
3768 
3769 	oldcnt = bus->pktgen_count;
3770 	oldmode = bus->pktgen_mode;
3771 
3772 	bus->pktgen_freq = pktgen.freq;
3773 	bus->pktgen_count = pktgen.count;
3774 	bus->pktgen_print = pktgen.print;
3775 	bus->pktgen_total = pktgen.total;
3776 	bus->pktgen_minlen = pktgen.minlen;
3777 	bus->pktgen_maxlen = pktgen.maxlen;
3778 	bus->pktgen_mode = pktgen.mode;
3779 	bus->pktgen_stop = pktgen.stop;
3780 
3781 	bus->pktgen_tick = bus->pktgen_ptick = 0;
3782 #if defined(LINUX)
3783 	bus->pktgen_prev_time = jiffies;
3784 #endif /* LINUX */
3785 	bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
3786 	bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
3787 
3788 	/* Clear counts for a new pktgen (mode change, or was stopped) */
3789 	if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) {
3790 		bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0;
3791 		bus->pktgen_prev_rcvd = bus->pktgen_fail = 0;
3792 	}
3793 
3794 	return 0;
3795 }
3796 #endif /* SDTEST */
3797 
3798 static int
dhdsdio_membytes(dhd_bus_t * bus,bool write,uint32 address,uint8 * data,uint size)3799 dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
3800 {
3801 	int bcmerror = 0;
3802 	uint32 sdaddr;
3803 	uint dsize;
3804 	uint8 *pdata;
3805 
3806 	/* In remap mode, adjust address beyond socram and redirect
3807 	 * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
3808 	 * is not backplane accessible
3809 	 */
3810 	if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address)) {
3811 		address -= bus->orig_ramsize;
3812 		address += SOCDEVRAM_BP_ADDR;
3813 	}
3814 
3815 	/* Determine initial transfer parameters */
3816 	sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
3817 	if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
3818 		dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
3819 	else
3820 		dsize = size;
3821 
3822 	/* Set the backplane window to include the start address */
3823 	if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
3824 		DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
3825 		goto xfer_done;
3826 	}
3827 
3828 	/* Do the transfer(s) */
3829 	while (size) {
3830 		DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
3831 		          __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
3832 		          (address & SBSDIO_SBWINDOW_MASK)));
3833 		if (dsize <= MAX_MEM_BUF) {
3834 			pdata = bus->membuf;
3835 			if (write)
3836 				memcpy(bus->membuf, data, dsize);
3837 		} else {
3838 			pdata = data;
3839 		}
3840 		if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, pdata, dsize))) {
3841 			DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
3842 			break;
3843 		}
3844 		if (dsize <= MAX_MEM_BUF && !write)
3845 			memcpy(data, bus->membuf, dsize);
3846 
3847 		/* Adjust for next transfer (if any) */
3848 		if ((size -= dsize)) {
3849 			data += dsize;
3850 			address += dsize;
3851 			if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
3852 				DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
3853 				break;
3854 			}
3855 			sdaddr = 0;
3856 			dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
3857 		}
3858 
3859 	}
3860 
3861 xfer_done:
3862 	/* Return the window to backplane enumeration space for core access */
3863 	if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
3864 		DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
3865 			bcmsdh_cur_sbwad(bus->sdh)));
3866 	}
3867 
3868 	return bcmerror;
3869 }
3870 
3871 #if defined(BCMSDIO_RXLIM_POST) || defined(BCMSDIO_TXSEQ_SYNC)
3872 static void
dhdsdio_txseq_sync(dhd_bus_t * bus,sdpcm_shared_t * sh)3873 dhdsdio_txseq_sync(dhd_bus_t *bus, sdpcm_shared_t *sh)
3874 {
3875 	struct dhd_conf *conf = bus->dhd->conf;
3876 
3877 	if (sh->flags & SDPCM_SHARED_RXLIM_POST) {
3878 #ifdef BCMSDIO_RXLIM_POST
3879 		if (conf->rxlim_en) {
3880 			if (sh->msgtrace_addr) {
3881 				bus->rxlim_en = TRUE;
3882 				bus->rxlim_addr = sh->msgtrace_addr;
3883 				DHD_INFO(("%s: RXLIM_POST enabled with rxlim_addr=0x%x\n",
3884 					__FUNCTION__, bus->rxlim_addr));
3885 			} else {
3886 				DHD_INFO(("%s: RXLIM_POST not enabled in fw\n", __FUNCTION__));
3887 			}
3888 		} else
3889 #endif /* BCMSDIO_RXLIM_POST */
3890 #ifdef BCMSDIO_TXSEQ_SYNC
3891 		if (conf->txseq_sync) {
3892 			uint8 val = 0;
3893 			sh->txseq_sync_addr = ltoh32(sh->txseq_sync_addr);
3894 			DHD_INFO(("%s: TXSEQ_SYNC enabled\n", __FUNCTION__));
3895 			if (0 == dhdsdio_membytes(bus, FALSE, sh->txseq_sync_addr, (uint8 *)&val, 1)) {
3896 				if (bus->tx_seq != val) {
3897 					DHD_INFO(("%s: Sync tx_seq from %d to %d\n",
3898 						__FUNCTION__, bus->tx_seq, val));
3899 					bus->tx_seq = val;
3900 					bus->tx_max = bus->tx_seq + 4;
3901 				}
3902 			}
3903 		} else
3904 #endif /* BCMSDIO_TXSEQ_SYNC */
3905 		{
3906 			DHD_INFO(("%s: rxlim_en and txseq_sync not enabled in config.txt\n", __FUNCTION__));
3907 		}
3908 		sh->flags &= ~SDPCM_SHARED_RXLIM_POST;
3909 	}
3910 	else {
3911 #ifdef BCMSDIO_RXLIM_POST
3912 		bus->rxlim_en = 0;
3913 #endif /* BCMSDIO_RXLIM_POST */
3914 #ifdef BCMSDIO_TXSEQ_SYNC
3915 		conf->txseq_sync = FALSE;
3916 #endif /* BCMSDIO_TXSEQ_SYNC */
3917 		DHD_INFO(("%s: TXSEQ_SYNC and RXLIM_POST not supported in fw\n", __FUNCTION__));
3918 	}
3919 }
3920 #endif /* BCMSDIO_RXLIM_POST || BCMSDIO_TXSEQ_SYNC */
3921 
3922 static int
dhdsdio_readshared(dhd_bus_t * bus,sdpcm_shared_t * sh)3923 dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
3924 {
3925 	uint32 addr;
3926 	int rv, i;
3927 	uint32 shaddr = 0;
3928 
3929 	if (bus->sih == NULL) {
3930 		if (bus->dhd && bus->dhd->dongle_reset) {
3931 			DHD_ERROR(("%s: Dongle is in reset state\n", __FUNCTION__));
3932 			return BCME_NOTREADY;
3933 		} else {
3934 			ASSERT(bus->dhd);
3935 			ASSERT(bus->sih);
3936 			DHD_ERROR(("%s: The address of sih is invalid\n", __FUNCTION__));
3937 			return BCME_ERROR;
3938 		}
3939 	}
3940 	/*
3941 	 * If SR is not implemented in 43430 FW we should not adjust shaddr
3942 	 * XXX Should be REMOVED after SR will be implemented in 43430 FW
3943 	 */
3944 	if ((CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
3945 		CHIPID(bus->sih->chip) == BCM43018_CHIP_ID) && !dhdsdio_sr_cap(bus))
3946 		bus->srmemsize = 0;
3947 
3948 	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
3949 	i = 0;
3950 	do {
3951 		/* Read last word in memory to determine address of sdpcm_shared structure */
3952 		if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
3953 			return rv;
3954 
3955 		addr = ltoh32(addr);
3956 
3957 		DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
3958 
3959 		/*
3960 		 * Check if addr is valid.
3961 		 * NVRAM length at the end of memory should have been overwritten.
3962 		 */
3963 		if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
3964 			if ((bus->srmemsize > 0) && (i++ == 0)) {
3965 				shaddr -= bus->srmemsize;
3966 			} else {
3967 				DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
3968 					__FUNCTION__, addr));
3969 				return BCME_ERROR;
3970 			}
3971 		} else
3972 			break;
3973 	} while (i < 2);
3974 
3975 	/* Read hndrte_shared structure */
3976 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
3977 		return rv;
3978 
3979 	/* Endianness */
3980 	sh->flags = ltoh32(sh->flags);
3981 	sh->trap_addr = ltoh32(sh->trap_addr);
3982 	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
3983 	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
3984 	sh->assert_line = ltoh32(sh->assert_line);
3985 	sh->console_addr = ltoh32(sh->console_addr);
3986 	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
3987 
3988 #if defined(BCMSDIO_RXLIM_POST) || defined(BCMSDIO_TXSEQ_SYNC)
3989 	dhdsdio_txseq_sync(bus, sh);
3990 #endif
3991 
3992 	/*
3993 	 * XXX - Allow a sdpcm_shared_t version mismatch between dhd structure
3994 	 * version 1 and firmware structure version 3.
3995 	 * The sdpcm_shared_t stucture fields used in this function are in the
3996 	 * same positions in these two structure versions.
3997 	 * For some chips in the FALCON release, the dhd driver is from the
3998 	 * FALCON branch (sdpcm_shared_t structure version 1) and the firmware
3999 	 * comes from the ROMTERM3 branch (sdpcm_shared_t structure version 1).
4000 	*/
4001 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
4002 		return BCME_OK;
4003 
4004 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
4005 		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
4006 		           "is different than sdpcm_shared version %d in dongle\n",
4007 		           __FUNCTION__, SDPCM_SHARED_VERSION,
4008 		           sh->flags & SDPCM_SHARED_VERSION_MASK));
4009 		return BCME_ERROR;
4010 	}
4011 
4012 	return BCME_OK;
4013 }
4014 
4015 #define CONSOLE_LINE_MAX	192
4016 
4017 #ifdef DHD_DEBUG
4018 static int
dhdsdio_readconsole(dhd_bus_t * bus)4019 dhdsdio_readconsole(dhd_bus_t *bus)
4020 {
4021 	dhd_console_t *c = &bus->console;
4022 	uint8 line[CONSOLE_LINE_MAX], ch;
4023 	uint32 n, idx, addr;
4024 	int rv;
4025 
4026 	/* Don't do anything until FWREADY updates console address */
4027 	if (bus->console_addr == 0)
4028 		return 0;
4029 
4030 	if (!KSO_ENAB(bus))
4031 		return 0;
4032 
4033 	/* Read console log struct */
4034 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, log);
4035 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
4036 		return rv;
4037 
4038 	/* Allocate console buffer (one time only) */
4039 	if (c->buf == NULL) {
4040 		c->bufsize = ltoh32(c->log.buf_size);
4041 		if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
4042 			return BCME_NOMEM;
4043 	}
4044 
4045 	idx = ltoh32(c->log.idx);
4046 
4047 	/* Protect against corrupt value */
4048 	if (idx > c->bufsize)
4049 		return BCME_ERROR;
4050 
4051 	/* Skip reading the console buffer if the index pointer has not moved */
4052 	if (idx == c->last)
4053 		return BCME_OK;
4054 
4055 	/* Read the console buffer */
4056 	/* xxx this could optimize and read only the portion of the buffer needed, but
4057 	 * it would also have to handle wrap-around.
4058 	 */
4059 	addr = ltoh32(c->log.buf);
4060 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
4061 		return rv;
4062 
4063 	while (c->last != idx) {
4064 		for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
4065 			if (c->last == idx) {
4066 				/* This would output a partial line.  Instead, back up
4067 				 * the buffer pointer and output this line next time around.
4068 				 */
4069 				if (c->last >= n)
4070 					c->last -= n;
4071 				else
4072 					c->last = c->bufsize - n;
4073 				goto break2;
4074 			}
4075 			ch = c->buf[c->last];
4076 			c->last = (c->last + 1) % c->bufsize;
4077 			if (ch == '\n')
4078 				break;
4079 			line[n] = ch;
4080 		}
4081 
4082 		if (n > 0) {
4083 			if (line[n - 1] == '\r')
4084 				n--;
4085 			line[n] = 0;
4086 			printf("CONSOLE: %s\n", line);
4087 #ifdef LOG_INTO_TCPDUMP
4088 			dhd_sendup_log(bus->dhd, line, n);
4089 #endif /* LOG_INTO_TCPDUMP */
4090 		}
4091 	}
4092 break2:
4093 
4094 	return BCME_OK;
4095 }
4096 #endif /* DHD_DEBUG */
4097 
4098 static int
dhdsdio_checkdied(dhd_bus_t * bus,char * data,uint size)4099 dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size)
4100 {
4101 	int bcmerror = 0;
4102 	uint msize = 512;
4103 	char *mbuffer = NULL;
4104 	char *console_buffer = NULL;
4105 	uint maxstrlen = 256;
4106 	char *str = NULL;
4107 	sdpcm_shared_t l_sdpcm_shared;
4108 	struct bcmstrbuf strbuf;
4109 	uint32 console_ptr, console_size, console_index;
4110 	uint8 line[CONSOLE_LINE_MAX], ch;
4111 	uint32 n, i, addr;
4112 	int rv;
4113 
4114 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
4115 
4116 	if (DHD_NOCHECKDIED_ON())
4117 		return 0;
4118 
4119 	if (data == NULL) {
4120 		/*
4121 		 * Called after a rx ctrl timeout. "data" is NULL.
4122 		 * allocate memory to trace the trap or assert.
4123 		 */
4124 		size = msize;
4125 		mbuffer = data = MALLOC(bus->dhd->osh, msize);
4126 		if (mbuffer == NULL) {
4127 			DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
4128 			bcmerror = BCME_NOMEM;
4129 			goto done;
4130 		}
4131 	}
4132 
4133 	if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
4134 		DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
4135 		bcmerror = BCME_NOMEM;
4136 		goto done;
4137 	}
4138 
4139 	if ((bcmerror = dhdsdio_readshared(bus, &l_sdpcm_shared)) < 0)
4140 		goto done;
4141 
4142 	bcm_binit(&strbuf, data, size);
4143 
4144 	bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
4145 	            l_sdpcm_shared.msgtrace_addr, l_sdpcm_shared.console_addr);
4146 
4147 	if ((l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
4148 		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
4149 		 * (Avoids conflict with real asserts for programmatic parsing of output.)
4150 		 */
4151 		bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
4152 	}
4153 
4154 	if ((l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
4155 		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
4156 		 * (Avoids conflict with real asserts for programmatic parsing of output.)
4157 		 */
4158 		bcm_bprintf(&strbuf, "No trap%s in dongle",
4159 		          (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
4160 		          ?"/assrt" :"");
4161 	} else {
4162 		if (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
4163 			/* Download assert */
4164 			bcm_bprintf(&strbuf, "Dongle assert");
4165 			if (l_sdpcm_shared.assert_exp_addr != 0) {
4166 				str[0] = '\0';
4167 				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
4168 				                                 l_sdpcm_shared.assert_exp_addr,
4169 				                                 (uint8 *)str, maxstrlen)) < 0)
4170 					goto done;
4171 
4172 				str[maxstrlen - 1] = '\0';
4173 				bcm_bprintf(&strbuf, " expr \"%s\"", str);
4174 			}
4175 
4176 			if (l_sdpcm_shared.assert_file_addr != 0) {
4177 				str[0] = '\0';
4178 				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
4179 				                   l_sdpcm_shared.assert_file_addr,
4180 				                                 (uint8 *)str, maxstrlen)) < 0)
4181 					goto done;
4182 
4183 				str[maxstrlen - 1] = '\0';
4184 				bcm_bprintf(&strbuf, " file \"%s\"", str);
4185 			}
4186 
4187 			bcm_bprintf(&strbuf, " line %d ", l_sdpcm_shared.assert_line);
4188 		}
4189 
4190 		if (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
4191 			trap_t *tr = &bus->dhd->last_trap_info;
4192 			bus->dhd->dongle_trap_occured = TRUE;
4193 			if ((bcmerror = dhdsdio_membytes(bus, FALSE,
4194 			                                 l_sdpcm_shared.trap_addr,
4195 			                                 (uint8*)tr, sizeof(trap_t))) < 0)
4196 				goto done;
4197 
4198 			bus->dongle_trap_addr = ltoh32(l_sdpcm_shared.trap_addr);
4199 
4200 			dhd_bus_dump_trap_info(bus, &strbuf);
4201 
4202 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log);
4203 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
4204 				(uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
4205 				goto printbuf;
4206 
4207 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.buf_size);
4208 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
4209 				(uint8 *)&console_size, sizeof(console_size))) < 0)
4210 				goto printbuf;
4211 
4212 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.idx);
4213 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
4214 				(uint8 *)&console_index, sizeof(console_index))) < 0)
4215 				goto printbuf;
4216 
4217 			console_ptr = ltoh32(console_ptr);
4218 			console_size = ltoh32(console_size);
4219 			console_index = ltoh32(console_index);
4220 
4221 			if (console_size > CONSOLE_BUFFER_MAX ||
4222 				!(console_buffer = MALLOC(bus->dhd->osh, console_size)))
4223 				goto printbuf;
4224 
4225 			if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr,
4226 				(uint8 *)console_buffer, console_size)) < 0)
4227 				goto printbuf;
4228 
4229 			for (i = 0, n = 0; i < console_size; i += n + 1) {
4230 				for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
4231 					ch = console_buffer[(console_index + i + n) % console_size];
4232 					if (ch == '\n')
4233 						break;
4234 					line[n] = ch;
4235 				}
4236 
4237 				if (n > 0) {
4238 					if (line[n - 1] == '\r')
4239 						n--;
4240 					line[n] = 0;
4241 					/* Don't use DHD_ERROR macro since we print
4242 					 * a lot of information quickly. The macro
4243 					 * will truncate a lot of the printfs
4244 					 */
4245 
4246 					if (dhd_msg_level & DHD_ERROR_VAL)
4247 						printf("CONSOLE: %s\n", line);
4248 				}
4249 			}
4250 		}
4251 	}
4252 
4253 printbuf:
4254 	if (l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
4255 		DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
4256 	}
4257 
4258 #if defined(DHD_FW_COREDUMP)
4259 	if (bus->dhd->memdump_enabled && (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP)) {
4260 		/* Mem dump to a file on device */
4261 		bus->dhd->memdump_type = DUMP_TYPE_DONGLE_TRAP;
4262 		/* xxx this sdunlock has been put as a WAR here. We tried to come up
4263 		  * with a better solution but with the current structure of sdlocks it is very
4264 		  * unlikely to have a better fix for now. The better Rearch of sdio bus
4265 		  * locking has been put up as a cleanup activity and a thorough
4266 		  * code walkthrough is needed.
4267 		  */
4268 		dhd_os_sdunlock(bus->dhd);
4269 		dhdsdio_mem_dump(bus);
4270 		dhd_os_sdlock(bus->dhd);
4271 #ifdef NDIS
4272 		/* Windows would like to crash and collect memory dump for analysis */
4273 		ASSERT(0 && "Dongle firmware died.");
4274 
4275 		/* For free drivers ASSERT will not bugcheck */
4276 		KeBugCheckEx(__LINE__, 0, 0, 0, 0);
4277 #endif
4278 	}
4279 #endif /* #if defined(DHD_FW_COREDUMP) */
4280 
4281 done:
4282 	if (mbuffer)
4283 		MFREE(bus->dhd->osh, mbuffer, msize);
4284 	if (str)
4285 		MFREE(bus->dhd->osh, str, maxstrlen);
4286 	if (console_buffer)
4287 		MFREE(bus->dhd->osh, console_buffer, console_size);
4288 
4289 	return bcmerror;
4290 }
4291 
4292 #if defined(DHD_FW_COREDUMP)
4293 int
dhd_bus_mem_dump(dhd_pub_t * dhdp)4294 dhd_bus_mem_dump(dhd_pub_t *dhdp)
4295 {
4296 	dhd_bus_t *bus = dhdp->bus;
4297 	if (dhdp->busstate == DHD_BUS_SUSPEND) {
4298 		DHD_ERROR(("%s: Bus is suspend so skip\n", __FUNCTION__));
4299 		return 0;
4300 	}
4301 	return dhdsdio_mem_dump(bus);
4302 }
4303 
4304 int
dhd_bus_get_mem_dump(dhd_pub_t * dhdp)4305 dhd_bus_get_mem_dump(dhd_pub_t *dhdp)
4306 {
4307 	if (!dhdp) {
4308 		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
4309 		return BCME_ERROR;
4310 	}
4311 
4312 	return dhdsdio_get_mem_dump(dhdp->bus);
4313 }
4314 
4315 static int
dhdsdio_get_mem_dump(dhd_bus_t * bus)4316 dhdsdio_get_mem_dump(dhd_bus_t *bus)
4317 {
4318 	int ret = BCME_ERROR;
4319 	int size = bus->ramsize;		/* Full mem size */
4320 	uint32 start = bus->dongle_ram_base;	/* Start address */
4321 	uint read_size = 0;			/* Read size of each iteration */
4322 	uint8 *p_buf = NULL, *databuf = NULL;
4323 
4324 	/* Get full mem size */
4325 	p_buf = dhd_get_fwdump_buf(bus->dhd, size);
4326 	if (!p_buf) {
4327 		DHD_ERROR(("%s: Out of memory (%d bytes)\n",
4328 			__FUNCTION__, size));
4329 		return BCME_ERROR;
4330 	}
4331 
4332 	dhd_os_sdlock(bus->dhd);
4333 	BUS_WAKE(bus);
4334 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
4335 
4336 	/* Read mem content */
4337 	DHD_ERROR(("Dump dongle memory\n"));
4338 	databuf = p_buf;
4339 	while (size) {
4340 		read_size = MIN(MEMBLOCK, size);
4341 		ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size);
4342 		if (ret) {
4343 			DHD_ERROR(("%s: Error membytes %d\n", __FUNCTION__, ret));
4344 			ret = BCME_ERROR;
4345 			break;
4346 		}
4347 		/* Decrement size and increment start address */
4348 		size -= read_size;
4349 		start += read_size;
4350 		databuf += read_size;
4351 	}
4352 
4353 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
4354 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
4355 		bus->activity = FALSE;
4356 		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
4357 	}
4358 
4359 	dhd_os_sdunlock(bus->dhd);
4360 
4361 	return ret;
4362 }
4363 
4364 static int
dhdsdio_mem_dump(dhd_bus_t * bus)4365 dhdsdio_mem_dump(dhd_bus_t *bus)
4366 {
4367 	dhd_pub_t *dhdp;
4368 	int ret = BCME_ERROR;
4369 
4370 	dhdp = bus->dhd;
4371 	if (!dhdp) {
4372 		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
4373 		return ret;
4374 	}
4375 
4376 	ret = dhdsdio_get_mem_dump(bus);
4377 	if (ret) {
4378 		DHD_ERROR(("%s: failed to get mem dump, err=%d\n",
4379 			__FUNCTION__, ret));
4380 	} else {
4381 		/* schedule a work queue to perform actual memdump.
4382 		 * dhd_mem_dump() performs the job
4383 		 */
4384 		dhd_schedule_memdump(dhdp, dhdp->soc_ram, dhdp->soc_ram_length);
4385 		/* soc_ram free handled in dhd_{free,clear} */
4386 	}
4387 
4388 	return ret;
4389 }
4390 #endif /* DHD_FW_COREDUMP */
4391 
4392 int
dhd_socram_dump(dhd_bus_t * bus)4393 dhd_socram_dump(dhd_bus_t * bus)
4394 {
4395 #if defined(DHD_FW_COREDUMP)
4396 	return (dhdsdio_mem_dump(bus));
4397 #else
4398 	return -1;
4399 #endif
4400 }
4401 
4402 int
dhdsdio_downloadvars(dhd_bus_t * bus,void * arg,int len)4403 dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
4404 {
4405 	int bcmerror = BCME_OK;
4406 
4407 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
4408 
4409 	if (bus->dhd->up &&
4410 		1) {
4411 		bcmerror = BCME_NOTDOWN;
4412 		goto err;
4413 	}
4414 	if (!len) {
4415 		bcmerror = BCME_BUFTOOSHORT;
4416 		goto err;
4417 	}
4418 
4419 	/* Free the old ones and replace with passed variables */
4420 	if (bus->vars)
4421 		MFREE(bus->dhd->osh, bus->vars, bus->varsz);
4422 
4423 	bus->vars = MALLOC(bus->dhd->osh, len);
4424 	bus->varsz = bus->vars ? len : 0;
4425 	if (bus->vars == NULL) {
4426 		bcmerror = BCME_NOMEM;
4427 		goto err;
4428 	}
4429 
4430 	/* Copy the passed variables, which should include the terminating double-null */
4431 	bcopy(arg, bus->vars, bus->varsz);
4432 err:
4433 	return bcmerror;
4434 }
4435 
4436 #ifdef DHD_DEBUG
4437 static int
dhd_serialconsole(dhd_bus_t * bus,bool set,bool enable,int * bcmerror)4438 dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror)
4439 {
4440 	int int_val;
4441 	uint32 addr, data, uart_enab = 0;
4442 
4443 	addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
4444 	data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
4445 	*bcmerror = 0;
4446 
4447 	bcmsdh_reg_write(bus->sdh, addr, 4, 1);
4448 	if (bcmsdh_regfail(bus->sdh)) {
4449 		*bcmerror = BCME_SDIO_ERROR;
4450 		return -1;
4451 	}
4452 	int_val = bcmsdh_reg_read(bus->sdh, data, 4);
4453 	if (bcmsdh_regfail(bus->sdh)) {
4454 		*bcmerror = BCME_SDIO_ERROR;
4455 		return -1;
4456 	}
4457 
4458 	if (!set)
4459 		return (int_val & uart_enab);
4460 	if (enable)
4461 		int_val |= uart_enab;
4462 	else
4463 		int_val &= ~uart_enab;
4464 	bcmsdh_reg_write(bus->sdh, data, 4, int_val);
4465 	if (bcmsdh_regfail(bus->sdh)) {
4466 		*bcmerror = BCME_SDIO_ERROR;
4467 		return -1;
4468 	}
4469 
4470 	return (int_val & uart_enab);
4471 }
4472 #endif /* BCMINTERNAL */
4473 
4474 static int
dhdsdio_doiovar(dhd_bus_t * bus,const bcm_iovar_t * vi,uint32 actionid,const char * name,void * params,uint plen,void * arg,uint len,uint val_size)4475 dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
4476                 void *params, uint plen, void *arg, uint len, uint val_size)
4477 {
4478 	int bcmerror = 0;
4479 	int32 int_val = 0;
4480 	bool bool_val = 0;
4481 
4482 	DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
4483 	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
4484 
4485 	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
4486 		goto exit;
4487 
4488 	if (plen >= sizeof(int_val))
4489 		bcopy(params, &int_val, sizeof(int_val));
4490 
4491 	bool_val = (int_val != 0) ? TRUE : FALSE;
4492 
4493 	/* Some ioctls use the bus */
4494 	dhd_os_sdlock(bus->dhd);
4495 
4496 	/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
4497 	if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
4498 	                                actionid == IOV_GVAL(IOV_DEVRESET))) {
4499 		bcmerror = BCME_NOTREADY;
4500 		goto exit;
4501 	}
4502 
4503 	/*
4504 	 * Special handling for keepSdioOn: New SDIO Wake-up Mechanism
4505 	 */
4506 	if ((vi->varid == IOV_KSO) && (IOV_ISSET(actionid))) {
4507 		dhdsdio_clk_kso_iovar(bus, bool_val);
4508 		goto exit;
4509 	} else if ((vi->varid == IOV_DEVSLEEP) && (IOV_ISSET(actionid))) {
4510 #ifdef BCMINTERNAL
4511 		/* XXX: Temp for debugging devsleep */
4512 		if (int_val == 2) {
4513 			bus->dpc_sched = TRUE;
4514 			dhd_sched_dpc(bus->dhd);
4515 		} else if (int_val == 3) {
4516 			bus->_slpauto = FALSE;
4517 		} else if (int_val == 4) {
4518 			bus->_slpauto = TRUE;
4519 		} else if (int_val == 5) {
4520 			bus->kso = TRUE;
4521 		} else if (int_val == 6) {
4522 			bus->kso = FALSE;
4523 		} else
4524 #endif
4525 		{
4526 			dhdsdio_clk_devsleep_iovar(bus, bool_val);
4527 			if (!SLPAUTO_ENAB(bus) && (bool_val == FALSE) && (bus->ipend)) {
4528 				DHD_ERROR(("INT pending in devsleep 1, dpc_sched: %d\n",
4529 					bus->dpc_sched));
4530 				if (!bus->dpc_sched) {
4531 					bus->dpc_sched = TRUE;
4532 					dhd_sched_dpc(bus->dhd);
4533 				}
4534 			}
4535 		}
4536 		goto exit;
4537 	}
4538 
4539 	/* Handle sleep stuff before any clock mucking */
4540 	if (vi->varid == IOV_SLEEP) {
4541 		if (IOV_ISSET(actionid)) {
4542 			bcmerror = dhdsdio_bussleep(bus, bool_val);
4543 		} else {
4544 			int_val = (int32)bus->sleeping;
4545 			bcopy(&int_val, arg, val_size);
4546 		}
4547 		goto exit;
4548 	}
4549 
4550 	/* Request clock to allow SDIO accesses */
4551 	if (!bus->dhd->dongle_reset) {
4552 		BUS_WAKE(bus);
4553 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
4554 	}
4555 
4556 	switch (actionid) {
4557 	case IOV_GVAL(IOV_INTR):
4558 		int_val = (int32)bus->intr;
4559 		bcopy(&int_val, arg, val_size);
4560 		break;
4561 
4562 	case IOV_SVAL(IOV_INTR):
4563 		bus->intr = bool_val;
4564 		bus->intdis = FALSE;
4565 		if (bus->dhd->up) {
4566 			if (bus->intr) {
4567 				DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
4568 				// terence 20141207: enbale intdis
4569 				bus->intdis = TRUE;
4570 				bcmsdh_intr_enable(bus->sdh);
4571 			} else {
4572 				DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
4573 				bcmsdh_intr_disable(bus->sdh);
4574 			}
4575 		}
4576 		break;
4577 
4578 	case IOV_GVAL(IOV_POLLRATE):
4579 		int_val = (int32)bus->pollrate;
4580 		bcopy(&int_val, arg, val_size);
4581 		break;
4582 
4583 	case IOV_SVAL(IOV_POLLRATE):
4584 		bus->pollrate = (uint)int_val;
4585 		bus->poll = (bus->pollrate != 0);
4586 		break;
4587 
4588 	case IOV_GVAL(IOV_IDLETIME):
4589 		int_val = bus->idletime;
4590 		bcopy(&int_val, arg, val_size);
4591 		break;
4592 
4593 	case IOV_SVAL(IOV_IDLETIME):
4594 		if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
4595 			bcmerror = BCME_BADARG;
4596 		} else {
4597 			bus->idletime = int_val;
4598 		}
4599 		break;
4600 
4601 	case IOV_GVAL(IOV_IDLECLOCK):
4602 		int_val = (int32)bus->idleclock;
4603 		bcopy(&int_val, arg, val_size);
4604 		break;
4605 
4606 	case IOV_SVAL(IOV_IDLECLOCK):
4607 		bus->idleclock = int_val;
4608 		break;
4609 
4610 	case IOV_GVAL(IOV_SD1IDLE):
4611 		int_val = (int32)sd1idle;
4612 		bcopy(&int_val, arg, val_size);
4613 		break;
4614 
4615 	case IOV_SVAL(IOV_SD1IDLE):
4616 		sd1idle = bool_val;
4617 		break;
4618 
4619 #ifdef DHD_DEBUG
4620 	case IOV_GVAL(IOV_CHECKDIED):
4621 		bcmerror = dhdsdio_checkdied(bus, arg, len);
4622 		break;
4623 #endif /* DHD_DEBUG */
4624 
4625 #ifdef DHD_BUS_MEM_ACCESS
4626 	case IOV_SVAL(IOV_MEMBYTES):
4627 	case IOV_GVAL(IOV_MEMBYTES):
4628 	{
4629 		uint32 address;
4630 		uint size, dsize;
4631 		uint8 *data;
4632 
4633 		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
4634 
4635 		ASSERT(plen >= 2*sizeof(int));
4636 
4637 		address = (uint32)int_val;
4638 		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
4639 		size = (uint)int_val;
4640 
4641 		/* Do some validation */
4642 		dsize = set ? plen - (2 * sizeof(int)) : len;
4643 		if (dsize < size) {
4644 			DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
4645 			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
4646 			bcmerror = BCME_BADARG;
4647 			break;
4648 		}
4649 
4650 		DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
4651 		          (set ? "write" : "read"), size, address));
4652 
4653 		/* check if CR4 */
4654 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
4655 			/*
4656 			 * If address is start of RAM (i.e. a downloaded image),
4657 			 * store the reset instruction to be written in 0
4658 			 */
4659 			if (set && address == bus->dongle_ram_base) {
4660 				bus->resetinstr = *(((uint32*)params) + 2);
4661 			}
4662 		}
4663 
4664 		/* Generate the actual data pointer */
4665 		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
4666 
4667 		/* Call to do the transfer */
4668 		bcmerror = dhdsdio_membytes(bus, set, address, data, size);
4669 
4670 		break;
4671 	}
4672 #endif /* DHD_BUS_MEM_ACCESS */
4673 
4674 	case IOV_GVAL(IOV_RAMSIZE):
4675 		int_val = (int32)bus->ramsize;
4676 		bcopy(&int_val, arg, val_size);
4677 		break;
4678 
4679 	case IOV_GVAL(IOV_RAMSTART):
4680 		int_val = (int32)bus->dongle_ram_base;
4681 		bcopy(&int_val, arg, val_size);
4682 		break;
4683 
4684 	case IOV_GVAL(IOV_SDIOD_DRIVE):
4685 		int_val = (int32)dhd_sdiod_drive_strength;
4686 		bcopy(&int_val, arg, val_size);
4687 		break;
4688 
4689 	case IOV_SVAL(IOV_SDIOD_DRIVE):
4690 		dhd_sdiod_drive_strength = int_val;
4691 		si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
4692 		break;
4693 
4694 	case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
4695 		bcmerror = dhdsdio_download_state(bus, bool_val);
4696 		break;
4697 
4698 	case IOV_SVAL(IOV_SOCRAM_STATE):
4699 		bcmerror = dhdsdio_download_state(bus, bool_val);
4700 		break;
4701 
4702 	case IOV_SVAL(IOV_VARS):
4703 		bcmerror = dhdsdio_downloadvars(bus, arg, len);
4704 		break;
4705 
4706 	case IOV_GVAL(IOV_READAHEAD):
4707 		int_val = (int32)dhd_readahead;
4708 		bcopy(&int_val, arg, val_size);
4709 		break;
4710 
4711 	case IOV_SVAL(IOV_READAHEAD):
4712 		if (bool_val && !dhd_readahead)
4713 			bus->nextlen = 0;
4714 		dhd_readahead = bool_val;
4715 		break;
4716 
4717 	case IOV_GVAL(IOV_SDRXCHAIN):
4718 		int_val = (int32)bus->use_rxchain;
4719 		bcopy(&int_val, arg, val_size);
4720 		break;
4721 
4722 	case IOV_SVAL(IOV_SDRXCHAIN):
4723 		if (bool_val && !bus->sd_rxchain)
4724 			bcmerror = BCME_UNSUPPORTED;
4725 		else
4726 			bus->use_rxchain = bool_val;
4727 		break;
4728 #ifndef BCMSPI
4729 	case IOV_GVAL(IOV_ALIGNCTL):
4730 		int_val = (int32)dhd_alignctl;
4731 		bcopy(&int_val, arg, val_size);
4732 		break;
4733 
4734 	case IOV_SVAL(IOV_ALIGNCTL):
4735 		dhd_alignctl = bool_val;
4736 		break;
4737 #endif /* BCMSPI */
4738 
4739 	case IOV_GVAL(IOV_SDALIGN):
4740 		int_val = DHD_SDALIGN;
4741 		bcopy(&int_val, arg, val_size);
4742 		break;
4743 
4744 #ifdef DHD_DEBUG
4745 	case IOV_GVAL(IOV_VARS):
4746 		if (bus->varsz < (uint)len)
4747 			bcopy(bus->vars, arg, bus->varsz);
4748 		else
4749 			bcmerror = BCME_BUFTOOSHORT;
4750 		break;
4751 #endif /* DHD_DEBUG */
4752 
4753 #ifdef DHD_DEBUG
4754 	/* XXX Until these return BCME ranges, make assumptions here */
4755 	case IOV_GVAL(IOV_SDREG):
4756 	{
4757 		sdreg_t *sd_ptr;
4758 		uintptr addr;
4759 		uint size;
4760 
4761 		sd_ptr = (sdreg_t *)params;
4762 
4763 		addr = ((uintptr)bus->regs + sd_ptr->offset);
4764 		size = sd_ptr->func;
4765 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
4766 		if (bcmsdh_regfail(bus->sdh))
4767 			bcmerror = BCME_SDIO_ERROR;
4768 		bcopy(&int_val, arg, sizeof(int32));
4769 		break;
4770 	}
4771 
4772 	case IOV_SVAL(IOV_SDREG):
4773 	{
4774 		sdreg_t *sd_ptr;
4775 		uintptr addr;
4776 		uint size;
4777 
4778 		sd_ptr = (sdreg_t *)params;
4779 
4780 		addr = ((uintptr)bus->regs + sd_ptr->offset);
4781 		size = sd_ptr->func;
4782 		bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
4783 		if (bcmsdh_regfail(bus->sdh))
4784 			bcmerror = BCME_SDIO_ERROR;
4785 		break;
4786 	}
4787 
4788 	/* XXX Same as above */
4789 	/* Same as above, but offset is not backplane (not SDIO core) */
4790 	case IOV_GVAL(IOV_SBREG):
4791 	{
4792 		sdreg_t sdreg;
4793 		uint32 addr, size;
4794 
4795 		bcopy(params, &sdreg, sizeof(sdreg));
4796 
4797 		addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
4798 		size = sdreg.func;
4799 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
4800 		if (bcmsdh_regfail(bus->sdh))
4801 			bcmerror = BCME_SDIO_ERROR;
4802 		bcopy(&int_val, arg, sizeof(int32));
4803 		break;
4804 	}
4805 
4806 	case IOV_SVAL(IOV_SBREG):
4807 	{
4808 		sdreg_t sdreg;
4809 		uint32 addr, size;
4810 
4811 		bcopy(params, &sdreg, sizeof(sdreg));
4812 
4813 		addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
4814 		size = sdreg.func;
4815 		bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
4816 		if (bcmsdh_regfail(bus->sdh))
4817 			bcmerror = BCME_SDIO_ERROR;
4818 		break;
4819 	}
4820 
4821 	case IOV_GVAL(IOV_SDCIS):
4822 	{
4823 		*(char *)arg = 0;
4824 
4825 		/* XXX Ignoring return codes, should be evident from printed results */
4826 		bcmstrcat(arg, "\nFunc 0\n");
4827 		bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4828 		bcmstrcat(arg, "\nFunc 1\n");
4829 		bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4830 		bcmstrcat(arg, "\nFunc 2\n");
4831 		bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4832 		break;
4833 	}
4834 
4835 	case IOV_GVAL(IOV_FORCEEVEN):
4836 		int_val = (int32)forcealign;
4837 		bcopy(&int_val, arg, val_size);
4838 		break;
4839 
4840 	case IOV_SVAL(IOV_FORCEEVEN):
4841 		forcealign = bool_val;
4842 		break;
4843 
4844 	case IOV_GVAL(IOV_TXBOUND):
4845 		int_val = (int32)dhd_txbound;
4846 		bcopy(&int_val, arg, val_size);
4847 		break;
4848 
4849 	case IOV_SVAL(IOV_TXBOUND):
4850 		dhd_txbound = (uint)int_val;
4851 		break;
4852 
4853 	case IOV_GVAL(IOV_RXBOUND):
4854 		int_val = (int32)dhd_rxbound;
4855 		bcopy(&int_val, arg, val_size);
4856 		break;
4857 
4858 	case IOV_SVAL(IOV_RXBOUND):
4859 		dhd_rxbound = (uint)int_val;
4860 		break;
4861 
4862 	case IOV_GVAL(IOV_TXMINMAX):
4863 		int_val = (int32)dhd_txminmax;
4864 		bcopy(&int_val, arg, val_size);
4865 		break;
4866 
4867 	case IOV_SVAL(IOV_TXMINMAX):
4868 		dhd_txminmax = (uint)int_val;
4869 		break;
4870 
4871 #ifdef DHD_DEBUG
4872 	case IOV_GVAL(IOV_SERIALCONS):
4873 		int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror);
4874 		if (bcmerror != 0)
4875 			break;
4876 
4877 		bcopy(&int_val, arg, val_size);
4878 		break;
4879 
4880 	case IOV_SVAL(IOV_SERIALCONS):
4881 		dhd_serialconsole(bus, TRUE, bool_val, &bcmerror);
4882 		break;
4883 #endif /* DHD_DEBUG */
4884 
4885 #if defined(BCMINTERNAL) && defined(BCMDBG)
4886 	case IOV_SVAL(IOV_SIALL):
4887 		DHD_ERROR(("Dumping all the Backplane registers\n"));
4888 		si_viewall(bus->sih, TRUE);
4889 		break;
4890 #endif /* defined(BCMINTERNAL) && defined(BCMDBG) */
4891 
4892 #endif /* DHD_DEBUG */
4893 
4894 #if defined(DHD_SPROM)
4895 	case IOV_SVAL(IOV_SPROM):
4896 	case IOV_GVAL(IOV_SPROM):
4897 	{
4898 		uint32 offset;
4899 		uint size, dsize;
4900 
4901 		bool set = (actionid == IOV_SVAL(IOV_SPROM));
4902 
4903 		ASSERT(plen >= 2*sizeof(int));
4904 
4905 		offset = (uint32)int_val;
4906 		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
4907 		size = (uint)int_val;
4908 
4909 		/* Avoid bigger size of srom reads that may be requested from app.
4910 		 * gSPI has only F1 OTP visible from CC.  There is no CIS in gSPI.
4911 		 */
4912 		if (bus->bus == SPI_BUS)
4913 			size = SBSDIO_CIS_SIZE_LIMIT;
4914 
4915 		/* Do some validation */
4916 		dsize = set ? plen - (2 * sizeof(int)) : len;
4917 		if (dsize < size) {
4918 			DHD_ERROR(("%s: error on srom %s, addr 0x%08x size %d dsize %d\n",
4919 			           __FUNCTION__, (set ? "write" : "read"), offset, size, dsize));
4920 			bcmerror = BCME_BADARG;
4921 			break;
4922 		}
4923 
4924 		if ((offset > SROM_MAX) || ((offset + size) > SROM_MAX)) {
4925 			DHD_ERROR(("%s: error on srom %s, offset %d size %d exceeds limit %d\n",
4926 			           __FUNCTION__, (set ? "write" : "read"), offset, size, SROM_MAX));
4927 			bcmerror = BCME_BADARG;
4928 			break;
4929 		}
4930 
4931 		if (!set) {
4932 			if (!ISALIGNED((uintptr)arg, sizeof(uint16))) {
4933 				DHD_ERROR(("%s: srom data pointer %p not word-aligned\n",
4934 				           __FUNCTION__, arg));
4935 				bcmerror = BCME_BADARG;
4936 				break;
4937 			}
4938 
4939 			GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
4940 			bcmerror = srom_read(bus->sih, DHD_BUS, (void*)bus->regs, bus->dhd->osh,
4941 			                     offset, size, (uint16*)arg, FALSE);
4942 			GCC_DIAGNOSTIC_POP();
4943 
4944 		} else {
4945 			arg = (void*)((uintptr)arg + 2 * sizeof(int));
4946 			if (!ISALIGNED((uintptr)arg, sizeof(uint16))) {
4947 				DHD_ERROR(("%s: srom data pointer %p not word-aligned\n",
4948 				           __FUNCTION__, arg));
4949 				bcmerror = BCME_BADARG;
4950 				break;
4951 			}
4952 			GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
4953 			bcmerror = srom_write(bus->sih, DHD_BUS, (void*)bus->regs, bus->dhd->osh,
4954 			                      offset, size, (uint16*)arg);
4955 			GCC_DIAGNOSTIC_POP();
4956 		}
4957 		break;
4958 	}
4959 #endif /* DHD_SPROM */
4960 
4961 #ifdef SDTEST
4962 	case IOV_GVAL(IOV_EXTLOOP):
4963 		int_val = (int32)bus->ext_loop;
4964 		bcopy(&int_val, arg, val_size);
4965 		break;
4966 
4967 	case IOV_SVAL(IOV_EXTLOOP):
4968 		bus->ext_loop = bool_val;
4969 		break;
4970 
4971 	case IOV_GVAL(IOV_PKTGEN):
4972 		bcmerror = dhdsdio_pktgen_get(bus, arg);
4973 		break;
4974 
4975 	case IOV_SVAL(IOV_PKTGEN):
4976 		bcmerror = dhdsdio_pktgen_set(bus, arg);
4977 		break;
4978 #endif /* SDTEST */
4979 
4980 #if defined(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL)
4981 	case IOV_GVAL(IOV_WATERMARK):
4982 		int_val = (int32)watermark;
4983 		bcopy(&int_val, arg, val_size);
4984 		break;
4985 
4986 	case IOV_SVAL(IOV_WATERMARK):
4987 		watermark = (uint)int_val;
4988 		watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark;
4989 		DHD_ERROR(("Setting watermark as 0x%x.\n", watermark));
4990 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL);
4991 		break;
4992 
4993 	case IOV_GVAL(IOV_MESBUSYCTRL):
4994 		int_val = (int32)mesbusyctrl;
4995 		bcopy(&int_val, arg, val_size);
4996 		break;
4997 
4998 	case IOV_SVAL(IOV_MESBUSYCTRL):
4999 		mesbusyctrl = (uint)int_val;
5000 		mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK)
5001 			? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl;
5002 		DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl));
5003 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
5004 			((uint8)mesbusyctrl | 0x80), NULL);
5005 		break;
5006 #endif /* define(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL) */
5007 
5008 #ifdef BCMINTERNAL
5009 	case IOV_GVAL(IOV_FIRSTREAD):
5010 		int_val = (int32)firstread;
5011 		bcopy(&int_val, arg, val_size);
5012 		break;
5013 
5014 	case IOV_SVAL(IOV_FIRSTREAD):
5015 		if ((int_val < 12) || (int_val > 32)) {
5016 			bcmerror = BCME_BADARG;
5017 			break;
5018 		}
5019 		firstread = (uint)int_val;
5020 		break;
5021 
5022 	case IOV_GVAL(IOV_TSTOPH):
5023 		int_val = tstoph;
5024 		bcopy(&int_val, arg, val_size);
5025 		break;
5026 
5027 	case IOV_SVAL(IOV_TSTOPH):
5028 		if (tstoph && bus->dhd->busstate == DHD_BUS_DOWN) {
5029 			tstoph = bool_val;
5030 			bus->dhd->busstate = DHD_BUS_DATA;
5031 			if (bus->intr) {
5032 				bus->intdis = FALSE;
5033 				bcmsdh_intr_enable(bus->sdh);
5034 			}
5035 		} else {
5036 			tstoph = bool_val;
5037 		}
5038 		break;
5039 
5040 	case IOV_GVAL(IOV_RETRYDATA):
5041 		int_val = (int32)retrydata;
5042 		bcopy(&int_val, arg, val_size);
5043 		break;
5044 
5045 	case IOV_SVAL(IOV_RETRYDATA):
5046 		retrydata = bool_val;
5047 		break;
5048 
5049 	case IOV_GVAL(IOV_CHECKFIFO):
5050 		int_val = (int32)checkfifo;
5051 		bcopy(&int_val, arg, val_size);
5052 		break;
5053 
5054 	case IOV_SVAL(IOV_CHECKFIFO):
5055 		checkfifo = bool_val;
5056 		break;
5057 
5058 	case IOV_GVAL(IOV_SDF2):
5059 	case IOV_SVAL(IOV_SDF2):
5060 	{
5061 		uint8 *buf;
5062 		int ret = BCME_OK;
5063 
5064 		if (!(buf = MALLOC(bus->dhd->osh, int_val))) {
5065 			bcmerror = BCME_NOMEM;
5066 			break;
5067 		}
5068 
5069 		if (actionid == IOV_SVAL(IOV_SDF2)) {
5070 			ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
5071 				F2SYNC, buf, int_val, NULL, NULL, NULL, 1);
5072 		} else {
5073 			ret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
5074 				F2SYNC, buf, int_val, NULL, NULL, NULL);
5075 		}
5076 		if (ret != BCME_OK) {
5077 			bcmerror = BCME_SDIO_ERROR;
5078 		}
5079 
5080 		MFREE(bus->dhd->osh, buf, int_val);
5081 
5082 		break;
5083 	}
5084 
5085 	case IOV_SVAL(IOV_CPU):
5086 		/* Go to the ARM core */
5087 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5088 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5089 			DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5090 			bcmerror = BCME_ERROR;
5091 			break;
5092 		}
5093 
5094 		/* Take the request action */
5095 		if (bool_val)
5096 			si_core_reset(bus->sih, 0, 0);
5097 		else
5098 			si_core_disable(bus->sih, 0);
5099 
5100 		if (bcmsdh_regfail(bus->sdh))
5101 			bcmerror = BCME_SDIO_ERROR;
5102 
5103 		/* Return to the SDIO core */
5104 		if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
5105 			si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5106 		break;
5107 
5108 	case IOV_GVAL(IOV_CPU):
5109 		/* Go to the ARM core */
5110 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5111 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5112 			DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5113 			bcmerror = BCME_ERROR;
5114 			break;
5115 		}
5116 
5117 		/* Get its status */
5118 		int_val = (int32)si_iscoreup(bus->sih);
5119 		bcopy(&int_val, arg, val_size);
5120 
5121 		/* Return to the SDIO core */
5122 		if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
5123 			si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5124 		break;
5125 
5126 	case IOV_SVAL(IOV_SDRESET):
5127 		bcmsdh_reset(bus->sdh);
5128 		break;
5129 
5130 	case IOV_SVAL(IOV_SDABORT):
5131 		if (int_val == 1 || int_val == 2)
5132 			bcmsdh_abort(bus->sdh, int_val);
5133 		else
5134 			bcmerror = BCME_BADARG;
5135 		break;
5136 
5137 	case IOV_GVAL(IOV_DOFLOW):
5138 		int_val = (int32)dhd_doflow;
5139 		bcopy(&int_val, arg, val_size);
5140 		break;
5141 
5142 	case IOV_SVAL(IOV_DOFLOW):
5143 		dhd_doflow = bool_val;
5144 		/* De flowcontrol if turning off flowcontrol */
5145 		if (!dhd_doflow)
5146 			dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
5147 		break;
5148 
5149 	case IOV_GVAL(IOV_CLOCKPOLL):
5150 		int_val = (int32)bus->clockpoll;
5151 		bcopy(&int_val, arg, val_size);
5152 		break;
5153 
5154 	case IOV_GVAL(IOV_MAXRAMSIZE):
5155 		int_val = (int32)bus->ramsize;
5156 		bcopy(&int_val, arg, val_size);
5157 		break;
5158 
5159 	case IOV_SVAL(IOV_MAXRAMSIZE):
5160 		dhd_dongle_ramsize = int_val;
5161 		dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
5162 		break;
5163 
5164 	case IOV_SVAL(IOV_CLOCKPOLL):
5165 		bus->clockpoll = bool_val;
5166 		break;
5167 #endif /* BCMINTERNAL */
5168 
5169 	case IOV_GVAL(IOV_DONGLEISOLATION):
5170 		int_val = bus->dhd->dongle_isolation;
5171 		bcopy(&int_val, arg, val_size);
5172 		break;
5173 
5174 	case IOV_SVAL(IOV_DONGLEISOLATION):
5175 		bus->dhd->dongle_isolation = bool_val;
5176 		break;
5177 
5178 	case IOV_SVAL(IOV_DEVRESET):
5179 		DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
5180 		           __FUNCTION__, bool_val, bus->dhd->dongle_reset,
5181 		           bus->dhd->busstate));
5182 
5183 		ASSERT(bus->dhd->osh);
5184 		/* ASSERT(bus->cl_devid); */
5185 
5186 		/* must release sdlock, since devreset also acquires it */
5187 		dhd_os_sdunlock(bus->dhd);
5188 		dhd_bus_devreset(bus->dhd, (uint8)bool_val);
5189 		dhd_os_sdlock(bus->dhd);
5190 		break;
5191 	/*
5192 	 * softap firmware is updated through module parameter or android private command
5193 	 */
5194 
5195 	case IOV_GVAL(IOV_DEVRESET):
5196 		DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
5197 
5198 		/* Get its status */
5199 		int_val = (bool) bus->dhd->dongle_reset;
5200 		bcopy(&int_val, arg, val_size);
5201 
5202 		break;
5203 
5204 	case IOV_GVAL(IOV_KSO):
5205 		int_val = dhdsdio_sleepcsr_get(bus);
5206 		bcopy(&int_val, arg, val_size);
5207 		break;
5208 
5209 	case IOV_GVAL(IOV_DEVCAP):
5210 		int_val = dhdsdio_devcap_get(bus);
5211 		bcopy(&int_val, arg, val_size);
5212 		break;
5213 
5214 	case IOV_SVAL(IOV_DEVCAP):
5215 		dhdsdio_devcap_set(bus, (uint8) int_val);
5216 		break;
5217 	case IOV_GVAL(IOV_TXGLOMSIZE):
5218 		int_val = (int32)bus->txglomsize;
5219 		bcopy(&int_val, arg, val_size);
5220 		break;
5221 
5222 	case IOV_SVAL(IOV_TXGLOMSIZE):
5223 		if (int_val > SDPCM_MAXGLOM_SIZE) {
5224 			bcmerror = BCME_ERROR;
5225 		} else {
5226 			bus->txglomsize = (uint)int_val;
5227 		}
5228 		break;
5229 	case IOV_SVAL(IOV_HANGREPORT):
5230 		bus->dhd->hang_report = bool_val;
5231 		DHD_ERROR(("%s: Set hang_report as %d\n", __FUNCTION__, bus->dhd->hang_report));
5232 		break;
5233 
5234 	case IOV_GVAL(IOV_HANGREPORT):
5235 		int_val = (int32)bus->dhd->hang_report;
5236 		bcopy(&int_val, arg, val_size);
5237 		break;
5238 
5239 	case IOV_GVAL(IOV_TXINRX_THRES):
5240 		int_val = bus->txinrx_thres;
5241 		bcopy(&int_val, arg, val_size);
5242 		break;
5243 	case IOV_SVAL(IOV_TXINRX_THRES):
5244 		if (int_val < 0) {
5245 			bcmerror = BCME_BADARG;
5246 		} else {
5247 			bus->txinrx_thres = int_val;
5248 		}
5249 		break;
5250 
5251 	case IOV_GVAL(IOV_SDIO_SUSPEND):
5252 		int_val = (bus->dhd->busstate == DHD_BUS_SUSPEND) ? 1 : 0;
5253 		bcopy(&int_val, arg, val_size);
5254 		break;
5255 
5256 	case IOV_SVAL(IOV_SDIO_SUSPEND):
5257 		if (bool_val) { /* Suspend */
5258 			dhdsdio_suspend(bus);
5259 		}
5260 		else { /* Resume */
5261 			dhdsdio_resume(bus);
5262 		}
5263 		break;
5264 
5265 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
5266 	case IOV_SVAL(IOV_GDB_SERVER):
5267 		if (bool_val == TRUE) {
5268 			debugger_init((void *) bus, &bus_ops, int_val, SI_ENUM_BASE(bus->sih));
5269 		} else {
5270 			debugger_close();
5271 		}
5272 		break;
5273 #endif /* DEBUGGER || DHD_DSCOPE */
5274 
5275 	default:
5276 		bcmerror = BCME_UNSUPPORTED;
5277 		break;
5278 	}
5279 
5280 exit:
5281 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
5282 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
5283 		bus->activity = FALSE;
5284 		dhdsdio_bussleep(bus, TRUE);
5285 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
5286 	}
5287 
5288 	dhd_os_sdunlock(bus->dhd);
5289 
5290 	return bcmerror;
5291 }
5292 
5293 static int
dhdsdio_write_vars(dhd_bus_t * bus)5294 dhdsdio_write_vars(dhd_bus_t *bus)
5295 {
5296 	int bcmerror = 0;
5297 	uint32 varsize, phys_size;
5298 	uint32 varaddr;
5299 	uint8 *vbuffer;
5300 	uint32 varsizew;
5301 #ifdef DHD_DEBUG
5302 	uint8 *nvram_ularray;
5303 #endif /* DHD_DEBUG */
5304 
5305 	/* Even if there are no vars are to be written, we still need to set the ramsize. */
5306 	varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
5307 	varaddr = (bus->ramsize - 4) - varsize;
5308 
5309 	// terence 20150412: fix for nvram failed to download
5310 	if (bus->dhd->conf->chip == BCM43340_CHIP_ID ||
5311 			bus->dhd->conf->chip == BCM43341_CHIP_ID) {
5312 		varsize = varsize ? ROUNDUP(varsize, 64) : 0;
5313 		varaddr = (bus->ramsize - 64) - varsize;
5314 	}
5315 
5316 	varaddr += bus->dongle_ram_base;
5317 
5318 	if (bus->vars) {
5319 		/* XXX: WAR for PR85623 */
5320 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 7)) {
5321 			if (((varaddr & 0x3C) == 0x3C) && (varsize > 4)) {
5322 				DHD_ERROR(("PR85623WAR in place\n"));
5323 				varsize += 4;
5324 				varaddr -= 4;
5325 			}
5326 		}
5327 
5328 		/* XXX In case the controller has trouble with odd bytes... */
5329 		vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
5330 		if (!vbuffer)
5331 			return BCME_NOMEM;
5332 
5333 		bzero(vbuffer, varsize);
5334 		bcopy(bus->vars, vbuffer, bus->varsz);
5335 
5336 		/* Write the vars list */
5337 		bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize);
5338 		if (bcmerror) {
5339 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
5340 				__FUNCTION__, bcmerror, varsize, varaddr));
5341 			return bcmerror;
5342 		}
5343 
5344 #ifdef DHD_DEBUG
5345 		/* Verify NVRAM bytes */
5346 		DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
5347 		nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
5348 		if (!nvram_ularray) {
5349 			MFREE(bus->dhd->osh, vbuffer, varsize);
5350 			return BCME_NOMEM;
5351 		}
5352 
5353 		/* Upload image to verify downloaded contents. */
5354 		memset(nvram_ularray, 0xaa, varsize);
5355 
5356 		/* Read the vars list to temp buffer for comparison */
5357 		bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
5358 		if (bcmerror) {
5359 				DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
5360 					__FUNCTION__, bcmerror, varsize, varaddr));
5361 		}
5362 		/* Compare the org NVRAM with the one read from RAM */
5363 		if (memcmp(vbuffer, nvram_ularray, varsize)) {
5364 			DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
5365 		} else
5366 			DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
5367 			__FUNCTION__));
5368 
5369 		MFREE(bus->dhd->osh, nvram_ularray, varsize);
5370 #endif /* DHD_DEBUG */
5371 
5372 		MFREE(bus->dhd->osh, vbuffer, varsize);
5373 	}
5374 
5375 #ifdef MINIME
5376 	phys_size = bus->ramsize;
5377 #else
5378 	phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
5379 #endif
5380 
5381 	phys_size += bus->dongle_ram_base;
5382 
5383 	/* adjust to the user specified RAM */
5384 	DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
5385 		phys_size, bus->ramsize));
5386 	DHD_INFO(("Vars are at %d, orig varsize is %d\n",
5387 		varaddr, varsize));
5388 	varsize = ((phys_size - 4) - varaddr);
5389 
5390 	/*
5391 	 * Determine the length token:
5392 	 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
5393 	 */
5394 #ifdef DHD_DEBUG
5395 	if (bcmerror) {
5396 		varsizew = 0;
5397 	} else
5398 #endif /* DHD_DEBUG */
5399 	{
5400 		varsizew = varsize / 4;
5401 		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
5402 		varsizew = htol32(varsizew);
5403 	}
5404 
5405 	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
5406 
5407 	/* Write the length token to the last word */
5408 	bcmerror = dhdsdio_membytes(bus, TRUE, (phys_size - 4),
5409 		(uint8*)&varsizew, 4);
5410 
5411 	return bcmerror;
5412 }
5413 
5414 bool
dhd_bus_is_multibp_capable(struct dhd_bus * bus)5415 dhd_bus_is_multibp_capable(struct dhd_bus *bus)
5416 {
5417 	return MULTIBP_CAP(bus->sih);
5418 }
5419 
5420 static int
dhdsdio_download_state(dhd_bus_t * bus,bool enter)5421 dhdsdio_download_state(dhd_bus_t *bus, bool enter)
5422 {
5423 	uint retries;
5424 	int bcmerror = 0;
5425 	int foundcr4 = 0;
5426 
5427 	if (!bus->sih)
5428 		return BCME_ERROR;
5429 	/* To enter download state, disable ARM and reset SOCRAM.
5430 	 * To exit download state, simply reset ARM (default is RAM boot).
5431 	 */
5432 	if (enter) {
5433 		bus->alp_only = TRUE;
5434 
5435 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5436 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5437 			if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
5438 				foundcr4 = 1;
5439 			} else {
5440 				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5441 				bcmerror = BCME_ERROR;
5442 				goto fail;
5443 			}
5444 		}
5445 
5446 		if (!foundcr4) {
5447 			si_core_disable(bus->sih, 0);
5448 			if (bcmsdh_regfail(bus->sdh)) {
5449 				bcmerror = BCME_SDIO_ERROR;
5450 				goto fail;
5451 			}
5452 
5453 			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
5454 				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
5455 				bcmerror = BCME_ERROR;
5456 				goto fail;
5457 			}
5458 
5459 			si_core_reset(bus->sih, 0, 0);
5460 			if (bcmsdh_regfail(bus->sdh)) {
5461 				DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n",
5462 				           __FUNCTION__));
5463 				bcmerror = BCME_SDIO_ERROR;
5464 				goto fail;
5465 			}
5466 
5467 			if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
5468 				CHIPID(bus->sih->chip) == BCM43018_CHIP_ID) {
5469 				/* Disabling Remap for SRAM_3 */
5470 				si_socram_set_bankpda(bus->sih, 0x3, 0x0);
5471 			}
5472 
5473 			/* Clear the top bit of memory */
5474 			if (bus->ramsize) {
5475 				uint32 zeros = 0;
5476 				if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4,
5477 				                     (uint8*)&zeros, 4) < 0) {
5478 					bcmerror = BCME_SDIO_ERROR;
5479 					goto fail;
5480 				}
5481 			}
5482 		} else {
5483 			/* For CR4,
5484 			 * Halt ARM
5485 			 * Remove ARM reset
5486 			 * Read RAM base address [0x18_0000]
5487 			 * [next] Download firmware
5488 			 * [done at else] Populate the reset vector
5489 			 * [done at else] Remove ARM halt
5490 			*/
5491 			/* Halt ARM & remove reset */
5492 			si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
5493 		}
5494 	} else {
5495 		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
5496 			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
5497 				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
5498 				bcmerror = BCME_ERROR;
5499 				goto fail;
5500 			}
5501 
5502 			if (!si_iscoreup(bus->sih)) {
5503 				DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
5504 				bcmerror = BCME_ERROR;
5505 				goto fail;
5506 			}
5507 
5508 			if ((bcmerror = dhdsdio_write_vars(bus))) {
5509 				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
5510 				goto fail;
5511 			}
5512 
5513 #ifdef BCMSDIOLITE
5514 			if (!si_setcore(bus->sih, CC_CORE_ID, 0)) {
5515 				DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__));
5516 				bcmerror = BCME_ERROR;
5517 				goto fail;
5518 			}
5519 #else
5520 			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
5521 			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
5522 				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
5523 				bcmerror = BCME_ERROR;
5524 				goto fail;
5525 			}
5526 #endif
5527 			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
5528 
5529 			/* XXX Change standby configuration here if necessary */
5530 
5531 			if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5532 			    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5533 				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5534 				bcmerror = BCME_ERROR;
5535 				goto fail;
5536 			}
5537 		} else {
5538 			/* cr4 has no socram, but tcm's */
5539 			/* write vars */
5540 			if ((bcmerror = dhdsdio_write_vars(bus))) {
5541 				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
5542 				goto fail;
5543 			}
5544 #ifdef BCMSDIOLITE
5545 			if (!si_setcore(bus->sih, CC_CORE_ID, 0)) {
5546 				DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__));
5547 				bcmerror = BCME_ERROR;
5548 				goto fail;
5549 			}
5550 #else
5551 			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
5552 			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
5553 				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
5554 				bcmerror = BCME_ERROR;
5555 				goto fail;
5556 			}
5557 #endif
5558 			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
5559 
5560 			/* switch back to arm core again */
5561 			if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
5562 				DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
5563 				bcmerror = BCME_ERROR;
5564 				goto fail;
5565 			}
5566 			/* write address 0 with reset instruction */
5567 			bcmerror = dhdsdio_membytes(bus, TRUE, 0,
5568 				(uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
5569 
5570 			if (bcmerror == BCME_OK) {
5571 				uint32 tmp;
5572 
5573 				/* verify write */
5574 				bcmerror = dhdsdio_membytes(bus, FALSE, 0,
5575 				                            (uint8 *)&tmp, sizeof(tmp));
5576 
5577 				if (bcmerror == BCME_OK && tmp != bus->resetinstr) {
5578 					DHD_ERROR(("%s: Failed to write 0x%08x to addr 0\n",
5579 					          __FUNCTION__, bus->resetinstr));
5580 					DHD_ERROR(("%s: contents of addr 0 is 0x%08x\n",
5581 					          __FUNCTION__, tmp));
5582 					bcmerror = BCME_SDIO_ERROR;
5583 					goto fail;
5584 				}
5585 			}
5586 
5587 			/* now remove reset and halt and continue to run CR4 */
5588 		}
5589 
5590 		si_core_reset(bus->sih, 0, 0);
5591 		if (bcmsdh_regfail(bus->sdh)) {
5592 			DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
5593 			bcmerror = BCME_SDIO_ERROR;
5594 			goto fail;
5595 		}
5596 
5597 		/* Allow HT Clock now that the ARM is running. */
5598 		bus->alp_only = FALSE;
5599 
5600 		bus->dhd->busstate = DHD_BUS_LOAD;
5601 	}
5602 
5603 fail:
5604 	/* Always return to SDIOD core */
5605 	if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
5606 		si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5607 
5608 	return bcmerror;
5609 }
5610 
5611 int
dhd_bus_iovar_op(dhd_pub_t * dhdp,const char * name,void * params,uint plen,void * arg,uint len,bool set)5612 dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
5613                  void *params, uint plen, void *arg, uint len, bool set)
5614 {
5615 	dhd_bus_t *bus = dhdp->bus;
5616 	const bcm_iovar_t *vi = NULL;
5617 	int bcmerror = 0;
5618 	uint val_size;
5619 	uint32 actionid;
5620 
5621 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5622 
5623 	ASSERT(name);
5624 
5625 	/* Get MUST have return space */
5626 	ASSERT(set || (arg && len));
5627 
5628 	/* Set does NOT take qualifiers */
5629 	ASSERT(!set || (!params && !plen));
5630 
5631 	/* Look up var locally; if not found pass to host driver */
5632 	if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
5633 		dhd_os_sdlock(bus->dhd);
5634 
5635 		BUS_WAKE(bus);
5636 
5637 		/* Turn on clock in case SD command needs backplane */
5638 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5639 
5640 		bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
5641 
5642 		/* Check for bus configuration changes of interest */
5643 
5644 		/* If it was divisor change, read the new one */
5645 		if (set && strcmp(name, "sd_divisor") == 0) {
5646 			if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
5647 			                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
5648 				bus->sd_divisor = -1;
5649 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
5650 			} else {
5651 				DHD_INFO(("%s: noted %s update, value now %d\n",
5652 				          __FUNCTION__, name, bus->sd_divisor));
5653 			}
5654 		}
5655 		/* If it was a mode change, read the new one */
5656 		if (set && strcmp(name, "sd_mode") == 0) {
5657 			if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
5658 			                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
5659 				bus->sd_mode = -1;
5660 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
5661 			} else {
5662 				DHD_INFO(("%s: noted %s update, value now %d\n",
5663 				          __FUNCTION__, name, bus->sd_mode));
5664 			}
5665 		}
5666 		/* Similar check for blocksize change */
5667 		if (set && strcmp(name, "sd_blocksize") == 0) {
5668 			int32 fnum = 2;
5669 			if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
5670 			                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
5671 				bus->blocksize = 0;
5672 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
5673 			} else {
5674 				DHD_INFO(("%s: noted %s update, value now %d\n",
5675 				          __FUNCTION__, "sd_blocksize", bus->blocksize));
5676 
5677 				dhdsdio_tune_fifoparam(bus);
5678 			}
5679 		}
5680 		bus->roundup = MIN(max_roundup, bus->blocksize);
5681 
5682 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
5683 			NO_OTHER_ACTIVE_BUS_USER(bus)) {
5684 			bus->activity = FALSE;
5685 			dhdsdio_bussleep(bus, TRUE);
5686 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
5687 		}
5688 
5689 		dhd_os_sdunlock(bus->dhd);
5690 		goto exit;
5691 	}
5692 
5693 	DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
5694 	         name, (set ? "set" : "get"), len, plen));
5695 
5696 	/* set up 'params' pointer in case this is a set command so that
5697 	 * the convenience int and bool code can be common to set and get
5698 	 */
5699 	if (params == NULL) {
5700 		params = arg;
5701 		plen = len;
5702 	}
5703 
5704 	if (vi->type == IOVT_VOID)
5705 		val_size = 0;
5706 	else if (vi->type == IOVT_BUFFER)
5707 		val_size = len;
5708 	else
5709 		/* all other types are integer sized */
5710 		val_size = sizeof(int);
5711 
5712 	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
5713 	bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
5714 
5715 exit:
5716 	return bcmerror;
5717 }
5718 
5719 void
dhd_bus_stop(struct dhd_bus * bus,bool enforce_mutex)5720 dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
5721 {
5722 	osl_t *osh;
5723 	uint32 local_hostintmask;
5724 	uint8 saveclk;
5725 	uint retries;
5726 	int err;
5727 	bool wlfc_enabled = FALSE;
5728 	unsigned long flags;
5729 
5730 	if (!bus->dhd)
5731 		return;
5732 
5733 	osh = bus->dhd->osh;
5734 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5735 
5736 	bcmsdh_waitlockfree(bus->sdh);
5737 
5738 	if (enforce_mutex)
5739 		dhd_os_sdlock(bus->dhd);
5740 
5741 	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) {
5742 		/* if Firmware already hangs disbale any interrupt */
5743 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
5744 		bus->dhd->busstate = DHD_BUS_DOWN;
5745 		bus->hostintmask = 0;
5746 		bcmsdh_intr_disable(bus->sdh);
5747 	} else {
5748 
5749 		BUS_WAKE(bus);
5750 
5751 		if (KSO_ENAB(bus)) {
5752 
5753 		/* Enable clock for device interrupts */
5754 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5755 
5756 		/* Disable and clear interrupts at the chip level also */
5757 		W_SDREG(0, &bus->regs->hostintmask, retries);
5758 		local_hostintmask = bus->hostintmask;
5759 		bus->hostintmask = 0;
5760 
5761 		/* Force clocks on backplane to be sure F2 interrupt propagates */
5762 		saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
5763 		if (!err) {
5764 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5765 			                 (saveclk | SBSDIO_FORCE_HT), &err);
5766 		}
5767 		if (err) {
5768 			DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
5769 			            __FUNCTION__, err));
5770 		}
5771 
5772 		/* Turn off the bus (F2), free any pending packets */
5773 		/* XXX How to wake up any waiting processes? */
5774 		/* XXX New API: bcmsdh_fn_set(bus->sdh, SDIO_FUNC_2, FALSE); */
5775 		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
5776 #if !defined(NDIS)
5777 		bcmsdh_intr_disable(bus->sdh); /* XXX bcmsdh_intr_mask(bus->sdh); */
5778 #endif /* !defined(NDIS) */
5779 #ifndef BCMSPI
5780 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
5781 #endif /* !BCMSPI */
5782 
5783 		/* Clear any pending interrupts now that F2 is disabled */
5784 		W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
5785 		}
5786 
5787 		/* Turn off the backplane clock (only) */
5788 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
5789 
5790 		/* Change our idea of bus state */
5791 		DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
5792 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
5793 		bus->dhd->busstate = DHD_BUS_DOWN;
5794 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
5795 	}
5796 
5797 #ifdef PROP_TXSTATUS
5798 	wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED);
5799 #endif
5800 	if (!wlfc_enabled) {
5801 #ifdef DHDTCPACK_SUPPRESS
5802 		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
5803 		 * when there is a newly coming packet from network stack.
5804 		 */
5805 		dhd_tcpack_info_tbl_clean(bus->dhd);
5806 #endif /* DHDTCPACK_SUPPRESS */
5807 		dhd_os_sdlock_txq(bus->dhd);
5808 		/* Clear the data packet queues */
5809 		pktq_flush(osh, &bus->txq, TRUE);
5810 		dhd_os_sdunlock_txq(bus->dhd);
5811 	}
5812 
5813 	/* Clear any held glomming stuff */
5814 	if (bus->glomd)
5815 		PKTFREE(osh, bus->glomd, FALSE);
5816 
5817 	if (bus->glom)
5818 		PKTFREE(osh, bus->glom, FALSE);
5819 
5820 	bus->glom = bus->glomd = NULL;
5821 
5822 	/* Clear rx control and wake any waiters */
5823 	/* XXX More important in disconnect, but no context? */
5824 	bus->rxlen = 0;
5825 	dhd_os_ioctl_resp_wake(bus->dhd);
5826 
5827 	/* Reset some F2 state stuff */
5828 	bus->rxskip = FALSE;
5829 	bus->tx_seq = bus->rx_seq = 0;
5830 
5831 	/* Initializing tx_max to a reasonable value to start xfer
5832 	 * Gets updated to correct value after receving the first
5833 	 * packet from firmware
5834 	 * XXX - Need to find a right mechanism to querry from
5835 	 * firmware when the device is coming up
5836 	 */
5837 	bus->tx_max = 4;
5838 
5839 	if (enforce_mutex)
5840 		dhd_os_sdunlock(bus->dhd);
5841 }
5842 
5843 #if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD)
5844 extern uint sd_txglom;
5845 #endif
5846 void
dhd_txglom_enable(dhd_pub_t * dhdp,bool enable)5847 dhd_txglom_enable(dhd_pub_t *dhdp, bool enable)
5848 {
5849 	/* can't enable host txglom by default, some platforms have no
5850 	 * (or crappy) ADMA support and txglom will cause kernel assertions (e.g.
5851 	 * panda board)
5852 	 */
5853 	dhd_bus_t *bus = dhdp->bus;
5854 #ifdef BCMSDIOH_TXGLOM
5855 	uint32 rxglom;
5856 	int32 ret;
5857 
5858 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5859 
5860 #ifdef BCMSDIOH_STD
5861 	if (enable)
5862 		enable = sd_txglom;
5863 #endif /* BCMSDIOH_STD */
5864 
5865 	if (enable) {
5866 		rxglom = 1;
5867 		ret = dhd_iovar(dhdp, 0, "bus:rxglom", (char *)&rxglom, sizeof(rxglom), NULL, 0,
5868 				TRUE);
5869 		if (ret >= 0)
5870 			bus->txglom_enable = TRUE;
5871 		else {
5872 #ifdef BCMSDIOH_STD
5873 			sd_txglom = 0;
5874 #endif /* BCMSDIOH_STD */
5875 			bus->txglom_enable = FALSE;
5876 		}
5877 	} else
5878 #endif /* BCMSDIOH_TXGLOM */
5879 		bus->txglom_enable = FALSE;
5880 	printf("%s: enable %d\n",  __FUNCTION__, bus->txglom_enable);
5881 	dhd_conf_set_txglom_params(bus->dhd, bus->txglom_enable);
5882 	bcmsdh_set_mode(bus->sdh, bus->dhd->conf->txglom_mode);
5883 }
5884 
5885 int
dhd_bus_init(dhd_pub_t * dhdp,bool enforce_mutex)5886 dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
5887 {
5888 	dhd_bus_t *bus = dhdp->bus;
5889 	dhd_timeout_t tmo;
5890 	uint retries = 0;
5891 	uint8 ready, enable;
5892 	int err, ret = 0;
5893 #ifdef BCMSPI
5894 	uint32 dstatus = 0;	/* gSPI device-status bits */
5895 #else /* BCMSPI */
5896 	uint8 saveclk;
5897 #endif /* BCMSPI */
5898 #if defined(SDIO_ISR_THREAD)
5899 	int intr_extn;
5900 #endif
5901 
5902 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5903 
5904 	ASSERT(bus->dhd);
5905 	if (!bus->dhd)
5906 		return 0;
5907 
5908 	if (enforce_mutex)
5909 		dhd_os_sdlock(bus->dhd);
5910 
5911 	if (bus->sih->chip == BCM43362_CHIP_ID) {
5912 		printf("%s: delay 100ms for BCM43362\n", __FUNCTION__);
5913 		OSL_DELAY(100000); // terence 20131209: delay for 43362
5914 	}
5915 
5916 	/* Make sure backplane clock is on, needed to generate F2 interrupt */
5917 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5918 	if (bus->clkstate != CLK_AVAIL) {
5919 		DHD_ERROR(("%s: clock state is wrong. state = %d\n", __FUNCTION__, bus->clkstate));
5920 		ret = -1;
5921 		goto exit;
5922 	}
5923 
5924 #ifdef BCMSPI
5925 	/* fake "ready" for spi, wake-wlan would have already enabled F1 and F2 */
5926 	ready = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
5927 	enable = 0;
5928 
5929 	/* Give the dongle some time to do its thing and set IOR2 */
5930 	dhd_timeout_start(&tmo, WAIT_F2RXFIFORDY * WAIT_F2RXFIFORDY_DELAY * 1000);
5931 	while (!enable && !dhd_timeout_expired(&tmo)) {
5932 		dstatus = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL);
5933 		if (dstatus & STATUS_F2_RX_READY)
5934 			enable = TRUE;
5935 	}
5936 
5937 	if (enable) {
5938 		DHD_ERROR(("Took %u usec before dongle is ready\n", tmo.elapsed));
5939 		enable = ready;
5940 	} else {
5941 		DHD_ERROR(("dstatus when timed out on f2-fifo not ready = 0x%x\n", dstatus));
5942 		DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed));
5943 		ret = -1;
5944 		goto exit;
5945 	}
5946 
5947 #else /* !BCMSPI */
5948 	/* Force clocks on backplane to be sure F2 interrupt propagates */
5949 	saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
5950 
5951 	if (!err) {
5952 #ifndef BCMQT
5953 		/* QT requires HT clock */
5954 		if (bus->sih->chip == BCM43012_CHIP_ID ||
5955 			bus->sih->chip == BCM43013_CHIP_ID ||
5956 			bus->sih->chip == BCM43014_CHIP_ID) {
5957 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5958 				(saveclk | SBSDIO_HT_AVAIL_REQ), &err);
5959 		} else
5960 #endif /* BCMQT */
5961 		{
5962 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5963 				(saveclk | SBSDIO_FORCE_HT), &err);
5964 		}
5965 	}
5966 
5967 	if (err) {
5968 		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
5969 		ret = -1;
5970 		goto exit;
5971 	}
5972 
5973 	/* Enable function 2 (frame transfers) */
5974 	/* XXX New API: change to bcmsdh_fn_set(sdh, SDIO_FUNC_2, TRUE); */
5975 	W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
5976 	        &bus->regs->tosbmailboxdata, retries);
5977 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
5978 
5979 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
5980 
5981 	/* Give the dongle some time to do its thing and set IOR2 */
5982 #ifdef BCMSLTGT
5983 	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000 * htclkratio);
5984 #else
5985 	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
5986 #endif /* BCMSLTGT */
5987 
5988 	ready = 0;
5989 	while (ready != enable && !dhd_timeout_expired(&tmo))
5990 	        ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
5991 
5992 #endif /* !BCMSPI */
5993 
5994 	DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
5995 	          __FUNCTION__, enable, ready, tmo.elapsed));
5996 
5997 #if defined(SDIO_ISR_THREAD)
5998 	if (dhdp->conf->intr_extn) {
5999 		intr_extn = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTR_EXTN, NULL);
6000 		if (intr_extn & 0x1) {
6001 			intr_extn |= 0x2;
6002 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTR_EXTN, intr_extn, NULL);
6003 		}
6004 	}
6005 #endif
6006 
6007 	/* XXX For simplicity, fail and await next call if F2 not ready.
6008 	 * XXX Should really set timer to poll, and/or enable interrupt;
6009 	 * XXX then put this process in wait until a result...
6010 	 */
6011 
6012 	/* If F2 successfully enabled, set core and enable interrupts */
6013 	if (ready == enable) {
6014 		/* Make sure we're talking to the core. */
6015 #ifdef BCMSDIOLITE
6016 		bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0);
6017 		ASSERT(bus->regs != NULL);
6018 #else
6019 		if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
6020 			bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
6021 		ASSERT(bus->regs != NULL);
6022 #endif
6023 		/* Set up the interrupt mask and enable interrupts */
6024 		bus->hostintmask = HOSTINTMASK;
6025 		/* corerev 4 could use the newer interrupt logic to detect the frames */
6026 #ifndef BCMSPI
6027 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) &&
6028 			(bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) {
6029 			bus->hostintmask &= ~I_HMB_FRAME_IND;
6030 			bus->hostintmask |= I_XMTDATA_AVAIL;
6031 		}
6032 #endif /* BCMSPI */
6033 		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
6034 
6035 		/* PR47410 - Lower F2 Watermark to avoid DMA Hang
6036 		 * in F2 when SD Clock is stopped.
6037 		 */
6038 		if (bus->sih->buscorerev < 15) {
6039 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
6040 				(uint8)watermark, &err);
6041 		}
6042 
6043 		/* Set bus state according to enable result */
6044 		dhdp->busstate = DHD_BUS_DATA;
6045 
6046 		/* Need to set fn2 block size to match fn1 block size.
6047 		 * Requests to fn2 go thru fn1. *
6048 		 * faltwig has this code contitioned with #if !BCMSPI_ANDROID.
6049 		 * It would be cleaner to use the ->sdh->block_sz[fno] instead of
6050 		 * 64, but this layer has no access to sdh types.
6051 		 */
6052 #if defined(NDIS)
6053 	{
6054 		uint8 *ptr = NULL;
6055 		uint16 block_sz = 64;
6056 		ptr = (uint8*) &block_sz;
6057 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0,
6058 			(SDIOD_FBR_BASE(SDIO_FUNC_2) + SDIOD_CCCR_BLKSIZE_0),
6059 			*ptr++, &err);
6060 		if (err == BCME_OK)
6061 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0,
6062 			(SDIOD_FBR_BASE(SDIO_FUNC_2) + SDIOD_CCCR_BLKSIZE_1),
6063 			*ptr++, &err);
6064 		if (err != BCME_OK) {
6065 			printf("%s: set block size for func 2 failed\n",
6066 				__FUNCTION__);
6067 			ret = -1;
6068 			goto exit;
6069 		}
6070 	}
6071 #endif /* NDIS */
6072 
6073 		/* XXX These need to change w/API updates */
6074 		/* bcmsdh_intr_unmask(bus->sdh); */
6075 
6076 		bus->intdis = FALSE;
6077 		if (bus->intr) {
6078 			DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
6079 #ifndef BCMSPI_ANDROID
6080 			bcmsdh_intr_enable(bus->sdh);
6081 #endif /* !BCMSPI_ANDROID */
6082 		} else {
6083 			DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
6084 			bcmsdh_intr_disable(bus->sdh);
6085 		}
6086 
6087 #ifdef DEBUG_LOST_INTERRUPTS
6088 		{
6089 			uint32 intstatus;
6090 			bool hostpending;
6091 			uint8 devena, devpend;
6092 			uint sdr_retries = 0;
6093 
6094 			hostpending = bcmsdh_intr_pending(bus->sdh);
6095 			devena = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL);
6096 			devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTPEND, NULL);
6097 
6098 			R_SDREG(intstatus, &bus->regs->intstatus, sdr_retries);
6099 			intstatus &= bus->hostintmask;
6100 
6101 			DHD_ERROR(("%s: interrupts -- host %s device ena/pend 0x%02x/0x%02x\n"
6102 			           "intstatus 0x%08x, hostmask 0x%08x\n", __FUNCTION__,
6103 			           (hostpending ? "PENDING" : "NOT PENDING"),
6104 			           devena, devpend, intstatus, bus->hostintmask));
6105 		}
6106 #endif /* DEBUG_LOST_INTERRUPTS */
6107 	}
6108 
6109 #ifndef BCMSPI
6110 
6111 	else {
6112 		if (dhdp->conf->chip == BCM4354_CHIP_ID) {
6113 			ret = -1;
6114 			goto exit;
6115 		}
6116 		/* Disable F2 again */
6117 		enable = SDIO_FUNC_ENABLE_1;
6118 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
6119 	}
6120 
6121 	if (dhdsdio_sr_cap(bus)) {
6122 		dhdsdio_sr_init(bus);
6123 		/* Masking the chip active interrupt  permanantly */
6124 		bus->hostintmask &= ~I_CHIPACTIVE;
6125 		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
6126 		DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
6127 		__FUNCTION__, bus->hostintmask));
6128 	} else {
6129 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
6130 			SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
6131 	}
6132 #endif /* !BCMSPI */
6133 
6134 	/* If we didn't come up, turn off backplane clock */
6135 	if (dhdp->busstate != DHD_BUS_DATA)
6136 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
6137 
6138 exit:
6139 	if (enforce_mutex)
6140 		dhd_os_sdunlock(bus->dhd);
6141 
6142 	/* XXX Temp errnum workaround: return ok, caller checks bus state */
6143 	return ret;
6144 }
6145 
6146 static void
dhdsdio_rxfail(dhd_bus_t * bus,bool abort,bool rtx)6147 dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
6148 {
6149 	bcmsdh_info_t *sdh = bus->sdh;
6150 	sdpcmd_regs_t *regs = bus->regs;
6151 	uint retries = 0;
6152 	uint16 lastrbc;
6153 	uint8 hi, lo;
6154 	int err;
6155 
6156 	DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
6157 	           (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
6158 
6159 	if (!KSO_ENAB(bus)) {
6160 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
6161 		return;
6162 	}
6163 
6164 	if (abort) {
6165 		bcmsdh_abort(sdh, SDIO_FUNC_2);
6166 	}
6167 
6168 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
6169 	if (err) {
6170 		DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__));
6171 		goto fail;
6172 	}
6173 	bus->f1regdata++;
6174 
6175 	/* Wait until the packet has been flushed (device/FIFO stable) */
6176 	for (lastrbc = retries = 0xffff; retries > 0; retries--) {
6177 		hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
6178 		lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, &err);
6179 		if (err) {
6180 			DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__));
6181 			goto fail;
6182 		}
6183 
6184 		bus->f1regdata += 2;
6185 
6186 		if ((hi == 0) && (lo == 0))
6187 			break;
6188 
6189 		if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
6190 			DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
6191 			           __FUNCTION__, lastrbc, ((hi << 8) + lo)));
6192 		}
6193 		lastrbc = (hi << 8) + lo;
6194 	}
6195 
6196 	if (!retries) {
6197 		DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
6198 	} else {
6199 		DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
6200 	}
6201 
6202 	if (rtx) {
6203 		bus->rxrtx++;
6204 		W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
6205 		bus->f1regdata++;
6206 		if (retries <= retry_limit) {
6207 			bus->rxskip = TRUE;
6208 		}
6209 	}
6210 
6211 	/* Clear partial in any case */
6212 	bus->nextlen = 0;
6213 
6214 fail:
6215 	/* If we can't reach the device, signal failure */
6216 	if (err || bcmsdh_regfail(sdh)) {
6217 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
6218 		bus->dhd->busstate = DHD_BUS_DOWN;
6219 	}
6220 }
6221 
6222 static void
dhdsdio_read_control(dhd_bus_t * bus,uint8 * hdr,uint len,uint doff)6223 dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
6224 {
6225 	bcmsdh_info_t *sdh = bus->sdh;
6226 	uint rdlen, pad;
6227 
6228 	int sdret;
6229 
6230 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
6231 
6232 	/* Control data already received in aligned rxctl */
6233 	if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
6234 		goto gotpkt;
6235 
6236 	ASSERT(bus->rxbuf);
6237 	/* Set rxctl for frame (w/optional alignment) */
6238 	bus->rxctl = bus->rxbuf;
6239 	if (dhd_alignctl) {
6240 		bus->rxctl += firstread;
6241 		if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
6242 			bus->rxctl += (DHD_SDALIGN - pad);
6243 		bus->rxctl -= firstread;
6244 	}
6245 	ASSERT(bus->rxctl >= bus->rxbuf);
6246 
6247 	/* Copy the already-read portion over */
6248 	bcopy(hdr, bus->rxctl, firstread);
6249 	if (len <= firstread)
6250 		goto gotpkt;
6251 
6252 	/* Copy the full data pkt in gSPI case and process ioctl. */
6253 	if (bus->bus == SPI_BUS) {
6254 		bcopy(hdr, bus->rxctl, len);
6255 		goto gotpkt;
6256 	}
6257 
6258 	/* Raise rdlen to next SDIO block to avoid tail command */
6259 	rdlen = len - firstread;
6260 	if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
6261 		pad = bus->blocksize - (rdlen % bus->blocksize);
6262 		if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
6263 		    ((len + pad) < bus->dhd->maxctl))
6264 			rdlen += pad;
6265 	} else if (rdlen % DHD_SDALIGN) {
6266 		rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
6267 	}
6268 
6269 	/* Satisfy length-alignment requirements */
6270 	if (forcealign && (rdlen & (ALIGNMENT - 1)))
6271 		rdlen = ROUNDUP(rdlen, ALIGNMENT);
6272 
6273 	/* Drop if the read is too big or it exceeds our maximum */
6274 	if ((rdlen + firstread) > bus->dhd->maxctl) {
6275 		DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
6276 		           __FUNCTION__, rdlen, bus->dhd->maxctl));
6277 		bus->dhd->rx_errors++;
6278 		dhdsdio_rxfail(bus, FALSE, FALSE);
6279 		goto done;
6280 	}
6281 
6282 	if ((len - doff) > bus->dhd->maxctl) {
6283 		DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
6284 		           __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
6285 		bus->dhd->rx_errors++; bus->rx_toolong++;
6286 		dhdsdio_rxfail(bus, FALSE, FALSE);
6287 		goto done;
6288 	}
6289 
6290 	/* XXX Could block readers with rxlen=0? */
6291 
6292 	/* Read remainder of frame body into the rxctl buffer */
6293 	sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
6294 	                            (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
6295 	bus->f2rxdata++;
6296 	ASSERT(sdret != BCME_PENDING);
6297 
6298 	/* Control frame failures need retransmission */
6299 	if (sdret < 0) {
6300 		DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
6301 		bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
6302 		dhdsdio_rxfail(bus, TRUE, TRUE);
6303 		goto done;
6304 	}
6305 
6306 gotpkt:
6307 
6308 #ifdef DHD_DEBUG
6309 	if (DHD_BYTES_ON() && DHD_CTL_ON()) {
6310 		prhex("RxCtrl", bus->rxctl, len);
6311 	}
6312 #endif
6313 
6314 	/* Point to valid data and indicate its length */
6315 	bus->rxctl += doff;
6316 	bus->rxlen = len - doff;
6317 
6318 done:
6319 	/* Awake any waiters */
6320 	dhd_os_ioctl_resp_wake(bus->dhd);
6321 }
6322 int
6323 dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
6324 	void **pkt, uint32 *pkt_count);
6325 
6326 static uint8
dhdsdio_rxglom(dhd_bus_t * bus,uint8 rxseq)6327 dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
6328 {
6329 	uint16 dlen, totlen;
6330 	uint8 *dptr, num = 0;
6331 
6332 	uint16 sublen, check;
6333 	void *pfirst, *plast, *pnext;
6334 	void * list_tail[DHD_MAX_IFS] = { NULL };
6335 	void * list_head[DHD_MAX_IFS] = { NULL };
6336 	uint8 idx;
6337 	osl_t *osh = bus->dhd->osh;
6338 
6339 	int errcode;
6340 	uint8 chan, seq, doff, sfdoff;
6341 	uint8 txmax;
6342 	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
6343 	uint reorder_info_len;
6344 
6345 	int ifidx = 0;
6346 	bool usechain = bus->use_rxchain;
6347 
6348 	/* If packets, issue read(s) and send up packet chain */
6349 	/* Return sequence numbers consumed? */
6350 
6351 	DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
6352 
6353 	/* If there's a descriptor, generate the packet chain */
6354 	if (bus->glomd) {
6355 		dhd_os_sdlock_rxq(bus->dhd);
6356 
6357 		pfirst = plast = pnext = NULL;
6358 		dlen = (uint16)PKTLEN(osh, bus->glomd);
6359 		dptr = PKTDATA(osh, bus->glomd);
6360 		if (!dlen || (dlen & 1)) {
6361 			DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
6362 			           __FUNCTION__, dlen));
6363 			dlen = 0;
6364 		}
6365 
6366 		for (totlen = num = 0; dlen; num++) {
6367 			/* Get (and move past) next length */
6368 			sublen = ltoh16_ua(dptr);
6369 			dlen -= sizeof(uint16);
6370 			dptr += sizeof(uint16);
6371 			if ((sublen < SDPCM_HDRLEN) ||
6372 			    ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
6373 				DHD_ERROR(("%s: descriptor len %d bad: %d\n",
6374 				           __FUNCTION__, num, sublen));
6375 				pnext = NULL;
6376 				break;
6377 			}
6378 			if (sublen % DHD_SDALIGN) {
6379 				DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
6380 				           __FUNCTION__, sublen, DHD_SDALIGN));
6381 				usechain = FALSE;
6382 			}
6383 			totlen += sublen;
6384 
6385 			/* For last frame, adjust read len so total is a block multiple */
6386 			if (!dlen) {
6387 				sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
6388 				totlen = ROUNDUP(totlen, bus->blocksize);
6389 			}
6390 
6391 			/* Allocate/chain packet for next subframe */
6392 			if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
6393 				DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
6394 				           __FUNCTION__, num, sublen));
6395 				break;
6396 			}
6397 			ASSERT(!PKTLINK(pnext));
6398 			if (!pfirst) {
6399 				ASSERT(!plast);
6400 				pfirst = plast = pnext;
6401 			} else {
6402 				ASSERT(plast);
6403 				PKTSETNEXT(osh, plast, pnext);
6404 				plast = pnext;
6405 			}
6406 
6407 			/* Adhere to start alignment requirements */
6408 			PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
6409 		}
6410 
6411 		/* If all allocations succeeded, save packet chain in bus structure */
6412 		if (pnext) {
6413 			DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
6414 			          __FUNCTION__, totlen, num));
6415 			if (DHD_GLOM_ON() && bus->nextlen) {
6416 				if (totlen != bus->nextlen) {
6417 					DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
6418 					          "rxseq %d\n", __FUNCTION__, bus->nextlen,
6419 					          totlen, rxseq));
6420 				}
6421 			}
6422 			bus->glom = pfirst;
6423 			pfirst = pnext = NULL;
6424 		} else {
6425 			if (pfirst)
6426 				PKTFREE(osh, pfirst, FALSE);
6427 			bus->glom = NULL;
6428 			num = 0;
6429 		}
6430 
6431 		/* Done with descriptor packet */
6432 		PKTFREE(osh, bus->glomd, FALSE);
6433 		bus->glomd = NULL;
6434 		bus->nextlen = 0;
6435 
6436 		dhd_os_sdunlock_rxq(bus->dhd);
6437 	}
6438 
6439 	/* Ok -- either we just generated a packet chain, or had one from before */
6440 	if (bus->glom) {
6441 		if (DHD_GLOM_ON()) {
6442 			DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
6443 			for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
6444 				DHD_GLOM(("    %p: %p len 0x%04x (%d)\n",
6445 				          pnext, (uint8*)PKTDATA(osh, pnext),
6446 				          PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
6447 			}
6448 		}
6449 
6450 		pfirst = bus->glom;
6451 		dlen = (uint16)pkttotlen(osh, pfirst);
6452 
6453 		/* Do an SDIO read for the superframe.  Configurable iovar to
6454 		 * read directly into the chained packet, or allocate a large
6455 		 * packet and and copy into the chain.
6456 		 */
6457 		if (usechain) {
6458 			errcode = dhd_bcmsdh_recv_buf(bus,
6459 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
6460 			                              F2SYNC, (uint8*)PKTDATA(osh, pfirst),
6461 			                              dlen, pfirst, NULL, NULL);
6462 		} else if (bus->dataptr) {
6463 			errcode = dhd_bcmsdh_recv_buf(bus,
6464 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
6465 			                              F2SYNC, bus->dataptr,
6466 			                              dlen, NULL, NULL, NULL);
6467 			sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
6468 			if (sublen != dlen) {
6469 				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
6470 				           __FUNCTION__, dlen, sublen));
6471 				errcode = -1;
6472 			}
6473 			pnext = NULL;
6474 			BCM_REFERENCE(pnext);
6475 		} else {
6476 			DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
6477 			errcode = -1;
6478 		}
6479 		bus->f2rxdata++;
6480 		ASSERT(errcode != BCME_PENDING);
6481 
6482 		/* On failure, kill the superframe, allow a couple retries */
6483 		if (errcode < 0) {
6484 			DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
6485 			           __FUNCTION__, dlen, errcode));
6486 			bus->dhd->rx_errors++; /* XXX Account for rtx?? */
6487 
6488 			if (bus->glomerr++ < 3) {
6489 				dhdsdio_rxfail(bus, TRUE, TRUE);
6490 			} else {
6491 				bus->glomerr = 0;
6492 				dhdsdio_rxfail(bus, TRUE, FALSE);
6493 				dhd_os_sdlock_rxq(bus->dhd);
6494 				PKTFREE(osh, bus->glom, FALSE);
6495 				dhd_os_sdunlock_rxq(bus->dhd);
6496 				bus->rxglomfail++;
6497 				bus->glom = NULL;
6498 			}
6499 			return 0;
6500 		}
6501 
6502 #ifdef DHD_DEBUG
6503 		if (DHD_GLOM_ON()) {
6504 			prhex("SUPERFRAME", PKTDATA(osh, pfirst),
6505 			      MIN(PKTLEN(osh, pfirst), 48));
6506 		}
6507 #endif
6508 
6509 		/* Validate the superframe header */
6510 		dptr = (uint8 *)PKTDATA(osh, pfirst);
6511 		sublen = ltoh16_ua(dptr);
6512 		check = ltoh16_ua(dptr + sizeof(uint16));
6513 
6514 		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6515 		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
6516 		bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
6517 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
6518 			DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
6519 			          __FUNCTION__, bus->nextlen, seq));
6520 			bus->nextlen = 0;
6521 		}
6522 		doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6523 		txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6524 
6525 		errcode = 0;
6526 		if ((uint16)~(sublen^check)) {
6527 			DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
6528 			           __FUNCTION__, sublen, check));
6529 			errcode = -1;
6530 		} else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
6531 			DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
6532 			           __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
6533 			errcode = -1;
6534 		} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
6535 			DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
6536 			           SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
6537 			errcode = -1;
6538 		} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
6539 			DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
6540 			errcode = -1;
6541 		} else if ((doff < SDPCM_HDRLEN) ||
6542 		           (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
6543 			DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
6544 				__FUNCTION__, doff, sublen, PKTLEN(osh, pfirst),
6545 				SDPCM_HDRLEN));
6546 			errcode = -1;
6547 		}
6548 
6549 		/* Check sequence number of superframe SW header */
6550 		if (rxseq != seq) {
6551 			DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
6552 			          __FUNCTION__, seq, rxseq));
6553 			bus->rx_badseq++;
6554 			rxseq = seq;
6555 		}
6556 
6557 		/* Check window for sanity */
6558 		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
6559 			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
6560 			           __FUNCTION__, txmax, bus->tx_seq));
6561 			txmax = bus->tx_max;
6562 		}
6563 		bus->tx_max = txmax;
6564 
6565 		/* Remove superframe header, remember offset */
6566 		PKTPULL(osh, pfirst, doff);
6567 		sfdoff = doff;
6568 
6569 		/* Validate all the subframe headers */
6570 		for (num = 0, pnext = pfirst; pnext && !errcode;
6571 		     num++, pnext = PKTNEXT(osh, pnext)) {
6572 			dptr = (uint8 *)PKTDATA(osh, pnext);
6573 			dlen = (uint16)PKTLEN(osh, pnext);
6574 			sublen = ltoh16_ua(dptr);
6575 			check = ltoh16_ua(dptr + sizeof(uint16));
6576 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6577 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6578 #ifdef DHD_DEBUG
6579 			if (DHD_GLOM_ON()) {
6580 				prhex("subframe", dptr, 32);
6581 			}
6582 #endif
6583 
6584 			if ((uint16)~(sublen^check)) {
6585 				DHD_ERROR(("%s (subframe %d): HW hdr error: "
6586 				           "len/check 0x%04x/0x%04x\n",
6587 				           __FUNCTION__, num, sublen, check));
6588 				errcode = -1;
6589 			} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
6590 				DHD_ERROR(("%s (subframe %d): length mismatch: "
6591 				           "len 0x%04x, expect 0x%04x\n",
6592 				           __FUNCTION__, num, sublen, dlen));
6593 				errcode = -1;
6594 			} else if ((chan != SDPCM_DATA_CHANNEL) &&
6595 			           (chan != SDPCM_EVENT_CHANNEL)) {
6596 				DHD_ERROR(("%s (subframe %d): bad channel %d\n",
6597 				           __FUNCTION__, num, chan));
6598 				errcode = -1;
6599 			} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
6600 				DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
6601 				           __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
6602 				errcode = -1;
6603 			}
6604 		}
6605 
6606 		if (errcode) {
6607 			/* Terminate frame on error, request a couple retries */
6608 			if (bus->glomerr++ < 3) {
6609 				/* Restore superframe header space */
6610 				PKTPUSH(osh, pfirst, sfdoff);
6611 				dhdsdio_rxfail(bus, TRUE, TRUE);
6612 			} else {
6613 				bus->glomerr = 0;
6614 				dhdsdio_rxfail(bus, TRUE, FALSE);
6615 				dhd_os_sdlock_rxq(bus->dhd);
6616 				PKTFREE(osh, bus->glom, FALSE);
6617 				dhd_os_sdunlock_rxq(bus->dhd);
6618 				bus->rxglomfail++;
6619 				bus->glom = NULL;
6620 			}
6621 			bus->nextlen = 0;
6622 			return 0;
6623 		}
6624 
6625 		/* Basic SD framing looks ok - process each packet (header) */
6626 		bus->glom = NULL;
6627 		plast = NULL;
6628 
6629 		dhd_os_sdlock_rxq(bus->dhd);
6630 		for (num = 0; pfirst; rxseq++, pfirst = pnext) {
6631 			pnext = PKTNEXT(osh, pfirst);
6632 			PKTSETNEXT(osh, pfirst, NULL);
6633 
6634 			dptr = (uint8 *)PKTDATA(osh, pfirst);
6635 			sublen = ltoh16_ua(dptr);
6636 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6637 			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
6638 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6639 
6640 			DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
6641 			          __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
6642 			          PKTLEN(osh, pfirst), sublen, chan, seq));
6643 
6644 			ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
6645 
6646 			if (rxseq != seq) {
6647 				DHD_GLOM(("%s: rx_seq %d, expected %d\n",
6648 				          __FUNCTION__, seq, rxseq));
6649 				bus->rx_badseq++;
6650 				rxseq = seq;
6651 			}
6652 
6653 #ifdef DHD_DEBUG
6654 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
6655 				prhex("Rx Subframe Data", dptr, dlen);
6656 			}
6657 #endif
6658 
6659 			PKTSETLEN(osh, pfirst, sublen);
6660 			PKTPULL(osh, pfirst, doff);
6661 
6662 			reorder_info_len = sizeof(reorder_info_buf);
6663 
6664 			if (PKTLEN(osh, pfirst) == 0) {
6665 				PKTFREE(bus->dhd->osh, pfirst, FALSE);
6666 				continue;
6667 			} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf,
6668 				&reorder_info_len) != 0) {
6669 				DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
6670 				bus->dhd->rx_errors++;
6671 				PKTFREE(osh, pfirst, FALSE);
6672 				continue;
6673 			}
6674 			if (reorder_info_len) {
6675 				uint32 free_buf_count;
6676 				void *ppfirst;
6677 
6678 				ppfirst = pfirst;
6679 				/* Reordering info from the firmware */
6680 				dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf,
6681 					reorder_info_len, &ppfirst, &free_buf_count);
6682 
6683 				if (free_buf_count == 0) {
6684 					continue;
6685 				} else {
6686 					void *temp;
6687 
6688 					/*  go to the end of the chain and attach the pnext there */
6689 					temp = ppfirst;
6690 					while (PKTNEXT(osh, temp) != NULL) {
6691 						temp = PKTNEXT(osh, temp);
6692 					}
6693 					pfirst = temp;
6694 					if (list_tail[ifidx] == NULL)
6695 						list_head[ifidx] = ppfirst;
6696 					else
6697 						PKTSETNEXT(osh, list_tail[ifidx], ppfirst);
6698 					list_tail[ifidx] = pfirst;
6699 				}
6700 
6701 				num += (uint8)free_buf_count;
6702 			} else {
6703 				/* this packet will go up, link back into chain and count it */
6704 
6705 				if (list_tail[ifidx] == NULL) {
6706 					list_head[ifidx] = list_tail[ifidx] = pfirst;
6707 				} else {
6708 					PKTSETNEXT(osh, list_tail[ifidx], pfirst);
6709 					list_tail[ifidx] = pfirst;
6710 				}
6711 				num++;
6712 			}
6713 #ifdef DHD_DEBUG
6714 			if (DHD_GLOM_ON()) {
6715 				DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
6716 				          __FUNCTION__, num, pfirst,
6717 				          PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
6718 				          PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
6719 				prhex("", (uint8 *)PKTDATA(osh, pfirst),
6720 				      MIN(PKTLEN(osh, pfirst), 32));
6721 			}
6722 #endif /* DHD_DEBUG */
6723 		}
6724 		dhd_os_sdunlock_rxq(bus->dhd);
6725 
6726 		for (idx = 0; idx < DHD_MAX_IFS; idx++) {
6727 			if (list_head[idx]) {
6728 				void *temp;
6729 				uint8 cnt = 0;
6730 				temp = list_head[idx];
6731 				do {
6732 					temp = PKTNEXT(osh, temp);
6733 					cnt++;
6734 				} while (temp);
6735 				if (cnt) {
6736 					dhd_os_sdunlock(bus->dhd);
6737 					dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
6738 					dhd_os_sdlock(bus->dhd);
6739 				}
6740 			}
6741 		}
6742 		bus->rxglomframes++;
6743 		bus->rxglompkts += num;
6744 	}
6745 	return num;
6746 }
6747 
6748 /* Return TRUE if there may be more frames to read */
6749 static uint
dhdsdio_readframes(dhd_bus_t * bus,uint maxframes,bool * finished)6750 dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
6751 {
6752 	osl_t *osh = bus->dhd->osh;
6753 	bcmsdh_info_t *sdh = bus->sdh;
6754 
6755 	uint16 len, check;	/* Extracted hardware header fields */
6756 	uint8 chan, seq, doff;	/* Extracted software header fields */
6757 	uint8 fcbits;		/* Extracted fcbits from software header */
6758 	uint8 delta;
6759 
6760 	void *pkt;	/* Packet for event or data frames */
6761 	uint16 pad;	/* Number of pad bytes to read */
6762 	uint16 rdlen;	/* Total number of bytes to read */
6763 	uint8 rxseq;	/* Next sequence number to expect */
6764 	uint rxleft = 0;	/* Remaining number of frames allowed */
6765 	int sdret;	/* Return code from bcmsdh calls */
6766 	uint8 txmax;	/* Maximum tx sequence offered */
6767 #ifdef BCMSPI
6768 	uint32 dstatus = 0;	/* gSPI device status bits of */
6769 #endif /* BCMSPI */
6770 	bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
6771 	uint8 *rxbuf;
6772 	int ifidx = 0;
6773 	uint rxcount = 0; /* Total frames read */
6774 	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
6775 	uint reorder_info_len;
6776 	uint pkt_count;
6777 
6778 #if defined(DHD_DEBUG) || defined(SDTEST)
6779 	bool sdtest = FALSE;	/* To limit message spew from test mode */
6780 #endif
6781 
6782 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
6783 	bus->readframes = TRUE;
6784 
6785 	if (!KSO_ENAB(bus)) {
6786 		DHD_ERROR(("%s: KSO off\n", __FUNCTION__));
6787 		bus->readframes = FALSE;
6788 		return 0;
6789 	}
6790 
6791 	ASSERT(maxframes);
6792 
6793 #ifdef SDTEST
6794 	/* Allow pktgen to override maxframes */
6795 	if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
6796 		maxframes = bus->pktgen_count;
6797 		sdtest = TRUE;
6798 	}
6799 #endif
6800 
6801 	/* Not finished unless we encounter no more frames indication */
6802 	*finished = FALSE;
6803 
6804 #ifdef BCMSPI
6805 	/* Get pktlen from gSPI device F0 reg. */
6806 	if (bus->bus == SPI_BUS) {
6807 		/* Peek in dstatus bits and find out size to do rx-read. */
6808 		dstatus = bcmsdh_get_dstatus(bus->sdh);
6809 		if (dstatus == 0)
6810 			DHD_ERROR(("%s:ZERO spi dstatus, a case observed in PR61352 hit !!!\n",
6811 			           __FUNCTION__));
6812 
6813 		DHD_TRACE(("Device status from regread = 0x%x\n", dstatus));
6814 		DHD_TRACE(("Device status from bit-reconstruction = 0x%x\n",
6815 		          bcmsdh_get_dstatus((void *)bus->sdh)));
6816 
6817 		/* Check underflow also, WAR for PR55150 */
6818 		if ((dstatus & STATUS_F2_PKT_AVAILABLE) && (((dstatus & STATUS_UNDERFLOW)) == 0)) {
6819 			bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
6820 			                STATUS_F2_PKT_LEN_SHIFT);
6821 			/* '0' size with pkt-available interrupt is eqvt to 2048 bytes */
6822 			bus->nextlen = (bus->nextlen == 0) ? SPI_MAX_PKT_LEN : bus->nextlen;
6823 			if (bus->dwordmode)
6824 				bus->nextlen = bus->nextlen << 2;
6825 			DHD_TRACE(("Entering %s: length to be read from gSPI = %d\n",
6826 			          __FUNCTION__, bus->nextlen));
6827 		} else {
6828 			if (dstatus & STATUS_F2_PKT_AVAILABLE)
6829 				DHD_ERROR(("Underflow during %s.\n", __FUNCTION__));
6830 			else
6831 				DHD_ERROR(("False pkt-available intr.\n"));
6832 			*finished = TRUE;
6833 			return (maxframes - rxleft);
6834 		}
6835 	}
6836 #endif /* BCMSPI */
6837 
6838 	for (rxseq = bus->rx_seq, rxleft = maxframes;
6839 	     !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
6840 	     rxseq++, rxleft--) {
6841 #ifdef DHDTCPACK_SUP_DBG
6842 		if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_DELAYTX) {
6843 			if (bus->dotxinrx == FALSE)
6844 				DHD_ERROR(("%s %d: dotxinrx FALSE with tcpack_sub_mode %d\n",
6845 					__FUNCTION__, __LINE__, bus->dhd->tcpack_sup_mode));
6846 		}
6847 #ifdef DEBUG_COUNTER
6848 		else if (pktq_mlen(&bus->txq, ~bus->flowcontrol) > 0) {
6849 			tack_tbl.cnt[bus->dotxinrx ? 6 : 7]++;
6850 		}
6851 #endif /* DEBUG_COUNTER */
6852 #endif /* DHDTCPACK_SUP_DBG */
6853 		/* tx more to improve rx performance */
6854 		if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
6855 			dhdsdio_sendpendctl(bus);
6856 		} else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
6857 			!bus->fcstate && DATAOK(bus) &&
6858 			(pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
6859 			dhdsdio_sendfromq(bus, dhd_txbound);
6860 #ifdef DHDTCPACK_SUPPRESS
6861 			/* In TCPACK_SUP_DELAYTX mode, do txinrx only if
6862 			 * 1. Any DATA packet to TX
6863 			 * 2. TCPACK to TCPDATA PSH packets.
6864 			 * in bus txq.
6865 			 */
6866 			bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ?
6867 				FALSE : TRUE;
6868 #endif
6869 		}
6870 
6871 		/* Handle glomming separately */
6872 		if (bus->glom || bus->glomd) {
6873 			uint8 cnt;
6874 			DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
6875 			          __FUNCTION__, bus->glomd, bus->glom));
6876 			cnt = dhdsdio_rxglom(bus, rxseq);
6877 			DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
6878 			rxseq += cnt - 1;
6879 			rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
6880 			continue;
6881 		}
6882 
6883 		/* Try doing single read if we can */
6884 		if (dhd_readahead && bus->nextlen) {
6885 			uint16 nextlen = bus->nextlen;
6886 			bus->nextlen = 0;
6887 
6888 			if (bus->bus == SPI_BUS) {
6889 				rdlen = len = nextlen;
6890 			} else {
6891 				rdlen = len = nextlen << 4;
6892 
6893 				/* Pad read to blocksize for efficiency */
6894 				if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
6895 					pad = bus->blocksize - (rdlen % bus->blocksize);
6896 					if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
6897 						((rdlen + pad + firstread) < MAX_RX_DATASZ))
6898 						rdlen += pad;
6899 				} else if (rdlen % DHD_SDALIGN) {
6900 					rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
6901 				}
6902 			}
6903 
6904 			/* We use bus->rxctl buffer in WinXP for initial control pkt receives.
6905 			 * Later we use buffer-poll for data as well as control packets.
6906 			 * This is required because dhd receives full frame in gSPI unlike SDIO.
6907 			 * After the frame is received we have to distinguish whether it is data
6908 			 * or non-data frame.
6909 			 */
6910 			/* Allocate a packet buffer */
6911 			dhd_os_sdlock_rxq(bus->dhd);
6912 			if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
6913 				if (bus->bus == SPI_BUS) {
6914 					bus->usebufpool = FALSE;
6915 					bus->rxctl = bus->rxbuf;
6916 					if (dhd_alignctl) {
6917 						bus->rxctl += firstread;
6918 						if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
6919 							bus->rxctl += (DHD_SDALIGN - pad);
6920 						bus->rxctl -= firstread;
6921 					}
6922 					ASSERT(bus->rxctl >= bus->rxbuf);
6923 					rxbuf = bus->rxctl;
6924 					/* Read the entire frame */
6925 					sdret = dhd_bcmsdh_recv_buf(bus,
6926 					                            bcmsdh_cur_sbwad(sdh),
6927 					                            SDIO_FUNC_2,
6928 					                            F2SYNC, rxbuf, rdlen,
6929 					                            NULL, NULL, NULL);
6930 					bus->f2rxdata++;
6931 					ASSERT(sdret != BCME_PENDING);
6932 
6933 #ifdef BCMSPI
6934 					/* PR55150 WAR: Wait for next pkt-available interrupt for
6935 					 * further processing
6936 					 */
6937 					if (bcmsdh_get_dstatus((void *)bus->sdh) &
6938 					                STATUS_UNDERFLOW) {
6939 						bus->nextlen = 0;
6940 						*finished = TRUE;
6941 						DHD_ERROR(("%s: read %d control bytes failed "
6942 						           "due to spi underflow\n",
6943 						           __FUNCTION__, rdlen));
6944 						/* dhd.rx_ctlerrs is higher level */
6945 						bus->rxc_errors++;
6946 						dhd_os_sdunlock_rxq(bus->dhd);
6947 						continue;
6948 					}
6949 #endif /* BCMSPI */
6950 
6951 					/* Control frame failures need retransmission */
6952 					if (sdret < 0) {
6953 						DHD_ERROR(("%s: read %d control bytes failed: %d\n",
6954 						   __FUNCTION__, rdlen, sdret));
6955 						/* dhd.rx_ctlerrs is higher level */
6956 						bus->rxc_errors++;
6957 						dhd_os_sdunlock_rxq(bus->dhd);
6958 						dhdsdio_rxfail(bus, TRUE,
6959 						    (bus->bus == SPI_BUS) ? FALSE : TRUE);
6960 						continue;
6961 					}
6962 				} else {
6963 					/* Give up on data, request rtx of events */
6964 					DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
6965 					           "expected rxseq %d\n",
6966 					           __FUNCTION__, len, rdlen, rxseq));
6967 					/* XXX Can't issue retry (NAK), frame not started. */
6968 					/* Just go try again w/normal header read */
6969 					dhd_os_sdunlock_rxq(bus->dhd);
6970 					continue;
6971 				}
6972 			} else {
6973 				if (bus->bus == SPI_BUS)
6974 					bus->usebufpool = TRUE;
6975 
6976 				ASSERT(!PKTLINK(pkt));
6977 				PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
6978 				rxbuf = (uint8 *)PKTDATA(osh, pkt);
6979 				/* Read the entire frame */
6980 				sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
6981 				                            SDIO_FUNC_2,
6982 				                            F2SYNC, rxbuf, rdlen,
6983 				                            pkt, NULL, NULL);
6984 				bus->f2rxdata++;
6985 				ASSERT(sdret != BCME_PENDING);
6986 #ifdef BCMSPI
6987 				/* PR55150 WAR: Wait for next pkt-available interrupt for further
6988 				 * processing
6989 				 */
6990 				if (bcmsdh_get_dstatus((void *)bus->sdh) & STATUS_UNDERFLOW) {
6991 					bus->nextlen = 0;
6992 					*finished = TRUE;
6993 					DHD_ERROR(("%s (nextlen): read %d bytes failed due "
6994 					           "to spi underflow\n",
6995 					           __FUNCTION__, rdlen));
6996 					PKTFREE(bus->dhd->osh, pkt, FALSE);
6997 					bus->dhd->rx_errors++;
6998 					dhd_os_sdunlock_rxq(bus->dhd);
6999 					continue;
7000 				}
7001 #endif /* BCMSPI */
7002 
7003 				if (sdret < 0) {
7004 					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
7005 					   __FUNCTION__, rdlen, sdret));
7006 					PKTFREE(bus->dhd->osh, pkt, FALSE);
7007 					bus->dhd->rx_errors++; /* XXX Account for rtx?? */
7008 					dhd_os_sdunlock_rxq(bus->dhd);
7009 					/* Force retry w/normal header read.  Don't attempt NAK for
7010 					 * gSPI
7011 					 */
7012 					dhdsdio_rxfail(bus, TRUE,
7013 					      (bus->bus == SPI_BUS) ? FALSE : TRUE);
7014 					continue;
7015 				}
7016 			}
7017 			dhd_os_sdunlock_rxq(bus->dhd);
7018 
7019 			/* Now check the header */
7020 			bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
7021 
7022 			/* Extract hardware header fields */
7023 			len = ltoh16_ua(bus->rxhdr);
7024 			check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
7025 
7026 			/* All zeros means readahead info was bad */
7027 			if (!(len|check)) {
7028 				DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
7029 				           __FUNCTION__));
7030 				dhd_os_sdlock_rxq(bus->dhd);
7031 				PKTFREE2();
7032 				dhd_os_sdunlock_rxq(bus->dhd);
7033 				GSPI_PR55150_BAILOUT;
7034 				continue;
7035 			}
7036 
7037 			/* Validate check bytes */
7038 			if ((uint16)~(len^check)) {
7039 				DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
7040 				           " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
7041 				           len, check));
7042 				dhd_os_sdlock_rxq(bus->dhd);
7043 				PKTFREE2();
7044 				dhd_os_sdunlock_rxq(bus->dhd);
7045 				bus->rx_badhdr++;
7046 				dhdsdio_rxfail(bus, FALSE, FALSE);
7047 				GSPI_PR55150_BAILOUT;
7048 				continue;
7049 			}
7050 
7051 			/* Validate frame length */
7052 			if (len < SDPCM_HDRLEN) {
7053 				/* XXX Might choose to allow length 4 for signaling */
7054 				DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
7055 				           __FUNCTION__, len));
7056 				dhd_os_sdlock_rxq(bus->dhd);
7057 				PKTFREE2();
7058 				dhd_os_sdunlock_rxq(bus->dhd);
7059 				GSPI_PR55150_BAILOUT;
7060 				continue;
7061 			}
7062 
7063 			/* Check for consistency with readahead info */
7064 #ifdef BCMSPI
7065 			if (bus->bus == SPI_BUS) {
7066 				if (bus->dwordmode) {
7067 					uint16 spilen;
7068 					spilen = ROUNDUP(len, 4);
7069 					len_consistent = (nextlen != spilen);
7070 				} else
7071 					len_consistent = (nextlen != len);
7072 			} else
7073 #endif  /* BCMSPI */
7074 				len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
7075 			if (len_consistent) {
7076 				/* Mismatch, force retry w/normal header (may be >4K) */
7077 				DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
7078 				           "expected rxseq %d\n",
7079 				           __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
7080 				dhd_os_sdlock_rxq(bus->dhd);
7081 				PKTFREE2();
7082 				dhd_os_sdunlock_rxq(bus->dhd);
7083 				dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
7084 				GSPI_PR55150_BAILOUT;
7085 				continue;
7086 			}
7087 
7088 			/* Extract software header fields */
7089 			chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7090 			seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7091 			doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7092 			txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7093 
7094 #ifdef BCMSPI
7095 			/* Save the readahead length if there is one */
7096 			if (bus->bus == SPI_BUS) {
7097 				/* Use reconstructed dstatus bits and find out readahead size */
7098 				dstatus = bcmsdh_get_dstatus((void *)bus->sdh);
7099 				DHD_INFO(("Device status from bit-reconstruction = 0x%x\n",
7100 				bcmsdh_get_dstatus((void *)bus->sdh)));
7101 				if (dstatus & STATUS_F2_PKT_AVAILABLE) {
7102 					bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
7103 					                STATUS_F2_PKT_LEN_SHIFT);
7104 					bus->nextlen = (bus->nextlen == 0) ?
7105 					           SPI_MAX_PKT_LEN : bus->nextlen;
7106 					if (bus->dwordmode)
7107 						bus->nextlen = bus->nextlen << 2;
7108 					DHD_INFO(("readahead len from gSPI = %d \n",
7109 					           bus->nextlen));
7110 					bus->dhd->rx_readahead_cnt ++;
7111 				} else {
7112 					bus->nextlen = 0;
7113 					*finished = TRUE;
7114 				}
7115 			} else {
7116 #endif /* BCMSPI */
7117 				bus->nextlen =
7118 				         bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
7119 				if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
7120 					DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
7121 					          " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
7122 					          seq));
7123 					bus->nextlen = 0;
7124 				}
7125 
7126 				bus->dhd->rx_readahead_cnt ++;
7127 #ifdef BCMSPI
7128 			}
7129 #endif /* BCMSPI */
7130 			/* Handle Flow Control */
7131 			fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7132 
7133 			delta = 0;
7134 			if (~bus->flowcontrol & fcbits) {
7135 				bus->fc_xoff++;
7136 				delta = 1;
7137 			}
7138 			if (bus->flowcontrol & ~fcbits) {
7139 				bus->fc_xon++;
7140 				delta = 1;
7141 			}
7142 
7143 			if (delta) {
7144 				bus->fc_rcvd++;
7145 				bus->flowcontrol = fcbits;
7146 			}
7147 
7148 			/* Check and update sequence number */
7149 			if (rxseq != seq) {
7150 				DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
7151 				          __FUNCTION__, seq, rxseq));
7152 				bus->rx_badseq++;
7153 				rxseq = seq;
7154 			}
7155 
7156 			/* Check window for sanity */
7157 			if ((uint8)(txmax - bus->tx_seq) > 0x70) {
7158 #ifdef BCMSPI
7159 				if ((bus->bus == SPI_BUS) && !(dstatus & STATUS_F2_RX_READY)) {
7160 					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
7161 						__FUNCTION__, txmax, bus->tx_seq));
7162 					txmax = bus->tx_seq + 2;
7163 				} else {
7164 #endif /* BCMSPI */
7165 					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
7166 						__FUNCTION__, txmax, bus->tx_seq));
7167 					txmax = bus->tx_max;
7168 #ifdef BCMSPI
7169 				}
7170 #endif /* BCMSPI */
7171 			}
7172 			bus->tx_max = txmax;
7173 
7174 #ifdef DHD_DEBUG
7175 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
7176 				prhex("Rx Data", rxbuf, len);
7177 			} else if (DHD_HDRS_ON()) {
7178 				prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
7179 			}
7180 #endif
7181 
7182 			if (chan == SDPCM_CONTROL_CHANNEL) {
7183 				if (bus->bus == SPI_BUS) {
7184 					dhdsdio_read_control(bus, rxbuf, len, doff);
7185 					if (bus->usebufpool) {
7186 						dhd_os_sdlock_rxq(bus->dhd);
7187 						PKTFREE(bus->dhd->osh, pkt, FALSE);
7188 						dhd_os_sdunlock_rxq(bus->dhd);
7189 					}
7190 					continue;
7191 				} else {
7192 					DHD_ERROR(("%s (nextlen): readahead on control"
7193 					           " packet %d?\n", __FUNCTION__, seq));
7194 					/* Force retry w/normal header read */
7195 					bus->nextlen = 0;
7196 					dhdsdio_rxfail(bus, FALSE, TRUE);
7197 					dhd_os_sdlock_rxq(bus->dhd);
7198 					PKTFREE2();
7199 					dhd_os_sdunlock_rxq(bus->dhd);
7200 					continue;
7201 				}
7202 			}
7203 
7204 			if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
7205 				DHD_ERROR(("Received %d bytes on %d channel. Running out of "
7206 				           "rx pktbuf's or not yet malloced.\n", len, chan));
7207 				continue;
7208 			}
7209 
7210 			/* Validate data offset */
7211 			if ((doff < SDPCM_HDRLEN) || (doff > len)) {
7212 				DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
7213 				           __FUNCTION__, doff, len, SDPCM_HDRLEN));
7214 				dhd_os_sdlock_rxq(bus->dhd);
7215 				PKTFREE2();
7216 				dhd_os_sdunlock_rxq(bus->dhd);
7217 				ASSERT(0);
7218 				dhdsdio_rxfail(bus, FALSE, FALSE);
7219 				continue;
7220 			}
7221 
7222 			/* All done with this one -- now deliver the packet */
7223 			goto deliver;
7224 		}
7225 		/* gSPI frames should not be handled in fractions */
7226 		if (bus->bus == SPI_BUS) {
7227 			break;
7228 		}
7229 
7230 		/* Read frame header (hardware and software) */
7231 		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
7232 		                            bus->rxhdr, firstread, NULL, NULL, NULL);
7233 		bus->f2rxhdrs++;
7234 		ASSERT(sdret != BCME_PENDING);
7235 
7236 		if (sdret < 0) {
7237 			DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
7238 			bus->rx_hdrfail++;
7239 #ifdef BCMINTERNAL
7240 			if (tstoph) {
7241 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7242 				bus->dhd->busstate = DHD_BUS_DOWN;
7243 				continue;
7244 			}
7245 #endif
7246 			dhdsdio_rxfail(bus, TRUE, TRUE);
7247 			continue;
7248 		}
7249 
7250 #ifdef DHD_DEBUG
7251 		if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
7252 			prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
7253 		}
7254 #endif
7255 
7256 		/* Extract hardware header fields */
7257 		len = ltoh16_ua(bus->rxhdr);
7258 		check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
7259 
7260 		/* All zeros means no more frames */
7261 		if (!(len|check)) {
7262 			*finished = TRUE;
7263 			break;
7264 		}
7265 
7266 		/* Validate check bytes */
7267 		if ((uint16)~(len^check)) {
7268 			DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
7269 			           __FUNCTION__, len, check));
7270 			bus->rx_badhdr++;
7271 			dhdsdio_rxfail(bus, FALSE, FALSE);
7272 			continue;
7273 		}
7274 
7275 		/* Validate frame length */
7276 		if (len < SDPCM_HDRLEN) {
7277 			/* XXX Might choose to allow length 4 for signaling */
7278 			DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len));
7279 			continue;
7280 		}
7281 
7282 		/* Extract software header fields */
7283 		chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7284 		seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7285 		doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7286 		txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7287 
7288 		/* Validate data offset */
7289 		if ((doff < SDPCM_HDRLEN) || (doff > len)) {
7290 			DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
7291 			           __FUNCTION__, doff, len, SDPCM_HDRLEN, seq));
7292 			bus->rx_badhdr++;
7293 			ASSERT(0);
7294 			dhdsdio_rxfail(bus, FALSE, FALSE);
7295 			continue;
7296 		}
7297 
7298 		/* Save the readahead length if there is one */
7299 		bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
7300 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
7301 			DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
7302 			          __FUNCTION__, bus->nextlen, seq));
7303 			bus->nextlen = 0;
7304 		}
7305 
7306 		/* Handle Flow Control */
7307 		fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7308 
7309 		delta = 0;
7310 		if (~bus->flowcontrol & fcbits) {
7311 			bus->fc_xoff++;
7312 			delta = 1;
7313 		}
7314 		if (bus->flowcontrol & ~fcbits) {
7315 			bus->fc_xon++;
7316 			delta = 1;
7317 		}
7318 
7319 		if (delta) {
7320 			bus->fc_rcvd++;
7321 			bus->flowcontrol = fcbits;
7322 		}
7323 
7324 		/* Check and update sequence number */
7325 		if (rxseq != seq) {
7326 			DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq));
7327 			bus->rx_badseq++;
7328 			rxseq = seq;
7329 		}
7330 
7331 		/* Check window for sanity */
7332 		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
7333 			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
7334 			           __FUNCTION__, txmax, bus->tx_seq));
7335 			txmax = bus->tx_max;
7336 		}
7337 		bus->tx_max = txmax;
7338 
7339 		/* Call a separate function for control frames */
7340 		if (chan == SDPCM_CONTROL_CHANNEL) {
7341 			dhdsdio_read_control(bus, bus->rxhdr, len, doff);
7342 			continue;
7343 		}
7344 
7345 		ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) ||
7346 		       (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL));
7347 
7348 		/* Length to read */
7349 		rdlen = (len > firstread) ? (len - firstread) : 0;
7350 
7351 		/* May pad read to blocksize for efficiency */
7352 		if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
7353 			pad = bus->blocksize - (rdlen % bus->blocksize);
7354 			if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
7355 			    ((rdlen + pad + firstread) < MAX_RX_DATASZ))
7356 				rdlen += pad;
7357 		} else if (rdlen % DHD_SDALIGN) {
7358 			rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
7359 		}
7360 
7361 		/* Satisfy length-alignment requirements */
7362 		if (forcealign && (rdlen & (ALIGNMENT - 1)))
7363 			rdlen = ROUNDUP(rdlen, ALIGNMENT);
7364 
7365 		if ((rdlen + firstread) > MAX_RX_DATASZ) {
7366 			/* Too long -- skip this frame */
7367 			DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen));
7368 			bus->dhd->rx_errors++; bus->rx_toolong++;
7369 			dhdsdio_rxfail(bus, FALSE, FALSE);
7370 			continue;
7371 		}
7372 
7373 		dhd_os_sdlock_rxq(bus->dhd);
7374 		if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) {
7375 			/* Give up on data, request rtx of events */
7376 			DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n",
7377 			           __FUNCTION__, rdlen, chan));
7378 			bus->dhd->rx_dropped++;
7379 			dhd_os_sdunlock_rxq(bus->dhd);
7380 			dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan));
7381 			continue;
7382 		}
7383 		dhd_os_sdunlock_rxq(bus->dhd);
7384 
7385 		ASSERT(!PKTLINK(pkt));
7386 
7387 		/* XXX Should check len for small packets in case we're done? */
7388 		/* Leave room for what we already read, and align remainder */
7389 		ASSERT(firstread < (PKTLEN(osh, pkt)));
7390 		PKTPULL(osh, pkt, firstread);
7391 		PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
7392 
7393 		/* Read the remaining frame data */
7394 		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
7395 		                            ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL);
7396 		bus->f2rxdata++;
7397 		ASSERT(sdret != BCME_PENDING);
7398 
7399 		if (sdret < 0) {
7400 			DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen,
7401 			           ((chan == SDPCM_EVENT_CHANNEL) ? "event" :
7402 			            ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret));
7403 			dhd_os_sdlock_rxq(bus->dhd);
7404 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7405 			dhd_os_sdunlock_rxq(bus->dhd);
7406 			bus->dhd->rx_errors++; /* XXX Account for rtx?? */
7407 			dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan));
7408 			continue;
7409 		}
7410 
7411 		/* Copy the already-read portion */
7412 		PKTPUSH(osh, pkt, firstread);
7413 		bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread);
7414 
7415 #ifdef DHD_DEBUG
7416 		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
7417 			prhex("Rx Data", PKTDATA(osh, pkt), len);
7418 		}
7419 #endif
7420 
7421 deliver:
7422 		/* Save superframe descriptor and allocate packet frame */
7423 		if (chan == SDPCM_GLOM_CHANNEL) {
7424 			if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
7425 				DHD_GLOM(("%s: got glom descriptor, %d bytes:\n",
7426 				          __FUNCTION__, len));
7427 #ifdef DHD_DEBUG
7428 				if (DHD_GLOM_ON()) {
7429 					prhex("Glom Data", PKTDATA(osh, pkt), len);
7430 				}
7431 #endif
7432 				PKTSETLEN(osh, pkt, len);
7433 				ASSERT(doff == SDPCM_HDRLEN);
7434 				PKTPULL(osh, pkt, SDPCM_HDRLEN);
7435 				bus->glomd = pkt;
7436 			} else {
7437 				DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__));
7438 				dhdsdio_rxfail(bus, FALSE, FALSE);
7439 			}
7440 			continue;
7441 		}
7442 
7443 		/* Fill in packet len and prio, deliver upward */
7444 		PKTSETLEN(osh, pkt, len);
7445 		PKTPULL(osh, pkt, doff);
7446 
7447 #ifdef SDTEST
7448 		/* Test channel packets are processed separately */
7449 		if (chan == SDPCM_TEST_CHANNEL) {
7450 			dhdsdio_testrcv(bus, pkt, seq);
7451 			continue;
7452 		}
7453 #endif /* SDTEST */
7454 
7455 		if (PKTLEN(osh, pkt) == 0) {
7456 			dhd_os_sdlock_rxq(bus->dhd);
7457 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7458 			dhd_os_sdunlock_rxq(bus->dhd);
7459 			continue;
7460 		} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt, reorder_info_buf,
7461 			&reorder_info_len) != 0) {
7462 			DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
7463 			dhd_os_sdlock_rxq(bus->dhd);
7464 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7465 			dhd_os_sdunlock_rxq(bus->dhd);
7466 			bus->dhd->rx_errors++;
7467 			continue;
7468 		}
7469 
7470 		if (reorder_info_len) {
7471 			/* Reordering info from the firmware */
7472 			dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len,
7473 				&pkt, &pkt_count);
7474 			if (pkt_count == 0)
7475 				continue;
7476 		} else {
7477 			pkt_count = 1;
7478 		}
7479 
7480 		/* XXX Release the lock around the rx delivery: an OS (like Windows)
7481 		 * might call tx in the same thread context, resulting in deadlock.
7482 		 */
7483 		/* Unlock during rx call */
7484 		dhd_os_sdunlock(bus->dhd);
7485 		dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
7486 		dhd_os_sdlock(bus->dhd);
7487 #if defined(SDIO_ISR_THREAD)
7488 		/* terence 20150615: fix for below error due to bussleep in watchdog after dhd_os_sdunlock here,
7489 		  * so call BUS_WAKE to wake up bus again
7490 		  * dhd_bcmsdh_recv_buf: Device asleep
7491 		  * dhdsdio_readframes: RXHEADER FAILED: -40
7492 		  * dhdsdio_rxfail: abort command, terminate frame, send NAK
7493 		*/
7494 		BUS_WAKE(bus);
7495 #endif
7496 	}
7497 	rxcount = maxframes - rxleft;
7498 #ifdef DHD_DEBUG
7499 	/* Message if we hit the limit */
7500 	if (!rxleft && !sdtest)
7501 		DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
7502 	else
7503 #endif /* DHD_DEBUG */
7504 	DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
7505 	/* Back off rxseq if awaiting rtx, update rx_seq */
7506 	if (bus->rxskip)
7507 		rxseq--;
7508 	bus->rx_seq = rxseq;
7509 
7510 	if (bus->reqbussleep)
7511 	{
7512 		dhdsdio_bussleep(bus, TRUE);
7513 		bus->reqbussleep = FALSE;
7514 	}
7515 	bus->readframes = FALSE;
7516 
7517 	return rxcount;
7518 }
7519 
7520 static uint32
dhdsdio_hostmail(dhd_bus_t * bus,uint32 * hmbd)7521 dhdsdio_hostmail(dhd_bus_t *bus, uint32 *hmbd)
7522 {
7523 	sdpcmd_regs_t *regs = bus->regs;
7524 	uint32 intstatus = 0;
7525 	uint32 hmb_data;
7526 	uint8 fcbits;
7527 	uint retries = 0;
7528 
7529 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7530 
7531 	/* Read mailbox data and ack that we did so */
7532 	R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
7533 	if (retries <= retry_limit)
7534 		W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
7535 	bus->f1regdata += 2;
7536 
7537 	/* Dongle recomposed rx frames, accept them again */
7538 	if (hmb_data & HMB_DATA_NAKHANDLED) {
7539 		DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq));
7540 		/* XXX ASSERT(bus->rxskip); */
7541 		if (!bus->rxskip) {
7542 			DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__));
7543 		}
7544 		bus->rxskip = FALSE;
7545 		intstatus |= FRAME_AVAIL_MASK(bus);
7546 	}
7547 
7548 	/*
7549 	 * DEVREADY does not occur with gSPI.
7550 	 */
7551 	if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
7552 		bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT;
7553 		if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
7554 			DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n",
7555 			           bus->sdpcm_ver, SDPCM_PROT_VERSION));
7556 		else
7557 			DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
7558 #ifndef BCMSPI
7559 		/* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */
7560 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
7561 		    (bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1)) {
7562 			uint32 val;
7563 
7564 			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
7565 			val &= ~CC_XMTDATAAVAIL_MODE;
7566 			val |= CC_XMTDATAAVAIL_CTRL;
7567 			W_REG(bus->dhd->osh, &bus->regs->corecontrol, val);
7568 
7569 			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
7570 		}
7571 #endif /* BCMSPI */
7572 
7573 #ifdef DHD_DEBUG
7574 		/* Retrieve console state address now that firmware should have updated it */
7575 		{
7576 			sdpcm_shared_t shared;
7577 			if (dhdsdio_readshared(bus, &shared) == 0)
7578 				bus->console_addr = shared.console_addr;
7579 		}
7580 #endif /* DHD_DEBUG */
7581 	}
7582 
7583 	/*
7584 	 * Flow Control has been moved into the RX headers and this out of band
7585 	 * method isn't used any more.  Leave this here for possibly remaining backward
7586 	 * compatible with older dongles
7587 	 */
7588 	if (hmb_data & HMB_DATA_FC) {
7589 		fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT;
7590 
7591 		if (fcbits & ~bus->flowcontrol)
7592 			bus->fc_xoff++;
7593 		if (bus->flowcontrol & ~fcbits)
7594 			bus->fc_xon++;
7595 
7596 		bus->fc_rcvd++;
7597 		bus->flowcontrol = fcbits;
7598 	}
7599 
7600 	/* At least print a message if FW halted */
7601 	if (hmb_data & HMB_DATA_FWHALT) {
7602 		DHD_ERROR(("FIRMWARE HALTED\n"));
7603 		dhdsdio_checkdied(bus, NULL, 0);
7604 	}
7605 
7606 	/* Shouldn't be any others */
7607 	if (hmb_data & ~(HMB_DATA_DEVREADY |
7608 	                 HMB_DATA_FWHALT |
7609 	                 HMB_DATA_NAKHANDLED |
7610 	                 HMB_DATA_FC |
7611 	                 HMB_DATA_FWREADY |
7612 	                 HMB_DATA_FCDATA_MASK |
7613 	                 HMB_DATA_VERSION_MASK)) {
7614 		DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
7615 	}
7616 
7617 	if (hmbd) {
7618 		*hmbd = hmb_data;
7619 	}
7620 
7621 	return intstatus;
7622 }
7623 
7624 #ifdef BCMSDIO_INTSTATUS_WAR
7625 static uint32
dhdsdio_read_intstatus_byte(dhd_bus_t * bus)7626 dhdsdio_read_intstatus_byte(dhd_bus_t *bus)
7627 {
7628 	bcmsdh_info_t *sdh = bus->sdh;
7629 	sdpcmd_regs_t *regs = bus->regs;
7630 	uint32 newstatus = 0, intstatus_byte = 0;
7631 	uint retries = 0;
7632 	int err1 = 0, err2 = 0, err3 = 0, err4 = 0;
7633 
7634 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7635 
7636 	/* read_intr_mode:
7637 	  * 0: word mode only (default)
7638 	  * 1: byte mode after read word failed
7639 	  * 2: byte mode only
7640 	*/
7641 	if (bus->dhd->conf->read_intr_mode) {
7642 		if (bus->dhd->conf->read_intr_mode == 1) {
7643 			R_SDREG(newstatus, &regs->intstatus, retries);
7644 			if (!bcmsdh_regfail(bus->sdh)) {
7645 				goto exit;
7646 			}
7647 		}
7648 		intstatus_byte = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7649 			((unsigned long)&regs->intstatus & 0xffff) + 0, &err1);
7650 		if (!err1)
7651 			newstatus |= intstatus_byte;
7652 		intstatus_byte = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7653 			((unsigned long)&regs->intstatus & 0xffff) + 1, &err2) << 8;
7654 		if (!err2)
7655 			newstatus |= intstatus_byte;
7656 		intstatus_byte |= bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7657 			((unsigned long)&regs->intstatus & 0xffff) + 2, &err3) << 16;
7658 		if (!err3)
7659 			newstatus |= intstatus_byte;
7660 		intstatus_byte |= bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7661 			((unsigned long)&regs->intstatus & 0xffff) + 3, &err4) << 24;
7662 		if (!err4)
7663 			newstatus |= intstatus_byte;
7664 
7665 		if (!err1 || !err2 || !err3 || !err4)
7666 			sdh->regfail = FALSE;
7667 	}
7668 	else {
7669 		R_SDREG(newstatus, &regs->intstatus, retries);
7670 	}
7671 
7672 exit:
7673 	return newstatus;
7674 }
7675 #endif
7676 
7677 static bool
dhdsdio_dpc(dhd_bus_t * bus)7678 dhdsdio_dpc(dhd_bus_t *bus)
7679 {
7680 	bcmsdh_info_t *sdh = bus->sdh;
7681 	sdpcmd_regs_t *regs = bus->regs;
7682 	uint32 intstatus, newstatus = 0;
7683 	uint retries = 0;
7684 	uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
7685 	uint txlimit = dhd_txbound; /* Tx frames to send before resched */
7686 	uint framecnt = 0;		  /* Temporary counter of tx/rx frames */
7687 	bool rxdone = TRUE;		  /* Flag for no more read data */
7688 	bool resched = FALSE;	  /* Flag indicating resched wanted */
7689 	unsigned long flags;
7690 #ifdef DEBUG_DPC_THREAD_WATCHDOG
7691 	bool is_resched_by_readframe = FALSE;
7692 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
7693 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7694 
7695 	dhd_os_sdlock(bus->dhd);
7696 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
7697 	if (bus->dhd->busstate == DHD_BUS_DOWN) {
7698 		DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
7699 		bus->intstatus = 0;
7700 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
7701 		dhd_os_sdunlock(bus->dhd);
7702 		return 0;
7703 	}
7704 
7705 	DHD_BUS_BUSY_SET_IN_DPC(bus->dhd);
7706 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
7707 
7708 	/* Start with leftover status bits */
7709 	intstatus = bus->intstatus;
7710 
7711 	if (!SLPAUTO_ENAB(bus) && !KSO_ENAB(bus)) {
7712 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
7713 		goto exit;
7714 	}
7715 
7716 	/* If waiting for HTAVAIL, check status */
7717 	if (!SLPAUTO_ENAB(bus) && (bus->clkstate == CLK_PENDING)) {
7718 		int err;
7719 		uint8 clkctl, devctl = 0;
7720 
7721 #ifdef DHD_DEBUG
7722 		/* Check for inconsistent device control */
7723 		devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
7724 		if (err) {
7725 			DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
7726 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7727 			bus->dhd->busstate = DHD_BUS_DOWN;
7728 		} else {
7729 			ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
7730 		}
7731 #endif /* DHD_DEBUG */
7732 
7733 		/* Read CSR, if clock on switch to AVAIL, else ignore */
7734 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
7735 		if (err) {
7736 			DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
7737 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7738 			bus->dhd->busstate = DHD_BUS_DOWN;
7739 		}
7740 
7741 		DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl));
7742 
7743 		if (SBSDIO_HTAV(clkctl)) {
7744 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
7745 			if (err) {
7746 				DHD_ERROR(("%s: error reading DEVCTL: %d\n",
7747 				           __FUNCTION__, err));
7748 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7749 				bus->dhd->busstate = DHD_BUS_DOWN;
7750 			}
7751 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
7752 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
7753 			if (err) {
7754 				DHD_ERROR(("%s: error writing DEVCTL: %d\n",
7755 				           __FUNCTION__, err));
7756 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7757 				bus->dhd->busstate = DHD_BUS_DOWN;
7758 			}
7759 			bus->clkstate = CLK_AVAIL;
7760 		} else {
7761 			goto clkwait;
7762 		}
7763 	}
7764 
7765 	BUS_WAKE(bus);
7766 
7767 	/* Make sure backplane clock is on */
7768 	dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
7769 	if (bus->clkstate != CLK_AVAIL)
7770 		goto clkwait;
7771 
7772 	/* Pending interrupt indicates new device status */
7773 	if (bus->ipend) {
7774 		bus->ipend = FALSE;
7775 #if defined(BT_OVER_SDIO)
7776 	bcmsdh_btsdio_process_f3_intr();
7777 #endif /* defined (BT_OVER_SDIO) */
7778 
7779 #ifdef BCMSDIO_INTSTATUS_WAR
7780 		newstatus = dhdsdio_read_intstatus_byte(bus);
7781 #else
7782 		R_SDREG(newstatus, &regs->intstatus, retries);
7783 #endif
7784 		bus->f1regdata++;
7785 		if (bcmsdh_regfail(bus->sdh))
7786 			newstatus = 0;
7787 		newstatus &= bus->hostintmask;
7788 		bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
7789 		if (newstatus) {
7790 			bus->f1regdata++;
7791 #ifndef BCMSPI
7792 			if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) &&
7793 				(newstatus == I_XMTDATA_AVAIL)) {
7794 			} else
7795 #endif /* BCMSPI */
7796 				W_SDREG(newstatus, &regs->intstatus, retries);
7797 		}
7798 	}
7799 
7800 	/* Merge new bits with previous */
7801 	intstatus |= newstatus;
7802 	bus->intstatus = 0;
7803 
7804 	/* Handle flow-control change: read new state in case our ack
7805 	 * crossed another change interrupt.  If change still set, assume
7806 	 * FC ON for safety, let next loop through do the debounce.
7807 	 */
7808 	if (intstatus & I_HMB_FC_CHANGE) {
7809 		intstatus &= ~I_HMB_FC_CHANGE;
7810 		W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
7811 		R_SDREG(newstatus, &regs->intstatus, retries);
7812 		bus->f1regdata += 2;
7813 		bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
7814 		intstatus |= (newstatus & bus->hostintmask);
7815 	}
7816 
7817 	/* Handle host mailbox indication */
7818 	if (intstatus & I_HMB_HOST_INT) {
7819 		uint32 hmbdata = 0;
7820 
7821 		intstatus &= ~I_HMB_HOST_INT;
7822 		intstatus |= dhdsdio_hostmail(bus, &hmbdata);
7823 
7824 	}
7825 
7826 #ifdef DHD_UCODE_DOWNLOAD
7827 exit_ucode:
7828 #endif /* DHD_UCODE_DOWNLOAD */
7829 
7830 	/* Just being here means nothing more to do for chipactive */
7831 	if (intstatus & I_CHIPACTIVE) {
7832 		/* ASSERT(bus->clkstate == CLK_AVAIL); */
7833 		intstatus &= ~I_CHIPACTIVE;
7834 	}
7835 
7836 	/* Handle host mailbox indication */
7837 	if (intstatus & I_HMB_HOST_INT) {
7838 		intstatus &= ~I_HMB_HOST_INT;
7839 		intstatus |= dhdsdio_hostmail(bus, NULL);
7840 	}
7841 
7842 	/* Generally don't ask for these, can get CRC errors... */
7843 	/* XXX Besides noting the error, should we ABORT/TERM? */
7844 	if (intstatus & I_WR_OOSYNC) {
7845 		DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
7846 		intstatus &= ~I_WR_OOSYNC;
7847 	}
7848 
7849 	if (intstatus & I_RD_OOSYNC) {
7850 		DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
7851 		intstatus &= ~I_RD_OOSYNC;
7852 	}
7853 
7854 	/* XXX Should reset or something here... */
7855 	if (intstatus & I_SBINT) {
7856 		DHD_ERROR(("Dongle reports SBINT\n"));
7857 		intstatus &= ~I_SBINT;
7858 	}
7859 
7860 	/* Would be active due to wake-wlan in gSPI */
7861 	if (intstatus & I_CHIPACTIVE) {
7862 		DHD_INFO(("Dongle reports CHIPACTIVE\n"));
7863 		intstatus &= ~I_CHIPACTIVE;
7864 	}
7865 
7866 	if (intstatus & I_HMB_FC_STATE) {
7867 		DHD_INFO(("Dongle reports HMB_FC_STATE\n"));
7868 		intstatus &= ~I_HMB_FC_STATE;
7869 	}
7870 
7871 	/* Ignore frame indications if rxskip is set */
7872 	if (bus->rxskip) {
7873 		intstatus &= ~FRAME_AVAIL_MASK(bus);
7874 	}
7875 
7876 	/* On frame indication, read available frames */
7877 	if (PKT_AVAILABLE(bus, intstatus)) {
7878 #ifdef BCMINTERNAL
7879 		if (checkfifo) {
7880 			int count, regerrs = 0;
7881 			uint32 fifoaddr, rdptr, rdoffs, endptrs;
7882 			uint32 datalow[8], datahigh[8];
7883 			uint coretype = bus->sih->buscoretype;
7884 			uint corerev = bus->sdpcmrev;
7885 
7886 			/* set fifoaddr to fetch xmt fifo pointers */
7887 			fifoaddr = (0xB << 16);
7888 			W_SDREG(fifoaddr, &SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr, retries);
7889 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7890 			R_SDREG(rdptr, &SDPCMFIFOREG(bus, coretype, corerev)->fifodatalow, retries);
7891 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7892 
7893 			/* Read the first 8 words out of the FIFO */
7894 			for (count = 0, rdoffs = (rdptr & 0x7F); count < 8; count++) {
7895 				fifoaddr = (0xA << 16) | rdoffs;
7896 				W_SDREG(fifoaddr,
7897 					&SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr,
7898 					retries);
7899 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7900 				R_SDREG(datalow[count],
7901 					&SDPCMFIFOREG(bus, coretype, corerev)->fifodatalow,
7902 					retries);
7903 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7904 				W_SDREG(fifoaddr,
7905 					&SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr,
7906 					retries);
7907 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7908 				R_SDREG(datahigh[count],
7909 					&SDPCMFIFOREG(bus, coretype, corerev)->fifodatahigh,
7910 					retries);
7911 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7912 				rdoffs = (rdoffs + 1) & 0x7F;
7913 			}
7914 
7915 			/* For the heck of it, read the pointers again */
7916 			fifoaddr = (0xB << 16);
7917 			W_SDREG(fifoaddr,
7918 				&SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr, retries);
7919 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7920 			R_SDREG(endptrs,
7921 				&SDPCMFIFOREG(bus, coretype, corerev)->fifodatalow, retries);
7922 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7923 
7924 			printf("Initial read of Transmit DMA Pointers: 0x%08x\n", rdptr);
7925 			printf("Transmit DMA Data\n");
7926 			for (count = 0, rdoffs = (rdptr & 0x7F); count < 8; count++) {
7927 				printf("0x%08x: 0x%08x 0x%08x\n", rdoffs,
7928 				       datahigh[count], datalow[count]);
7929 				rdoffs = (rdoffs + 1) & 0x7F;
7930 			}
7931 			printf("Final read of Transmit DMA Pointers: 0x%08x\n", endptrs);
7932 			printf("Register errors: %d\n", regerrs);
7933 
7934 			checkfifo = FALSE;
7935 		}
7936 #endif /* BCMINTERNAL */
7937 
7938 		framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
7939 		if (rxdone || bus->rxskip)
7940 			intstatus  &= ~FRAME_AVAIL_MASK(bus);
7941 		rxlimit -= MIN(framecnt, rxlimit);
7942 	}
7943 
7944 	/* Keep still-pending events for next scheduling */
7945 	bus->intstatus = intstatus;
7946 
7947 clkwait:
7948 	/* Re-enable interrupts to detect new device events (mailbox, rx frame)
7949 	 * or clock availability.  (Allows tx loop to check ipend if desired.)
7950 	 * (Unless register access seems hosed, as we may not be able to ACK...)
7951 	 */
7952 	if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) &&
7953 			!(bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) {
7954 		DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
7955 		          __FUNCTION__, rxdone, framecnt));
7956 		bus->intdis = FALSE;
7957 #if defined(OOB_INTR_ONLY)
7958 		bcmsdh_oob_intr_set(bus->sdh, TRUE);
7959 #endif /* defined(OOB_INTR_ONLY) */
7960 #if !defined(NDIS)
7961 		bcmsdh_intr_enable(sdh);
7962 #endif /* !defined(NDIS) */
7963 #ifdef BCMSPI_ANDROID
7964 		if (*dhd_spi_lockcount == 0)
7965 			bcmsdh_oob_intr_set(bus->sdh, TRUE);
7966 #endif /* BCMSPI_ANDROID */
7967 	}
7968 
7969 #if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
7970 	/* In case of SW-OOB(using edge trigger),
7971 	 * Check interrupt status in the dongle again after enable irq on the host.
7972 	 * and rechedule dpc if interrupt is pended in the dongle.
7973 	 * There is a chance to miss OOB interrupt while irq is disabled on the host.
7974 	 * No need to do this with HW-OOB(level trigger)
7975 	 */
7976 	R_SDREG(newstatus, &regs->intstatus, retries);
7977 	if (bcmsdh_regfail(bus->sdh))
7978 		newstatus = 0;
7979 	if (newstatus & bus->hostintmask) {
7980 		bus->ipend = TRUE;
7981 		resched = TRUE;
7982 	}
7983 #endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */
7984 
7985 #ifdef BCMSDIO_RXLIM_POST
7986 	if (!DATAOK(bus) && bus->rxlim_en) {
7987 		uint8 rxlim = 0;
7988 		if (0 == dhdsdio_membytes(bus, FALSE, bus->rxlim_addr, (uint8 *)&rxlim, 1)) {
7989 			if (bus->tx_max != rxlim) {
7990 				DHD_INFO(("%s: bus->tx_max/rxlim=%d/%d\n", __FUNCTION__,
7991 					bus->tx_max, rxlim));
7992 				bus->tx_max = rxlim;
7993 			}
7994 		}
7995 	}
7996 #endif /* BCMSDIO_RXLIM_POST */
7997 
7998 #ifdef PROP_TXSTATUS
7999 	dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
8000 #endif
8001 
8002 	if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
8003 		dhdsdio_sendpendctl(bus);
8004 #ifdef CONSOLE_DPC
8005 	else if (DATAOK(bus) && strlen(bus->cons_cmd) && (bus->clkstate == CLK_AVAIL) &&
8006 			!bus->fcstate) {
8007 		dhd_bus_console_in(bus->dhd, bus->cons_cmd, strlen(bus->cons_cmd));
8008 	}
8009 #endif
8010 
8011 	/* Send queued frames (limit 1 if rx may still be pending) */
8012 	else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
8013 	    pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
8014 
8015 			if (bus->dhd->conf->dhd_txminmax < 0)
8016 				framecnt = rxdone ? txlimit : MIN(txlimit, DATABUFCNT(bus));
8017 			else
8018 				framecnt = rxdone ? txlimit : MIN(txlimit, bus->dhd->conf->dhd_txminmax);
8019 			framecnt = dhdsdio_sendfromq(bus, framecnt);
8020 			txlimit -= framecnt;
8021 	}
8022 	/* Resched the DPC if ctrl cmd is pending on bus credit */
8023 	if (bus->ctrl_frame_stat) {
8024 		if (bus->dhd->conf->txctl_tmo_fix) {
8025 			set_current_state(TASK_INTERRUPTIBLE);
8026 			if (!kthread_should_stop())
8027 				schedule_timeout(1);
8028 			set_current_state(TASK_RUNNING);
8029 		}
8030 		resched = TRUE;
8031 	}
8032 
8033 	/* Resched if events or tx frames are pending, else await next interrupt */
8034 	/* On failed register access, all bets are off: no resched or interrupts */
8035 	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
8036 		if ((bus->sih && bus->sih->buscorerev >= 12) && !(dhdsdio_sleepcsr_get(bus) &
8037 			SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
8038 			/* Bus failed because of KSO */
8039 			DHD_ERROR(("%s: Bus failed due to KSO\n", __FUNCTION__));
8040 			bus->kso = FALSE;
8041 		} else {
8042 			DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
8043 				__FUNCTION__));
8044 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
8045 			bus->dhd->busstate = DHD_BUS_DOWN;
8046 			bus->intstatus = 0;
8047 			/* XXX Under certain conditions it may be reasonable to enable interrupts.
8048 			 * E.g. if we get occasional 'bcmsdh_regfail' we should be able to continue
8049 			 * operation. May want to make the decision to enable or not based on count
8050 			 * of failures, so in case of bus lock up we avoid continuous interrupt.
8051 			 */
8052 		}
8053 	} else if (bus->clkstate == CLK_PENDING) {
8054 		/* Awaiting I_CHIPACTIVE; don't resched */
8055 	} else if (bus->intstatus || bus->ipend ||
8056 			(!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
8057 			PKT_AVAILABLE(bus, bus->intstatus)) {  /* Read multiple frames */
8058 		resched = TRUE;
8059 	}
8060 
8061 	bus->dpc_sched = resched;
8062 
8063 	/* If we're done for now, turn off clock request. */
8064 	/* XXX Leave request on if just waiting for new credit? */
8065 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING) &&
8066 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8067 		bus->activity = FALSE;
8068 		dhdsdio_bussleep(bus, TRUE);
8069 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8070 	}
8071 
8072 exit:
8073 
8074 	if (!resched) {
8075 		/* Re-enable interrupts to detect new device events (mailbox, rx frame)
8076 		 * or clock availability.  (Allows tx loop to check ipend if desired.)
8077 		 * (Unless register access seems hosed, as we may not be able to ACK...)
8078 		 */
8079 		if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) &&
8080 				(bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) {
8081 			DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
8082 					  __FUNCTION__, rxdone, framecnt));
8083 			bus->intdis = FALSE;
8084 #if defined(OOB_INTR_ONLY)
8085 			bcmsdh_oob_intr_set(bus->sdh, TRUE);
8086 #endif /* defined(OOB_INTR_ONLY) */
8087 			bcmsdh_intr_enable(sdh);
8088 		}
8089 		if (dhd_dpcpoll) {
8090 			if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) {
8091 				resched = TRUE;
8092 #ifdef DEBUG_DPC_THREAD_WATCHDOG
8093 				is_resched_by_readframe = TRUE;
8094 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
8095 			}
8096 		}
8097 	}
8098 
8099 #ifdef TPUT_MONITOR
8100 	dhd_conf_tput_monitor(bus->dhd);
8101 #endif
8102 
8103 	if (bus->ctrl_wait && TXCTLOK(bus))
8104 		wake_up_interruptible(&bus->ctrl_tx_wait);
8105 	dhd_os_sdunlock(bus->dhd);
8106 #ifdef DEBUG_DPC_THREAD_WATCHDOG
8107 	if (bus->dhd->dhd_bug_on) {
8108 		DHD_INFO(("%s: resched = %d ctrl_frame_stat = %d intstatus 0x%08x"
8109 			" ipend = %d pktq_mlen = %d is_resched_by_readframe = %d \n",
8110 			__FUNCTION__, resched, bus->ctrl_frame_stat,
8111 			bus->intstatus, bus->ipend,
8112 			pktq_mlen(&bus->txq, ~bus->flowcontrol), is_resched_by_readframe));
8113 
8114 			bus->dhd->dhd_bug_on = FALSE;
8115 	}
8116 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
8117 
8118 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
8119 	DHD_BUS_BUSY_CLEAR_IN_DPC(bus->dhd);
8120 	dhd_os_busbusy_wake(bus->dhd);
8121 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
8122 
8123 	return resched;
8124 }
8125 
8126 bool
dhd_bus_dpc(struct dhd_bus * bus)8127 dhd_bus_dpc(struct dhd_bus *bus)
8128 {
8129 	bool resched;
8130 
8131 	/* Call the DPC directly. */
8132 	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
8133 	resched = dhdsdio_dpc(bus);
8134 
8135 	return resched;
8136 }
8137 
8138 void
dhdsdio_isr(void * arg)8139 dhdsdio_isr(void *arg)
8140 {
8141 	dhd_bus_t *bus = (dhd_bus_t*)arg;
8142 	bcmsdh_info_t *sdh;
8143 
8144 	if (!bus) {
8145 		DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
8146 		return;
8147 	}
8148 	sdh = bus->sdh;
8149 
8150 	if (bus->dhd->busstate == DHD_BUS_DOWN) {
8151 		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
8152 		return;
8153 	}
8154 	/* XXX Overall operation:
8155 	 * XXX   - Mask further interrupts
8156 	 * XXX   - Read/ack intstatus
8157 	 * XXX   - Take action based on bits and state
8158 	 * XXX   - Reenable interrupts (as per state)
8159 	 */
8160 
8161 	DHD_INTR(("%s: Enter\n", __FUNCTION__));
8162 
8163 	/* Count the interrupt call */
8164 	bus->intrcount++;
8165 	bus->ipend = TRUE;
8166 
8167 	/* Shouldn't get this interrupt if we're sleeping? */
8168 	if (!SLPAUTO_ENAB(bus)) {
8169 		if (bus->sleeping) {
8170 			DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
8171 			return;
8172 		} else if (!KSO_ENAB(bus)) {
8173 			DHD_ERROR(("ISR in devsleep 1\n"));
8174 		}
8175 	}
8176 
8177 	/* Disable additional interrupts (is this needed now)? */
8178 	if (bus->intr) {
8179 		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
8180 	} else {
8181 		DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
8182 	}
8183 
8184 #ifdef BCMSPI_ANDROID
8185 	bcmsdh_oob_intr_set(bus->sdh, FALSE);
8186 #endif /* BCMSPI_ANDROID */
8187 #if !defined(NDIS)
8188 	bcmsdh_intr_disable(sdh); /* XXX New API: bcmsdh_intr_mask()? */
8189 #endif /* !defined(NDIS) */
8190 	bus->intdis = TRUE;
8191 
8192 #if defined(SDIO_ISR_THREAD)
8193 	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
8194 	DHD_OS_WAKE_LOCK(bus->dhd);
8195 	/* terence 20150209: dpc should be scheded again if dpc_sched is TRUE or dhd_bus_txdata can
8196 	    not schedule anymore because dpc_sched is TRUE now.
8197 	 */
8198 	if (dhdsdio_dpc(bus)) {
8199 		bus->dpc_sched = TRUE;
8200 		dhd_sched_dpc(bus->dhd);
8201 	}
8202 	DHD_OS_WAKE_UNLOCK(bus->dhd);
8203 #else
8204 #if !defined(NDIS)
8205 	bus->dpc_sched = TRUE;
8206 	dhd_sched_dpc(bus->dhd);
8207 #endif /* !defined(NDIS) */
8208 #endif /* defined(SDIO_ISR_THREAD) */
8209 
8210 }
8211 
8212 #ifdef PKT_STATICS
8213 void
dhd_bus_dump_txpktstatics(dhd_pub_t * dhdp)8214 dhd_bus_dump_txpktstatics(dhd_pub_t *dhdp)
8215 {
8216 	dhd_bus_t *bus = dhdp->bus;
8217 	uint32 total = 0;
8218 	uint i;
8219 
8220 	printf("%s: TYPE EVENT: %d pkts (size=%d) transfered\n",
8221 		__FUNCTION__, bus->tx_statics.event_count, bus->tx_statics.event_size);
8222 	printf("%s: TYPE CTRL:  %d pkts (size=%d) transfered\n",
8223 		__FUNCTION__, bus->tx_statics.ctrl_count, bus->tx_statics.ctrl_size);
8224 	printf("%s: TYPE DATA:  %d pkts (size=%d) transfered\n",
8225 		__FUNCTION__, bus->tx_statics.data_count, bus->tx_statics.data_size);
8226 	printf("%s: Glom size distribution:\n", __FUNCTION__);
8227 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8228 		total += bus->tx_statics.glom_cnt[i];
8229 	}
8230 	printk(KERN_CONT DHD_LOG_PREFIXS);
8231 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8232 		printk(KERN_CONT "%02d: %5d", i+1, bus->tx_statics.glom_cnt[i]);
8233 		if ((i+1)%8)
8234 			printk(KERN_CONT ", ");
8235 		else {
8236 			printk("\n");
8237 			printk(KERN_CONT DHD_LOG_PREFIXS);
8238 		}
8239 	}
8240 	printk("\n");
8241 	printk(KERN_CONT DHD_LOG_PREFIXS);
8242 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8243 		printk(KERN_CONT "%02d:%5d%%", i+1, (bus->tx_statics.glom_cnt[i]*100)/total);
8244 		if ((i+1)%8)
8245 			printk(KERN_CONT ", ");
8246 		else {
8247 			printk("\n");
8248 			printk(KERN_CONT DHD_LOG_PREFIXS);
8249 		}
8250 	}
8251 	printk("\n");
8252 	printf("%s: Glom spend time distribution(us):\n", __FUNCTION__);
8253 	printk(KERN_CONT DHD_LOG_PREFIXS);
8254 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8255 		printk(KERN_CONT "%02d: %5u", i+1, bus->tx_statics.glom_cnt_us[i]);
8256 		if ((i+1)%8)
8257 			printk(KERN_CONT ", ");
8258 		else {
8259 			printk("\n");
8260 			printk(KERN_CONT DHD_LOG_PREFIXS);
8261 		}
8262 	}
8263 	printk("\n");
8264 	if (total) {
8265 		printf("%s: data(%d)/glom(%d)=%d, glom_max=%d\n",
8266 			__FUNCTION__, bus->tx_statics.data_count, total,
8267 			bus->tx_statics.data_count/total, bus->tx_statics.glom_max);
8268 	}
8269 	printf("%s: TYPE RX GLOM: %d pkts (size=%d) transfered\n",
8270 		__FUNCTION__, bus->tx_statics.glom_count, bus->tx_statics.glom_size);
8271 	printf("%s: TYPE TEST: %d pkts (size=%d) transfered\n",
8272 		__FUNCTION__, bus->tx_statics.test_count, bus->tx_statics.test_size);
8273 
8274 #ifdef KSO_DEBUG
8275 	printf("%s: kso try distribution(us):\n", __FUNCTION__);
8276 	printk(KERN_CONT DHD_LOG_PREFIXS);
8277 	for (i=0; i<10; i++) {
8278 		printk(KERN_CONT "[%d]: %d, ", i, dhdp->conf->kso_try_array[i]);
8279 	}
8280 	printk("\n");
8281 #endif
8282 }
8283 
8284 void
dhd_bus_clear_txpktstatics(dhd_pub_t * dhdp)8285 dhd_bus_clear_txpktstatics(dhd_pub_t *dhdp)
8286 {
8287 	dhd_bus_t *bus = dhdp->bus;
8288 	memset((uint8*) &bus->tx_statics, 0, sizeof(pkt_statics_t));
8289 }
8290 #endif
8291 
8292 #ifdef SDTEST
8293 static void
dhdsdio_pktgen_init(dhd_bus_t * bus)8294 dhdsdio_pktgen_init(dhd_bus_t *bus)
8295 {
8296 	/* Default to specified length, or full range */
8297 	if (dhd_pktgen_len) {
8298 		bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN);
8299 		bus->pktgen_minlen = bus->pktgen_maxlen;
8300 	} else {
8301 		bus->pktgen_maxlen = MAX_PKTGEN_LEN;
8302 		bus->pktgen_minlen = 0;
8303 	}
8304 	bus->pktgen_len = (uint16)bus->pktgen_minlen;
8305 
8306 	/* Default to per-watchdog burst with 10s print time */
8307 	bus->pktgen_freq = 1;
8308 	bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0;
8309 	bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
8310 
8311 	/* Default to echo mode */
8312 	bus->pktgen_mode = DHD_PKTGEN_ECHO;
8313 	bus->pktgen_stop = 1;
8314 }
8315 
8316 static void
dhdsdio_pktgen(dhd_bus_t * bus)8317 dhdsdio_pktgen(dhd_bus_t *bus)
8318 {
8319 	void *pkt;
8320 	uint8 *data;
8321 	uint pktcount;
8322 	uint fillbyte;
8323 	osl_t *osh = bus->dhd->osh;
8324 	uint16 len;
8325 #if defined(LINUX)
8326 	ulong time_lapse;
8327 	uint sent_pkts;
8328 	uint rcvd_pkts;
8329 #endif /* LINUX */
8330 
8331 	/* Display current count if appropriate */
8332 	if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
8333 		bus->pktgen_ptick = 0;
8334 		printf("%s: send attempts %d, rcvd %d, errors %d\n",
8335 		       __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
8336 
8337 #if defined(LINUX)
8338 		/* Print throughput stats only for constant length packet runs */
8339 		if (bus->pktgen_minlen == bus->pktgen_maxlen) {
8340 			time_lapse = jiffies - bus->pktgen_prev_time;
8341 			bus->pktgen_prev_time = jiffies;
8342 			sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent;
8343 			bus->pktgen_prev_sent = bus->pktgen_sent;
8344 			rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd;
8345 			bus->pktgen_prev_rcvd = bus->pktgen_rcvd;
8346 
8347 			printf("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n",
8348 			  __FUNCTION__,
8349 			  (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8,
8350 			  (rcvd_pkts * bus->pktgen_len  / jiffies_to_msecs(time_lapse)) * 8);
8351 		}
8352 #endif /* LINUX */
8353 	}
8354 
8355 	/* For recv mode, just make sure dongle has started sending */
8356 	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
8357 		if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) {
8358 			bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING;
8359 			dhdsdio_sdtest_set(bus, bus->pktgen_total);
8360 		}
8361 		return;
8362 	}
8363 
8364 	/* Otherwise, generate or request the specified number of packets */
8365 	for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
8366 		/* Stop if total has been reached */
8367 		if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) {
8368 			bus->pktgen_count = 0;
8369 			break;
8370 		}
8371 
8372 		/* Allocate an appropriate-sized packet */
8373 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
8374 			len = SDPCM_TEST_PKT_CNT_FLD_LEN;
8375 		} else {
8376 			len = bus->pktgen_len;
8377 		}
8378 		if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
8379 		                   TRUE))) {;
8380 			DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
8381 			break;
8382 		}
8383 		PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
8384 		data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
8385 
8386 		/* Write test header cmd and extra based on mode */
8387 		switch (bus->pktgen_mode) {
8388 		case DHD_PKTGEN_ECHO:
8389 			*data++ = SDPCM_TEST_ECHOREQ;
8390 			*data++ = (uint8)bus->pktgen_sent;
8391 			break;
8392 
8393 		case DHD_PKTGEN_SEND:
8394 			*data++ = SDPCM_TEST_DISCARD;
8395 			*data++ = (uint8)bus->pktgen_sent;
8396 			break;
8397 
8398 		case DHD_PKTGEN_RXBURST:
8399 			*data++ = SDPCM_TEST_BURST;
8400 			*data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */
8401 			break;
8402 
8403 		default:
8404 			DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode));
8405 			PKTFREE(osh, pkt, TRUE);
8406 			bus->pktgen_count = 0;
8407 			return;
8408 		}
8409 
8410 		/* Write test header length field */
8411 		*data++ = (bus->pktgen_len >> 0);
8412 		*data++ = (bus->pktgen_len >> 8);
8413 
8414 		/* Write frame count in a 4 byte field adjucent to SDPCM test header for
8415 		 * burst mode
8416 		 */
8417 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
8418 			*data++ = (uint8)(bus->pktgen_count >> 0);
8419 			*data++ = (uint8)(bus->pktgen_count >> 8);
8420 			*data++ = (uint8)(bus->pktgen_count >> 16);
8421 			*data++ = (uint8)(bus->pktgen_count >> 24);
8422 		} else {
8423 
8424 			/* Then fill in the remainder -- N/A for burst */
8425 			for (fillbyte = 0; fillbyte < len; fillbyte++)
8426 				*data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent);
8427 		}
8428 
8429 #ifdef DHD_DEBUG
8430 		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
8431 			data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
8432 			prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
8433 		}
8434 #endif
8435 
8436 		/* Send it */
8437 		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) {
8438 			bus->pktgen_fail++;
8439 			if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail)
8440 				bus->pktgen_count = 0;
8441 		}
8442 		bus->pktgen_sent++;
8443 
8444 		/* Bump length if not fixed, wrap at max */
8445 		if (++bus->pktgen_len > bus->pktgen_maxlen)
8446 			bus->pktgen_len = (uint16)bus->pktgen_minlen;
8447 
8448 		/* Special case for burst mode: just send one request! */
8449 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
8450 			break;
8451 	}
8452 }
8453 
8454 static void
dhdsdio_sdtest_set(dhd_bus_t * bus,uint count)8455 dhdsdio_sdtest_set(dhd_bus_t *bus, uint count)
8456 {
8457 	void *pkt;
8458 	uint8 *data;
8459 	osl_t *osh = bus->dhd->osh;
8460 
8461 	/* Allocate the packet */
8462 	if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
8463 		SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) {
8464 		DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
8465 		return;
8466 	}
8467 	PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
8468 		SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN);
8469 	data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
8470 
8471 	/* Fill in the test header */
8472 	*data++ = SDPCM_TEST_SEND;
8473 	*data++ = (count > 0)?TRUE:FALSE;
8474 	*data++ = (bus->pktgen_maxlen >> 0);
8475 	*data++ = (bus->pktgen_maxlen >> 8);
8476 	*data++ = (uint8)(count >> 0);
8477 	*data++ = (uint8)(count >> 8);
8478 	*data++ = (uint8)(count >> 16);
8479 	*data++ = (uint8)(count >> 24);
8480 
8481 	/* Send it */
8482 	if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK)
8483 		bus->pktgen_fail++;
8484 }
8485 
8486 static void
dhdsdio_testrcv(dhd_bus_t * bus,void * pkt,uint seq)8487 dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
8488 {
8489 	osl_t *osh = bus->dhd->osh;
8490 	uint8 *data;
8491 	uint pktlen;
8492 
8493 	uint8 cmd;
8494 	uint8 extra;
8495 	uint16 len;
8496 	uint16 offset;
8497 
8498 	/* Check for min length */
8499 	if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) {
8500 		DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen));
8501 		PKTFREE(osh, pkt, FALSE);
8502 		return;
8503 	}
8504 
8505 	/* Extract header fields */
8506 	data = PKTDATA(osh, pkt);
8507 	cmd = *data++;
8508 	extra = *data++;
8509 	len = *data++; len += *data++ << 8;
8510 	DHD_TRACE(("%s:cmd:%d, xtra:%d,len:%d\n", __FUNCTION__, cmd, extra, len));
8511 	/* Check length for relevant commands */
8512 	if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) {
8513 		if (pktlen != len + SDPCM_TEST_HDRLEN) {
8514 			DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d"
8515 			           " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
8516 			PKTFREE(osh, pkt, FALSE);
8517 			return;
8518 		}
8519 	}
8520 
8521 	/* Process as per command */
8522 	switch (cmd) {
8523 	case SDPCM_TEST_ECHOREQ:
8524 		/* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
8525 		*(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP;
8526 		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) == BCME_OK) {
8527 			bus->pktgen_sent++;
8528 		} else {
8529 			bus->pktgen_fail++;
8530 			PKTFREE(osh, pkt, FALSE);
8531 		}
8532 		bus->pktgen_rcvd++;
8533 		break;
8534 
8535 	case SDPCM_TEST_ECHORSP:
8536 		if (bus->ext_loop) {
8537 			PKTFREE(osh, pkt, FALSE);
8538 			bus->pktgen_rcvd++;
8539 			break;
8540 		}
8541 
8542 		for (offset = 0; offset < len; offset++, data++) {
8543 			if (*data != SDPCM_TEST_FILL(offset, extra)) {
8544 				DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: "
8545 				           "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
8546 				           offset, len, SDPCM_TEST_FILL(offset, extra), *data));
8547 				break;
8548 			}
8549 		}
8550 		PKTFREE(osh, pkt, FALSE);
8551 		bus->pktgen_rcvd++;
8552 		break;
8553 
8554 	case SDPCM_TEST_DISCARD:
8555 		{
8556 			int i = 0;
8557 			uint8 *prn = data;
8558 			uint8 testval = extra;
8559 			for (i = 0; i < len; i++) {
8560 				if (*prn != testval) {
8561 					DHD_ERROR(("DIErr@Pkt#:%d,Ix:%d, expected:0x%x, got:0x%x\n",
8562 						i, bus->pktgen_rcvd_rcvsession, testval, *prn));
8563 					prn++; testval++;
8564 				}
8565 			}
8566 		}
8567 		PKTFREE(osh, pkt, FALSE);
8568 		bus->pktgen_rcvd++;
8569 		break;
8570 
8571 	case SDPCM_TEST_BURST:
8572 	case SDPCM_TEST_SEND:
8573 	default:
8574 		DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
8575 		          " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
8576 		PKTFREE(osh, pkt, FALSE);
8577 		break;
8578 	}
8579 
8580 	/* For recv mode, stop at limit (and tell dongle to stop sending) */
8581 	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
8582 		if (bus->pktgen_rcv_state != PKTGEN_RCV_IDLE) {
8583 			bus->pktgen_rcvd_rcvsession++;
8584 
8585 			if (bus->pktgen_total &&
8586 				(bus->pktgen_rcvd_rcvsession >= bus->pktgen_total)) {
8587 			bus->pktgen_count = 0;
8588 			DHD_ERROR(("Pktgen:rcv test complete!\n"));
8589 			bus->pktgen_rcv_state = PKTGEN_RCV_IDLE;
8590 			dhdsdio_sdtest_set(bus, FALSE);
8591 				bus->pktgen_rcvd_rcvsession = 0;
8592 			}
8593 		}
8594 	}
8595 }
8596 #endif /* SDTEST */
8597 
dhd_bus_oob_intr_register(dhd_pub_t * dhdp)8598 int dhd_bus_oob_intr_register(dhd_pub_t *dhdp)
8599 {
8600 	int err = 0;
8601 
8602 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8603 	err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus);
8604 #endif
8605 	return err;
8606 }
8607 
dhd_bus_oob_intr_unregister(dhd_pub_t * dhdp)8608 void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
8609 {
8610 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8611 	bcmsdh_oob_intr_unregister(dhdp->bus->sdh);
8612 #endif
8613 }
8614 
dhd_bus_oob_intr_set(dhd_pub_t * dhdp,bool enable)8615 void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
8616 {
8617 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8618 	bcmsdh_oob_intr_set(dhdp->bus->sdh, enable);
8619 #endif
8620 }
8621 
dhd_bus_get_oob_irq_num(dhd_pub_t * dhdp)8622 int dhd_bus_get_oob_irq_num(dhd_pub_t *dhdp)
8623 {
8624 	int irq_num = 0;
8625 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8626 	irq_num = bcmsdh_get_oob_intr_num(dhdp->bus->sdh);
8627 #endif /* OOB_INTR_ONLY || BCMSPI_ANDROID */
8628 	return irq_num;
8629 }
8630 
8631 #ifdef LINUX
dhd_bus_to_dev(struct dhd_bus * bus)8632 struct device *dhd_bus_to_dev(struct dhd_bus *bus)
8633 {
8634 	return (struct device *)bcmsdh_get_dev(bus->sdh);
8635 }
8636 #endif /* LINUX */
8637 
dhd_bus_dev_pm_stay_awake(dhd_pub_t * dhdpub)8638 void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
8639 {
8640 #ifdef LINUX
8641 	bcmsdh_dev_pm_stay_awake(dhdpub->bus->sdh);
8642 #endif
8643 }
8644 
dhd_bus_dev_pm_relax(dhd_pub_t * dhdpub)8645 void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub)
8646 {
8647 #ifdef LINUX
8648 	bcmsdh_dev_relax(dhdpub->bus->sdh);
8649 #endif
8650 }
8651 
dhd_bus_dev_pm_enabled(dhd_pub_t * dhdpub)8652 bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub)
8653 {
8654 	bool enabled = FALSE;
8655 
8656 #ifdef LINUX
8657 	enabled = bcmsdh_dev_pm_enabled(dhdpub->bus->sdh);
8658 #endif
8659 	return enabled;
8660 }
8661 
8662 extern bool
dhd_bus_watchdog(dhd_pub_t * dhdp)8663 dhd_bus_watchdog(dhd_pub_t *dhdp)
8664 {
8665 	dhd_bus_t *bus;
8666 	unsigned long flags;
8667 
8668 	DHD_TIMER(("%s: Enter\n", __FUNCTION__));
8669 
8670 	bus = dhdp->bus;
8671 
8672 	if (bus->dhd->dongle_reset)
8673 		return FALSE;
8674 
8675 	if (bus->dhd->hang_was_sent) {
8676 		dhd_os_wd_timer(bus->dhd, 0);
8677 		return FALSE;
8678 	}
8679 
8680 	/* Ignore the timer if simulating bus down */
8681 	if (!SLPAUTO_ENAB(bus) && bus->sleeping)
8682 		return FALSE;
8683 
8684 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
8685 	if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp) ||
8686 			DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp)) {
8687 		DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8688 		return FALSE;
8689 	}
8690 	DHD_BUS_BUSY_SET_IN_WD(dhdp);
8691 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8692 
8693 	dhd_os_sdlock(bus->dhd);
8694 
8695 	/* Poll period: check device if appropriate. */
8696 	// terence 20160615: remove !SLPAUTO_ENAB(bus) to fix not able to polling if sr supported
8697 	if (1 && (bus->poll && (++bus->polltick >= bus->pollrate))) {
8698 		uint32 intstatus = 0;
8699 
8700 		/* Reset poll tick */
8701 		bus->polltick = 0;
8702 
8703 		/* Check device if no interrupts */
8704 		if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
8705 #ifdef DEBUG_LOST_INTERRUPTS
8706 			uint retries = 0;
8707 			bool hostpending;
8708 			uint8 devena, devpend;
8709 
8710 			/* Make sure backplane clock is on */
8711 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8712 
8713 			hostpending = bcmsdh_intr_pending(bus->sdh);
8714 			devena = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL);
8715 			devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTPEND, NULL);
8716 
8717 			R_SDREG(intstatus, &bus->regs->intstatus, retries);
8718 			intstatus &= bus->hostintmask;
8719 
8720 			if (intstatus && !hostpending) {
8721 				DHD_ERROR(("%s: !hpend: ena 0x%02x pend 0x%02x intstatus 0x%08x\n",
8722 				           __FUNCTION__, devena, devpend, intstatus));
8723 			}
8724 #endif /* DEBUG_LOST_INTERRUPTS */
8725 
8726 #ifndef BCMSPI
8727 			/* XXX Needs to be fixed for polling operation (in CE) */
8728 			if (!bus->dpc_sched) {
8729 				uint8 devpend;
8730 				devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
8731 				                          SDIOD_CCCR_INTPEND, NULL);
8732 				intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
8733 			}
8734 #else
8735 			if (!bus->dpc_sched) {
8736 				uint32 devpend;
8737 				devpend = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0,
8738 					SPID_STATUS_REG, NULL);
8739 				intstatus = devpend & STATUS_F2_PKT_AVAILABLE;
8740 			}
8741 #endif /* !BCMSPI */
8742 
8743 			/* If there is something, make like the ISR and schedule the DPC */
8744 			if (intstatus) {
8745 				bus->pollcnt++;
8746 				bus->ipend = TRUE;
8747 				if (bus->intr) {
8748 					bcmsdh_intr_disable(bus->sdh);
8749 				}
8750 				bus->dpc_sched = TRUE;
8751 				dhd_sched_dpc(bus->dhd);
8752 			}
8753 		}
8754 
8755 		/* Update interrupt tracking */
8756 		bus->lastintrs = bus->intrcount;
8757 	}
8758 
8759 	if ((!bus->dpc_sched) && pktq_n_pkts_tot(&bus->txq)) {
8760 		bus->dpc_sched = TRUE;
8761 		dhd_sched_dpc(bus->dhd);
8762 	}
8763 
8764 #ifdef DHD_DEBUG
8765 	/* Poll for console output periodically */
8766 	if (dhdp->busstate == DHD_BUS_DATA && dhdp->dhd_console_ms != 0) {
8767 		bus->console.count += dhd_watchdog_ms;
8768 		if (bus->console.count >= dhdp->dhd_console_ms) {
8769 			bus->console.count -= dhdp->dhd_console_ms;
8770 			/* Make sure backplane clock is on */
8771 			if (SLPAUTO_ENAB(bus))
8772 				dhdsdio_bussleep(bus, FALSE);
8773 			else
8774 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8775 			if (dhdsdio_readconsole(bus) < 0)
8776 				dhdp->dhd_console_ms = 0;	/* On error, stop trying */
8777 		}
8778 	}
8779 #endif /* DHD_DEBUG */
8780 
8781 #ifdef SDTEST
8782 	/* Generate packets if configured */
8783 	if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
8784 		/* Make sure backplane clock is on */
8785 		if (SLPAUTO_ENAB(bus))
8786 			dhdsdio_bussleep(bus, FALSE);
8787 		else
8788 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8789 		bus->pktgen_tick = 0;
8790 		dhdsdio_pktgen(bus);
8791 	}
8792 #endif
8793 
8794 	/* On idle timeout clear activity flag and/or turn off clock */
8795 #ifdef DHD_USE_IDLECOUNT
8796 	if (bus->activity)
8797 		bus->activity = FALSE;
8798 	else {
8799 		bus->idlecount++;
8800 
8801 		/*
8802 		 * If the condition to switch off the clock is reached And if
8803 		 * BT is inactive (in case of BT_OVER_SDIO build) turn off clk.
8804 		 *
8805 		 * Consider the following case, DHD is configured with
8806 		 * 1) idletime == DHD_IDLE_IMMEDIATE
8807 		 * 2) BT is the last user of the clock
8808 		 * We cannot disable the clock from __dhdsdio_clk_disable
8809 		 * since WLAN might be using it. If WLAN is active then
8810 		 * from the respective function/context after doing the job
8811 		 * the clk is turned off.
8812 		 * But if WLAN is actually inactive then the watchdog should
8813 		 * disable the clock. So the condition check below should be
8814 		 * bus->idletime != 0 instead of idletime == 0
8815 		 */
8816 		if ((bus->idletime != 0) && (bus->idlecount >= bus->idletime) &&
8817 			NO_OTHER_ACTIVE_BUS_USER(bus)) {
8818 			DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
8819 			if (!bus->poll && SLPAUTO_ENAB(bus)) {
8820 				if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
8821 					dhd_os_wd_timer(bus->dhd, 0);
8822 			} else
8823 				dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8824 
8825 			bus->idlecount = 0;
8826 		}
8827 	}
8828 #else
8829 	if ((bus->idletime != 0) && (bus->clkstate == CLK_AVAIL) &&
8830 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8831 		if (++bus->idlecount >= bus->idletime) {
8832 			bus->idlecount = 0;
8833 			if (bus->activity) {
8834 				bus->activity = FALSE;
8835 #if !defined(OEM_ANDROID) && !defined(NDIS)
8836 /* XXX
8837  * For Android turn off clocks as soon as possible, to improve power
8838  * efficiency. For non-android, extend clock-active period for voice
8839  * quality reasons (see PR84690/Jira:SWWLAN-7650).
8840  */
8841 			} else {
8842 #endif /* !defined(OEM_ANDROID) && !defined(NDIS) */
8843 				if (!bus->poll && SLPAUTO_ENAB(bus)) {
8844 					if (!bus->readframes)
8845 						dhdsdio_bussleep(bus, TRUE);
8846 					else
8847 						bus->reqbussleep = TRUE;
8848 				} else {
8849 					dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8850 				}
8851 			}
8852 		}
8853 	}
8854 #endif /* DHD_USE_IDLECOUNT */
8855 
8856 	dhd_os_sdunlock(bus->dhd);
8857 
8858 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
8859 	DHD_BUS_BUSY_CLEAR_IN_WD(dhdp);
8860 	dhd_os_busbusy_wake(dhdp);
8861 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8862 
8863 	return bus->ipend;
8864 }
8865 
8866 extern int
dhd_bus_console_in(dhd_pub_t * dhdp,uchar * msg,uint msglen)8867 dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
8868 {
8869 	dhd_bus_t *bus = dhdp->bus;
8870 	uint32 addr, val;
8871 	int rv;
8872 	void *pkt;
8873 
8874 #ifndef CONSOLE_DPC
8875 	/* Exclusive bus access */
8876 	dhd_os_sdlock(bus->dhd);
8877 #endif
8878 
8879 	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
8880 	if (bus->console_addr == 0) {
8881 		rv = BCME_UNSUPPORTED;
8882 		goto exit;
8883 	}
8884 
8885 	/* Don't allow input if dongle is in reset */
8886 	if (bus->dhd->dongle_reset) {
8887 		rv = BCME_NOTREADY;
8888 		goto exit;
8889 	}
8890 
8891 #ifndef CONSOLE_DPC
8892 	if (!DATAOK(bus)) {
8893 		DHD_CTL(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d, pktq_len %d\n",
8894 			__FUNCTION__, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
8895 		rv = BCME_NOTREADY;
8896 		goto exit;
8897 	}
8898 
8899 	/* Request clock to allow SDIO accesses */
8900 	BUS_WAKE(bus);
8901 	/* No pend allowed since txpkt is called later, ht clk has to be on */
8902 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8903 #endif
8904 
8905 	/* Zero cbuf_index */
8906 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx);
8907 	/* handle difference in definition of hnd_log_t in certain branches */
8908 	if (dhdp->wlc_ver_major < 14) {
8909 		addr -= sizeof(uint32);
8910 	}
8911 	val = htol32(0);
8912 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
8913 		goto done;
8914 
8915 	/* Write message into cbuf */
8916 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf);
8917 	/* handle difference in definition of hnd_log_t in certain branches */
8918 	if (dhdp->wlc_ver_major < 14) {
8919 		addr -= sizeof(uint32);
8920 	}
8921 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
8922 		goto done;
8923 
8924 	/* Write length into vcons_in */
8925 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, vcons_in);
8926 	val = htol32(msglen);
8927 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
8928 		goto done;
8929 
8930 	/* Bump dongle by sending an empty packet on the event channel.
8931 	 * sdpcm_sendup (RX) checks for virtual console input.
8932 	 */
8933 	if ((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL)
8934 		rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
8935 
8936 done:
8937 #ifndef CONSOLE_DPC
8938 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
8939 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8940 		bus->activity = FALSE;
8941 		dhdsdio_bussleep(bus, TRUE);
8942 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8943 	}
8944 #endif
8945 
8946 exit:
8947 #ifdef CONSOLE_DPC
8948 	memset(bus->cons_cmd, 0, sizeof(bus->cons_cmd));
8949 #else
8950 	dhd_os_sdunlock(bus->dhd);
8951 #endif
8952 	return rv;
8953 }
8954 
8955 #ifdef CONSOLE_DPC
8956 extern int
dhd_bus_txcons(dhd_pub_t * dhdp,uchar * msg,uint msglen)8957 dhd_bus_txcons(dhd_pub_t *dhdp, uchar *msg, uint msglen)
8958 {
8959 	dhd_bus_t *bus = dhdp->bus;
8960 	int ret = BCME_OK;
8961 
8962 	dhd_os_sdlock(bus->dhd);
8963 
8964 	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
8965 	if (bus->console_addr == 0) {
8966 		ret = BCME_UNSUPPORTED;
8967 		goto exit;
8968 	}
8969 
8970 	/* Don't allow input if dongle is in reset */
8971 	if (bus->dhd->dongle_reset) {
8972 		ret = BCME_NOTREADY;
8973 		goto exit;
8974 	}
8975 
8976 	if (msglen >= sizeof(bus->cons_cmd)) {
8977 		DHD_ERROR(("%s: \"%s\"(%d) too long\n", __FUNCTION__, msg, msglen));
8978 		ret = BCME_BADARG;
8979 		goto exit;
8980 	}
8981 
8982 	if (!strlen(bus->cons_cmd)) {
8983 		strncpy(bus->cons_cmd, msg, sizeof(bus->cons_cmd));
8984 		DHD_CTL(("%s: \"%s\" delay send, tx_max %d, tx_seq %d, pktq_len %d\n",
8985 			__FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
8986 		if (!bus->dpc_sched) {
8987 			bus->dpc_sched = TRUE;
8988 			dhd_sched_dpc(bus->dhd);
8989 		}
8990 	} else {
8991 		DHD_CTL(("%s: \"%s\" is pending, tx_max %d, tx_seq %d, pktq_len %d\n",
8992 			__FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
8993 		ret = BCME_NOTREADY;
8994 	}
8995 
8996 exit:
8997 	dhd_os_sdunlock(bus->dhd);
8998 
8999 	return ret;
9000 }
9001 #endif
9002 
9003 #if defined(DHD_DEBUG) && !defined(BCMSDIOLITE)
9004 static void
dhd_dump_cis(uint fn,uint8 * cis)9005 dhd_dump_cis(uint fn, uint8 *cis)
9006 {
9007 	uint byte, tag, tdata;
9008 	DHD_INFO(("Function %d CIS:\n", fn));
9009 
9010 	for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
9011 		if ((byte % 16) == 0)
9012 			DHD_INFO(("    "));
9013 		DHD_INFO(("%02x ", cis[byte]));
9014 		if ((byte % 16) == 15)
9015 			DHD_INFO(("\n"));
9016 		if (!tdata--) {
9017 			tag = cis[byte];
9018 			if (tag == 0xff)
9019 				break;
9020 			else if (!tag)
9021 				tdata = 0;
9022 			else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
9023 				tdata = cis[byte + 1] + 1;
9024 			else
9025 				DHD_INFO(("]"));
9026 		}
9027 	}
9028 	if ((byte % 16) != 15)
9029 		DHD_INFO(("\n"));
9030 }
9031 #endif /* DHD_DEBUG */
9032 
9033 static bool
dhdsdio_chipmatch(uint16 chipid)9034 dhdsdio_chipmatch(uint16 chipid)
9035 {
9036 	if (chipid == BCM4330_CHIP_ID)
9037 		return TRUE;
9038 	if (chipid == BCM43362_CHIP_ID)
9039 		return TRUE;
9040 	if (chipid == BCM43340_CHIP_ID)
9041 		return TRUE;
9042 	if (chipid == BCM43341_CHIP_ID)
9043 		return TRUE;
9044 	if (chipid == BCM4334_CHIP_ID)
9045 		return TRUE;
9046 	if (chipid == BCM4324_CHIP_ID)
9047 		return TRUE;
9048 	if (chipid == BCM4335_CHIP_ID)
9049 		return TRUE;
9050 	if (chipid == BCM4339_CHIP_ID)
9051 		return TRUE;
9052 	if (BCM4345_CHIP(chipid))
9053 		return TRUE;
9054 	if (chipid == BCM4350_CHIP_ID)
9055 		return TRUE;
9056 	if (chipid == BCM4354_CHIP_ID)
9057 		return TRUE;
9058 	if (chipid == BCM4358_CHIP_ID)
9059 		return TRUE;
9060 	if (chipid == BCM43569_CHIP_ID)
9061 		return TRUE;
9062 	if (chipid == BCM4371_CHIP_ID)
9063 		return TRUE;
9064 	if (chipid == BCM43430_CHIP_ID)
9065 		return TRUE;
9066 	if (chipid == BCM43018_CHIP_ID)
9067 		return TRUE;
9068 	if (BCM4349_CHIP(chipid))
9069 		return TRUE;
9070 #ifdef UNRELEASEDCHIP
9071 	if ((chipid == BCM4347_CHIP_ID) ||
9072 		(chipid == BCM4357_CHIP_ID) ||
9073 		(chipid == BCM4361_CHIP_ID))
9074 		return TRUE;
9075 #endif
9076 	if (chipid == BCM4364_CHIP_ID)
9077 			return TRUE;
9078 
9079 	if (chipid == BCM43012_CHIP_ID)
9080 		return TRUE;
9081 
9082 	if (chipid == BCM43014_CHIP_ID)
9083 		return TRUE;
9084 
9085 	if (chipid == BCM43013_CHIP_ID)
9086 		return TRUE;
9087 
9088 	if (chipid == BCM4369_CHIP_ID)
9089 		return TRUE;
9090 
9091 	if (BCM4378_CHIP(chipid)) {
9092 		return TRUE;
9093 	}
9094 
9095 	if (chipid == BCM4362_CHIP_ID)
9096 		return TRUE;
9097 	if (chipid == BCM43751_CHIP_ID)
9098 		return TRUE;
9099 	if (chipid == BCM43752_CHIP_ID)
9100 		return TRUE;
9101 
9102 	return FALSE;
9103 }
9104 
9105 static void *
dhdsdio_probe(uint16 venid,uint16 devid,uint16 bus_no,uint16 slot,uint16 func,uint bustype,void * regsva,osl_t * osh,void * sdh)9106 dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
9107 	uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
9108 {
9109 	int ret;
9110 	dhd_bus_t *bus;
9111 
9112 	DHD_MUTEX_LOCK();
9113 
9114 	/* Init global variables at run-time, not as part of the declaration.
9115 	 * This is required to support init/de-init of the driver. Initialization
9116 	 * of globals as part of the declaration results in non-deterministic
9117 	 * behavior since the value of the globals may be different on the
9118 	 * first time that the driver is initialized vs subsequent initializations.
9119 	 */
9120 	dhd_txbound = DHD_TXBOUND;
9121 	dhd_rxbound = DHD_RXBOUND;
9122 #ifdef BCMSPI
9123 	dhd_alignctl = FALSE;
9124 #else
9125 	dhd_alignctl = TRUE;
9126 #endif /* BCMSPI */
9127 	sd1idle = TRUE;
9128 	dhd_readahead = TRUE;
9129 	retrydata = FALSE;
9130 
9131 #ifdef DISABLE_FLOW_CONTROL
9132 	dhd_doflow = FALSE;
9133 #endif /* DISABLE_FLOW_CONTROL */
9134 	dhd_dongle_ramsize = 0;
9135 	dhd_txminmax = DHD_TXMINMAX;
9136 
9137 #ifdef BCMSPI
9138 	forcealign = FALSE;
9139 #else
9140 	forcealign = TRUE;
9141 #endif /* !BCMSPI */
9142 
9143 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9144 	DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
9145 
9146 	/* We make assumptions about address window mappings */
9147 	ASSERT((uintptr)regsva == si_enum_base(devid));
9148 
9149 	/* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
9150 	 * means early parse could fail, so here we should get either an ID
9151 	 * we recognize OR (-1) indicating we must request power first.
9152 	 */
9153 	/* Check the Vendor ID */
9154 	switch (venid) {
9155 		case 0x0000:
9156 		case VENDOR_BROADCOM:
9157 			break;
9158 		default:
9159 			DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
9160 			           __FUNCTION__, venid));
9161 			goto forcereturn;
9162 	}
9163 
9164 	/* Check the Device ID and make sure it's one that we support */
9165 	switch (devid) {
9166 #ifdef BCMINTERNAL
9167 		case SDIOD_FPGA_ID:
9168 			DHD_INFO(("%s: found FPGA Dongle\n", __FUNCTION__));
9169 			break;
9170 #endif /* BCMINTERNAL */
9171 		case 0:
9172 			DHD_INFO(("%s: allow device id 0, will check chip internals\n",
9173 			          __FUNCTION__));
9174 			break;
9175 
9176 		default:
9177 			DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
9178 			           __FUNCTION__, venid, devid));
9179 			goto forcereturn;
9180 	}
9181 
9182 	if (osh == NULL) {
9183 		DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__));
9184 		goto forcereturn;
9185 	}
9186 
9187 	/* Allocate private bus interface state */
9188 	if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
9189 		DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
9190 		goto fail;
9191 	}
9192 	bzero(bus, sizeof(dhd_bus_t));
9193 	bus->sdh = sdh;
9194 	bus->cl_devid = (uint16)devid;
9195 	bus->bus = DHD_BUS;
9196 	bus->bus_num = bus_no;
9197 	bus->slot_num = slot;
9198 	bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
9199 	bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */
9200 #ifdef BT_OVER_SDIO
9201 	bus->bt_use_count = 0;
9202 #endif
9203 
9204 #if defined(LINUX) && defined(SUPPORT_P2P_GO_PS)
9205 	init_waitqueue_head(&bus->bus_sleep);
9206 #endif /* LINUX && SUPPORT_P2P_GO_PS */
9207 	init_waitqueue_head(&bus->ctrl_tx_wait);
9208 
9209 	/* attempt to attach to the dongle */
9210 	if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
9211 		DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__));
9212 		goto fail;
9213 	}
9214 
9215 	/* Attach to the dhd/OS/network interface */
9216 	if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) {
9217 		DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
9218 		goto fail;
9219 	}
9220 
9221 #if defined(GET_OTP_MAC_ENABLE) || defined(GET_OTP_MODULE_NAME)
9222 	dhd_conf_get_otp(bus->dhd, sdh, bus->sih);
9223 #endif
9224 
9225 	/* Allocate buffers */
9226 	if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
9227 		DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
9228 		goto fail;
9229 	}
9230 
9231 	if (!(dhdsdio_probe_init(bus, osh, sdh))) {
9232 		DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__));
9233 		goto fail;
9234 	}
9235 
9236 	if (bus->intr) {
9237 		/* Register interrupt callback, but mask it (not operational yet). */
9238 		DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
9239 		bcmsdh_intr_disable(sdh); /* XXX New API: bcmsdh_intr_mask()? */
9240 		if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
9241 			DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
9242 			           __FUNCTION__, ret));
9243 			goto fail;
9244 		}
9245 		DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
9246 	} else {
9247 		DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
9248 		           __FUNCTION__));
9249 	}
9250 
9251 	DHD_INFO(("%s: completed!!\n", __FUNCTION__));
9252 
9253 	/* if firmware path present try to download and bring up bus */
9254 	bus->dhd->hang_report  = TRUE;
9255 #if 0 // terence 20150325: fix for WPA/WPA2 4-way handshake fail in hostapd
9256 #if defined(LINUX) || defined(linux)
9257 	if (dhd_download_fw_on_driverload) {
9258 #endif /* LINUX || linux */
9259 		if ((ret = dhd_bus_start(bus->dhd)) != 0) {
9260 			DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__));
9261 #if !defined(OEM_ANDROID)
9262 			if (ret == BCME_NOTUP)
9263 #endif /* !OEM_ANDROID */
9264 				goto fail;
9265 		}
9266 #if defined(LINUX) || defined(linux)
9267 	}
9268 	else {
9269 		/* Set random MAC address during boot time */
9270 		get_random_bytes(&bus->dhd->mac.octet[3], 3);
9271 		/* Adding BRCM OUI */
9272 		bus->dhd->mac.octet[0] = 0;
9273 		bus->dhd->mac.octet[1] = 0x90;
9274 		bus->dhd->mac.octet[2] = 0x4C;
9275 	}
9276 #endif /* LINUX || linux */
9277 #endif
9278 #if defined(BT_OVER_SDIO)
9279 	/* At this point Regulators are turned on and iconditionaly sdio bus is started
9280 	 * based upon dhd_download_fw_on_driverload check, so
9281 	 * increase the bus user count, this count will only be disabled inside
9282 	 * dhd_register_if() function if flag dhd_download_fw_on_driverload is set to false,
9283 	 * i.e FW download during insmod is not needed, otherwise it will not be decremented
9284 	 * so that WALN will always hold the bus untill rmmod is done.
9285 	 */
9286 	dhdsdio_bus_usr_cnt_inc(bus->dhd);
9287 #endif /* BT_OVER_SDIO */
9288 
9289 	/* Ok, have the per-port tell the stack we're open for business */
9290 	if (dhd_attach_net(bus->dhd, TRUE) != 0) {
9291 		DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
9292 		goto fail;
9293 	}
9294 
9295 #ifdef BCMHOST_XTAL_PU_TIME_MOD
9296 	bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11);
9297 	bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001);
9298 #endif /* BCMHOST_XTAL_PU_TIME_MOD */
9299 
9300 #if defined(MULTIPLE_SUPPLICANT)
9301 	wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
9302 #endif /* MULTIPLE_SUPPLICANT */
9303 	DHD_MUTEX_UNLOCK();
9304 
9305 	return bus;
9306 
9307 fail:
9308 	dhdsdio_release(bus, osh);
9309 
9310 forcereturn:
9311 	DHD_MUTEX_UNLOCK();
9312 
9313 	return NULL;
9314 }
9315 
9316 static bool
dhdsdio_probe_attach(struct dhd_bus * bus,osl_t * osh,void * sdh,void * regsva,uint16 devid)9317 dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
9318                      uint16 devid)
9319 {
9320 #ifndef BCMSPI
9321 	int err = 0;
9322 	uint8 clkctl = 0;
9323 #endif /* !BCMSPI */
9324 
9325 	bus->alp_only = TRUE;
9326 	bus->sih = NULL;
9327 
9328 	/* Return the window to backplane enumeration space for core access */
9329 	if (dhdsdio_set_siaddr_window(bus, si_enum_base(devid))) {
9330 		DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
9331 	}
9332 
9333 #if defined(DHD_DEBUG) && !defined(CUSTOMER_HW4_DEBUG)
9334 	DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n",
9335 		bcmsdh_reg_read(bus->sdh, si_enum_base(devid), 4)));
9336 #endif /* DHD_DEBUG && !CUSTOMER_HW4_DEBUG */
9337 
9338 #ifndef BCMSPI	/* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */
9339 
9340 	/* Force PLL off until si_attach() programs PLL control regs */
9341 
9342 	/* XXX Ideally should not access F1 power control regs before
9343 	 * reading CIS and confirming device.  But strapping option for
9344 	 * low-power start requires turning on ALP before reading CIS,
9345 	 * and at some point bcmsdh should read the CIS for the ID and
9346 	 * not even tell us if it's some other device.  At this point
9347 	 * (see above) we should know it's us (powered on) or can't read
9348 	 * CIS so we need to power on and try.
9349 	 */
9350 
9351 	/* WAR for PR 39902: must force HT off until PLL programmed. */
9352 	/* WAR for PR43618, PR44891: don't do ALPReq until ALPAvail set */
9353 
9354 	/* XXX Replace write/read sequence with single bcmsdh_cfg_raw() call */
9355 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err);
9356 	if (!err)
9357 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
9358 
9359 	if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
9360 		DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
9361 		           err, DHD_INIT_CLKCTL1, clkctl));
9362 		goto fail;
9363 	}
9364 
9365 #endif /* !BCMSPI */
9366 
9367 #ifdef DHD_DEBUG
9368 	if (DHD_INFO_ON()) {
9369 		uint fn, numfn;
9370 		uint8 *cis = NULL;
9371 		int local_err = 0;
9372 
9373 #ifndef BCMSPI
9374 		numfn = bcmsdh_query_iofnum(sdh);
9375 		ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
9376 
9377 		/* Make sure ALP is available before trying to read CIS */
9378 		SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
9379 		                                    SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
9380 		          !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
9381 
9382 		/* Now request ALP be put on the bus */
9383 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
9384 		                 DHD_INIT_CLKCTL2, &local_err);
9385 		/* XXX Account for possible delay between ALP available and on active */
9386 		OSL_DELAY(65);
9387 #else
9388 		numfn = 0; /* internally func is hardcoded to 1 as gSPI has cis on F1 only */
9389 #endif /* !BCMSPI */
9390 #ifndef BCMSDIOLITE
9391 		if (!(cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
9392 			DHD_INFO(("dhdsdio_probe: cis malloc failed\n"));
9393 			goto fail;
9394 		}
9395 
9396 		for (fn = 0; fn <= numfn; fn++) {
9397 			bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
9398 			if ((err = bcmsdh_cis_read(sdh, fn, cis,
9399 				SBSDIO_CIS_SIZE_LIMIT))) {
9400 				DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n",
9401 					fn, err));
9402 				break;
9403 			}
9404 			dhd_dump_cis(fn, cis);
9405 		}
9406 		MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
9407 #else
9408 	BCM_REFERENCE(cis);
9409 	BCM_REFERENCE(fn);
9410 #endif /* DHD_DEBUG */
9411 		if (local_err) {
9412 			DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n"));
9413 			goto fail;
9414 		}
9415 	}
9416 #endif /* DHD_DEBUG */
9417 
9418 	/* si_attach() will provide an SI handle and scan the backplane */
9419 	if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
9420 	                           &bus->vars, &bus->varsz))) {
9421 		DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
9422 		goto fail;
9423 	}
9424 
9425 #ifdef DHD_DEBUG
9426 	DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n",
9427 		bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg));
9428 #endif /* DHD_DEBUG */
9429 
9430 	/* XXX Let the layers below dhd know the chipid and chiprev for
9431 	 * controlling sw WARs for hw PRs
9432 	 */
9433 	bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
9434 
9435 	if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
9436 		DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
9437 		           __FUNCTION__, bus->sih->chip));
9438 #ifdef BCMINTERNAL
9439 		if (dhd_anychip)
9440 			DHD_ERROR(("Continuing anyway...\n"));
9441 		else
9442 #endif /* BCMINTERNAL */
9443 		goto fail;
9444 	}
9445 
9446 	if (bus->sih->buscorerev >= 12)
9447 		dhdsdio_clk_kso_init(bus);
9448 	else
9449 		bus->kso = TRUE;
9450 
9451 	si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
9452 
9453 #ifdef BCMINTERNAL
9454 	/* Check if there is a PMU in the chip.  The FPGA does not have a PMU. */
9455 	if (!(bus->sih->cccaps & CC_CAP_PMU)) {
9456 		DHD_NOPMU(bus) = 1;
9457 	}
9458 #endif /* BCMINTERNAL */
9459 
9460 	/* Get info on the ARM and SOCRAM cores... */
9461 	/* XXX Should really be qualified by device id */
9462 	if (!DHD_NOPMU(bus)) {
9463 		if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
9464 		    (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
9465 		    (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
9466 			bus->armrev = si_corerev(bus->sih);
9467 		} else {
9468 			DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
9469 			goto fail;
9470 		}
9471 
9472 		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
9473 			if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
9474 				DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
9475 				goto fail;
9476 			}
9477 		} else {
9478 			/* cr4 has a different way to find the RAM size from TCM's */
9479 			if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
9480 				DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
9481 				goto fail;
9482 			}
9483 			/* also populate base address */
9484 			switch ((uint16)bus->sih->chip) {
9485 			case BCM4335_CHIP_ID:
9486 			case BCM4339_CHIP_ID:
9487 				bus->dongle_ram_base = CR4_4335_RAM_BASE;
9488 				break;
9489 			case BCM4350_CHIP_ID:
9490 			case BCM4354_CHIP_ID:
9491 			case BCM4358_CHIP_ID:
9492 			case BCM43569_CHIP_ID:
9493 			case BCM4371_CHIP_ID:
9494 				bus->dongle_ram_base = CR4_4350_RAM_BASE;
9495 				break;
9496 			case BCM4360_CHIP_ID:
9497 				bus->dongle_ram_base = CR4_4360_RAM_BASE;
9498 				break;
9499 			CASE_BCM4345_CHIP:
9500 				bus->dongle_ram_base = (bus->sih->chiprev < 6)  /* from 4345C0 */
9501 					? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
9502 				break;
9503 			case BCM4349_CHIP_GRPID:
9504 				/* RAM based changed from 4349c0(revid=9) onwards */
9505 				bus->dongle_ram_base = ((bus->sih->chiprev < 9) ?
9506 					CR4_4349_RAM_BASE: CR4_4349_RAM_BASE_FROM_REV_9);
9507 				break;
9508 			case BCM4364_CHIP_ID:
9509 				bus->dongle_ram_base = CR4_4364_RAM_BASE;
9510 				break;
9511 #ifdef UNRELEASEDCHIP
9512 	                case BCM4347_CHIP_ID:
9513 	                case BCM4357_CHIP_ID:
9514 	                case BCM4361_CHIP_ID:
9515 				bus->dongle_ram_base = CR4_4347_RAM_BASE;
9516 				break;
9517 #endif
9518 			case BCM4362_CHIP_ID:
9519 				bus->dongle_ram_base = CR4_4362_RAM_BASE;
9520 				break;
9521 			case BCM43751_CHIP_ID:
9522 				bus->dongle_ram_base = CR4_43751_RAM_BASE;
9523 				break;
9524 			case BCM43752_CHIP_ID:
9525 				bus->dongle_ram_base = CR4_43752_RAM_BASE;
9526 				break;
9527 			case BCM4369_CHIP_ID:
9528 				bus->dongle_ram_base = CR4_4369_RAM_BASE;
9529 				break;
9530 			case BCM4378_CHIP_GRPID:
9531 				bus->dongle_ram_base = CR4_4378_RAM_BASE;
9532 				break;
9533 			default:
9534 				bus->dongle_ram_base = 0;
9535 				DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
9536 				           __FUNCTION__, bus->dongle_ram_base));
9537 			}
9538 		}
9539 		bus->ramsize = bus->orig_ramsize;
9540 		if (dhd_dongle_ramsize)
9541 			dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
9542 
9543 		DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
9544 		           bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
9545 
9546 		bus->srmemsize = si_socram_srmem_size(bus->sih);
9547 	}
9548 
9549 	/* ...but normally deal with the SDPCMDEV core */
9550 #ifdef BCMSDIOLITE
9551 	if (!(bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0))) {
9552 		DHD_ERROR(("%s: failed to find Chip Common core!\n", __FUNCTION__));
9553 		goto fail;
9554 	}
9555 #else
9556 	if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
9557 	    !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
9558 		DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
9559 		goto fail;
9560 	}
9561 #endif
9562 	bus->sdpcmrev = si_corerev(bus->sih);
9563 
9564 	/* Set core control so an SDIO reset does a backplane reset */
9565 	OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
9566 #ifndef BCMSPI
9567 	bus->rxint_mode = SDIO_DEVICE_HMB_RXINT;
9568 
9569 	if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
9570 		(bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1))
9571 	{
9572 		uint32 val;
9573 
9574 		val = R_REG(osh, &bus->regs->corecontrol);
9575 		val &= ~CC_XMTDATAAVAIL_MODE;
9576 		val |= CC_XMTDATAAVAIL_CTRL;
9577 		W_REG(osh, &bus->regs->corecontrol, val);
9578 	}
9579 #endif /* BCMSPI */
9580 
9581 	/* XXX Tx needs priority queue, where to determine levels? */
9582 	/* XXX Should it try to do WLC mapping, or just pass through? */
9583 	pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
9584 
9585 	/* Locate an appropriately-aligned portion of hdrbuf */
9586 #ifndef DYNAMIC_MAX_HDR_READ
9587 	bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN);
9588 #endif
9589 
9590 	/* Set the poll and/or interrupt flags */
9591 	bus->intr = (bool)dhd_intr;
9592 	if ((bus->poll = (bool)dhd_poll))
9593 		bus->pollrate = 1;
9594 
9595 	/* Setting default Glom size */
9596 	bus->txglomsize = SDPCM_DEFGLOM_SIZE;
9597 
9598 	return TRUE;
9599 
9600 fail:
9601 	if (bus->sih != NULL) {
9602 		si_detach(bus->sih);
9603 		bus->sih = NULL;
9604 	}
9605 	return FALSE;
9606 }
9607 
9608 static bool
dhdsdio_probe_malloc(dhd_bus_t * bus,osl_t * osh,void * sdh)9609 dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
9610 {
9611 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9612 
9613 	if (bus->dhd->maxctl) {
9614 		bus->rxblen = ROUNDUP((bus->dhd->maxctl+SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
9615 		if (!(bus->rxbuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxblen))) {
9616 			DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
9617 			           __FUNCTION__, bus->rxblen));
9618 			goto fail;
9619 		}
9620 	}
9621 	/* Allocate buffer to receive glomed packet */
9622 	if (!(bus->databuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
9623 		DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
9624 			__FUNCTION__, MAX_DATA_BUF));
9625 		/* release rxbuf which was already located as above */
9626 		if (!bus->rxblen)
9627 			DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen);
9628 		goto fail;
9629 	}
9630 	/* Allocate buffer to membuf */
9631 	bus->membuf = MALLOC(osh, MAX_MEM_BUF);
9632 	if (bus->membuf == NULL) {
9633 		DHD_ERROR(("%s: MALLOC of %d-byte membuf failed\n",
9634 			__FUNCTION__, MAX_MEM_BUF));
9635 		if (bus->databuf) {
9636 #ifndef CONFIG_DHD_USE_STATIC_BUF
9637 			MFREE(osh, bus->databuf, MAX_DATA_BUF);
9638 #endif
9639 			bus->databuf = NULL;
9640 		}
9641 		/* release rxbuf which was already located as above */
9642 		if (!bus->rxblen)
9643 			DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen);
9644 		goto fail;
9645 	}
9646 	memset(bus->membuf, 0, MAX_MEM_BUF);
9647 
9648 	/* Align the buffer */
9649 	if ((uintptr)bus->databuf % DHD_SDALIGN)
9650 		bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
9651 	else
9652 		bus->dataptr = bus->databuf;
9653 
9654 	return TRUE;
9655 
9656 fail:
9657 	return FALSE;
9658 }
9659 
9660 static bool
dhdsdio_probe_init(dhd_bus_t * bus,osl_t * osh,void * sdh)9661 dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
9662 {
9663 	int32 fnum;
9664 
9665 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9666 
9667 	bus->_srenab = FALSE;
9668 
9669 #ifdef SDTEST
9670 	dhdsdio_pktgen_init(bus);
9671 #endif /* SDTEST */
9672 
9673 #ifndef BCMSPI
9674 	/* Disable F2 to clear any intermediate frame state on the dongle */
9675 	/* XXX New API: change to bcmsdh_fn_set(sdh, SDIO_FUNC_2, FALSE); */
9676 	/* XXX Might write SRES instead, or reset ARM (download prep)? */
9677 	bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
9678 #endif /* !BCMSPI */
9679 
9680 	DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
9681 	bus->dhd->busstate = DHD_BUS_DOWN;
9682 	bus->sleeping = FALSE;
9683 	bus->rxflow = FALSE;
9684 	bus->prev_rxlim_hit = 0;
9685 
9686 #ifndef BCMSPI
9687 	/* Done with backplane-dependent accesses, can drop clock... */
9688 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
9689 #endif /* !BCMSPI */
9690 
9691 	/* ...and initialize clock/power states */
9692 	bus->clkstate = CLK_SDONLY;
9693 	bus->idletime = (int32)dhd_idletime;
9694 	bus->idleclock = DHD_IDLE_ACTIVE;
9695 
9696 	/* Query the SD clock speed */
9697 	if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
9698 	                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
9699 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"));
9700 		bus->sd_divisor = -1;
9701 	} else {
9702 		DHD_INFO(("%s: Initial value for %s is %d\n",
9703 		          __FUNCTION__, "sd_divisor", bus->sd_divisor));
9704 	}
9705 
9706 	/* Query the SD bus mode */
9707 	if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
9708 	                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
9709 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode"));
9710 		bus->sd_mode = -1;
9711 	} else {
9712 		DHD_INFO(("%s: Initial value for %s is %d\n",
9713 		          __FUNCTION__, "sd_mode", bus->sd_mode));
9714 	}
9715 
9716 	/* Query the F2 block size, set roundup accordingly */
9717 	fnum = 2;
9718 	if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
9719 	                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
9720 		bus->blocksize = 0;
9721 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
9722 	} else {
9723 		DHD_INFO(("%s: Initial value for %s is %d\n",
9724 		          __FUNCTION__, "sd_blocksize", bus->blocksize));
9725 
9726 		dhdsdio_tune_fifoparam(bus);
9727 	}
9728 	bus->roundup = MIN(max_roundup, bus->blocksize);
9729 
9730 #ifdef DHDENABLE_TAILPAD
9731 	if (bus->pad_pkt)
9732 		PKTFREE(osh, bus->pad_pkt, FALSE);
9733 	bus->pad_pkt = PKTGET(osh, SDIO_MAX_BLOCK_SIZE, FALSE);
9734 	if (bus->pad_pkt == NULL)
9735 		DHD_ERROR(("failed to allocate padding packet\n"));
9736 	else {
9737 		int alignment_offset = 0;
9738 		uintptr pktprt = (uintptr)PKTDATA(osh, bus->pad_pkt);
9739 		if (!(pktprt&1) && (pktprt = (pktprt % DHD_SDALIGN)))
9740 			PKTPUSH(osh, bus->pad_pkt, alignment_offset);
9741 		PKTSETNEXT(osh, bus->pad_pkt, NULL);
9742 	}
9743 #endif /* DHDENABLE_TAILPAD */
9744 
9745 	/* Query if bus module supports packet chaining, default to use if supported */
9746 	if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
9747 	                    &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) {
9748 		bus->sd_rxchain = FALSE;
9749 	} else {
9750 		DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
9751 		          __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")));
9752 	}
9753 	bus->use_rxchain = (bool)bus->sd_rxchain;
9754 	bus->txinrx_thres = CUSTOM_TXINRX_THRES;
9755 	/* TX first in dhdsdio_readframes() */
9756 	bus->dotxinrx = TRUE;
9757 
9758 #ifdef PKT_STATICS
9759 	dhd_bus_clear_txpktstatics(bus->dhd);
9760 #endif
9761 
9762 	return TRUE;
9763 }
9764 
9765 int
dhd_bus_download_firmware(struct dhd_bus * bus,osl_t * osh,char * pfw_path,char * pnv_path,char * pclm_path,char * pconf_path)9766 dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
9767                           char *pfw_path, char *pnv_path,
9768                           char *pclm_path, char *pconf_path)
9769 {
9770 	int ret;
9771 
9772 	bus->fw_path = pfw_path;
9773 	bus->nv_path = pnv_path;
9774 	bus->dhd->clm_path = pclm_path;
9775 	bus->dhd->conf_path = pconf_path;
9776 
9777 	ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
9778 
9779 	return ret;
9780 }
9781 
9782 int
dhd_set_bus_params(struct dhd_bus * bus)9783 dhd_set_bus_params(struct dhd_bus *bus)
9784 {
9785 	int ret = 0;
9786 
9787 	if (bus->dhd->conf->dhd_poll >= 0) {
9788 		bus->poll = bus->dhd->conf->dhd_poll;
9789 		if (!bus->pollrate)
9790 			bus->pollrate = 1;
9791 		printf("%s: set polling mode %d\n", __FUNCTION__, bus->dhd->conf->dhd_poll);
9792 	}
9793 	if (bus->dhd->conf->use_rxchain >= 0) {
9794 		bus->use_rxchain = (bool)bus->dhd->conf->use_rxchain;
9795 	}
9796 	if (bus->dhd->conf->txinrx_thres >= 0) {
9797 		bus->txinrx_thres = bus->dhd->conf->txinrx_thres;
9798 	}
9799 	if (bus->dhd->conf->txglomsize >= 0) {
9800 		bus->txglomsize = bus->dhd->conf->txglomsize;
9801 	}
9802 #ifdef MINIME
9803 	if (bus->dhd->conf->fw_type == FW_TYPE_MINIME) {
9804 		bus->ramsize = bus->dhd->conf->ramsize;
9805 		printf("%s: set ramsize 0x%x\n", __FUNCTION__, bus->ramsize);
9806 	}
9807 #endif
9808 #ifdef DYNAMIC_MAX_HDR_READ
9809 	if (bus->dhd->conf->max_hdr_read <= 0) {
9810 		bus->dhd->conf->max_hdr_read = MAX_HDR_READ;
9811 	}
9812 	if (bus->hdrbufp) {
9813 		MFREE(bus->dhd->osh, bus->hdrbufp, bus->dhd->conf->max_hdr_read + DHD_SDALIGN);
9814 	}
9815 	bus->hdrbufp = MALLOC(bus->dhd->osh, bus->dhd->conf->max_hdr_read + DHD_SDALIGN);
9816 	if (bus->hdrbufp == NULL) {
9817 		DHD_ERROR(("%s: MALLOC of %d-byte hdrbufp failed\n",
9818 			__FUNCTION__, bus->dhd->conf->max_hdr_read + DHD_SDALIGN));
9819 		ret = -1;
9820 		goto exit;
9821 	}
9822 	bus->rxhdr = (uint8 *)ROUNDUP((uintptr)bus->hdrbufp, DHD_SDALIGN);
9823 
9824 exit:
9825 #endif
9826 	return ret;
9827 }
9828 
9829 static int
dhdsdio_download_firmware(struct dhd_bus * bus,osl_t * osh,void * sdh)9830 dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
9831 {
9832 	int ret;
9833 
9834 #if defined(SUPPORT_MULTIPLE_REVISION)
9835 	if (concate_revision(bus, bus->fw_path, bus->nv_path) != 0) {
9836 		DHD_ERROR(("%s: fail to concatnate revison \n",
9837 			__FUNCTION__));
9838 		return BCME_BADARG;
9839 	}
9840 #endif /* SUPPORT_MULTIPLE_REVISION */
9841 
9842 #if defined(DHD_BLOB_EXISTENCE_CHECK)
9843 	dhd_set_blob_support(bus->dhd, bus->fw_path);
9844 #endif /* DHD_BLOB_EXISTENCE_CHECK */
9845 
9846 	DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
9847 		__FUNCTION__, bus->fw_path, bus->nv_path));
9848 	DHD_OS_WAKE_LOCK(bus->dhd);
9849 
9850 	dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
9851 	ret = dhd_set_bus_params(bus);
9852 	if (ret) {
9853 		goto exit;
9854 	}
9855 
9856 	/* Download the firmware */
9857 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
9858 
9859 	ret = _dhdsdio_download_firmware(bus);
9860 
9861 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
9862 
9863 exit:
9864 	DHD_OS_WAKE_UNLOCK(bus->dhd);
9865 	return ret;
9866 }
9867 
9868 /* Detach and free everything */
9869 static void
dhdsdio_release(dhd_bus_t * bus,osl_t * osh)9870 dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
9871 {
9872 	bool dongle_isolation = FALSE;
9873 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9874 
9875 	if (bus) {
9876 		ASSERT(osh);
9877 
9878 		if (bus->dhd) {
9879 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
9880 			debugger_close();
9881 #endif /* DEBUGGER || DHD_DSCOPE */
9882 			dongle_isolation = bus->dhd->dongle_isolation;
9883 			dhd_detach(bus->dhd);
9884 		}
9885 
9886 		/* De-register interrupt handler */
9887 		bcmsdh_intr_disable(bus->sdh);
9888 		bcmsdh_intr_dereg(bus->sdh);
9889 
9890 		if (bus->dhd) {
9891 			dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
9892 			dhd_free(bus->dhd);
9893 			bus->dhd = NULL;
9894 		}
9895 
9896 		dhdsdio_release_malloc(bus, osh);
9897 
9898 #ifdef DHD_DEBUG
9899 		if (bus->console.buf != NULL)
9900 			MFREE(osh, bus->console.buf, bus->console.bufsize);
9901 #endif
9902 
9903 #ifdef DHDENABLE_TAILPAD
9904 		if (bus->pad_pkt)
9905 			PKTFREE(osh, bus->pad_pkt, FALSE);
9906 #endif /* DHDENABLE_TAILPAD */
9907 #ifdef DYNAMIC_MAX_HDR_READ
9908 	if (bus->hdrbufp) {
9909 		MFREE(osh, bus->hdrbufp, MAX_HDR_READ + DHD_SDALIGN);
9910 	}
9911 #endif
9912 
9913 		MFREE(osh, bus, sizeof(dhd_bus_t));
9914 	}
9915 
9916 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
9917 }
9918 
9919 static void
dhdsdio_release_malloc(dhd_bus_t * bus,osl_t * osh)9920 dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
9921 {
9922 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9923 
9924 	if (bus->dhd && bus->dhd->dongle_reset)
9925 		return;
9926 
9927 	if (bus->rxbuf) {
9928 #ifndef CONFIG_DHD_USE_STATIC_BUF
9929 		MFREE(osh, bus->rxbuf, bus->rxblen);
9930 #endif
9931 		bus->rxctl = NULL;
9932 		bus->rxlen = 0;
9933 	}
9934 
9935 	if (bus->databuf) {
9936 #ifndef CONFIG_DHD_USE_STATIC_BUF
9937 		MFREE(osh, bus->databuf, MAX_DATA_BUF);
9938 #endif
9939 	}
9940 
9941 	if (bus->membuf) {
9942 		MFREE(osh, bus->membuf, MAX_MEM_BUF);
9943 		bus->membuf = NULL;
9944 	}
9945 
9946 	if (bus->vars && bus->varsz) {
9947 		MFREE(osh, bus->vars, bus->varsz);
9948 	}
9949 
9950 }
9951 
9952 static void
dhdsdio_release_dongle(dhd_bus_t * bus,osl_t * osh,bool dongle_isolation,bool reset_flag)9953 dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
9954 {
9955 	DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
9956 		bus->dhd, bus->dhd->dongle_reset));
9957 
9958 	if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
9959 		return;
9960 
9961 	if (bus->sih) {
9962 		/* In Win10, system will be BSOD if using "sysprep" to do OS image */
9963 		/* Skip this will not cause the BSOD. */
9964 #if !defined(BCMLXSDMMC) && !defined(NDIS)
9965 		/* XXX - Using the watchdog to reset the chip does not allow
9966 		 * further SDIO communication.  For the SDMMC Driver, this
9967 		 * causes interrupt to not be de-registered properly.
9968 		 */
9969 		/* XXX: dongle isolation mode is on don't reset the chip */
9970 		if (bus->dhd) {
9971 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
9972 		}
9973 		if (KSO_ENAB(bus) && (dongle_isolation == FALSE))
9974 			si_watchdog(bus->sih, 4);
9975 #endif /* !defined(BCMLXSDMMC) */
9976 		if (bus->dhd) {
9977 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
9978 		}
9979 		si_detach(bus->sih);
9980 		bus->sih = NULL;
9981 		if (bus->vars && bus->varsz)
9982 			MFREE(osh, bus->vars, bus->varsz);
9983 		bus->vars = NULL;
9984 	}
9985 
9986 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
9987 }
9988 
9989 static void
dhdsdio_disconnect(void * ptr)9990 dhdsdio_disconnect(void *ptr)
9991 {
9992 	dhd_bus_t *bus = (dhd_bus_t *)ptr;
9993 
9994 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9995 
9996 	DHD_MUTEX_LOCK();
9997 	if (bus) {
9998 		ASSERT(bus->dhd);
9999 		/* Advertise bus remove during rmmod */
10000 		dhdsdio_advertise_bus_remove(bus->dhd);
10001 		dhdsdio_release(bus, bus->dhd->osh);
10002 	}
10003 	DHD_MUTEX_UNLOCK();
10004 
10005 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
10006 }
10007 
10008 static int
dhdsdio_suspend(void * context)10009 dhdsdio_suspend(void *context)
10010 {
10011 	int ret = 0;
10012 #ifdef SUPPORT_P2P_GO_PS
10013 	int wait_time = 0;
10014 #endif /* SUPPORT_P2P_GO_PS */
10015 
10016 #if defined(LINUX)
10017 	dhd_bus_t *bus = (dhd_bus_t*)context;
10018 	unsigned long flags;
10019 
10020 	DHD_ERROR(("%s Enter\n", __FUNCTION__));
10021 	if (bus->dhd == NULL) {
10022 		DHD_ERROR(("bus not inited\n"));
10023 		return BCME_ERROR;
10024 	}
10025 	if (bus->dhd->prot == NULL) {
10026 		DHD_ERROR(("prot is not inited\n"));
10027 		return BCME_ERROR;
10028 	}
10029 
10030 	if (bus->dhd->up == FALSE) {
10031 		return BCME_OK;
10032 	}
10033 
10034 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10035 	if (bus->dhd->busstate != DHD_BUS_DATA && bus->dhd->busstate != DHD_BUS_SUSPEND) {
10036 		DHD_ERROR(("not in a readystate to LPBK  is not inited\n"));
10037 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10038 		return BCME_ERROR;
10039 	}
10040 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10041 	if (bus->dhd->dongle_reset) {
10042 		DHD_ERROR(("Dongle is in reset state.\n"));
10043 		return -EIO;
10044 	}
10045 
10046 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10047 	/* stop all interface network queue. */
10048 	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
10049 	bus->dhd->busstate = DHD_BUS_SUSPEND;
10050 #if defined(LINUX) || defined(linux)
10051 	if (DHD_BUS_BUSY_CHECK_IN_TX(bus->dhd)) {
10052 		DHD_ERROR(("Tx Request is not ended\n"));
10053 		bus->dhd->busstate = DHD_BUS_DATA;
10054 		/* resume all interface network queue. */
10055 		dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
10056 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10057 		return -EBUSY;
10058 	}
10059 #endif /* LINUX || linux */
10060 	DHD_BUS_BUSY_SET_SUSPEND_IN_PROGRESS(bus->dhd);
10061 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10062 
10063 #ifdef SUPPORT_P2P_GO_PS
10064 	if (bus->idletime > 0) {
10065 		wait_time = msecs_to_jiffies(bus->idletime * dhd_watchdog_ms);
10066 	}
10067 #endif /* SUPPORT_P2P_GO_PS */
10068 	ret = dhd_os_check_wakelock(bus->dhd);
10069 #ifdef SUPPORT_P2P_GO_PS
10070 	// terence 20141124: fix for suspend issue
10071 	if (SLPAUTO_ENAB(bus) && (!ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) {
10072 		if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) {
10073 			if (!bus->sleeping) {
10074 				ret = 1;
10075 			}
10076 		}
10077 	}
10078 #endif /* SUPPORT_P2P_GO_PS */
10079 
10080 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10081 	if (ret) {
10082 		bus->dhd->busstate = DHD_BUS_DATA;
10083 		/* resume all interface network queue. */
10084 		dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
10085 	}
10086 	bus->dhd->hostsleep = 2;
10087 	DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd);
10088 	dhd_os_busbusy_wake(bus->dhd);
10089 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10090 
10091 #endif /* LINUX */
10092 	return ret;
10093 }
10094 
10095 static int
dhdsdio_resume(void * context)10096 dhdsdio_resume(void *context)
10097 {
10098 	dhd_bus_t *bus = (dhd_bus_t*)context;
10099 	ulong flags;
10100 
10101 	DHD_ERROR(("%s Enter\n", __FUNCTION__));
10102 
10103 	if (bus->dhd->up == FALSE) {
10104 		return BCME_OK;
10105 	}
10106 
10107 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10108 	DHD_BUS_BUSY_SET_RESUME_IN_PROGRESS(bus->dhd);
10109 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10110 
10111 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
10112 	if (dhd_os_check_if_up(bus->dhd))
10113 		bcmsdh_oob_intr_set(bus->sdh, TRUE);
10114 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
10115 
10116 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10117 	DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd);
10118 	bus->dhd->hostsleep = 0;
10119 	bus->dhd->busstate = DHD_BUS_DATA;
10120 	dhd_os_busbusy_wake(bus->dhd);
10121 	/* resume all interface network queue. */
10122 	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
10123 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10124 
10125 	return 0;
10126 }
10127 
10128 /* Register/Unregister functions are called by the main DHD entry
10129  * point (e.g. module insertion) to link with the bus driver, in
10130  * order to look for or await the device.
10131  */
10132 
10133 static bcmsdh_driver_t dhd_sdio = {
10134 	dhdsdio_probe,
10135 	dhdsdio_disconnect,
10136 	dhdsdio_suspend,
10137 	dhdsdio_resume
10138 };
10139 
10140 int
dhd_bus_register(void)10141 dhd_bus_register(void)
10142 {
10143 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
10144 
10145 	return bcmsdh_register(&dhd_sdio);
10146 }
10147 
10148 void
dhd_bus_unregister(void)10149 dhd_bus_unregister(void)
10150 {
10151 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
10152 
10153 	bcmsdh_unregister();
10154 }
10155 
10156 #if defined(BCMLXSDMMC)
10157 /* Register a dummy SDIO client driver in order to be notified of new SDIO device */
dhd_bus_reg_sdio_notify(void * semaphore)10158 int dhd_bus_reg_sdio_notify(void* semaphore)
10159 {
10160 	return bcmsdh_reg_sdio_notify(semaphore);
10161 }
10162 
dhd_bus_unreg_sdio_notify(void)10163 void dhd_bus_unreg_sdio_notify(void)
10164 {
10165 	bcmsdh_unreg_sdio_notify();
10166 }
10167 #endif /* defined(BCMLXSDMMC) */
10168 
10169 #ifdef BCMEMBEDIMAGE
10170 static int
dhdsdio_download_code_array(struct dhd_bus * bus)10171 dhdsdio_download_code_array(struct dhd_bus *bus)
10172 {
10173 	int bcmerror = -1;
10174 	int offset = 0;
10175 	unsigned char *ularray = NULL;
10176 
10177 	DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__));
10178 
10179 	/* Download image */
10180 	while ((offset + MEMBLOCK) < sizeof(dlarray)) {
10181 		/* check if CR4 */
10182 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
10183 			/* if address is 0, store the reset instruction to be written in 0 */
10184 
10185 			if (offset == 0) {
10186 				bus->resetinstr = *(((uint32*)dlarray));
10187 				/* Add start of RAM address to the address given by user */
10188 				offset += bus->dongle_ram_base;
10189 			}
10190 		}
10191 
10192 		bcmerror = dhdsdio_membytes(bus, TRUE, offset,
10193 			(uint8 *) (dlarray + offset), MEMBLOCK);
10194 		if (bcmerror) {
10195 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10196 			        __FUNCTION__, bcmerror, MEMBLOCK, offset));
10197 			goto err;
10198 		}
10199 
10200 		offset += MEMBLOCK;
10201 	}
10202 
10203 	if (offset < sizeof(dlarray)) {
10204 		bcmerror = dhdsdio_membytes(bus, TRUE, offset,
10205 			(uint8 *) (dlarray + offset), sizeof(dlarray) - offset);
10206 		if (bcmerror) {
10207 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10208 			        __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
10209 			goto err;
10210 		}
10211 	}
10212 
10213 #ifdef DHD_DEBUG
10214 	/* Upload and compare the downloaded code */
10215 	{
10216 		ularray = MALLOC(bus->dhd->osh, bus->ramsize);
10217 		/* Upload image to verify downloaded contents. */
10218 		offset = 0;
10219 		memset(ularray, 0xaa, bus->ramsize);
10220 		while ((offset + MEMBLOCK) < sizeof(dlarray)) {
10221 			bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK);
10222 			if (bcmerror) {
10223 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10224 					__FUNCTION__, bcmerror, MEMBLOCK, offset));
10225 				goto err;
10226 			}
10227 
10228 			offset += MEMBLOCK;
10229 		}
10230 
10231 		if (offset < sizeof(dlarray)) {
10232 			bcmerror = dhdsdio_membytes(bus, FALSE, offset,
10233 				ularray + offset, sizeof(dlarray) - offset);
10234 			if (bcmerror) {
10235 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10236 					__FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
10237 				goto err;
10238 			}
10239 		}
10240 
10241 		if (memcmp(dlarray, ularray, sizeof(dlarray))) {
10242 			DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n",
10243 			           __FUNCTION__, dlimagename, dlimagever, dlimagedate));
10244 			goto err;
10245 		} else
10246 			DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n",
10247 			           __FUNCTION__, dlimagename, dlimagever, dlimagedate));
10248 
10249 	}
10250 #endif /* DHD_DEBUG */
10251 
10252 err:
10253 	if (ularray)
10254 		MFREE(bus->dhd->osh, ularray, bus->ramsize);
10255 	return bcmerror;
10256 }
10257 #endif /* BCMEMBEDIMAGE */
10258 
10259 #ifdef DHD_LINUX_STD_FW_API
10260 static int
dhdsdio_download_code_file(struct dhd_bus * bus,char * pfw_path)10261 dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
10262 {
10263 	int bcmerror = -1;
10264 	int offset = 0;
10265 	int len;
10266 	uint8 *memblock = NULL, *memptr;
10267 #ifdef CHECK_DOWNLOAD_FW
10268 	uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct
10269 #endif
10270 	uint memblock_size = MEMBLOCK;
10271 #ifdef DHD_DEBUG_DOWNLOADTIME
10272 	unsigned long initial_jiffies = 0;
10273 	uint firmware_sz = 0;
10274 #endif
10275 	int offset_end = bus->ramsize;
10276 	const struct firmware *fw = NULL;
10277 	int buf_offset = 0, residual_len = 0;
10278 
10279 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
10280 
10281 	/* XXX: Should succeed in opening image if it is actually given through registry
10282 	 * entry or in module param.
10283 	 */
10284 	bcmerror = dhd_os_get_img_fwreq(&fw, bus->fw_path);
10285 	if (bcmerror < 0) {
10286 		DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
10287 			bcmerror));
10288 		goto err;
10289 	}
10290 	residual_len = fw->size;
10291 
10292 	/* Update the dongle image download block size depending on the F1 block size */
10293 #ifndef NDIS
10294 	if (sd_f1_blocksize == 512)
10295 		memblock_size = MAX_MEMBLOCK;
10296 #endif /* !NDIS */
10297 
10298 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
10299 	if (memblock == NULL) {
10300 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10301 			memblock_size));
10302 		goto err;
10303 	}
10304 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
10305 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
10306 
10307 #ifdef CHECK_DOWNLOAD_FW
10308 		if (bus->dhd->conf->fwchk) {
10309 			memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
10310 			if (memptr_tmp == NULL) {
10311 				DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
10312 				goto err;
10313 			}
10314 		}
10315 #endif
10316 
10317 #ifdef DHD_DEBUG_DOWNLOADTIME
10318 	initial_jiffies = jiffies;
10319 #endif
10320 
10321 	/* Download image */
10322 	while (residual_len) {
10323 		len = MIN(residual_len, memblock_size);
10324 		bcopy((uint8 *)fw->data + buf_offset, (uint8 *)memptr, len);
10325 		/* check if CR4 */
10326 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
10327 			/* if address is 0, store the reset instruction to be written in 0 */
10328 
10329 			if (offset == 0) {
10330 				bus->resetinstr = *(((uint32*)memptr));
10331 				/* Add start of RAM address to the address given by user */
10332 				offset += bus->dongle_ram_base;
10333 				offset_end += offset;
10334 			}
10335 		}
10336 
10337 		bcmerror = dhdsdio_membytes(bus, TRUE, offset, (uint8 *)memptr, len);
10338 		if (bcmerror) {
10339 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10340 			        __FUNCTION__, bcmerror, memblock_size, offset));
10341 			goto err;
10342 		}
10343 
10344 #ifdef CHECK_DOWNLOAD_FW
10345 		if (bus->dhd->conf->fwchk) {
10346 			bcmerror = dhdsdio_membytes(bus, FALSE, offset, memptr_tmp, len);
10347 			if (bcmerror) {
10348 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10349 				        __FUNCTION__, bcmerror, MEMBLOCK, offset));
10350 				goto err;
10351 			}
10352 			if (memcmp(memptr_tmp, memptr, len)) {
10353 				DHD_ERROR(("%s: Downloaded image is corrupted at 0x%08x\n", __FUNCTION__, offset));
10354 				bcmerror = BCME_ERROR;
10355 				goto err;
10356 			} else
10357 				DHD_INFO(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__));
10358 		}
10359 #endif
10360 
10361 		offset += memblock_size;
10362 #ifdef DHD_DEBUG_DOWNLOADTIME
10363 		firmware_sz += len;
10364 #endif
10365 		if (offset >= offset_end) {
10366 			DHD_ERROR(("%s: invalid address access to %x (offset end: %x)\n",
10367 				__FUNCTION__, offset, offset_end));
10368 			bcmerror = BCME_ERROR;
10369 			goto err;
10370 		}
10371 		residual_len -= len;
10372 		buf_offset += len;
10373 	}
10374 
10375 #ifdef DHD_DEBUG_DOWNLOADTIME
10376 	DHD_ERROR(("Firmware download time for %u bytes: %u ms\n",
10377 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
10378 #endif
10379 
10380 err:
10381 	if (memblock)
10382 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
10383 #ifdef CHECK_DOWNLOAD_FW
10384 	if (bus->dhd->conf->fwchk) {
10385 		if (memptr_tmp)
10386 			MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN);
10387 	}
10388 #endif
10389 
10390 	if (fw) {
10391 		dhd_os_close_img_fwreq(fw);
10392 	}
10393 
10394 	return bcmerror;
10395 }
10396 #else
10397 static int
dhdsdio_download_code_file(struct dhd_bus * bus,char * pfw_path)10398 dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
10399 {
10400 	int bcmerror = -1;
10401 	int offset = 0;
10402 	int len;
10403 	void *image = NULL;
10404 	uint8 *memblock = NULL, *memptr;
10405 #ifdef CHECK_DOWNLOAD_FW
10406 	uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct
10407 #endif
10408 	uint memblock_size = MEMBLOCK;
10409 #ifdef DHD_DEBUG_DOWNLOADTIME
10410 	unsigned long initial_jiffies = 0;
10411 	uint firmware_sz = 0;
10412 #endif
10413 
10414 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
10415 
10416 	/* XXX: Should succeed in opening image if it is actually given through registry
10417 	 * entry or in module param.
10418 	 */
10419 	image = dhd_os_open_image1(bus->dhd, pfw_path);
10420 	if (image == NULL) {
10421 		printf("%s: Open firmware file failed %s\n", __FUNCTION__, pfw_path);
10422 		goto err;
10423 	}
10424 
10425 	/* Update the dongle image download block size depending on the F1 block size */
10426 #ifndef NDIS
10427 	if (sd_f1_blocksize == 512)
10428 		memblock_size = MAX_MEMBLOCK;
10429 #endif /* !NDIS */
10430 
10431 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
10432 	if (memblock == NULL) {
10433 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10434 			memblock_size));
10435 		goto err;
10436 	}
10437 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
10438 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
10439 
10440 #ifdef CHECK_DOWNLOAD_FW
10441 	if (bus->dhd->conf->fwchk) {
10442 		memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
10443 		if (memptr_tmp == NULL) {
10444 			DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
10445 			goto err;
10446 		}
10447 	}
10448 #endif
10449 
10450 #ifdef DHD_DEBUG_DOWNLOADTIME
10451 	initial_jiffies = jiffies;
10452 #endif
10453 
10454 	/* Download image */
10455 	while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) {
10456 		// terence 20150412: fix for firmware failed to download
10457 		if (bus->dhd->conf->chip == BCM43340_CHIP_ID ||
10458 				bus->dhd->conf->chip == BCM43341_CHIP_ID) {
10459 			if (len % 64 != 0) {
10460 				memset(memptr+len, 0, len%64);
10461 				len += (64 - len%64);
10462 			}
10463 		}
10464 		if (len < 0) {
10465 			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
10466 			bcmerror = BCME_ERROR;
10467 			goto err;
10468 		}
10469 		/* check if CR4 */
10470 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
10471 			/* if address is 0, store the reset instruction to be written in 0 */
10472 
10473 			if (offset == 0) {
10474 				bus->resetinstr = *(((uint32*)memptr));
10475 				/* Add start of RAM address to the address given by user */
10476 				offset += bus->dongle_ram_base;
10477 			}
10478 		}
10479 
10480 		bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
10481 		if (bcmerror) {
10482 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10483 			        __FUNCTION__, bcmerror, memblock_size, offset));
10484 			goto err;
10485 		}
10486 
10487 #ifdef CHECK_DOWNLOAD_FW
10488 		if (bus->dhd->conf->fwchk) {
10489 			bcmerror = dhdsdio_membytes(bus, FALSE, offset, memptr_tmp, len);
10490 			if (bcmerror) {
10491 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10492 				        __FUNCTION__, bcmerror, MEMBLOCK, offset));
10493 				goto err;
10494 			}
10495 			if (memcmp(memptr_tmp, memptr, len)) {
10496 				DHD_ERROR(("%s: Downloaded image is corrupted at 0x%08x\n", __FUNCTION__, offset));
10497 				bcmerror = BCME_ERROR;
10498 				goto err;
10499 			} else
10500 				DHD_INFO(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__));
10501 		}
10502 #endif
10503 
10504 		offset += memblock_size;
10505 #ifdef DHD_DEBUG_DOWNLOADTIME
10506 		firmware_sz += len;
10507 #endif
10508 	}
10509 
10510 #ifdef DHD_DEBUG_DOWNLOADTIME
10511 	DHD_ERROR(("Firmware download time for %u bytes: %u ms\n",
10512 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
10513 #endif
10514 
10515 err:
10516 	if (memblock)
10517 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
10518 #ifdef CHECK_DOWNLOAD_FW
10519 	if (bus->dhd->conf->fwchk) {
10520 		if (memptr_tmp)
10521 			MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN);
10522 	}
10523 #endif
10524 
10525 	if (image)
10526 		dhd_os_close_image1(bus->dhd, image);
10527 
10528 	return bcmerror;
10529 }
10530 #endif /* DHD_LINUX_STD_FW_API */
10531 
10532 #ifdef DHD_UCODE_DOWNLOAD
10533 /* Currently supported only for the chips in which ucode RAM is AXI addressable */
10534 static uint32
dhdsdio_ucode_base(struct dhd_bus * bus)10535 dhdsdio_ucode_base(struct dhd_bus *bus)
10536 {
10537 	uint32 ucode_base = 0;
10538 
10539 	switch ((uint16)bus->sih->chip) {
10540 	case BCM43012_CHIP_ID:
10541 	case BCM43013_CHIP_ID:
10542 	case BCM43014_CHIP_ID:
10543 		ucode_base = 0xE8020000;
10544 		break;
10545 	default:
10546 		DHD_ERROR(("%s: Unsupported!\n", __func__));
10547 		break;
10548 	}
10549 
10550 	return ucode_base;
10551 }
10552 
10553 static int
dhdsdio_download_ucode_file(struct dhd_bus * bus,char * ucode_path)10554 dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path)
10555 {
10556 	int bcmerror = -1;
10557 	int offset = 0;
10558 	int len;
10559 	uint32 ucode_base;
10560 	void *image = NULL;
10561 	uint8 *memblock = NULL, *memptr;
10562 	uint memblock_size = MEMBLOCK;
10563 #ifdef DHD_DEBUG_DOWNLOADTIME
10564 	unsigned long initial_jiffies = 0;
10565 	uint firmware_sz = 0;
10566 #endif
10567 
10568 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, ucode_path));
10569 
10570 	ucode_base = dhdsdio_ucode_base(bus);
10571 
10572 	/* XXX: Should succeed in opening image if it is actually given through registry
10573 	 * entry or in module param.
10574 	 */
10575 	image = dhd_os_open_image1(bus->dhd, ucode_path);
10576 	if (image == NULL)
10577 		goto err;
10578 
10579 	/* Update the dongle image download block size depending on the F1 block size */
10580 	if (sd_f1_blocksize == 512)
10581 		memblock_size = MAX_MEMBLOCK;
10582 
10583 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
10584 	if (memblock == NULL) {
10585 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10586 			memblock_size));
10587 		goto err;
10588 	}
10589 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
10590 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
10591 
10592 #ifdef DHD_DEBUG_DOWNLOADTIME
10593 	initial_jiffies = jiffies;
10594 #endif
10595 
10596 	/* Download image */
10597 	while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) {
10598 		if (len < 0) {
10599 			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
10600 			bcmerror = BCME_ERROR;
10601 			goto err;
10602 		}
10603 
10604 		bcmerror = dhdsdio_membytes(bus, TRUE, (ucode_base + offset), memptr, len);
10605 		if (bcmerror) {
10606 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10607 			        __FUNCTION__, bcmerror, memblock_size, offset));
10608 			goto err;
10609 		}
10610 
10611 		offset += memblock_size;
10612 #ifdef DHD_DEBUG_DOWNLOADTIME
10613 		firmware_sz += len;
10614 #endif
10615 	}
10616 
10617 #ifdef DHD_DEBUG_DOWNLOADTIME
10618 	DHD_ERROR(("ucode download time for %u bytes: %u ms\n",
10619 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
10620 #endif
10621 
10622 err:
10623 	if (memblock)
10624 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
10625 
10626 	if (image)
10627 		dhd_os_close_image1(bus->dhd, image);
10628 
10629 	return bcmerror;
10630 } /* dhdsdio_download_ucode_file */
10631 
10632 void
dhd_bus_ucode_download(struct dhd_bus * bus)10633 dhd_bus_ucode_download(struct dhd_bus *bus)
10634 {
10635 	uint32 shaddr = 0, shdata = 0;
10636 
10637 	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
10638 	dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&shdata, 4);
10639 
10640 	DHD_TRACE(("%s: shdata:[0x%08x :0x%08x]\n", __func__, shaddr, shdata));
10641 
10642 	if (shdata == UCODE_DOWNLOAD_REQUEST)
10643 	{
10644 		DHD_ERROR(("%s: Received ucode download request!\n", __func__));
10645 
10646 		/* Download the ucode */
10647 		if (!dhd_get_ucode_path(bus->dhd)) {
10648 			DHD_ERROR(("%s: bus->uc_path not set!\n", __func__));
10649 			return;
10650 		}
10651 		dhdsdio_download_ucode_file(bus, dhd_get_ucode_path(bus->dhd));
10652 
10653 		DHD_ERROR(("%s: Ucode downloaded successfully!\n", __func__));
10654 
10655 		shdata = UCODE_DOWNLOAD_COMPLETE;
10656 		dhdsdio_membytes(bus, TRUE, shaddr, (uint8 *)&shdata, 4);
10657 	}
10658 }
10659 
10660 #endif /* DHD_UCODE_DOWNLOAD */
10661 
10662 static int
dhdsdio_download_nvram(struct dhd_bus * bus)10663 dhdsdio_download_nvram(struct dhd_bus *bus)
10664 {
10665 	int bcmerror = -1;
10666 	uint len, memblock_len = 0;
10667 	char * memblock = NULL;
10668 	char *bufp;
10669 	char *pnv_path;
10670 	bool nvram_file_exists;
10671 
10672 	pnv_path = bus->nv_path;
10673 
10674 	nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
10675 
10676 	len = MAX_NVRAMBUF_SIZE;
10677 	if (nvram_file_exists)
10678 		bcmerror = dhd_get_download_buffer(bus->dhd, pnv_path, NVRAM, &memblock,
10679 			(int *)&len);
10680 	else
10681 		bcmerror = dhd_get_download_buffer(bus->dhd, NULL, NVRAM, &memblock, (int *)&len);
10682 
10683 	if (bcmerror != BCME_OK)
10684 		goto err;
10685 
10686 #ifdef DHD_LINUX_STD_FW_API
10687 	memblock_len = len;
10688 #else
10689 	memblock_len = MAX_NVRAMBUF_SIZE;
10690 #endif /* DHD_LINUX_STD_FW_API */
10691 
10692 	if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
10693 		bufp = (char *)memblock;
10694 		bufp[len] = 0;
10695 		len = process_nvram_vars(bufp, len);
10696 		if (len % 4) {
10697 			len += 4 - (len % 4);
10698 		}
10699 		bufp += len;
10700 		*bufp++ = 0;
10701 		if (len)
10702 			bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
10703 		if (bcmerror) {
10704 			DHD_ERROR(("%s: error downloading vars: %d\n",
10705 			           __FUNCTION__, bcmerror));
10706 		}
10707 	} else {
10708 		DHD_ERROR(("%s: error reading nvram file: %d\n",
10709 		           __FUNCTION__, len));
10710 		bcmerror = BCME_SDIO_ERROR;
10711 	}
10712 
10713 err:
10714 	if (memblock)
10715 		dhd_free_download_buffer(bus->dhd, memblock, memblock_len);
10716 
10717 	return bcmerror;
10718 }
10719 
10720 static int
_dhdsdio_download_firmware(struct dhd_bus * bus)10721 _dhdsdio_download_firmware(struct dhd_bus *bus)
10722 {
10723 	int bcmerror = -1;
10724 
10725 	bool embed = FALSE;	/* download embedded firmware */
10726 	bool dlok = FALSE;	/* download firmware succeeded */
10727 
10728 	/* Out immediately if no image to download */
10729 	if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
10730 #ifdef BCMEMBEDIMAGE
10731 		embed = TRUE;
10732 #else
10733 		return bcmerror;
10734 #endif
10735 	}
10736 
10737 	/* Keep arm in reset */
10738 	if (dhdsdio_download_state(bus, TRUE)) {
10739 		DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
10740 		goto err;
10741 	}
10742 
10743 	/* External image takes precedence if specified */
10744 	if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
10745 		if (dhdsdio_download_code_file(bus, bus->fw_path)) {
10746 			DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
10747 #ifdef BCMEMBEDIMAGE
10748 			embed = TRUE;
10749 #else
10750 			goto err;
10751 #endif
10752 		} else {
10753 			embed = FALSE;
10754 			dlok = TRUE;
10755 		}
10756 	}
10757 
10758 #ifdef BCMEMBEDIMAGE
10759 	if (embed) {
10760 		if (dhdsdio_download_code_array(bus)) {
10761 			DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
10762 			goto err;
10763 		} else {
10764 			dlok = TRUE;
10765 		}
10766 	}
10767 #else
10768 	BCM_REFERENCE(embed);
10769 #endif
10770 	if (!dlok) {
10771 		DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
10772 		goto err;
10773 	}
10774 
10775 	/* External nvram takes precedence if specified */
10776 	if (dhdsdio_download_nvram(bus)) {
10777 		DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
10778 		goto err;
10779 	}
10780 
10781 	/* Take arm out of reset */
10782 	if (dhdsdio_download_state(bus, FALSE)) {
10783 		DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
10784 		goto err;
10785 	}
10786 
10787 	bcmerror = 0;
10788 
10789 err:
10790 	return bcmerror;
10791 }
10792 
10793 static int
dhd_bcmsdh_recv_buf(dhd_bus_t * bus,uint32 addr,uint fn,uint flags,uint8 * buf,uint nbytes,void * pkt,bcmsdh_cmplt_fn_t complete_fn,void * handle)10794 dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
10795 	void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle)
10796 {
10797 	int status;
10798 
10799 	if (!KSO_ENAB(bus)) {
10800 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
10801 		return BCME_NODEVICE;
10802 	}
10803 
10804 	status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete_fn, handle);
10805 
10806 	return status;
10807 }
10808 
10809 static int
dhd_bcmsdh_send_buf(dhd_bus_t * bus,uint32 addr,uint fn,uint flags,uint8 * buf,uint nbytes,void * pkt,bcmsdh_cmplt_fn_t complete_fn,void * handle,int max_retry)10810 dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
10811 	void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle, int max_retry)
10812 {
10813 	int ret;
10814 	int i = 0;
10815 	int retries = 0;
10816 	bcmsdh_info_t *sdh;
10817 
10818 	if (!KSO_ENAB(bus)) {
10819 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
10820 		return BCME_NODEVICE;
10821 	}
10822 
10823 	sdh = bus->sdh;
10824 	do {
10825 		ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,
10826 			pkt, complete_fn, handle);
10827 
10828 		bus->f2txdata++;
10829 		ASSERT(ret != BCME_PENDING);
10830 
10831 		if (ret == BCME_NODEVICE) {
10832 			DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__));
10833 		} else if (ret < 0) {
10834 			/* On failure, abort the command and terminate the frame */
10835 			DHD_ERROR(("%s: sdio error %d, abort command and terminate frame.\n",
10836 				__FUNCTION__, ret));
10837 			bus->tx_sderrs++;
10838 			bus->f1regdata++;
10839 			bus->dhd->tx_errors++;
10840 			bcmsdh_abort(sdh, SDIO_FUNC_2);
10841 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
10842 				SFC_WF_TERM, NULL);
10843 			for (i = 0; i < READ_FRM_CNT_RETRIES; i++) {
10844 				uint8 hi, lo;
10845 				hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI,
10846 					NULL);
10847 				lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO,
10848 					NULL);
10849 				bus->f1regdata += 2;
10850 				if ((hi == 0) && (lo == 0))
10851 					break;
10852 			}
10853 		}
10854 	} while ((ret < 0) && retrydata && ++retries < max_retry);
10855 
10856 	return ret;
10857 }
10858 
10859 uint8
dhd_bus_is_ioready(struct dhd_bus * bus)10860 dhd_bus_is_ioready(struct dhd_bus *bus)
10861 {
10862 	uint8 enable;
10863 	bcmsdh_info_t *sdh;
10864 	ASSERT(bus);
10865 	ASSERT(bus->sih != NULL);
10866 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
10867 	sdh = bus->sdh;
10868 	return (enable == bcmsdh_cfg_read(sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL));
10869 }
10870 
10871 uint
dhd_bus_chip(struct dhd_bus * bus)10872 dhd_bus_chip(struct dhd_bus *bus)
10873 {
10874 	ASSERT(bus->sih != NULL);
10875 	return bus->sih->chip;
10876 }
10877 
10878 uint
dhd_bus_chiprev(struct dhd_bus * bus)10879 dhd_bus_chiprev(struct dhd_bus *bus)
10880 {
10881 	ASSERT(bus);
10882 	ASSERT(bus->sih != NULL);
10883 	return bus->sih->chiprev;
10884 }
10885 
10886 void *
dhd_bus_pub(struct dhd_bus * bus)10887 dhd_bus_pub(struct dhd_bus *bus)
10888 {
10889 	return bus->dhd;
10890 }
10891 
10892 void *
dhd_bus_sih(struct dhd_bus * bus)10893 dhd_bus_sih(struct dhd_bus *bus)
10894 {
10895 	return (void *)bus->sih;
10896 }
10897 
10898 void *
dhd_bus_txq(struct dhd_bus * bus)10899 dhd_bus_txq(struct dhd_bus *bus)
10900 {
10901 	return &bus->txq;
10902 }
10903 
10904 uint
dhd_bus_hdrlen(struct dhd_bus * bus)10905 dhd_bus_hdrlen(struct dhd_bus *bus)
10906 {
10907 	return (bus->txglom_enable) ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
10908 }
10909 
10910 void
dhd_bus_set_dotxinrx(struct dhd_bus * bus,bool val)10911 dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val)
10912 {
10913 	bus->dotxinrx = val;
10914 }
10915 
10916 /*
10917  *  dhdsdio_advertise_bus_cleanup advertises that clean up is under progress
10918  * to other bus user contexts like Tx, Rx, IOVAR, WD etc and it waits for other contexts
10919  * to gracefully exit. All the bus usage contexts before marking busstate as busy, will check for
10920  * whether the busstate is DHD_BUS_DOWN or DHD_BUS_DOWN_IN_PROGRESS, if so
10921  * they will exit from there itself without marking dhd_bus_busy_state as BUSY.
10922  */
10923 static void
dhdsdio_advertise_bus_cleanup(dhd_pub_t * dhdp)10924 dhdsdio_advertise_bus_cleanup(dhd_pub_t	 *dhdp)
10925 {
10926 	unsigned long flags;
10927 	int timeleft;
10928 
10929 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
10930 	dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS;
10931 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
10932 
10933 	timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
10934 #ifdef LINUX
10935 	if ((timeleft == 0) || (timeleft == 1))
10936 #else
10937 	if (timeleft == 0)
10938 #endif
10939 	{
10940 		/* XXX This condition ideally should not occur, this means some
10941 		 * bus usage context is not clearing the respective usage bit, print
10942 		 * dhd_bus_busy_state and crash the host for further debugging.
10943 		 */
10944 		DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
10945 				__FUNCTION__, dhdp->dhd_bus_busy_state));
10946 		ASSERT(0);
10947 	}
10948 
10949 	return;
10950 }
10951 
10952 static void
dhdsdio_advertise_bus_remove(dhd_pub_t * dhdp)10953 dhdsdio_advertise_bus_remove(dhd_pub_t	 *dhdp)
10954 {
10955 	unsigned long flags;
10956 	int timeleft;
10957 
10958 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
10959 	dhdp->busstate = DHD_BUS_REMOVE;
10960 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
10961 
10962 	timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
10963 	if ((timeleft == 0) || (timeleft == 1)) {
10964 		DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
10965 				__FUNCTION__, dhdp->dhd_bus_busy_state));
10966 		ASSERT(0);
10967 	}
10968 
10969 	return;
10970 }
10971 
10972 int
dhd_bus_devreset(dhd_pub_t * dhdp,uint8 flag)10973 dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
10974 {
10975 	int bcmerror = 0;
10976 	dhd_bus_t *bus;
10977 	unsigned long flags;
10978 
10979 	bus = dhdp->bus;
10980 
10981 	if (flag == TRUE) {
10982 		if (!bus->dhd->dongle_reset) {
10983 			DHD_ERROR(("%s: == Power OFF ==\n", __FUNCTION__));
10984 			dhdsdio_advertise_bus_cleanup(bus->dhd);
10985 			dhd_os_sdlock(dhdp);
10986 			dhd_os_wd_timer(dhdp, 0);
10987 #if defined(OEM_ANDROID)
10988 #if !defined(IGNORE_ETH0_DOWN)
10989 			/* Force flow control as protection when stop come before ifconfig_down */
10990 			dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
10991 #endif /* !defined(IGNORE_ETH0_DOWN) */
10992 #endif /* OEM_ANDROID */
10993 			/* Expect app to have torn down any connection before calling */
10994 			/* Stop the bus, disable F2 */
10995 			dhd_bus_stop(bus, FALSE);
10996 
10997 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
10998 			/* Clean up any pending IRQ */
10999 			dhd_enable_oob_intr(bus, FALSE);
11000 			bcmsdh_oob_intr_set(bus->sdh, FALSE);
11001 			bcmsdh_oob_intr_unregister(bus->sdh);
11002 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
11003 
11004 			/* Clean tx/rx buffer pointers, detach from the dongle */
11005 			dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
11006 
11007 			bus->dhd->dongle_reset = TRUE;
11008 			DHD_ERROR(("%s: making dhdpub up FALSE\n", __FUNCTION__));
11009 			bus->dhd->up = FALSE;
11010 			dhd_txglom_enable(dhdp, FALSE);
11011 			dhd_os_sdunlock(dhdp);
11012 
11013 			DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
11014 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
11015 			bus->dhd->busstate = DHD_BUS_DOWN;
11016 			DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
11017 
11018 			DHD_TRACE(("%s:  WLAN OFF DONE\n", __FUNCTION__));
11019 			/* App can now remove power from device */
11020 		} else
11021 			bcmerror = BCME_SDIO_ERROR;
11022 	} else {
11023 		/* App must have restored power to device before calling */
11024 
11025 		printf("%s: == Power ON ==\n", __FUNCTION__);
11026 
11027 		if (bus->dhd->dongle_reset) {
11028 			/* Turn on WLAN */
11029 			dhd_os_sdlock(dhdp);
11030 			/* Reset SD client */
11031 			bcmsdh_reset(bus->sdh);
11032 
11033 			/* Attempt to re-attach & download */
11034 			if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
11035 				(uint32 *)(uintptr)si_enum_base(bus->cl_devid),
11036 				bus->cl_devid)) {
11037 
11038 				DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
11039 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
11040 				bus->dhd->busstate = DHD_BUS_DOWN;
11041 				DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
11042 				/* Attempt to download binary to the dongle */
11043 				if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
11044 				    dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) {
11045 
11046 					/* Re-init bus, enable F2 transfer */
11047 					bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
11048 					if (bcmerror == BCME_OK) {
11049 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
11050 						dhd_enable_oob_intr(bus, TRUE);
11051 						bcmsdh_oob_intr_register(bus->sdh,
11052 							dhdsdio_isr, bus);
11053 						bcmsdh_oob_intr_set(bus->sdh, TRUE);
11054 #elif defined(FORCE_WOWLAN)
11055 						dhd_enable_oob_intr(bus, TRUE);
11056 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
11057 
11058 						bus->dhd->dongle_reset = FALSE;
11059 						bus->dhd->up = TRUE;
11060 
11061 #if defined(OEM_ANDROID) && !defined(IGNORE_ETH0_DOWN)
11062 						/* Restore flow control  */
11063 						dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
11064 #endif /* defined(OEM_ANDROID) &&  (!defined(IGNORE_ETH0_DOWN)) */
11065 						dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
11066 
11067 						DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
11068 					} else {
11069 						dhd_bus_stop(bus, FALSE);
11070 						dhdsdio_release_dongle(bus, bus->dhd->osh,
11071 							TRUE, FALSE);
11072 					}
11073 				} else {
11074 					DHD_ERROR(("%s Failed to download binary to the dongle\n",
11075 						__FUNCTION__));
11076 					if (bus->sih != NULL) {
11077 						si_detach(bus->sih);
11078 						bus->sih = NULL;
11079 					}
11080 					bcmerror = BCME_SDIO_ERROR;
11081 				}
11082 			} else
11083 				bcmerror = BCME_SDIO_ERROR;
11084 
11085 			dhd_os_sdunlock(dhdp);
11086 		} else {
11087 			DHD_INFO(("%s called when dongle is not in reset\n",
11088 				__FUNCTION__));
11089 #if defined(OEM_ANDROID)
11090 			DHD_INFO(("Will call dhd_bus_start instead\n"));
11091 			dhd_bus_resume(dhdp, 1);
11092 #if defined(HW_OOB) || defined(FORCE_WOWLAN)
11093 			dhd_conf_set_hw_oob_intr(bus->sdh, bus->sih); // terence 20120615: fix for OOB initial issue
11094 #endif
11095 			if ((bcmerror = dhd_bus_start(dhdp)) != 0)
11096 				DHD_ERROR(("%s: dhd_bus_start fail with %d\n",
11097 					__FUNCTION__, bcmerror));
11098 #endif /* defined(OEM_ANDROID) */
11099 		}
11100 	}
11101 
11102 #ifdef PKT_STATICS
11103 	dhd_bus_clear_txpktstatics(dhdp);
11104 #endif
11105 	return bcmerror;
11106 }
11107 
11108 #if defined(LINUX)
dhd_bus_suspend(dhd_pub_t * dhdpub)11109 int dhd_bus_suspend(dhd_pub_t *dhdpub)
11110 {
11111 	return bcmsdh_stop(dhdpub->bus->sdh);
11112 }
11113 
dhd_bus_resume(dhd_pub_t * dhdpub,int stage)11114 int dhd_bus_resume(dhd_pub_t *dhdpub, int stage)
11115 {
11116 	return bcmsdh_start(dhdpub->bus->sdh, stage);
11117 }
11118 #endif /* defined(LINUX) */
11119 
11120 /* Get Chip ID version */
dhd_bus_chip_id(dhd_pub_t * dhdp)11121 uint dhd_bus_chip_id(dhd_pub_t *dhdp)
11122 {
11123 	dhd_bus_t *bus = dhdp->bus;
11124 
11125 	if (bus && bus->sih)
11126 		return bus->sih->chip;
11127 	else
11128 		return 0;
11129 }
11130 
11131 /* Get Chip Rev ID version */
dhd_bus_chiprev_id(dhd_pub_t * dhdp)11132 uint dhd_bus_chiprev_id(dhd_pub_t *dhdp)
11133 {
11134 	dhd_bus_t *bus = dhdp->bus;
11135 
11136 	if (bus && bus->sih)
11137 		return bus->sih->chiprev;
11138 	else
11139 		return 0;
11140 }
11141 
11142 /* Get Chip Pkg ID version */
dhd_bus_chippkg_id(dhd_pub_t * dhdp)11143 uint dhd_bus_chippkg_id(dhd_pub_t *dhdp)
11144 {
11145 	dhd_bus_t *bus = dhdp->bus;
11146 
11147 	return bus->sih->chippkg;
11148 }
11149 
dhd_bus_get_ids(struct dhd_bus * bus,uint32 * bus_type,uint32 * bus_num,uint32 * slot_num)11150 int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num, uint32 *slot_num)
11151 {
11152 	*bus_type = bus->bus;
11153 	*bus_num = bus->bus_num;
11154 	*slot_num = bus->slot_num;
11155 	return 0;
11156 }
11157 
11158 int
dhd_bus_membytes(dhd_pub_t * dhdp,bool set,uint32 address,uint8 * data,uint size)11159 dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size)
11160 {
11161 	dhd_bus_t *bus;
11162 
11163 	bus = dhdp->bus;
11164 	return dhdsdio_membytes(bus, set, address, data, size);
11165 }
11166 
11167 #if defined(SUPPORT_MULTIPLE_REVISION)
11168 static int
concate_revision_bcm4335(dhd_bus_t * bus,char * fw_path,char * nv_path)11169 concate_revision_bcm4335(dhd_bus_t *bus, char *fw_path, char *nv_path)
11170 {
11171 
11172 	uint chipver;
11173 #if defined(SUPPORT_MULTIPLE_CHIPS)
11174 	char chipver_tag[10] = "_4335";
11175 #else
11176 	char chipver_tag[4] = {0, };
11177 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11178 
11179 	DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__));
11180 	if (bus->sih->chip != BCM4335_CHIP_ID) {
11181 		DHD_ERROR(("%s:Chip is not BCM4335\n", __FUNCTION__));
11182 		return -1;
11183 	}
11184 	chipver = bus->sih->chiprev;
11185 	DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
11186 	if (chipver == 0x0) {
11187 		DHD_ERROR(("----- CHIP bcm4335_A0 -----\n"));
11188 		strcat(chipver_tag, "_a0");
11189 	} else if (chipver == 0x1) {
11190 		DHD_ERROR(("----- CHIP bcm4335_B0 -----\n"));
11191 #if defined(SUPPORT_MULTIPLE_CHIPS)
11192 		strcat(chipver_tag, "_b0");
11193 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11194 	}
11195 
11196 	strcat(fw_path, chipver_tag);
11197 	strcat(nv_path, chipver_tag);
11198 	return 0;
11199 }
11200 
11201 static int
concate_revision_bcm4339(dhd_bus_t * bus,char * fw_path,char * nv_path)11202 concate_revision_bcm4339(dhd_bus_t *bus, char *fw_path, char *nv_path)
11203 {
11204 
11205 	uint chipver;
11206 #if defined(SUPPORT_MULTIPLE_CHIPS)
11207 	char chipver_tag[10] = "_4339";
11208 #else
11209 	char chipver_tag[4] = {0, };
11210 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11211 
11212 	DHD_TRACE(("%s: BCM4339 Multiple Revision Check\n", __FUNCTION__));
11213 	if (bus->sih->chip != BCM4339_CHIP_ID) {
11214 		DHD_ERROR(("%s:Chip is not BCM4339\n", __FUNCTION__));
11215 		return -1;
11216 	}
11217 	chipver = bus->sih->chiprev;
11218 	DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
11219 	if (chipver == 0x1) {
11220 		DHD_ERROR(("----- CHIP bcm4339_A0 -----\n"));
11221 		strcat(chipver_tag, "_a0");
11222 	} else {
11223 		DHD_ERROR(("----- CHIP bcm4339 unknown revision %d -----\n",
11224 			chipver));
11225 	}
11226 
11227 	strcat(fw_path, chipver_tag);
11228 	strcat(nv_path, chipver_tag);
11229 	return 0;
11230 }
11231 
concate_revision_bcm4350(dhd_bus_t * bus,char * fw_path,char * nv_path)11232 static int concate_revision_bcm4350(dhd_bus_t *bus, char *fw_path, char *nv_path)
11233 {
11234 	uint32 chip_ver;
11235 #if defined(SUPPORT_MULTIPLE_CHIPS)
11236 	char chipver_tag[10] = {0, };
11237 #else
11238 	char chipver_tag[4] = {0, };
11239 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11240 	chip_ver = bus->sih->chiprev;
11241 
11242 #if defined(SUPPORT_MULTIPLE_CHIPS)
11243 	if (chip_ver == 3)
11244 		strcat(chipver_tag, "_4354");
11245 	else
11246 		strcat(chipver_tag, "_4350");
11247 #endif
11248 
11249 	if (chip_ver == 3) {
11250 		DHD_ERROR(("----- CHIP 4354 A0 -----\n"));
11251 		strcat(chipver_tag, "_a0");
11252 	} else {
11253 		DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
11254 	}
11255 
11256 	strcat(fw_path, chipver_tag);
11257 	strcat(nv_path, chipver_tag);
11258 	return 0;
11259 }
11260 
concate_revision_bcm4354(dhd_bus_t * bus,char * fw_path,char * nv_path)11261 static int concate_revision_bcm4354(dhd_bus_t *bus, char *fw_path, char *nv_path)
11262 {
11263 	uint32 chip_ver;
11264 #if defined(SUPPORT_MULTIPLE_CHIPS)
11265 	char chipver_tag[10] = "_4354";
11266 #else
11267 #if !defined(CUSTOMER_HW4)
11268 	char chipver_tag[4] = {0, };
11269 #endif /* !CUSTOMER_HW4 */
11270 #endif /* SUPPORT_MULTIPLE_CHIPS */
11271 
11272 	chip_ver = bus->sih->chiprev;
11273 #if !defined(SUPPORT_MULTIPLE_CHIPS) && defined(CUSTOMER_HW4)
11274 	DHD_INFO(("----- CHIP 4354, ver=%x -----\n", chip_ver));
11275 #else
11276 	if (chip_ver == 1) {
11277 		DHD_ERROR(("----- CHIP 4354 A1 -----\n"));
11278 		strcat(chipver_tag, "_a1");
11279 	} else {
11280 		DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
11281 	}
11282 
11283 	strcat(fw_path, chipver_tag);
11284 	strcat(nv_path, chipver_tag);
11285 #endif /* !SUPPORT_MULTIPLE_CHIPS && CUSTOMER_HW4 */
11286 
11287 	return 0;
11288 }
11289 
11290 static int
concate_revision_bcm43454(dhd_bus_t * bus,char * fw_path,char * nv_path)11291 concate_revision_bcm43454(dhd_bus_t *bus, char *fw_path, char *nv_path)
11292 {
11293 	char chipver_tag[10] = {0, };
11294 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
11295 	int base_system_rev_for_nv = 0;
11296 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
11297 
11298 	DHD_TRACE(("%s: BCM43454 Multiple Revision Check\n", __FUNCTION__));
11299 	if (bus->sih->chip != BCM43454_CHIP_ID) {
11300 		DHD_ERROR(("%s:Chip is not BCM43454!\n", __FUNCTION__));
11301 		return -1;
11302 	}
11303 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
11304 	base_system_rev_for_nv = dhd_get_system_rev();
11305 	if (base_system_rev_for_nv > 0) {
11306 		DHD_ERROR(("----- Board Rev  [%d] -----\n", base_system_rev_for_nv));
11307 		sprintf(chipver_tag, "_r%02d", base_system_rev_for_nv);
11308 	}
11309 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
11310 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW
11311 	DHD_ERROR(("----- Rev [%d] Fot MULTIPLE Board. -----\n", system_hw_rev));
11312 	if ((system_hw_rev >= 8) && (system_hw_rev <= 11)) {
11313 		DHD_ERROR(("This HW is Rev 08 ~ 11. this is For FD-HW\n"));
11314 		strcat(chipver_tag, "_FD");
11315 	}
11316 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
11317 
11318 	strcat(nv_path, chipver_tag);
11319 	return 0;
11320 }
11321 
11322 int
concate_revision(dhd_bus_t * bus,char * fw_path,char * nv_path)11323 concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path)
11324 {
11325 	int res = 0;
11326 
11327 	if (!bus || !bus->sih) {
11328 		DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
11329 		return -1;
11330 	}
11331 
11332 	switch (bus->sih->chip) {
11333 	case BCM4335_CHIP_ID:
11334 		res = concate_revision_bcm4335(bus, fw_path, nv_path);
11335 
11336 		break;
11337 	case BCM4339_CHIP_ID:
11338 		res = concate_revision_bcm4339(bus, fw_path, nv_path);
11339 		break;
11340 	case BCM4350_CHIP_ID:
11341 		res = concate_revision_bcm4350(bus, fw_path, nv_path);
11342 		break;
11343 	case BCM4354_CHIP_ID:
11344 		res = concate_revision_bcm4354(bus, fw_path, nv_path);
11345 		break;
11346 	case BCM43454_CHIP_ID:
11347 		res = concate_revision_bcm43454(bus, fw_path, nv_path);
11348 		break;
11349 
11350 		/* XXX: Add New Multiple CHIP ID */
11351 	default:
11352 		DHD_ERROR(("REVISION SPECIFIC feature is not required\n"));
11353 		/* XXX: if revision specific feature is not required then return true always */
11354 		return res;
11355 	}
11356 
11357 	if (res == 0) {
11358 #ifdef BCMDBG
11359 		printf("dhd concatenated fw & nv:\n   fw_path:%s\n"
11360 			"   nv_path:%s\n", fw_path, nv_path);
11361 		printf("make sure they exist\n");
11362 #endif
11363 	}
11364 	return res;
11365 }
11366 #endif /* SUPPORT_MULTIPLE_REVISION */
11367 
11368 #if defined(NDIS)
11369 void
dhd_bus_reject_ioreqs(dhd_pub_t * dhdp,bool reject)11370 dhd_bus_reject_ioreqs(dhd_pub_t *dhdp, bool reject)
11371 {
11372 
11373 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
11374 
11375 	bcmsdh_reject_ioreqs(dhdp->bus->sdh, reject);
11376 }
11377 
11378 void
dhd_bus_waitfor_iodrain(dhd_pub_t * dhdp)11379 dhd_bus_waitfor_iodrain(dhd_pub_t *dhdp)
11380 {
11381 
11382 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
11383 
11384 	bcmsdh_waitfor_iodrain(dhdp->bus->sdh);
11385 }
11386 #endif /* (NDIS) */
11387 
11388 void
dhd_bus_update_fw_nv_path(struct dhd_bus * bus,char * pfw_path,char * pnv_path,char * pclm_path,char * pconf_path)11389 dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path,
11390 									char *pclm_path, char *pconf_path)
11391 {
11392 	bus->fw_path = pfw_path;
11393 	bus->nv_path = pnv_path;
11394 	bus->dhd->clm_path = pclm_path;
11395 	bus->dhd->conf_path = pconf_path;
11396 }
11397 
11398 int
dhd_enableOOB(dhd_pub_t * dhd,bool sleep)11399 dhd_enableOOB(dhd_pub_t *dhd, bool sleep)
11400 {
11401 	dhd_bus_t *bus = dhd->bus;
11402 	sdpcmd_regs_t *regs = bus->regs;
11403 	uint retries = 0;
11404 
11405 	if (sleep) {
11406 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11407 		/* Tell device to start using OOB wakeup */
11408 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
11409 		if (retries > retry_limit) {
11410 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
11411 			return BCME_BUSY;
11412 		}
11413 		/* Turn off our contribution to the HT clock request */
11414 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
11415 	} else {
11416 		/* Make sure the controller has the bus up */
11417 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11418 
11419 		/* Send misc interrupt to indicate OOB not needed */
11420 		W_SDREG(0, &regs->tosbmailboxdata, retries);
11421 		if (retries <= retry_limit)
11422 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
11423 
11424 		if (retries > retry_limit)
11425 			DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
11426 
11427 		/* Make sure we have SD bus access */
11428 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
11429 	}
11430 	return BCME_OK;
11431 }
11432 
11433 void
dhd_bus_pktq_flush(dhd_pub_t * dhdp)11434 dhd_bus_pktq_flush(dhd_pub_t *dhdp)
11435 {
11436 	dhd_bus_t *bus = dhdp->bus;
11437 	bool wlfc_enabled = FALSE;
11438 
11439 #ifdef PROP_TXSTATUS
11440 	wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED);
11441 #endif
11442 	if (!wlfc_enabled) {
11443 #ifdef DHDTCPACK_SUPPRESS
11444 		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
11445 		 * when there is a newly coming packet from network stack.
11446 		 */
11447 		dhd_tcpack_info_tbl_clean(bus->dhd);
11448 #endif /* DHDTCPACK_SUPPRESS */
11449 		/* Clear the data packet queues */
11450 		pktq_flush(dhdp->osh, &bus->txq, TRUE);
11451 	}
11452 }
11453 
11454 #ifdef BCMSDIO
11455 int
dhd_sr_config(dhd_pub_t * dhd,bool on)11456 dhd_sr_config(dhd_pub_t *dhd, bool on)
11457 {
11458 	dhd_bus_t *bus = dhd->bus;
11459 
11460 	if (!bus->_srenab)
11461 		return -1;
11462 
11463 	return dhdsdio_clk_devsleep_iovar(bus, on);
11464 }
11465 
11466 uint16
dhd_get_chipid(struct dhd_bus * bus)11467 dhd_get_chipid(struct dhd_bus *bus)
11468 {
11469 	if (bus && bus->sih)
11470 		return (uint16)bus->sih->chip;
11471 	else
11472 		return 0;
11473 }
11474 #endif /* BCMSDIO */
11475 
11476 #ifdef DEBUGGER
11477 static uint32
dhd_sdio_reg_read(struct dhd_bus * bus,ulong addr)11478 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr)
11479 {
11480 	uint32 rval;
11481 
11482 	dhd_os_sdlock(bus->dhd);
11483 
11484 	BUS_WAKE(bus);
11485 
11486 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11487 
11488 	rval = bcmsdh_reg_read(bus->sdh, addr, 4);
11489 
11490 	dhd_os_sdunlock(bus->dhd);
11491 
11492 	return rval;
11493 }
11494 
11495 static void
dhd_sdio_reg_write(struct dhd_bus * bus,ulong addr,uint32 val)11496 dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val)
11497 {
11498 	dhd_os_sdlock(bus->dhd);
11499 
11500 	BUS_WAKE(bus);
11501 
11502 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11503 
11504 	bcmsdh_reg_write(bus->sdh, addr, 4, val);
11505 
11506 	dhd_os_sdunlock(bus->dhd);
11507 }
11508 
11509 #endif /* DEBUGGER */
11510 
11511 #if defined(SOFTAP_TPUT_ENHANCE)
dhd_bus_setidletime(dhd_pub_t * dhdp,int idle_time)11512 void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time)
11513 {
11514 	if (!dhdp || !dhdp->bus) {
11515 		DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
11516 		return;
11517 	}
11518 	dhdp->bus->idletime = idle_time;
11519 }
11520 
dhd_bus_getidletime(dhd_pub_t * dhdp,int * idle_time)11521 void dhd_bus_getidletime(dhd_pub_t *dhdp, int* idle_time)
11522 {
11523 	if (!dhdp || !dhdp->bus) {
11524 		DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
11525 		return;
11526 	}
11527 
11528 	if (!idle_time) {
11529 		DHD_ERROR(("%s:Arg idle_time is NULL\n", __FUNCTION__));
11530 		return;
11531 	}
11532 	*idle_time = dhdp->bus->idletime;
11533 }
11534 #endif /* SOFTAP_TPUT_ENHANCE */
11535 
11536 #if defined(BT_OVER_SDIO)
dhd_bus_cfg_read(void * h,uint fun_num,uint32 addr,int * err)11537 uint8 dhd_bus_cfg_read(void *h, uint fun_num, uint32 addr, int *err)
11538 {
11539 	uint8 intrd;
11540 	dhd_pub_t *dhdp = (dhd_pub_t *)h;
11541 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
11542 
11543 	dhd_os_sdlock(bus->dhd);
11544 
11545 	intrd = bcmsdh_cfg_read(bus->sdh, fun_num, addr, err);
11546 
11547 	dhd_os_sdunlock(bus->dhd);
11548 
11549 	return intrd;
11550 } EXPORT_SYMBOL(dhd_bus_cfg_read);
11551 
dhd_bus_cfg_write(void * h,uint fun_num,uint32 addr,uint8 val,int * err)11552 void dhd_bus_cfg_write(void *h, uint fun_num, uint32 addr, uint8 val, int *err)
11553 {
11554 	dhd_pub_t *dhdp = (dhd_pub_t *)h;
11555 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
11556 
11557 	dhd_os_sdlock(bus->dhd);
11558 
11559 	bcmsdh_cfg_write(bus->sdh, fun_num, addr, val, err);
11560 
11561 	dhd_os_sdunlock(bus->dhd);
11562 
11563 } EXPORT_SYMBOL(dhd_bus_cfg_write);
11564 
11565 static int
extract_hex_field(char * line,uint16 start_pos,uint16 num_chars,uint16 * value)11566 extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value)
11567 {
11568 	char field [8];
11569 
11570 	strlcpy(field, line + start_pos, sizeof(field));
11571 
11572 	return (sscanf (field, "%hX", value) == 1);
11573 }
11574 
11575 static int
read_more_btbytes(struct dhd_bus * bus,void * file,char * line,int * addr_mode,uint16 * hi_addr,uint32 * dest_addr,uint8 * data_bytes,uint32 * num_bytes)11576 read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode, uint16 * hi_addr,
11577 	uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes)
11578 {
11579 	int		str_len;
11580 	uint16	num_data_bytes, addr, data_pos, type, w, i;
11581 	uint32	abs_base_addr32 = 0;
11582 	*num_bytes = 0;
11583 
11584 	while (!*num_bytes)
11585 	{
11586 		str_len = dhd_os_gets_image(bus->dhd, line, BTFW_MAX_STR_LEN, file);
11587 
11588 		DHD_TRACE(("%s: Len :0x%x  %s\n", __FUNCTION__, str_len, line));
11589 
11590 		if (str_len == 0) {
11591 			break;
11592 		} else if (str_len > 9) {
11593 			extract_hex_field(line, 1, 2, &num_data_bytes);
11594 			extract_hex_field(line, 3, 4, &addr);
11595 			extract_hex_field(line, 7, 2, &type);
11596 
11597 			data_pos = 9;
11598 			for (i = 0; i < num_data_bytes; i++) {
11599 				extract_hex_field(line, data_pos, 2, &w);
11600 				data_bytes [i] = (uint8)(w & 0x00FF);
11601 				data_pos += 2;
11602 			}
11603 
11604 			if (type == BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS) {
11605 				*hi_addr = (data_bytes [0] << 8) | data_bytes [1];
11606 				*addr_mode = BTFW_ADDR_MODE_EXTENDED;
11607 			} else if (type == BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS) {
11608 				*hi_addr = (data_bytes [0] << 8) | data_bytes [1];
11609 				*addr_mode = BTFW_ADDR_MODE_SEGMENT;
11610 			} else if (type == BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS) {
11611 				abs_base_addr32 = (data_bytes [0] << 24) | (data_bytes [1] << 16) |
11612 					(data_bytes [2] << 8) | data_bytes [3];
11613 				*addr_mode = BTFW_ADDR_MODE_LINEAR32;
11614 			} else if (type == BTFW_HEX_LINE_TYPE_DATA) {
11615 				*dest_addr = addr;
11616 				if (*addr_mode == BTFW_ADDR_MODE_EXTENDED)
11617 					*dest_addr += (*hi_addr << 16);
11618 				else if (*addr_mode == BTFW_ADDR_MODE_SEGMENT)
11619 					*dest_addr += (*hi_addr << 4);
11620 				else if (*addr_mode == BTFW_ADDR_MODE_LINEAR32)
11621 					*dest_addr += abs_base_addr32;
11622 				*num_bytes = num_data_bytes;
11623 			}
11624 		}
11625 	}
11626 	return (*num_bytes > 0);
11627 }
11628 
11629 static int
_dhdsdio_download_btfw(struct dhd_bus * bus)11630 _dhdsdio_download_btfw(struct dhd_bus *bus)
11631 {
11632 	int	bcm_error = -1;
11633 	void	*image = NULL;
11634 	uint8	*mem_blk = NULL, *mem_ptr = NULL, *data_ptr = NULL;
11635 
11636 	uint32 offset_addr = 0, offset_len = 0, bytes_to_write = 0;
11637 
11638 	char	*line = NULL;
11639 	uint32	dest_addr = 0, num_bytes;
11640 	uint16	hiAddress = 0;
11641 	uint32	start_addr, start_data, end_addr, end_data, i, index, pad,
11642 	bt2wlan_pwrup_adr;
11643 
11644 	int	addr_mode		= BTFW_ADDR_MODE_EXTENDED;
11645 
11646 	/* Out immediately if no image to download */
11647 	if ((bus->btfw_path == NULL) || (bus->btfw_path[0] == '\0')) {
11648 		return 0;
11649 	}
11650 
11651 	/* XXX: Should succeed in opening image if it is actually given through registry
11652 	 * entry or in module param.
11653 	 */
11654 	image = dhd_os_open_image1(bus->dhd, bus->btfw_path);
11655 	if (image == NULL)
11656 		goto err;
11657 
11658 	mem_ptr = mem_blk = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN);
11659 	if (mem_blk == NULL) {
11660 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
11661 			BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN));
11662 		goto err;
11663 	}
11664 	if ((uint32)(uintptr)mem_blk % DHD_SDALIGN)
11665 		mem_ptr += (DHD_SDALIGN - ((uint32)(uintptr)mem_blk % DHD_SDALIGN));
11666 
11667 	data_ptr = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE - 8);
11668 	if (data_ptr == NULL) {
11669 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
11670 			BTFW_DOWNLOAD_BLK_SIZE - 8));
11671 		goto err;
11672 	}
11673 	/* Write to BT register to hold WLAN wake high during BT FW download */
11674 	bt2wlan_pwrup_adr = BTMEM_OFFSET + BT2WLAN_PWRUP_ADDR;
11675 	bcmsdh_reg_write(bus->sdh, bt2wlan_pwrup_adr, 4, BT2WLAN_PWRUP_WAKE);
11676 	/*
11677 	  * Wait for at least 2msec for the clock to be ready/Available.
11678 	  */
11679 	OSL_DELAY(2000);
11680 
11681 	line = MALLOC(bus->dhd->osh, BTFW_MAX_STR_LEN);
11682 	if (line == NULL) {
11683 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
11684 			__FUNCTION__, BTFW_MAX_STR_LEN));
11685 		goto err;
11686 	}
11687 	memset(line, 0, BTFW_MAX_STR_LEN);
11688 
11689 	while (read_more_btbytes (bus, image, line, &addr_mode, &hiAddress, &dest_addr,
11690 		data_ptr, &num_bytes)) {
11691 
11692 		DHD_TRACE(("read %d bytes at address %08X\n", num_bytes, dest_addr));
11693 
11694 		start_addr = BTMEM_OFFSET + dest_addr;
11695 		index = 0;
11696 
11697 		/* Make sure the start address is 4 byte aligned to avoid alignment issues
11698 		 * with SD host controllers
11699 		 */
11700 		if (!ISALIGNED(start_addr, 4)) {
11701 			pad = start_addr % 4;
11702 			start_addr = ROUNDDN(start_addr, 4);
11703 			start_data = bcmsdh_reg_read(bus->sdh, start_addr, 4);
11704 			for (i = 0; i < pad; i++, index++) {
11705 			    mem_ptr[index] = (uint8)((uint8 *)&start_data)[i];
11706 			}
11707 		}
11708 		bcopy(data_ptr, &(mem_ptr[index]), num_bytes);
11709 		index += num_bytes;
11710 
11711 		/* Make sure the length is multiple of 4bytes to avoid alignment issues
11712 		 * with SD host controllers
11713 		 */
11714 		end_addr = start_addr + index;
11715 		if (!ISALIGNED(end_addr, 4)) {
11716 			end_addr = ROUNDDN(end_addr, 4);
11717 			end_data = bcmsdh_reg_read(bus->sdh, end_addr, 4);
11718 			for (i = (index % 4); i < 4; i++, index++) {
11719 				mem_ptr[index] = (uint8)((uint8 *)&end_data)[i];
11720 			}
11721 		}
11722 
11723 		offset_addr = start_addr & 0xFFF;
11724 		offset_len =  offset_addr + index;
11725 		if (offset_len <= 0x1000) {
11726 			bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr, index);
11727 			if (bcm_error) {
11728 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
11729 				__FUNCTION__, bcm_error, num_bytes, start_addr));
11730 				goto err;
11731 			}
11732 		}
11733 		else {
11734 			bytes_to_write = 0x1000 - offset_addr;
11735 			bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr,
11736 				bytes_to_write);
11737 			if (bcm_error) {
11738 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
11739 				__FUNCTION__, bcm_error, num_bytes, start_addr));
11740 				goto err;
11741 			}
11742 
11743 			OSL_DELAY(10000);
11744 
11745 			bcm_error = dhdsdio_membytes(bus, TRUE, (start_addr + bytes_to_write),
11746 				(mem_ptr + bytes_to_write), (index - bytes_to_write));
11747 			if (bcm_error) {
11748 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
11749 					__FUNCTION__, bcm_error, num_bytes, start_addr));
11750 				goto err;
11751 			}
11752 		}
11753 		memset(line, 0, BTFW_MAX_STR_LEN);
11754 	}
11755 
11756 	bcm_error = 0;
11757 err:
11758 	if (mem_blk)
11759 		MFREE(bus->dhd->osh, mem_blk, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN);
11760 
11761 	if (data_ptr)
11762 		MFREE(bus->dhd->osh, data_ptr, BTFW_DOWNLOAD_BLK_SIZE - 8);
11763 
11764 	if (line)
11765 		MFREE(bus->dhd->osh, line, BTFW_MAX_STR_LEN);
11766 
11767 	if (image)
11768 		dhd_os_close_image1(bus->dhd, image);
11769 
11770 	return bcm_error;
11771 }
11772 
11773 static int
dhdsdio_download_btfw(struct dhd_bus * bus,osl_t * osh,void * sdh)11774 dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh)
11775 {
11776 	int ret;
11777 
11778 	DHD_TRACE(("%s: btfw path=%s\n",
11779 		__FUNCTION__, bus->btfw_path));
11780 	DHD_OS_WAKE_LOCK(bus->dhd);
11781 	dhd_os_sdlock(bus->dhd);
11782 
11783 	/* Download the firmware */
11784 	ret = _dhdsdio_download_btfw(bus);
11785 
11786 	dhd_os_sdunlock(bus->dhd);
11787 	DHD_OS_WAKE_UNLOCK(bus->dhd);
11788 
11789 	return ret;
11790 }
11791 
11792 int
dhd_bus_download_btfw(struct dhd_bus * bus,osl_t * osh,char * pbtfw_path)11793 dhd_bus_download_btfw(struct dhd_bus *bus, osl_t *osh,
11794                           char *pbtfw_path)
11795 {
11796 	int ret;
11797 
11798 	bus->btfw_path = pbtfw_path;
11799 
11800 	ret = dhdsdio_download_btfw(bus, osh, bus->sdh);
11801 
11802 	return ret;
11803 }
11804 #endif /* defined (BT_OVER_SDIO) */
11805 
11806 void
dhd_bus_dump_trap_info(dhd_bus_t * bus,struct bcmstrbuf * strbuf)11807 dhd_bus_dump_trap_info(dhd_bus_t *bus, struct bcmstrbuf *strbuf)
11808 {
11809 	trap_t *tr = &bus->dhd->last_trap_info;
11810 
11811 	bcm_bprintf(strbuf,
11812 		"Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
11813 		"lp 0x%x, rpc 0x%x Trap offset 0x%x, "
11814 		"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
11815 		"r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
11816 		ltoh32(tr->type), ltoh32(tr->epc), ltoh32(tr->cpsr), ltoh32(tr->spsr),
11817 		ltoh32(tr->r13), ltoh32(tr->r14), ltoh32(tr->pc),
11818 		ltoh32(bus->dongle_trap_addr),
11819 		ltoh32(tr->r0), ltoh32(tr->r1), ltoh32(tr->r2), ltoh32(tr->r3),
11820 		ltoh32(tr->r4), ltoh32(tr->r5), ltoh32(tr->r6), ltoh32(tr->r7));
11821 
11822 }
11823 
11824 static int
dhd_bcmsdh_send_buffer(void * bus,uint8 * frame,uint16 len)11825 dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len)
11826 {
11827 	int ret = -1;
11828 
11829 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(((dhd_bus_t*)bus)->sdh),
11830 		SDIO_FUNC_2, F2SYNC, frame, len, NULL, NULL, NULL, TXRETRIES);
11831 
11832 	if (ret == BCME_OK)
11833 		((dhd_bus_t*)bus)->tx_seq = (((dhd_bus_t*)bus)->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
11834 
11835 	return ret;
11836 }
11837 
11838 /* Function to set the min res mask depending on the chip ID used */
11839 bool
dhd_bus_set_default_min_res_mask(struct dhd_bus * bus)11840 dhd_bus_set_default_min_res_mask(struct dhd_bus *bus)
11841 {
11842 	if ((bus == NULL) || (bus->sih == NULL)) {
11843 		DHD_ERROR(("%s(): Invalid Arguments \r\n", __FUNCTION__));
11844 		return FALSE;
11845 	}
11846 
11847 	switch (bus->sih->chip) {
11848 	case BCM4339_CHIP_ID:
11849 		bcmsdh_reg_write(bus->sdh, SI_ENUM_BASE(bus->sih) + 0x618, 4, 0x3fcaf377);
11850 		if (bcmsdh_regfail(bus->sdh)) {
11851 			DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
11852 			return FALSE;
11853 		}
11854 		break;
11855 
11856 	case BCM43012_CHIP_ID:
11857 	case BCM43013_CHIP_ID:
11858 	case BCM43014_CHIP_ID:
11859 		bcmsdh_reg_write(bus->sdh,
11860 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(pmuregs_t, min_res_mask)),
11861 			4, DEFAULT_43012_MIN_RES_MASK);
11862 		if (bcmsdh_regfail(bus->sdh)) {
11863 			DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
11864 			return FALSE;
11865 		}
11866 		break;
11867 
11868 	default:
11869 		DHD_ERROR(("%s: Unhandled chip id\n", __FUNCTION__));
11870 		return FALSE;
11871 	}
11872 
11873 	return TRUE;
11874 }
11875 
11876 /* Function to reset PMU registers */
11877 void
dhd_bus_pmu_reg_reset(dhd_pub_t * dhdp)11878 dhd_bus_pmu_reg_reset(dhd_pub_t *dhdp)
11879 {
11880 	struct dhd_bus *bus = dhdp->bus;
11881 	bcmsdh_reg_write(bus->sdh, si_get_pmu_reg_addr(bus->sih,
11882 		OFFSETOF(pmuregs_t, swscratch)), 4, 0x0);
11883 	if (bcmsdh_regfail(bus->sdh)) {
11884 		DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
11885 	}
11886 }
11887 
11888 int
dhd_bus_readwrite_bp_addr(dhd_pub_t * dhdp,uint addr,uint size,uint * data,bool read)11889 dhd_bus_readwrite_bp_addr(dhd_pub_t *dhdp, uint addr, uint size, uint* data, bool read)
11890 {
11891 	int bcmerror = 0;
11892 	struct dhd_bus *bus = dhdp->bus;
11893 
11894 	if (read) {
11895 		*data = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
11896 	} else {
11897 		bcmsdh_reg_write(bus->sdh, addr, size, *data);
11898 	}
11899 
11900 	if (bcmsdh_regfail(bus->sdh))
11901 		bcmerror = BCME_SDIO_ERROR;
11902 
11903 	return bcmerror;
11904 }
11905 
dhd_get_idletime(dhd_pub_t * dhd)11906 int dhd_get_idletime(dhd_pub_t *dhd)
11907 {
11908 	return dhd->bus->idletime;
11909 }
11910 
11911 #ifdef DHD_WAKE_STATUS
11912 wake_counts_t*
dhd_bus_get_wakecount(dhd_pub_t * dhd)11913 dhd_bus_get_wakecount(dhd_pub_t *dhd)
11914 {
11915 	if (!dhd->bus) {
11916 		return NULL;
11917 	}
11918 	return &dhd->bus->wake_counts;
11919 }
11920 int
dhd_bus_get_bus_wake(dhd_pub_t * dhd)11921 dhd_bus_get_bus_wake(dhd_pub_t *dhd)
11922 {
11923 	return bcmsdh_set_get_wake(dhd->bus->sdh, 0);
11924 }
11925 #endif /* DHD_WAKE_STATUS */
11926 
11927 int
dhd_bus_sleep(dhd_pub_t * dhdp,bool sleep,uint32 * intstatus)11928 dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus)
11929 {
11930 	dhd_bus_t *bus = dhdp->bus;
11931 	uint32 retry = 0;
11932 	int ret = 0;
11933 
11934 	if (bus) {
11935 		dhd_os_sdlock(dhdp);
11936 		BUS_WAKE(bus);
11937 		R_SDREG(*intstatus, &bus->regs->intstatus, retry);
11938 		if (sleep) {
11939 			if (SLPAUTO_ENAB(bus)) {
11940 				ret = dhdsdio_bussleep(bus, sleep);
11941 				if (ret != BCME_BUSY)
11942 					dhd_os_wd_timer(bus->dhd, 0);
11943 			} else
11944 				dhdsdio_clkctl(bus, CLK_NONE, FALSE);
11945 		}
11946 		dhd_os_sdunlock(dhdp);
11947 	} else {
11948 		DHD_ERROR(("bus is NULL\n"));
11949 		ret = -1;
11950 	}
11951 
11952 	return ret;
11953 }
11954