xref: /OK3568_Linux_fs/external/rkwifibt/drivers/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 <wl_android.h>
73 #include <dhd_config.h>
74 #ifdef DHD_PKTDUMP_TOFW
75 #include <dhd_linux_pktdump.h>
76 #endif
77 #include <linux/mmc/sdio_func.h>
78 #include <dhd_linux.h>
79 #include <linux/mmc/host.h>
80 #include "bcmsdh_sdmmc.h"
81 
82 #ifdef PROP_TXSTATUS
83 #include <dhd_wlfc.h>
84 #endif
85 #ifdef DHDTCPACK_SUPPRESS
86 #include <dhd_ip.h>
87 #endif /* DHDTCPACK_SUPPRESS */
88 
89 #ifdef BT_OVER_SDIO
90 #include <dhd_bt_interface.h>
91 #endif /* BT_OVER_SDIO */
92 
93 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
94 #include <debugger.h>
95 #endif /* DEBUGGER || DHD_DSCOPE */
96 
97 bool dhd_mp_halting(dhd_pub_t *dhdp);
98 extern void bcmsdh_waitfor_iodrain(void *sdh);
99 extern void bcmsdh_reject_ioreqs(void *sdh, bool reject);
100 extern bool  bcmsdh_fatal_error(void *sdh);
101 static int dhdsdio_suspend(void *context);
102 static int dhdsdio_resume(void *context);
103 
104 #ifndef DHDSDIO_MEM_DUMP_FNAME
105 #define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
106 #endif
107 
108 #define QLEN		(1024) /* bulk rx and tx queue lengths */
109 #define FCHI		(QLEN - 10)
110 #define FCLOW		(FCHI / 2)
111 #define PRIOMASK	7 	/* XXX FixMe: should come from elsewhere...
112 				 * MAXPRIO?  PKTQ_MAX_PREC? WLC? Other?
113 				 */
114 
115 #define TXRETRIES	2	/* # of retries for tx frames */
116 #define READ_FRM_CNT_RETRIES	3
117 #ifndef DHD_RXBOUND
118 #define DHD_RXBOUND	50	/* Default for max rx frames in one scheduling */
119 #endif
120 
121 #ifndef DHD_TXBOUND
122 #define DHD_TXBOUND	20	/* Default for max tx frames in one scheduling */
123 #endif
124 
125 #define DHD_TXMINMAX	1	/* Max tx frames if rx still pending */
126 
127 #define MEMBLOCK	2048		/* Block size used for downloading of dongle image */
128 #define MAX_MEMBLOCK  (32 * 1024)	/* Block size used for downloading of dongle image */
129 
130 #define MAX_DATA_BUF	(64 * 1024)	/* Must be large enough to hold biggest possible glom */
131 #define MAX_MEM_BUF	4096
132 
133 #ifndef DHD_FIRSTREAD
134 #define DHD_FIRSTREAD   32
135 #endif
136 #if !ISPOWEROF2(DHD_FIRSTREAD)
137 #error DHD_FIRSTREAD is not a power of 2!
138 #endif
139 
140 /* Total length of frame header for dongle protocol */
141 #define SDPCM_HDRLEN	(SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
142 #define SDPCM_HDRLEN_TXGLOM	(SDPCM_HDRLEN + SDPCM_HWEXT_LEN)
143 #define MAX_TX_PKTCHAIN_CNT	SDPCM_MAXGLOM_SIZE
144 
145 #ifdef SDTEST
146 #define SDPCM_RESERVE	(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
147 #else
148 #define SDPCM_RESERVE	(SDPCM_HDRLEN + DHD_SDALIGN)
149 #endif
150 
151 /* Space for header read, limit for data packets */
152 #ifndef MAX_HDR_READ
153 #define MAX_HDR_READ	32
154 #endif
155 #if !ISPOWEROF2(MAX_HDR_READ)
156 #error MAX_HDR_READ is not a power of 2!
157 #endif
158 
159 #define MAX_RX_DATASZ	2048	/* XXX Should be based on PKTGET limits? */
160 
161 /* Maximum milliseconds to wait for F2 to come up */
162 #ifdef BCMQT
163 #define DHD_WAIT_F2RDY  30000
164 #else
165 #define DHD_WAIT_F2RDY	3000
166 #endif /* BCMQT */
167 
168 /* Maximum usec to wait for HTAVAIL to come up */
169 #ifdef BCMQT
170 #define DHD_WAIT_HTAVAIL	10000000
171 #else
172 #define DHD_WAIT_HTAVAIL	10000
173 #endif /* BCMQT */
174 
175 /* Bump up limit on waiting for HT to account for first startup;
176  * if the image is doing a CRC calculation before programming the PMU
177  * for HT availability, it could take a couple hundred ms more, so
178  * max out at a 1 second (1000000us).
179  */
180 #if (PMU_MAX_TRANSITION_DLY <= 1000000)
181 #undef PMU_MAX_TRANSITION_DLY
182 #ifdef NO_EXT32K
183 #define PMU_MAX_TRANSITION_DLY (1000000*5)
184 #else
185 #define PMU_MAX_TRANSITION_DLY 1000000
186 #endif
187 #endif // endif
188 
189 /* hooks for limiting threshold custom tx num in rx processing */
190 #define DEFAULT_TXINRX_THRES    0
191 #ifndef CUSTOM_TXINRX_THRES
192 #define CUSTOM_TXINRX_THRES     DEFAULT_TXINRX_THRES
193 #endif
194 
195 /* Value for ChipClockCSR during initial setup */
196 #define DHD_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
197 #define DHD_INIT_CLKCTL2	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
198 
199 /* Flags for SDH calls */
200 #define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
201 /* XXX #define F2ASYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED | SDIO_REQ_ASYNC) */
202 
203 /* Packet free applicable unconditionally for sdio and sdspi.  Conditional if
204  * bufpool was present for gspi bus.
205  */
206 #define PKTFREE2()		if ((bus->bus != SPI_BUS) || bus->usebufpool) \
207 					PKTFREE(bus->dhd->osh, pkt, FALSE);
208 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
209 
210 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW
211 extern unsigned int system_hw_rev;
212 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
213 
214 /* Device console log buffer state */
215 #define CONSOLE_LINE_MAX	192
216 #define CONSOLE_BUFFER_MAX	8192
217 typedef struct dhd_console {
218 	uint		count;			/* Poll interval msec counter */
219 	uint		log_addr;		/* Log struct address (fixed) */
220 	hnd_log_t	log;			/* Log struct (host copy) */
221 	uint		bufsize;		/* Size of log buffer */
222 	uint8		*buf;			/* Log buffer (host copy) */
223 	uint		last;			/* Last buffer read index */
224 } dhd_console_t;
225 
226 #define	REMAP_ENAB(bus)			((bus)->remap)
227 #define	REMAP_ISADDR(bus, a)		(((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
228 #define	KSO_ENAB(bus)			((bus)->kso)
229 #define	SR_ENAB(bus)			((bus)->_srenab)
230 #define	SLPAUTO_ENAB(bus)		((SR_ENAB(bus)) && ((bus)->_slpauto))
231 
232 #define	MIN_RSRC_SR			0x3
233 #define	CORE_CAPEXT_ADDR_OFFSET		(0x64c)
234 #define	CORE_CAPEXT_SR_SUPPORTED_MASK	(1 << 1)
235 #define RCTL_MACPHY_DISABLE_MASK	(1 << 26)
236 #define RCTL_LOGIC_DISABLE_MASK		(1 << 27)
237 
238 #define	OOB_WAKEUP_ENAB(bus)		((bus)->_oobwakeup)
239 #define	GPIO_DEV_SRSTATE		16	/* Host gpio17 mapped to device gpio0 SR state */
240 #define	GPIO_DEV_SRSTATE_TIMEOUT	320000	/* 320ms */
241 #define	GPIO_DEV_WAKEUP			17	/* Host gpio17 mapped to device gpio1 wakeup */
242 #define	CC_CHIPCTRL2_GPIO1_WAKEUP	(1  << 0)
243 #define	CC_CHIPCTRL3_SR_ENG_ENABLE	(1  << 2)
244 #define OVERFLOW_BLKSZ512_WM		96
245 #define OVERFLOW_BLKSZ512_MES		80
246 
247 #define CC_PMUCC3	(0x3)
248 
249 #ifdef DHD_UCODE_DOWNLOAD
250 /* Ucode host download related macros */
251 #define UCODE_DOWNLOAD_REQUEST  0xCAFECAFE
252 #define UCODE_DOWNLOAD_COMPLETE 0xABCDABCD
253 #endif /* DHD_UCODE_DOWNLOAD */
254 
255 #if defined(BT_OVER_SDIO)
256 #define BTMEM_OFFSET			0x19000000
257 /* BIT0 => WLAN Power UP and BIT1=> WLAN Wake */
258 #define BT2WLAN_PWRUP_WAKE		0x03
259 #define BT2WLAN_PWRUP_ADDR		0x640894	/* This address is specific to 43012B0 */
260 
261 #define BTFW_MAX_STR_LEN		600
262 #define BTFW_DOWNLOAD_BLK_SIZE		(BTFW_MAX_STR_LEN/2 + 8)
263 
264 #define BTFW_ADDR_MODE_UNKNOWN		0
265 #define BTFW_ADDR_MODE_EXTENDED		1
266 #define BTFW_ADDR_MODE_SEGMENT		2
267 #define BTFW_ADDR_MODE_LINEAR32		3
268 
269 #define BTFW_HEX_LINE_TYPE_DATA				0
270 #define BTFW_HEX_LINE_TYPE_END_OF_DATA			1
271 #define BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS	2
272 #define BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS		4
273 #define BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS	5
274 
275 #endif /* defined (BT_OVER_SDIO) */
276 
277 /* Private data for SDIO bus interaction */
278 typedef struct dhd_bus {
279 	dhd_pub_t	*dhd;
280 
281 	bcmsdh_info_t	*sdh;			/* Handle for BCMSDH calls */
282 	si_t		*sih;			/* Handle for SI calls */
283 	char		*vars;			/* Variables (from CIS and/or other) */
284 	uint		varsz;			/* Size of variables buffer */
285 	uint32		sbaddr;			/* Current SB window pointer (-1, invalid) */
286 
287 	sdpcmd_regs_t	*regs;			/* Registers for SDIO core */
288 	uint		sdpcmrev;		/* SDIO core revision */
289 	uint		armrev;			/* CPU core revision */
290 	uint		ramrev;			/* SOCRAM core revision */
291 	uint32		ramsize;		/* Size of RAM in SOCRAM (bytes) */
292 	uint32		orig_ramsize;		/* Size of RAM in SOCRAM (bytes) */
293 	uint32		srmemsize;		/* Size of SRMEM */
294 
295 	uint32		bus;			/* gSPI or SDIO bus */
296 	uint32		bus_num;		/* bus number */
297 	uint32		slot_num;		/* slot ID */
298 	uint32		hostintmask;	/* Copy of Host Interrupt Mask */
299 	uint32		intstatus;		/* Intstatus bits (events) pending */
300 	bool		dpc_sched;		/* Indicates DPC schedule (intrpt rcvd) */
301 	bool		fcstate;		/* State of dongle flow-control */
302 
303 	uint16		cl_devid;		/* cached devid for dhdsdio_probe_attach() */
304 	char		*fw_path;		/* module_param: path to firmware image */
305 	char		*nv_path;		/* module_param: path to nvram vars file */
306 
307 	uint		blocksize;		/* Block size of SDIO transfers */
308 	uint		roundup;		/* Max roundup limit */
309 
310 	struct pktq	txq;			/* Queue length used for flow-control */
311 	uint8		flowcontrol;		/* per prio flow control bitmask */
312 	uint8		tx_seq;			/* Transmit sequence number (next) */
313 	uint8		tx_max;			/* Maximum transmit sequence allowed */
314 
315 #ifdef DYNAMIC_MAX_HDR_READ
316 	uint8		*hdrbufp;
317 #else
318 	uint8		hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
319 #endif
320 	uint8		*rxhdr;			/* Header of current rx frame (in hdrbuf) */
321 	uint16		nextlen;		/* Next Read Len from last header */
322 	uint8		rx_seq;			/* Receive sequence number (expected) */
323 	bool		rxskip;			/* Skip receive (awaiting NAK ACK) */
324 
325 	void		*glomd;			/* Packet containing glomming descriptor */
326 	void		*glom;			/* Packet chain for glommed superframe */
327 	uint		glomerr;		/* Glom packet read errors */
328 
329 	uint8		*rxbuf;			/* Buffer for receiving control packets */
330 	uint		rxblen;			/* Allocated length of rxbuf */
331 	uint8		*rxctl;			/* Aligned pointer into rxbuf */
332 	uint8		*databuf;		/* Buffer for receiving big glom packet */
333 	uint8		*dataptr;		/* Aligned pointer into databuf */
334 	uint		rxlen;			/* Length of valid data in buffer */
335 
336 	uint8		sdpcm_ver;		/* Bus protocol reported by dongle */
337 
338 	bool		intr;			/* Use interrupts */
339 	bool		poll;			/* Use polling */
340 	bool		ipend;			/* Device interrupt is pending */
341 	bool		intdis;			/* Interrupts disabled by isr */
342 	uint 		intrcount;		/* Count of device interrupt callbacks */
343 	uint		lastintrs;		/* Count as of last watchdog timer */
344 	uint		spurious;		/* Count of spurious interrupts */
345 	uint		pollrate;		/* Ticks between device polls */
346 	uint		polltick;		/* Tick counter */
347 	uint		pollcnt;		/* Count of active polls */
348 
349 	dhd_console_t	console;		/* Console output polling support */
350 	uint		console_addr;		/* Console address from shared struct */
351 
352 	uint		regfails;		/* Count of R_REG/W_REG failures */
353 
354 	uint		clkstate;		/* State of sd and backplane clock(s) */
355 	bool		activity;		/* Activity flag for clock down */
356 	int32		idletime;		/* Control for activity timeout */
357 	int32		idlecount;		/* Activity timeout counter */
358 	int32		idleclock;		/* How to set bus driver when idle */
359 	int32		sd_divisor;		/* Speed control to bus driver */
360 	int32		sd_mode;		/* Mode control to bus driver */
361 	int32		sd_rxchain;		/* If bcmsdh api accepts PKT chains */
362 	bool		use_rxchain;		/* If dhd should use PKT chains */
363 	bool		sleeping;		/* Is SDIO bus sleeping? */
364 #if defined(LINUX) && defined(SUPPORT_P2P_GO_PS)
365 	wait_queue_head_t bus_sleep;
366 #endif /* LINUX && SUPPORT_P2P_GO_PS */
367 	bool		ctrl_wait;
368 	wait_queue_head_t ctrl_tx_wait;
369 	uint		rxflow_mode;		/* Rx flow control mode */
370 	bool		rxflow;			/* Is rx flow control on */
371 	uint		prev_rxlim_hit;		/* Is prev rx limit exceeded (per dpc schedule) */
372 #ifdef BCMINTERNAL
373 	bool		_nopmu;			/* No PMU (FPGA), don't try it */
374 	bool		clockpoll;		/* Force clock polling (no chipactive interrupt) */
375 #endif
376 	bool		alp_only;		/* Don't use HT clock (ALP only) */
377 	/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
378 	bool		usebufpool;
379 	int32		txinrx_thres;	/* num of in-queued pkts */
380 	int32		dotxinrx;	/* tx first in dhdsdio_readframes */
381 #ifdef BCMSDIO_RXLIM_POST
382 	bool		rxlim_en;
383 	uint32		rxlim_addr;
384 #endif /* BCMSDIO_RXLIM_POST */
385 #ifdef SDTEST
386 	/* external loopback */
387 	bool		ext_loop;
388 	uint8		loopid;
389 
390 	/* pktgen configuration */
391 	uint		pktgen_freq;		/* Ticks between bursts */
392 	uint		pktgen_count;		/* Packets to send each burst */
393 	uint		pktgen_print;		/* Bursts between count displays */
394 	uint		pktgen_total;		/* Stop after this many */
395 	uint		pktgen_minlen;		/* Minimum packet data len */
396 	uint		pktgen_maxlen;		/* Maximum packet data len */
397 	uint		pktgen_mode;		/* Configured mode: tx, rx, or echo */
398 	uint		pktgen_stop;		/* Number of tx failures causing stop */
399 
400 	/* active pktgen fields */
401 	uint		pktgen_tick;		/* Tick counter for bursts */
402 	uint		pktgen_ptick;		/* Burst counter for printing */
403 	uint		pktgen_sent;		/* Number of test packets generated */
404 	uint		pktgen_rcvd;		/* Number of test packets received */
405 	uint		pktgen_prev_time;	/* Time at which previous stats where printed */
406 	uint		pktgen_prev_sent;	/* Number of test packets generated when
407 						 * previous stats were printed
408 						 */
409 	uint		pktgen_prev_rcvd;	/* Number of test packets received when
410 						 * previous stats were printed
411 						 */
412 	uint		pktgen_fail;		/* Number of failed send attempts */
413 	uint16		pktgen_len;		/* Length of next packet to send */
414 #define PKTGEN_RCV_IDLE     (0)
415 #define PKTGEN_RCV_ONGOING  (1)
416 	uint16		pktgen_rcv_state;		/* receive state */
417 	uint		pktgen_rcvd_rcvsession;	/* test pkts rcvd per rcv session. */
418 #endif /* SDTEST */
419 
420 	/* Some additional counters */
421 	uint		tx_sderrs;		/* Count of tx attempts with sd errors */
422 	uint		fcqueued;		/* Tx packets that got queued */
423 	uint		rxrtx;			/* Count of rtx requests (NAK to dongle) */
424 	uint		rx_toolong;		/* Receive frames too long to receive */
425 	uint		rxc_errors;		/* SDIO errors when reading control frames */
426 	uint		rx_hdrfail;		/* SDIO errors on header reads */
427 	uint		rx_badhdr;		/* Bad received headers (roosync?) */
428 	uint		rx_badseq;		/* Mismatched rx sequence number */
429 	uint		fc_rcvd;		/* Number of flow-control events received */
430 	uint		fc_xoff;		/* Number which turned on flow-control */
431 	uint		fc_xon;			/* Number which turned off flow-control */
432 	uint		rxglomfail;		/* Failed deglom attempts */
433 	uint		rxglomframes;		/* Number of glom frames (superframes) */
434 	uint		rxglompkts;		/* Number of packets from glom frames */
435 	uint		f2rxhdrs;		/* Number of header reads */
436 	uint		f2rxdata;		/* Number of frame data reads */
437 	uint		f2txdata;		/* Number of f2 frame writes */
438 	uint		f1regdata;		/* Number of f1 register accesses */
439 	wake_counts_t	wake_counts;		/* Wake up counter */
440 #ifdef BCMSPI
441 	bool		dwordmode;
442 #endif /* BCMSPI */
443 #ifdef DHDENABLE_TAILPAD
444 	uint		tx_tailpad_chain;	/* Number of tail padding by chaining pad_pkt */
445 	uint		tx_tailpad_pktget;	/* Number of tail padding by new PKTGET */
446 #endif /* DHDENABLE_TAILPAD */
447 #ifdef BCMINTERNAL
448 	uint		tx_deferred;		/* Tx calls queued while event pending */
449 #endif
450 	uint8		*ctrl_frame_buf;
451 	uint32		ctrl_frame_len;
452 	bool		ctrl_frame_stat;
453 #ifndef BCMSPI
454 	uint32		rxint_mode;	/* rx interrupt mode */
455 #endif /* BCMSPI */
456 	bool		remap;		/* Contiguous 1MB RAM: 512K socram + 512K devram
457 					 * Available with socram rev 16
458 					 * Remap region not DMA-able
459 					 */
460 	bool		kso;
461 	bool		_slpauto;
462 	bool		_oobwakeup;
463 	bool		_srenab;
464 	bool        readframes;
465 	bool        reqbussleep;
466 	uint32		resetinstr;
467 	uint32		dongle_ram_base;
468 
469 	void		*glom_pkt_arr[SDPCM_MAXGLOM_SIZE];	/* Array of pkts for glomming */
470 	uint32		txglom_cnt;	/* Number of pkts in the glom array */
471 	uint32		txglom_total_len;	/* Total length of pkts in glom array */
472 	bool		txglom_enable;	/* Flag to indicate whether tx glom is enabled/disabled */
473 	uint32		txglomsize;	/* Glom size limitation */
474 #ifdef DHDENABLE_TAILPAD
475 	void		*pad_pkt;
476 #endif /* DHDENABLE_TAILPAD */
477 	uint32		dongle_trap_addr; /* device trap addr location in device memory */
478 #if defined(BT_OVER_SDIO)
479 	char		*btfw_path;	/* module_param: path to BT firmware image */
480 	uint32		bt_use_count; /* Counter that tracks whether BT is using the bus */
481 #endif /* defined (BT_OVER_SDIO) */
482 	uint		txglomframes;	/* Number of tx glom frames (superframes) */
483 	uint		txglompkts;		/* Number of packets from tx glom frames */
484 #ifdef PKT_STATICS
485 	struct pkt_statics tx_statics;
486 #endif
487 	uint8		*membuf;		/* Buffer for dhdsdio_membytes */
488 #ifdef CONSOLE_DPC
489 	char		cons_cmd[16];
490 #endif
491 } dhd_bus_t;
492 
493 /*
494  * Whenever DHD_IDLE_IMMEDIATE condition is handled, we have to now check if
495  * BT is active too. Instead of adding #ifdef code in all the places, we thought
496  * of adding one macro check as part of the if condition that checks for DHD_IDLE_IMMEDIATE
497  * In case of non BT over SDIO builds, this macro will always return TRUE. In case
498  * of the builds where BT_OVER_SDIO is enabled, it will expand to a condition check
499  * that checks if bt_use_count is zero. So this macro will return equate to 1 if
500  * bt_use_count is 0, indicating that there are no active users and if bt_use_count
501  * is non zero it would return 0 there by preventing the caller from executing the
502  * sleep calls.
503  */
504 #ifdef BT_OVER_SDIO
505 #define NO_OTHER_ACTIVE_BUS_USER(bus)		(bus->bt_use_count == 0)
506 #else
507 #define NO_OTHER_ACTIVE_BUS_USER(bus)		(1)
508 #endif /* BT_OVER_SDIO */
509 
510 /* clkstate */
511 #define CLK_NONE	0
512 #define CLK_SDONLY	1
513 #define CLK_PENDING	2	/* Not used yet */
514 #define CLK_AVAIL	3
515 
516 #ifdef BCMINTERNAL
517 #define DHD_NOPMU(dhd)	((dhd)->_nopmu)
518 #else
519 #define DHD_NOPMU(dhd)	(FALSE)
520 #endif
521 
522 #if defined(BCMSDIOH_STD)
523 #define BLK_64_MAXTXGLOM 20
524 #endif /* BCMSDIOH_STD */
525 
526 #ifdef DHD_DEBUG
527 static int qcount[NUMPRIO];
528 static int tx_packets[NUMPRIO];
529 #endif /* DHD_DEBUG */
530 
531 /* Deferred transmit */
532 const uint dhd_deferred_tx = 1;
533 
534 extern uint dhd_watchdog_ms;
535 #ifndef NDIS
536 extern uint sd_f1_blocksize;
537 #endif /* !NDIS */
538 
539 #ifdef BCMSPI_ANDROID
540 extern uint *dhd_spi_lockcount;
541 #endif /* BCMSPI_ANDROID */
542 
543 extern void dhd_os_wd_timer(void *bus, uint wdtick);
544 int dhd_enableOOB(dhd_pub_t *dhd, bool sleep);
545 
546 #ifdef DHD_PM_CONTROL_FROM_FILE
547 extern bool g_pm_control;
548 #endif /* DHD_PM_CONTROL_FROM_FILE */
549 
550 /* Tx/Rx bounds */
551 uint dhd_txbound;
552 uint dhd_rxbound;
553 uint dhd_txminmax = DHD_TXMINMAX;
554 
555 /* override the RAM size if possible */
556 #define DONGLE_MIN_RAMSIZE (128 *1024)
557 int dhd_dongle_ramsize;
558 
559 uint dhd_doflow = TRUE;
560 uint dhd_dpcpoll = FALSE;
561 
562 #ifdef linux
563 module_param(dhd_doflow, uint, 0644);
564 module_param(dhd_dpcpoll, uint, 0644);
565 #endif
566 
567 static bool dhd_alignctl;
568 
569 static bool sd1idle;
570 
571 static bool retrydata;
572 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
573 
574 #ifndef BCMINTERNAL
575 #ifdef BCMSPI
576 /* At a watermark around 8 the spid hits underflow error. */
577 static uint watermark = 32;
578 static uint mesbusyctrl = 0;
579 #else
580 static uint watermark = 8;
581 static uint mesbusyctrl = 0;
582 #endif /* BCMSPI */
583 #ifdef DYNAMIC_MAX_HDR_READ
584 uint firstread = DHD_FIRSTREAD;
585 #else
586 static const uint firstread = DHD_FIRSTREAD;
587 #endif
588 #else /* BCMINTERNAL */
589 /* PR47410: low watermark to avoid F2 hang after SD clock stops */
590 /* PR48178: read to (not through) bus burst to avoid F2 underflow */
591 #ifdef BCMSPI
592 static uint watermark = 32;
593 static uint mesbusyctrl = 0;
594 #else
595 static uint watermark = 8;
596 static uint mesbusyctrl = 0;
597 #endif /* BCMSPI */
598 static uint firstread = DHD_FIRSTREAD;
599 /* Additional knobs in case we need them */
600 static bool tstoph = FALSE;
601 static bool checkfifo = FALSE;
602 uint dhd_anychip = 0;
603 #endif /* BCMINTERNAL */
604 
605 /* Retry count for register access failures */
606 static const uint retry_limit = 2;
607 
608 /* Force even SD lengths (some host controllers mess up on odd bytes) */
609 static bool forcealign;
610 
611 #if defined(DEBUGGER)
612 static uint32 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr);
613 static void dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val);
614 
615 /** the debugger layer will call back into this (bus) layer to read/write dongle memory */
616 static struct dhd_dbg_bus_ops_s  bus_ops = {
617 	.read_u16 = NULL,
618 	.read_u32 = dhd_sdio_reg_read,
619 	.write_u32 = dhd_sdio_reg_write,
620 };
621 #endif /* DEBUGGER */
622 
623 #define ALIGNMENT  4
624 
625 #if (defined(OOB_INTR_ONLY) && defined(HW_OOB)) || defined(FORCE_WOWLAN)
626 extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
627 #endif
628 
629 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
630 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
631 #endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
632 #define PKTALIGN(osh, p, len, align)					\
633 	do {								\
634 		uintptr datalign;						\
635 		datalign = (uintptr)PKTDATA((osh), (p));		\
636 		datalign = ROUNDUP(datalign, (align)) - datalign;	\
637 		ASSERT(datalign < (align));				\
638 		ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign));	\
639 		if (datalign)						\
640 			PKTPULL((osh), (p), (uint)datalign);			\
641 		PKTSETLEN((osh), (p), (len));				\
642 	} while (0)
643 
644 /* Limit on rounding up frames */
645 static const uint max_roundup = 512;
646 
647 /* Try doing readahead */
648 static bool dhd_readahead;
649 
650 #if defined(BCMSDIOH_TXGLOM_EXT)
651 bool
dhdsdio_is_dataok(dhd_bus_t * bus)652 dhdsdio_is_dataok(dhd_bus_t *bus) {
653 	return (((uint8)(bus->tx_max - bus->tx_seq) - bus->dhd->conf->tx_max_offset > 1) && \
654 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0));
655 }
656 
657 uint8
dhdsdio_get_databufcnt(dhd_bus_t * bus)658 dhdsdio_get_databufcnt(dhd_bus_t *bus) {
659 	return ((uint8)(bus->tx_max - bus->tx_seq) - 1 - bus->dhd->conf->tx_max_offset);
660 }
661 #endif
662 
663 /* To check if there's window offered */
664 #if defined(BCMSDIOH_TXGLOM_EXT)
665 #define DATAOK(bus) dhdsdio_is_dataok(bus)
666 #else
667 #define DATAOK(bus) \
668 	(((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
669 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
670 #endif
671 
672 /* To check if there's window offered for ctrl frame */
673 #define TXCTLOK(bus) \
674 	(((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
675 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
676 
677 /* Number of pkts available in dongle for data RX */
678 #if defined(BCMSDIOH_TXGLOM_EXT)
679 #define DATABUFCNT(bus) dhdsdio_get_databufcnt(bus)
680 #else
681 #define DATABUFCNT(bus) \
682 	((uint8)(bus->tx_max - bus->tx_seq) - 1)
683 #endif
684 
685 /* Macros to get register read/write status */
686 /* NOTE: these assume a local dhdsdio_bus_t *bus! */
687 /* XXX Need to replace these with something better. */
688 #define R_SDREG(regvar, regaddr, retryvar) \
689 do { \
690 	retryvar = 0; \
691 	do { \
692 		regvar = R_REG(bus->dhd->osh, regaddr); \
693 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
694 	if (retryvar) { \
695 		bus->regfails += (retryvar-1); \
696 		if (retryvar > retry_limit) { \
697 			DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
698 			           __FUNCTION__, __LINE__)); \
699 			regvar = 0; \
700 		} \
701 	} \
702 } while (0)
703 
704 #define W_SDREG(regval, regaddr, retryvar) \
705 do { \
706 	retryvar = 0; \
707 	do { \
708 		W_REG(bus->dhd->osh, regaddr, regval); \
709 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
710 	if (retryvar) { \
711 		bus->regfails += (retryvar-1); \
712 		if (retryvar > retry_limit) \
713 			DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
714 			           __FUNCTION__, __LINE__)); \
715 	} \
716 } while (0)
717 
718 #define BUS_WAKE(bus) \
719 	do { \
720 		bus->idlecount = 0; \
721 		if ((bus)->sleeping) \
722 			dhdsdio_bussleep((bus), FALSE); \
723 	} while (0);
724 
725 /*
726  * pktavail interrupts from dongle to host can be managed in 3 different ways
727  * whenever there is a packet available in dongle to transmit to host.
728  *
729  * Mode 0:	Dongle writes the software host mailbox and host is interrupted.
730  * Mode 1:	(sdiod core rev >= 4)
731  *		Device sets a new bit in the intstatus whenever there is a packet
732  *		available in fifo.  Host can't clear this specific status bit until all the
733  *		packets are read from the FIFO.  No need to ack dongle intstatus.
734  * Mode 2:	(sdiod core rev >= 4)
735  *		Device sets a bit in the intstatus, and host acks this by writing
736  *		one to this bit.  Dongle won't generate anymore packet interrupts
737  *		until host reads all the packets from the dongle and reads a zero to
738  *		figure that there are no more packets.  No need to disable host ints.
739  *		Need to ack the intstatus.
740  */
741 
742 #define SDIO_DEVICE_HMB_RXINT		0	/* default old way */
743 #define SDIO_DEVICE_RXDATAINT_MODE_0	1	/* from sdiod rev 4 */
744 #define SDIO_DEVICE_RXDATAINT_MODE_1	2	/* from sdiod rev 4 */
745 
746 #ifdef BCMSPI
747 
748 #define FRAME_AVAIL_MASK(bus) I_HMB_FRAME_IND
749 
750 #define DHD_BUS			SPI_BUS
751 
752 /* check packet-available-interrupt in piggybacked dstatus */
753 #define PKT_AVAILABLE(bus, intstatus)	(bcmsdh_get_dstatus(bus->sdh) & STATUS_F2_PKT_AVAILABLE)
754 
755 #define HOSTINTMASK		(I_HMB_FC_CHANGE | I_HMB_HOST_INT)
756 
757 #define GSPI_PR55150_BAILOUT									\
758 do {												\
759 	uint32 dstatussw = bcmsdh_get_dstatus((void *)bus->sdh);				\
760 	uint32 dstatushw = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL);	\
761 	uint32 intstatuserr = 0;								\
762 	uint retries = 0;									\
763 												\
764 	R_SDREG(intstatuserr, &bus->regs->intstatus, retries);					\
765 	printf("dstatussw = 0x%x, dstatushw = 0x%x, intstatus = 0x%x\n",			\
766 	        dstatussw, dstatushw, intstatuserr); 						\
767 												\
768 	bus->nextlen = 0;									\
769 	*finished = TRUE;									\
770 } while (0)
771 
772 #else /* BCMSDIO */
773 
774 #define FRAME_AVAIL_MASK(bus) 	\
775 	((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL)
776 
777 #define DHD_BUS			SDIO_BUS
778 
779 #define PKT_AVAILABLE(bus, intstatus)	((intstatus) & (FRAME_AVAIL_MASK(bus)))
780 
781 #define HOSTINTMASK		(I_HMB_SW_MASK | I_CHIPACTIVE)
782 
783 #define GSPI_PR55150_BAILOUT
784 
785 #endif /* BCMSPI */
786 
787 #ifdef SDTEST
788 static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
789 static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count);
790 #endif
791 
792 static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size);
793 #ifdef DHD_DEBUG
794 static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror);
795 #endif /* DHD_DEBUG */
796 
797 #if defined(DHD_FW_COREDUMP)
798 static int dhdsdio_mem_dump(dhd_bus_t *bus);
799 static int dhdsdio_get_mem_dump(dhd_bus_t *bus);
800 #endif /* DHD_FW_COREDUMP */
801 static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap);
802 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
803 
804 static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
805 static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
806 static void dhdsdio_disconnect(void *ptr);
807 static bool dhdsdio_chipmatch(uint16 chipid);
808 static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
809                                  void * regsva, uint16  devid);
810 static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
811 static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
812 static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation,
813 	bool reset_flag);
814 
815 static void dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size);
816 static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
817 	uint8 *buf, uint nbytes,
818 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
819 static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
820 	uint8 *buf, uint nbytes,
821 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry);
822 static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt);
823 static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
824 	int prev_chain_total_len, bool last_chained_pkt,
825 	int *pad_pkt_len, void **new_pkt
826 #if defined(BCMSDIOH_TXGLOM_EXT)
827 	, int first_frame
828 #endif
829 );
830 static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt);
831 
832 static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh);
833 static int _dhdsdio_download_firmware(dhd_bus_t *bus);
834 
835 #ifdef DHD_UCODE_DOWNLOAD
836 static int dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path);
837 #endif /* DHD_UCODE_DOWNLOAD */
838 static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path);
839 static int dhdsdio_download_nvram(dhd_bus_t *bus);
840 #ifdef BCMEMBEDIMAGE
841 static int dhdsdio_download_code_array(dhd_bus_t *bus);
842 #endif
843 static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep);
844 static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok);
845 static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus);
846 static bool dhdsdio_dpc(dhd_bus_t *bus);
847 static int dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len);
848 static int dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode);
849 static int dhdsdio_sdclk(dhd_bus_t *bus, bool on);
850 static void dhdsdio_advertise_bus_cleanup(dhd_pub_t *dhdp);
851 static void dhdsdio_advertise_bus_remove(dhd_pub_t *dhdp);
852 
853 #if defined(BT_OVER_SDIO)
854 static int extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value);
855 static int read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode,
856 	uint16 * hi_addr, uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes);
857 static int dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh);
858 static int _dhdsdio_download_btfw(struct dhd_bus *bus);
859 #endif /* defined (BT_OVER_SDIO) */
860 
861 #ifdef DHD_WAKE_STATUS
862 int bcmsdh_get_total_wake(bcmsdh_info_t *bcmsdh);
863 int bcmsdh_set_get_wake(bcmsdh_info_t *bcmsdh, int flag);
864 #endif /* DHD_WAKE_STATUS */
865 
866 /*
867  * PR 114233: [4335] Sdio 3.0 overflow due to spur mode PLL change
868  */
869 static void
dhdsdio_tune_fifoparam(struct dhd_bus * bus)870 dhdsdio_tune_fifoparam(struct dhd_bus *bus)
871 {
872 	int err;
873 	uint8 devctl, wm, mes;
874 
875 	if (bus->sih->buscorerev >= 15) {
876 		/* See .ppt in PR for these recommended values */
877 		if (bus->blocksize == 512) {
878 			wm = OVERFLOW_BLKSZ512_WM;
879 			mes = OVERFLOW_BLKSZ512_MES;
880 		} else {
881 			mes = bus->blocksize/4;
882 			wm = bus->blocksize/4;
883 		}
884 
885 		/* XXX: Need to set watermark since SBSDIO_WATERMARK could be overwritten
886 		 based on watermark value in other place. Refer to SWDHD-17.
887 		*/
888 		watermark = wm;
889 		mesbusyctrl = mes;
890 	} else {
891 		DHD_INFO(("skip fifotune: SdioRev(%d) is lower than minimal requested ver\n",
892 			bus->sih->buscorerev));
893 		return;
894 	}
895 
896 	/* Update watermark */
897 	if (wm > 0) {
898 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err);
899 
900 		devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
901 		devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
902 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
903 	}
904 
905 	/* Update MES */
906 	if (mes > 0) {
907 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
908 			(mes | SBSDIO_MESBUSYCTRL_ENAB), &err);
909 	}
910 
911 	DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n",
912 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err),
913 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err),
914 		bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err)));
915 }
916 
917 static void
dhd_dongle_setramsize(struct dhd_bus * bus,int mem_size)918 dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size)
919 {
920 	int32 min_size =  DONGLE_MIN_RAMSIZE;
921 	/* Restrict the ramsize to user specified limit */
922 	DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
923 		dhd_dongle_ramsize, min_size));
924 	if ((dhd_dongle_ramsize > min_size) &&
925 		(dhd_dongle_ramsize < (int32)bus->orig_ramsize))
926 		bus->ramsize = dhd_dongle_ramsize;
927 }
928 
929 static int
dhdsdio_set_siaddr_window(dhd_bus_t * bus,uint32 address)930 dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
931 {
932 	int err = 0;
933 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
934 	                 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
935 	if (!err)
936 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
937 		                 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
938 	if (!err)
939 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
940 		                 (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
941 	return err;
942 }
943 
944 #ifdef BCMSPI
945 static void
dhdsdio_wkwlan(dhd_bus_t * bus,bool on)946 dhdsdio_wkwlan(dhd_bus_t *bus, bool on)
947 {
948 	int err;
949 	uint32 regdata;
950 	bcmsdh_info_t *sdh = bus->sdh;
951 
952 	/* XXX: sdiod cores have SPI as a block, PCMCIA doesn't have the gspi core */
953 	/* XXX: may be we don't even need this check at all */
954 	if (bus->sih->buscoretype == SDIOD_CORE_ID) {
955 		/* wake up wlan function :WAKE_UP goes as ht_avail_request and alp_avail_request */
956 		regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL);
957 		DHD_INFO(("F0 REG0 rd = 0x%x\n", regdata));
958 
959 		if (on == TRUE)
960 			regdata |= WAKE_UP;
961 		else
962 			regdata &= ~WAKE_UP;
963 
964 		bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err);
965 	}
966 }
967 #endif /* BCMSPI */
968 
969 #ifdef USE_OOB_GPIO1
970 static int
dhdsdio_oobwakeup_init(dhd_bus_t * bus)971 dhdsdio_oobwakeup_init(dhd_bus_t *bus)
972 {
973 	uint32 val, addr, data;
974 
975 	bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP);
976 
977 	addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
978 	data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
979 
980 	/* Set device for gpio1 wakeup */
981 	bcmsdh_reg_write(bus->sdh, addr, 4, 2);
982 	val = bcmsdh_reg_read(bus->sdh, data, 4);
983 	val |= CC_CHIPCTRL2_GPIO1_WAKEUP;
984 	bcmsdh_reg_write(bus->sdh, data, 4, val);
985 
986 	bus->_oobwakeup = TRUE;
987 
988 	return 0;
989 }
990 #endif /* USE_OOB_GPIO1 */
991 
992 #ifndef BCMSPI
993 /*
994  * Query if FW is in SR mode
995  */
996 static bool
dhdsdio_sr_cap(dhd_bus_t * bus)997 dhdsdio_sr_cap(dhd_bus_t *bus)
998 {
999 	bool cap = FALSE;
1000 	uint32  core_capext, addr, data;
1001 
1002 	if (bus->sih->chip == BCM43430_CHIP_ID ||
1003 		bus->sih->chip == BCM43018_CHIP_ID) {
1004 		/* check if fw initialized sr engine */
1005 		addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, sr_control1);
1006 		if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0)
1007 			cap = TRUE;
1008 
1009 		return cap;
1010 	}
1011 	if (
1012 #ifdef UNRELEASEDCHIP
1013 		(bus->sih->chip == BCM4347_CHIP_ID) ||
1014 		(bus->sih->chip == BCM4357_CHIP_ID) ||
1015 		(bus->sih->chip == BCM4361_CHIP_ID) ||
1016 #endif
1017 		0) {
1018 			core_capext = FALSE;
1019 	} else if ((bus->sih->chip == BCM4330_CHIP_ID) ||
1020 		(bus->sih->chip == BCM43362_CHIP_ID) ||
1021 		(BCM4347_CHIP(bus->sih->chip))) {
1022 			core_capext = FALSE;
1023 	} else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
1024 		(bus->sih->chip == BCM4339_CHIP_ID) ||
1025 		BCM4345_CHIP(bus->sih->chip) ||
1026 		(bus->sih->chip == BCM4354_CHIP_ID) ||
1027 		(bus->sih->chip == BCM4358_CHIP_ID) ||
1028 		(bus->sih->chip == BCM43569_CHIP_ID) ||
1029 		(bus->sih->chip == BCM4371_CHIP_ID) ||
1030 		(BCM4349_CHIP(bus->sih->chip))		||
1031 		(bus->sih->chip == BCM4350_CHIP_ID) ||
1032 		(bus->sih->chip == BCM4362_CHIP_ID) ||
1033 		(bus->sih->chip == BCM43012_CHIP_ID) ||
1034 		(bus->sih->chip == BCM43013_CHIP_ID) ||
1035 		(bus->sih->chip == BCM43014_CHIP_ID) ||
1036 		(bus->sih->chip == BCM43751_CHIP_ID) ||
1037 		(bus->sih->chip == BCM43752_CHIP_ID)) {
1038 		core_capext = TRUE;
1039 	} else {
1040 		/* XXX: For AOB, CORE_CAPEXT_ADDR is moved to PMU core */
1041 		core_capext = bcmsdh_reg_read(bus->sdh,
1042 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, core_cap_ext)),
1043 			4);
1044 
1045 		core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
1046 	}
1047 	if (!(core_capext))
1048 		return FALSE;
1049 
1050 	if ((bus->sih->chip == BCM4335_CHIP_ID) ||
1051 		(bus->sih->chip == BCM4339_CHIP_ID) ||
1052 		BCM4345_CHIP(bus->sih->chip) ||
1053 		(bus->sih->chip == BCM4354_CHIP_ID) ||
1054 		(bus->sih->chip == BCM4358_CHIP_ID) ||
1055 		(bus->sih->chip == BCM43569_CHIP_ID) ||
1056 		(bus->sih->chip == BCM4371_CHIP_ID) ||
1057 		(bus->sih->chip == BCM4350_CHIP_ID)) {
1058 		uint32 enabval = 0;
1059 		addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
1060 		data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
1061 		/* XXX: assuming the dongle doesn't change chipcontrol_addr, because
1062 		* if that happens, the chipcontrol_data read will be wrong. So we need
1063 		* to make sure the dongle and host will not access chipcontrol_addr
1064 		* simultaneously at this point.
1065 		*/
1066 		bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3);
1067 		enabval = bcmsdh_reg_read(bus->sdh, data, 4);
1068 
1069 		if ((bus->sih->chip == BCM4350_CHIP_ID) ||
1070 			BCM4345_CHIP(bus->sih->chip) ||
1071 			(bus->sih->chip == BCM4354_CHIP_ID) ||
1072 			(bus->sih->chip == BCM4358_CHIP_ID) ||
1073 			(bus->sih->chip == BCM43569_CHIP_ID) ||
1074 			(bus->sih->chip == BCM4371_CHIP_ID))
1075 			enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
1076 
1077 		/* XXX: not checking the CC_PMUCC3_SRCC_SR_ENG_ENAB bit [val 4], but
1078 		* will check the whole register to be non-zero so that, sleep sequence
1079 		* can be also checked without enabling SR.
1080 		*/
1081 		if (enabval)
1082 			cap = TRUE;
1083 	} else {
1084 		data = bcmsdh_reg_read(bus->sdh,
1085 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, retention_ctl)),
1086 			4);
1087 		if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
1088 			cap = TRUE;
1089 	}
1090 
1091 	return cap;
1092 }
1093 
1094 static int
dhdsdio_sr_init(dhd_bus_t * bus)1095 dhdsdio_sr_init(dhd_bus_t *bus)
1096 {
1097 	uint8 val;
1098 	int err = 0;
1099 
1100 	if (bus->sih->chip == BCM43012_CHIP_ID ||
1101 		bus->sih->chip == BCM43013_CHIP_ID ||
1102 		bus->sih->chip == BCM43014_CHIP_ID) {
1103 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1104 		val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
1105 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1106 			1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT, &err);
1107 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1108 	} else {
1109 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1110 		val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
1111 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1112 			1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
1113 		val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
1114 	}
1115 
1116 #ifdef USE_CMD14
1117 	/* Add CMD14 Support */
1118 	dhdsdio_devcap_set(bus,
1119 		(SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT));
1120 #endif /* USE_CMD14 */
1121 
1122 	if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
1123 		CHIPID(bus->sih->chip) == BCM43018_CHIP_ID ||
1124 		CHIPID(bus->sih->chip) == BCM4339_CHIP_ID ||
1125 		CHIPID(bus->sih->chip) == BCM4362_CHIP_ID ||
1126 		CHIPID(bus->sih->chip) == BCM43012_CHIP_ID ||
1127 		CHIPID(bus->sih->chip) == BCM43013_CHIP_ID ||
1128 		CHIPID(bus->sih->chip) == BCM43014_CHIP_ID ||
1129 		CHIPID(bus->sih->chip) == BCM43751_CHIP_ID ||
1130 		CHIPID(bus->sih->chip) == BCM43752_CHIP_ID)
1131 			dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
1132 
1133 	if (bus->sih->chip == BCM43012_CHIP_ID ||
1134 		bus->sih->chip == BCM43013_CHIP_ID ||
1135 		bus->sih->chip == BCM43014_CHIP_ID) {
1136 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
1137 			SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_HT_AVAIL_REQ, &err);
1138 	} else {
1139 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
1140 			SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
1141 	}
1142 	bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
1143 
1144 	bus->_srenab = TRUE;
1145 
1146 	return 0;
1147 }
1148 #endif /* BCMSPI */
1149 
1150 /*
1151  * FIX: Be sure KSO bit is enabled
1152  * Currently, it's defaulting to 0 which should be 1.
1153  */
1154 static int
dhdsdio_clk_kso_init(dhd_bus_t * bus)1155 dhdsdio_clk_kso_init(dhd_bus_t *bus)
1156 {
1157 	uint8 val;
1158 	int err = 0;
1159 
1160 	/* set flag */
1161 	bus->kso = TRUE;
1162 
1163 	/*
1164 	 * Enable KeepSdioOn (KSO) bit for normal operation
1165 	 * Default is 0 (4334A0) so set it. Fixed in B0.
1166 	 */
1167 	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, NULL);
1168 	if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
1169 		val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
1170 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, val, &err);
1171 		if (err)
1172 			DHD_ERROR(("%s: SBSDIO_FUNC1_SLEEPCSR err: 0x%x\n", __FUNCTION__, err));
1173 	}
1174 
1175 	return 0;
1176 }
1177 
1178 #define KSO_DBG(x)
1179 /* XXX KSO set typically takes depending on resource up & number of
1180 * resources which were down. Max value is PMU_MAX_TRANSITION_DLY usec.
1181 * Currently the KSO attempt loop is such that, it waits
1182 * (KSO_WAIT_US [50usec] time + 2 SDIO operations) * MAX_KSO_ATTEMPTS.
1183 * So setting a value of maximum PMU_MAX_TRANSITION_DLY as wait time.,
1184 * to calculate MAX_KSO_ATTEMPTS.
1185 */
1186 #define KSO_WAIT_US 50
1187 #define KSO_WAIT_MS 1
1188 #define KSO_SLEEP_RETRY_COUNT 20
1189 #define KSO_WAKE_RETRY_COUNT 100
1190 #define ERROR_BCME_NODEVICE_MAX 1
1191 
1192 #define DEFAULT_MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
1193 #ifndef CUSTOM_MAX_KSO_ATTEMPTS
1194 #define CUSTOM_MAX_KSO_ATTEMPTS DEFAULT_MAX_KSO_ATTEMPTS
1195 #endif
1196 
1197 static int
dhdsdio_clk_kso_enab(dhd_bus_t * bus,bool on)1198 dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
1199 {
1200 	uint8 wr_val = 0, rd_val, cmp_val, bmask;
1201 	int err = 0;
1202 	int try_cnt = 0, try_max = CUSTOM_MAX_KSO_ATTEMPTS;
1203 	struct dhd_conf *conf = bus->dhd->conf;
1204 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)) && !defined(ANDROID13_KERNEL515_BKPORT)
1205 	wifi_adapter_info_t *adapter = NULL;
1206 	uint32 bus_type = -1, bus_num = -1, slot_num = -1;
1207 #else
1208 	struct mmc_host *host;
1209 	struct sdioh_info *sd = (struct sdioh_info *)(bus->sdh->sdioh);
1210 	struct sdio_func *func = sd->func[SDIO_FUNC_0];
1211 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1212 
1213 	KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
1214 
1215 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)) && !defined(ANDROID13_KERNEL515_BKPORT)
1216 	dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num);
1217 	adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
1218 	sdio_retune_crc_disable(adapter->sdio_func);
1219 	if (on)
1220 		sdio_retune_hold_now(adapter->sdio_func);
1221 #else
1222 	host = func->card->host;
1223 	mmc_retune_disable(host);
1224 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1225 
1226 	wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
1227 
1228 	/* XXX 1st KSO write goes to AOS wake up core if device is asleep  */
1229 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
1230 
1231 	/* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared.
1232 	 * So the further reads of KSO register could fail. Thereby just bailing out immediately
1233 	 * after clearing KSO bit, to avoid polling of KSO bit.
1234 	 */
1235 	if ((!on) && (bus->sih->chip == BCM43012_CHIP_ID ||
1236 		bus->sih->chip == BCM43013_CHIP_ID ||
1237 		bus->sih->chip == BCM43014_CHIP_ID)) {
1238 		goto exit;
1239 	}
1240 
1241 	if (on) {
1242 		/* XXX
1243 		 *  device WAKEUP through KSO:
1244 		 *  write bit 0 & read back until
1245 		 *  both bits 0(kso bit) & 1 (dev on status) are set
1246 		 */
1247 		cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |  SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
1248 		bmask = cmp_val;
1249 
1250 #if defined(NDIS)
1251 		/* XXX Windows Host controller hangs if chip still sleeps before read.
1252 		 * So during a wake we write 0x1 for 5 msec to guarantee that chip is a wake.
1253 		 */
1254 		for (int i = 0; i < KSO_WAKE_RETRY_COUNT; i++) {
1255 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR,
1256 				wr_val, &err);
1257 			OSL_DELAY(KSO_WAIT_US);
1258 		}
1259 
1260 		rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1261 		if (((rd_val & bmask) != cmp_val) || err) {
1262 			/* Sdio Bus Failure - Bus hang */
1263 			DHD_ERROR(("%s> op:%s, ERROR: SDIO Bus Hang, rd_val:%x, ERR:%x \n",
1264 				__FUNCTION__, "KSO_SET", rd_val, err));
1265 		}
1266 #else
1267 		OSL_SLEEP(3);
1268 #endif /* defined(NDIS) */
1269 
1270 	} else {
1271 		/* Put device to sleep, turn off  KSO  */
1272 		cmp_val = 0;
1273 		/* XXX only check for bit0, bit1(devon status) may not get cleared right away */
1274 		bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
1275 	}
1276 #if !defined(NDIS)
1277 	/* XXX We can't use polling in Windows since Windows Host controller
1278 	 * hangs if chip is a sleep during read or write.
1279 	 */
1280 
1281 	if (conf->kso_try_max)
1282 		try_max = conf->kso_try_max;
1283 	do {
1284 		/*
1285 		 *  XXX reliable KSO bit set/clr:
1286 		 *  the sdiod sleep write access appears to be is synced to PMU 32khz clk
1287 		 *  just one write attempt may fail,(same is with read ?)
1288 		 *  in any case, read it back until it matches written value
1289 		 */
1290 		rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1291 		if (((rd_val & bmask) == cmp_val) && !err)
1292 			break;
1293 
1294 		KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err));
1295 
1296 		if (((try_cnt + 1) % KSO_SLEEP_RETRY_COUNT) == 0) {
1297 			OSL_SLEEP(KSO_WAIT_MS);
1298 		} else
1299 			OSL_DELAY(KSO_WAIT_US);
1300 
1301 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
1302 	} while (try_cnt++ < try_max);
1303 
1304 #ifdef KSO_DEBUG
1305 	if (try_cnt > 0 && try_cnt <= 10)
1306 		conf->kso_try_array[0] += 1;
1307 	else if (try_cnt <= 50)
1308 		conf->kso_try_array[1] += 1;
1309 	else if (try_cnt <= 100)
1310 		conf->kso_try_array[2] += 1;
1311 	else if (try_cnt <= 200)
1312 		conf->kso_try_array[3] += 1;
1313 	else if (try_cnt <= 500)
1314 		conf->kso_try_array[4] += 1;
1315 	else if (try_cnt <= 1000)
1316 		conf->kso_try_array[5] += 1;
1317 	else if (try_cnt <= 2000)
1318 		conf->kso_try_array[6] += 1;
1319 	else if (try_cnt <= 5000)
1320 		conf->kso_try_array[7] += 1;
1321 	else if (try_cnt <= 10000)
1322 		conf->kso_try_array[8] += 1;
1323 	else
1324 		conf->kso_try_array[9] += 1;
1325 #endif
1326 	if (try_cnt > 2)
1327 		KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n",
1328 			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
1329 
1330 	if (try_cnt > try_max)  {
1331 		DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n",
1332 			__FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
1333 #ifdef KSO_DEBUG
1334 		{
1335 			int i;
1336 			printk(KERN_CONT DHD_LOG_PREFIXS);
1337 			for (i=0; i<10; i++) {
1338 				printk(KERN_CONT "[%d]: %d, ", i, conf->kso_try_array[i]);
1339 		 	}
1340 			printk("\n");
1341 		}
1342 #endif
1343 	}
1344 #endif /* !defined(NDIS) */
1345 
1346 exit:
1347 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)) && !defined(ANDROID13_KERNEL515_BKPORT)
1348 	if (on)
1349 		sdio_retune_release(adapter->sdio_func);
1350 	sdio_retune_crc_enable(adapter->sdio_func);
1351 #else
1352 	mmc_retune_enable(host);
1353 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) */
1354 
1355 	return err;
1356 }
1357 
1358 static int
dhdsdio_clk_kso_iovar(dhd_bus_t * bus,bool on)1359 dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bool on)
1360 {
1361 	int err = 0;
1362 
1363 	if (on == FALSE) {
1364 
1365 		BUS_WAKE(bus);
1366 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1367 
1368 		DHD_ERROR(("%s: KSO disable clk: 0x%x\n", __FUNCTION__,
1369 			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1370 			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1371 		dhdsdio_clk_kso_enab(bus, FALSE);
1372 	} else {
1373 		DHD_ERROR(("%s: KSO enable\n", __FUNCTION__));
1374 
1375 		/* Make sure we have SD bus access */
1376 		if (bus->clkstate == CLK_NONE) {
1377 			DHD_ERROR(("%s: Request SD clk\n", __FUNCTION__));
1378 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1379 		}
1380 
1381 		dhdsdio_clk_kso_enab(bus, TRUE);
1382 
1383 		DHD_ERROR(("%s: sleepcsr: 0x%x\n", __FUNCTION__,
1384 			dhdsdio_sleepcsr_get(bus)));
1385 	}
1386 
1387 	bus->kso = on;
1388 	BCM_REFERENCE(err);
1389 
1390 	return 0;
1391 }
1392 
1393 static uint8
dhdsdio_sleepcsr_get(dhd_bus_t * bus)1394 dhdsdio_sleepcsr_get(dhd_bus_t *bus)
1395 {
1396 	int err = 0;
1397 	uint8 val = 0;
1398 
1399 	val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
1400 	/* XXX: Propagate error */
1401 	if (err)
1402 		DHD_TRACE(("Failed to read SLEEPCSR: %d\n", err));
1403 
1404 	return val;
1405 }
1406 
1407 uint8
dhdsdio_devcap_get(dhd_bus_t * bus)1408 dhdsdio_devcap_get(dhd_bus_t *bus)
1409 {
1410 	return bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL);
1411 }
1412 
1413 static int
dhdsdio_devcap_set(dhd_bus_t * bus,uint8 cap)1414 dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap)
1415 {
1416 	int err = 0;
1417 
1418 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, cap, &err);
1419 	if (err)
1420 		DHD_ERROR(("%s: devcap set err: 0x%x\n", __FUNCTION__, err));
1421 
1422 	return 0;
1423 }
1424 
1425 static int
dhdsdio_clk_devsleep_iovar(dhd_bus_t * bus,bool on)1426 dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on)
1427 {
1428 	int err = 0, retry;
1429 	uint8 val;
1430 
1431 	retry = 0;
1432 	if (on == TRUE) {
1433 		/* Enter Sleep */
1434 
1435 		/* Be sure we request clk before going to sleep
1436 		 * so we can wake-up with clk request already set
1437 		 * else device can go back to sleep immediately
1438 		 */
1439 		if (!SLPAUTO_ENAB(bus))
1440 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
1441 		else {
1442 			/* XXX: Check if Host cleared clock request
1443 			 * XXX: With CMD14, Host does not need to explicitly toggle clock requests
1444 			 * XXX: Just keep clock request active and use CMD14 to enter/exit sleep
1445 			 */
1446 			val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
1447 			if ((val & SBSDIO_CSR_MASK) == 0) {
1448 				DHD_ERROR(("%s: No clock before enter sleep:0x%x\n",
1449 					__FUNCTION__, val));
1450 
1451 				/* Reset clock request */
1452 				bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
1453 					SBSDIO_ALP_AVAIL_REQ, &err);
1454 				DHD_ERROR(("%s: clock before sleep:0x%x\n", __FUNCTION__,
1455 					bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1456 					SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1457 			}
1458 		}
1459 
1460 		DHD_TRACE(("%s: clk before sleep: 0x%x\n", __FUNCTION__,
1461 			bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1462 			SBSDIO_FUNC1_CHIPCLKCSR, &err)));
1463 #ifdef USE_CMD14
1464 		err = bcmsdh_sleep(bus->sdh, TRUE);
1465 #else
1466 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) {
1467 			if (sd1idle) {
1468 				/* Change to SD1 mode */
1469 				dhdsdio_set_sdmode(bus, 1);
1470 			}
1471 		}
1472 
1473 		err = dhdsdio_clk_kso_enab(bus, FALSE);
1474 		if (OOB_WAKEUP_ENAB(bus))
1475 		{
1476 #if !defined(NDIS)
1477 			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE);  /* GPIO_1 is off */
1478 #endif /* !defined(NDIS) */
1479 		}
1480 #endif /* USE_CMD14 */
1481 
1482 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock != DHD_IDLE_ACTIVE)) {
1483 			DHD_TRACE(("%s: Turnoff SD clk\n", __FUNCTION__));
1484 			/* Now remove the SD clock */
1485 			err = dhdsdio_sdclk(bus, FALSE);
1486 		}
1487 	} else {
1488 		/* Exit Sleep */
1489 		/* Make sure we have SD bus access */
1490 		if (bus->clkstate == CLK_NONE) {
1491 			DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__));
1492 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
1493 		}
1494 #ifdef USE_CMD14
1495 		err = bcmsdh_sleep(bus->sdh, FALSE);
1496 		if (SLPAUTO_ENAB(bus) && (err != 0)) {
1497 			/* XXX: CMD14 exit sleep is failing somehow
1498 			 * XXX: Is Host out of sync with device?
1499 			 * XXX: Try toggling the reverse
1500 			 */
1501 			OSL_DELAY(10000);
1502 			DHD_TRACE(("%s: Resync device sleep\n", __FUNCTION__));
1503 
1504 			/* Toggle sleep to resync with host and device */
1505 			err = bcmsdh_sleep(bus->sdh, TRUE);
1506 			OSL_DELAY(10000);
1507 			err = bcmsdh_sleep(bus->sdh, FALSE);
1508 
1509 			/* XXX: Ugly hack for host-device out-of-sync while testing
1510 			 * XXX: Need to root-cause
1511 			 */
1512 			if (err) {
1513 				/* XXX: Host and device out-of-sync */
1514 				OSL_DELAY(10000);
1515 				DHD_ERROR(("%s: CMD14 exit failed again!\n", __FUNCTION__));
1516 
1517 				/* Toggle sleep to resync with host and device */
1518 				err = bcmsdh_sleep(bus->sdh, TRUE);
1519 				OSL_DELAY(10000);
1520 				err = bcmsdh_sleep(bus->sdh, FALSE);
1521 				if (err) {
1522 					/* XXX: Give up and assumed it has exited sleep
1523 					 * XXX: Device probably dead at this point
1524 					 * XXX: So far only happens with SR
1525 					 */
1526 					DHD_ERROR(("%s: CMD14 exit failed twice!\n", __FUNCTION__));
1527 					DHD_ERROR(("%s: FATAL: Device non-response!\n",
1528 						__FUNCTION__));
1529 					err = 0;
1530 				}
1531 			}
1532 		}
1533 #else
1534 		if (OOB_WAKEUP_ENAB(bus))
1535 		{
1536 #if !defined(NDIS)
1537 			err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE);  /* GPIO_1 is on */
1538 #endif /* !defined(NDIS) */
1539 		}
1540 		/* PR 101351: sdiod_aos sleep followed by immediate wakeup
1541 		 *    before sdiod_aos takes over has a problem.
1542 		 * Set KSO after ExitSleep.
1543 		 */
1544 		do {
1545 			err = dhdsdio_clk_kso_enab(bus, TRUE);
1546 			if (err)
1547 				OSL_SLEEP(10);
1548 		} while ((err != 0) && (++retry < 3));
1549 
1550 		if (err != 0) {
1551 			DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry));
1552 #ifndef BT_OVER_SDIO
1553 			err = 0; /* continue anyway */
1554 #endif /* BT_OVER_SDIO */
1555 		}
1556 
1557 		if ((SLPAUTO_ENAB(bus)) && (bus->idleclock == DHD_IDLE_STOP)) {
1558 			dhdsdio_set_sdmode(bus, bus->sd_mode);
1559 		}
1560 #endif /* !USE_CMD14 */
1561 
1562 		if (err == 0) {
1563 			uint8 csr;
1564 
1565 			/* Wait for device ready during transition to wake-up */
1566 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1567 				(((csr = dhdsdio_sleepcsr_get(bus)) &
1568 				SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) !=
1569 				(SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000));
1570 
1571 			DHD_TRACE(("%s: ExitSleep sleepcsr: 0x%x\n", __FUNCTION__, csr));
1572 
1573 			if (!(csr & SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) {
1574 				DHD_ERROR(("%s:ERROR: ExitSleep device NOT Ready! 0x%x\n",
1575 					__FUNCTION__, csr));
1576 				err = BCME_NODEVICE;
1577 			}
1578 
1579 			/* PR 101351: sdiod_aos sleep followed by immediate wakeup
1580 			 *    before sdiod_aos takes over has a problem.
1581 			 */
1582 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1583 				(((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
1584 				SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) !=
1585 				(SBSDIO_HT_AVAIL)), (DHD_WAIT_HTAVAIL));
1586 
1587 			DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr));
1588 			if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) {
1589 				DHD_ERROR(("%s:ERROR: device NOT Ready! 0x%x\n",
1590 					__FUNCTION__, csr));
1591 				err = BCME_NODEVICE;
1592 			}
1593 		}
1594 	}
1595 
1596 	/* Update if successful */
1597 	if (err == 0)
1598 		bus->kso = on ? FALSE : TRUE;
1599 	else {
1600 		DHD_ERROR(("%s: Sleep request failed: kso:%d on:%d err:%d\n",
1601 			__FUNCTION__, bus->kso, on, err));
1602 		if (!on && retry > 2)
1603 			bus->kso = FALSE;
1604 	}
1605 
1606 	return err;
1607 }
1608 
1609 /* Turn backplane clock on or off */
1610 static int
dhdsdio_htclk(dhd_bus_t * bus,bool on,bool pendok)1611 dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
1612 {
1613 #define HT_AVAIL_ERROR_MAX 10
1614 	static int ht_avail_error = 0;
1615 	int err;
1616 	uint8 clkctl, clkreq, devctl;
1617 	bcmsdh_info_t *sdh;
1618 
1619 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1620 
1621 	clkctl = 0;
1622 	sdh = bus->sdh;
1623 
1624 #ifdef BCMINTERNAL
1625 	if (DHD_NOPMU(bus)) {
1626 		/* There is no PMU present, so just fake the clock state... */
1627 		bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
1628 		return BCME_OK;
1629 	}
1630 
1631 	if (bus->clockpoll)
1632 		pendok = FALSE;
1633 #endif /* BCMINTERNAL */
1634 
1635 	if (!KSO_ENAB(bus))
1636 		return BCME_OK;
1637 
1638 	if (SLPAUTO_ENAB(bus)) {
1639 		bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
1640 		return BCME_OK;
1641 	}
1642 
1643 	if (on) {
1644 		/* Request HT Avail */
1645 		clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
1646 
1647 #ifdef BCMSPI
1648 		dhdsdio_wkwlan(bus, TRUE);
1649 #endif /* BCMSPI */
1650 
1651 		/* XXX Should be able to early-exit if pendok && PENDING */
1652 
1653 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1654 		if (err) {
1655 			ht_avail_error++;
1656 			if (ht_avail_error < HT_AVAIL_ERROR_MAX) {
1657 				DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
1658 			}
1659 
1660 #ifdef OEM_ANDROID
1661 			else if (ht_avail_error == HT_AVAIL_ERROR_MAX) {
1662 				bus->dhd->hang_reason = HANG_REASON_HT_AVAIL_ERROR;
1663 				dhd_os_send_hang_message(bus->dhd);
1664 			}
1665 #endif /* OEM_ANDROID */
1666 			return BCME_ERROR;
1667 		} else {
1668 			ht_avail_error = 0;
1669 		}
1670 
1671 		/* Check current status */
1672 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
1673 		if (err) {
1674 			DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
1675 			return BCME_ERROR;
1676 		}
1677 
1678 #if !defined(OOB_INTR_ONLY)
1679 		/* Go to pending and await interrupt if appropriate */
1680 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
1681 			/* Allow only clock-available interrupt */
1682 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1683 			if (err) {
1684 				DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
1685 				           __FUNCTION__, err));
1686 				return BCME_ERROR;
1687 			}
1688 
1689 			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
1690 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1691 			DHD_INFO(("CLKCTL: set PENDING\n"));
1692 			bus->clkstate = CLK_PENDING;
1693 			return BCME_OK;
1694 		} else
1695 #endif /* !defined (OOB_INTR_ONLY) */
1696 		{
1697 			if (bus->clkstate == CLK_PENDING) {
1698 				/* Cancel CA-only interrupt filter */
1699 				devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1700 				devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1701 				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1702 			}
1703 		}
1704 #ifndef BCMSDIOLITE
1705 		/* Otherwise, wait here (polling) for HT Avail */
1706 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1707 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
1708 				((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
1709 			                                    SBSDIO_FUNC1_CHIPCLKCSR, &err)),
1710 			          !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
1711 		}
1712 		if (err) {
1713 			DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
1714 			return BCME_ERROR;
1715 		}
1716 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
1717 			DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
1718 			           __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
1719 			return BCME_ERROR;
1720 		}
1721 #endif /* BCMSDIOLITE */
1722 		/* Mark clock available */
1723 		bus->clkstate = CLK_AVAIL;
1724 		DHD_INFO(("CLKCTL: turned ON\n"));
1725 
1726 #if defined(DHD_DEBUG)
1727 		if (bus->alp_only == TRUE) {
1728 #if !defined(BCMLXSDMMC)
1729 			/* XXX For the SDMMC Driver stack, if DHD was unloaded,
1730 			 * the chip is not completely reset, so in this case,
1731 			 * the PMU may already be programmed to allow HT clock.
1732 			 */
1733 			if (!SBSDIO_ALPONLY(clkctl)) {
1734 				DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
1735 			}
1736 #endif /* !defined(BCMLXSDMMC) */
1737 		} else {
1738 			if (SBSDIO_ALPONLY(clkctl)) {
1739 				DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
1740 			}
1741 		}
1742 #endif /* defined (DHD_DEBUG) */
1743 
1744 		bus->activity = TRUE;
1745 #ifdef DHD_USE_IDLECOUNT
1746 		bus->idlecount = 0;
1747 #endif /* DHD_USE_IDLECOUNT */
1748 	} else {
1749 		clkreq = 0;
1750 
1751 		if (bus->clkstate == CLK_PENDING) {
1752 			/* Cancel CA-only interrupt filter */
1753 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
1754 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
1755 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
1756 		}
1757 
1758 		bus->clkstate = CLK_SDONLY;
1759 		if (!SR_ENAB(bus)) {
1760 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
1761 			DHD_INFO(("CLKCTL: turned OFF\n"));
1762 			if (err) {
1763 				DHD_ERROR(("%s: Failed access turning clock off: %d\n",
1764 				           __FUNCTION__, err));
1765 				return BCME_ERROR;
1766 			}
1767 		}
1768 #ifdef BCMSPI
1769 			dhdsdio_wkwlan(bus, FALSE);
1770 #endif /* BCMSPI */
1771 	}
1772 	return BCME_OK;
1773 }
1774 
1775 /* Change SD1/SD4 bus mode */
1776 static int
dhdsdio_set_sdmode(dhd_bus_t * bus,int32 sd_mode)1777 dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode)
1778 {
1779 	int err;
1780 
1781 	err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
1782 		&sd_mode, sizeof(sd_mode), TRUE);
1783 	if (err) {
1784 		DHD_ERROR(("%s: error changing sd_mode: %d\n",
1785 			__FUNCTION__, err));
1786 		return BCME_ERROR;
1787 	}
1788 	return BCME_OK;
1789 }
1790 
1791 /* Change idle/active SD state */
1792 static int
dhdsdio_sdclk(dhd_bus_t * bus,bool on)1793 dhdsdio_sdclk(dhd_bus_t *bus, bool on)
1794 {
1795 #ifndef BCMSPI
1796 	int err;
1797 	int32 iovalue;
1798 
1799 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1800 
1801 	if (on) {
1802 		if (bus->idleclock == DHD_IDLE_STOP) {
1803 			/* Turn on clock and restore mode */
1804 			iovalue = 1;
1805 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
1806 			                      &iovalue, sizeof(iovalue), TRUE);
1807 			if (err) {
1808 				DHD_ERROR(("%s: error enabling sd_clock: %d\n",
1809 				           __FUNCTION__, err));
1810 				return BCME_ERROR;
1811 			}
1812 
1813 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
1814 			/* Restore clock speed */
1815 			iovalue = bus->sd_divisor;
1816 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
1817 			                      &iovalue, sizeof(iovalue), TRUE);
1818 			if (err) {
1819 				DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
1820 				           __FUNCTION__, err));
1821 				return BCME_ERROR;
1822 			}
1823 		}
1824 		bus->clkstate = CLK_SDONLY;
1825 	} else {
1826 		/* Stop or slow the SD clock itself */
1827 		if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
1828 			DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
1829 			           __FUNCTION__, bus->sd_divisor, bus->sd_mode));
1830 			return BCME_ERROR;
1831 		}
1832 		if (bus->idleclock == DHD_IDLE_STOP) {
1833 			iovalue = 0;
1834 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
1835 			                      &iovalue, sizeof(iovalue), TRUE);
1836 			if (err) {
1837 				DHD_ERROR(("%s: error disabling sd_clock: %d\n",
1838 				           __FUNCTION__, err));
1839 				return BCME_ERROR;
1840 			}
1841 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
1842 			/* Set divisor to idle value */
1843 			iovalue = bus->idleclock;
1844 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
1845 			                      &iovalue, sizeof(iovalue), TRUE);
1846 			if (err) {
1847 				DHD_ERROR(("%s: error changing sd_divisor: %d\n",
1848 				           __FUNCTION__, err));
1849 				return BCME_ERROR;
1850 			}
1851 		}
1852 		bus->clkstate = CLK_NONE;
1853 	}
1854 #endif /* BCMSPI */
1855 
1856 	return BCME_OK;
1857 }
1858 
1859 /* Transition SD and backplane clock readiness */
1860 static int
dhdsdio_clkctl(dhd_bus_t * bus,uint target,bool pendok)1861 dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
1862 {
1863 	int ret = BCME_OK;
1864 #ifdef DHD_DEBUG
1865 	uint oldstate = bus->clkstate;
1866 #endif /* DHD_DEBUG */
1867 
1868 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
1869 
1870 	/* Early exit if we're already there */
1871 	if (bus->clkstate == target) {
1872 		if (target == CLK_AVAIL) {
1873 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1874 			bus->activity = TRUE;
1875 #ifdef DHD_USE_IDLECOUNT
1876 			bus->idlecount = 0;
1877 #endif /* DHD_USE_IDLECOUNT */
1878 		}
1879 		return ret;
1880 	}
1881 
1882 	switch (target) {
1883 	case CLK_AVAIL:
1884 		/* Make sure SD clock is available */
1885 		if (bus->clkstate == CLK_NONE)
1886 			dhdsdio_sdclk(bus, TRUE);
1887 		/* Now request HT Avail on the backplane */
1888 		ret = dhdsdio_htclk(bus, TRUE, pendok);
1889 		if (ret == BCME_OK) {
1890 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1891 		bus->activity = TRUE;
1892 #ifdef DHD_USE_IDLECOUNT
1893 			bus->idlecount = 0;
1894 #endif /* DHD_USE_IDLECOUNT */
1895 		}
1896 		break;
1897 
1898 	case CLK_SDONLY:
1899 
1900 #ifdef BT_OVER_SDIO
1901 		/*
1902 		 * If the request is to switch off Back plane clock,
1903 		 * confirm that BT is inactive before doing so.
1904 		 * If this call had come from Non Watchdog context any way
1905 		 * the Watchdog would switch off the clock again when
1906 		 * nothing is to be done & Bt has finished using the bus.
1907 		 */
1908 		if (bus->bt_use_count != 0) {
1909 			DHD_INFO(("%s(): Req CLK_SDONLY, BT is active %d not switching off \r\n",
1910 				__FUNCTION__, bus->bt_use_count));
1911 			ret = BCME_OK;
1912 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1913 			break;
1914 		}
1915 
1916 		DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n",
1917 			__FUNCTION__));
1918 #endif /* BT_OVER_SDIO */
1919 
1920 		/* Remove HT request, or bring up SD clock */
1921 		if (bus->clkstate == CLK_NONE)
1922 			ret = dhdsdio_sdclk(bus, TRUE);
1923 		else if (bus->clkstate == CLK_AVAIL)
1924 			ret = dhdsdio_htclk(bus, FALSE, FALSE);
1925 		else
1926 			DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
1927 			           bus->clkstate, target));
1928 		if (ret == BCME_OK) {
1929 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
1930 		}
1931 		break;
1932 
1933 	case CLK_NONE:
1934 
1935 #ifdef BT_OVER_SDIO
1936 		/*
1937 		 * If the request is to switch off Back plane clock,
1938 		 * confirm that BT is inactive before doing so.
1939 		 * If this call had come from Non Watchdog context any way
1940 		 * the Watchdog would switch off the clock again when
1941 		 * nothing is to be done & Bt has finished using the bus.
1942 		 */
1943 		if (bus->bt_use_count != 0) {
1944 			DHD_INFO(("%s(): Request CLK_NONE BT is active %d not switching off \r\n",
1945 				__FUNCTION__, bus->bt_use_count));
1946 			ret = BCME_OK;
1947 			break;
1948 		}
1949 
1950 		DHD_INFO(("%s(): Request CLK_NONE BT is NOT active switching off \r\n",
1951 			__FUNCTION__));
1952 #endif /* BT_OVER_SDIO */
1953 
1954 		/* Make sure to remove HT request */
1955 		if (bus->clkstate == CLK_AVAIL)
1956 			ret = dhdsdio_htclk(bus, FALSE, FALSE);
1957 		/* Now remove the SD clock */
1958 		ret = dhdsdio_sdclk(bus, FALSE);
1959 #ifdef DHD_DEBUG
1960 		if (bus->dhd->dhd_console_ms == 0)
1961 #endif /* DHD_DEBUG */
1962 		if (bus->poll == 0)
1963 			dhd_os_wd_timer(bus->dhd, 0);
1964 		break;
1965 	}
1966 #ifdef DHD_DEBUG
1967 	DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
1968 #endif /* DHD_DEBUG */
1969 
1970 	return ret;
1971 }
1972 
1973 static int
dhdsdio_bussleep(dhd_bus_t * bus,bool sleep)1974 dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
1975 {
1976 	int err = 0;
1977 	bcmsdh_info_t *sdh = bus->sdh;
1978 	sdpcmd_regs_t *regs = bus->regs;
1979 	uint retries = 0;
1980 #if defined(BCMSDIOH_STD)
1981 	uint32 sd3_tuning_disable = FALSE;
1982 #endif /* BCMSDIOH_STD */
1983 #if defined(WL_EXT_IAPSTA) && defined(DHD_LOSSLESS_ROAMING)
1984 	int state;
1985 #endif /* WL_EXT_IAPSTA && DHD_LOSSLESS_ROAMING */
1986 
1987 	DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
1988 	         (sleep ? "SLEEP" : "WAKE"),
1989 	          (bus->sleeping ? "SLEEP" : "WAKE")));
1990 
1991 	if (bus->dhd->hang_was_sent)
1992 		return BCME_ERROR;
1993 
1994 	/* Done if we're already in the requested state */
1995 	if (sleep == bus->sleeping)
1996 		return BCME_OK;
1997 
1998 	/* Going to sleep: set the alarm and turn off the lights... */
1999 	if (sleep) {
2000 		/* Don't sleep if something is pending */
2001 #ifdef DHD_USE_IDLECOUNT
2002 		if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq) ||
2003 			bus->readframes || bus->ctrl_frame_stat)
2004 #else
2005 		if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq))
2006 #endif /* DHD_USE_IDLECOUNT */
2007 			return BCME_BUSY;
2008 #if defined(WL_EXT_IAPSTA) && defined(DHD_LOSSLESS_ROAMING)
2009 		state = wl_ext_any_sta_handshaking(bus->dhd);
2010 		if (state) {
2011 			DHD_ERROR(("handshaking %d\n", state));
2012 			return BCME_BUSY;
2013 		}
2014 #endif /* WL_EXT_IAPSTA && DHD_LOSSLESS_ROAMING */
2015 
2016 #ifdef BT_OVER_SDIO
2017 		/*
2018 		 * The following is the assumption based on which the hook is placed.
2019 		 * From WLAN driver, either from the active contexts OR from the Watchdog contexts
2020 		 * we will be attempting to Go to Sleep. AT that moment if we see that BT is still
2021 		 * actively using the bus, we will return BCME_BUSY from here, but the bus->sleeping
2022 		 * state would not have changed. So the caller can then schedule the Watchdog again
2023 		 * which will come and attempt to sleep at a later point.
2024 		 *
2025 		 * In case if BT is the only one and is the last user, we don't switch off the clock
2026 		 * immediately, we allow the WLAN to decide when to sleep i.e from the watchdog.
2027 		 * Now if the watchdog becomes active and attempts to switch off the clock and if
2028 		 * another WLAN context is active they are any way serialized with sdlock.
2029 		 */
2030 		if (bus->bt_use_count != 0) {
2031 			DHD_INFO(("%s(): Cannot sleep BT is active \r\n", __FUNCTION__));
2032 			return BCME_BUSY;
2033 		}
2034 #endif /* !BT_OVER_SDIO */
2035 
2036 		/* XXX Is it an error to sleep when not in data state? */
2037 
2038 		if (!SLPAUTO_ENAB(bus)) {
2039 			/* Disable SDIO interrupts (no longer interested) */
2040 			bcmsdh_intr_disable(bus->sdh);
2041 
2042 			/* Make sure the controller has the bus up */
2043 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2044 
2045 			/* Tell device to start using OOB wakeup */
2046 			W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
2047 			if (retries > retry_limit)
2048 				DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
2049 
2050 			/* Turn off our contribution to the HT clock request */
2051 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
2052 
2053 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
2054 				SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
2055 
2056 			/* Isolate the bus */
2057 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
2058 					SBSDIO_DEVCTL_PADS_ISO, NULL);
2059 		} else {
2060 #ifdef FORCE_SWOOB_ENABLE
2061 			/* Tell device to start using OOB wakeup */
2062 			W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
2063 			if (retries > retry_limit)
2064 				DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
2065 #endif
2066 			/* Leave interrupts enabled since device can exit sleep and
2067 			 * interrupt host
2068 			 */
2069 			err = dhdsdio_clk_devsleep_iovar(bus, TRUE /* sleep */);
2070 		}
2071 
2072 		/* Change state */
2073 		bus->sleeping = TRUE;
2074 #if defined(BCMSDIOH_STD)
2075 		sd3_tuning_disable = TRUE;
2076 		err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0,
2077 			&sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE);
2078 #endif /* BCMSDIOH_STD */
2079 #if defined(LINUX) && defined(SUPPORT_P2P_GO_PS)
2080 		wake_up(&bus->bus_sleep);
2081 #endif /* LINUX && SUPPORT_P2P_GO_PS */
2082 		/* XXX Should be able to turn off clock and power */
2083 		/* XXX Make sure GPIO interrupt input is enabled */
2084 	} else {
2085 		/* Waking up: bus power up is ok, set local state */
2086 
2087 		if (!SLPAUTO_ENAB(bus)) {
2088 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, &err);
2089 
2090 			/* Force pad isolation off if possible (in case power never toggled) */
2091 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
2092 
2093 			/* XXX Make sure GPIO interrupt input is disabled */
2094 			/* XXX Should be able to turn on power and clock */
2095 
2096 			/* Make sure the controller has the bus up */
2097 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2098 
2099 			/* Send misc interrupt to indicate OOB not needed */
2100 			W_SDREG(0, &regs->tosbmailboxdata, retries);
2101 			if (retries <= retry_limit)
2102 				W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
2103 
2104 			if (retries > retry_limit)
2105 				DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
2106 
2107 			/* Make sure we have SD bus access */
2108 			dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
2109 
2110 			/* Enable interrupts again */
2111 			if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
2112 				bus->intdis = FALSE;
2113 				bcmsdh_intr_enable(bus->sdh);
2114 			}
2115 		} else {
2116 			err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */);
2117 #ifdef FORCE_SWOOB_ENABLE
2118 			/* Send misc interrupt to indicate OOB not needed */
2119 			W_SDREG(0, &regs->tosbmailboxdata, retries);
2120 			if (retries <= retry_limit)
2121 				W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
2122 #endif
2123 #ifdef BT_OVER_SDIO
2124 			if (err < 0) {
2125 				struct net_device *net = NULL;
2126 				dhd_pub_t *dhd = bus->dhd;
2127 				net = dhd_idx2net(dhd, 0);
2128 				if (net != NULL) {
2129 					DHD_ERROR(("<< WIFI HANG by KSO Enabled failure\n"));
2130 					dhd_os_sdunlock(dhd);
2131 					net_os_send_hang_message(net);
2132 					dhd_os_sdlock(dhd);
2133 				} else {
2134 					DHD_ERROR(("<< WIFI HANG Fail because net is NULL\n"));
2135 				}
2136 			}
2137 #endif /* BT_OVER_SDIO */
2138 		}
2139 
2140 		if (err == 0) {
2141 			/* Change state */
2142 			bus->sleeping = FALSE;
2143 #if defined(BCMSDIOH_STD)
2144 			sd3_tuning_disable = FALSE;
2145 			err = bcmsdh_iovar_op(bus->sdh, "sd3_tuning_disable", NULL, 0,
2146 				&sd3_tuning_disable, sizeof(sd3_tuning_disable), TRUE);
2147 #endif /* BCMSDIOH_STD */
2148 		}
2149 	}
2150 
2151 	return err;
2152 }
2153 
2154 #ifdef BT_OVER_SDIO
2155 /*
2156  * Call this function to Get the Clock running.
2157  * Assumes that the caller holds the sdlock.
2158  * bus - Pointer to the dhd_bus handle
2159  * can_wait - TRUE if the caller can wait until the clock becomes ready
2160  *            FALSE if the caller cannot wait
2161  */
__dhdsdio_clk_enable(struct dhd_bus * bus,bus_owner_t owner,int can_wait)2162 int __dhdsdio_clk_enable(struct dhd_bus *bus, bus_owner_t owner, int can_wait)
2163 {
2164 	int ret = BCME_ERROR;
2165 
2166 	BCM_REFERENCE(owner);
2167 
2168 	bus->bt_use_count++;
2169 
2170 	/*
2171 	 * We can call BUS_WAKE, clkctl multiple times, both of the items
2172 	 * have states and if its already ON, no new configuration is done
2173 	 */
2174 
2175 	/* Wake up the Dongle FW from SR */
2176 	BUS_WAKE(bus);
2177 
2178 	/*
2179 	 * Make sure back plane ht clk is on
2180 	 * CLK_AVAIL - Turn On both SD & HT clock
2181 	 */
2182 	ret = dhdsdio_clkctl(bus, CLK_AVAIL, can_wait);
2183 
2184 	DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__,
2185 		bus->bt_use_count));
2186 	return ret;
2187 }
2188 
2189 /*
2190  * Call this function to relinquish the Clock.
2191  * Assumes that the caller holds the sdlock.
2192  * bus - Pointer to the dhd_bus handle
2193  * can_wait - TRUE if the caller can wait until the clock becomes ready
2194  *            FALSE if the caller cannot wait
2195  */
__dhdsdio_clk_disable(struct dhd_bus * bus,bus_owner_t owner,int can_wait)2196 int __dhdsdio_clk_disable(struct dhd_bus *bus, bus_owner_t owner, int can_wait)
2197 {
2198 	int ret = BCME_ERROR;
2199 
2200 	BCM_REFERENCE(owner);
2201 	BCM_REFERENCE(can_wait);
2202 
2203 	if (bus->bt_use_count == 0) {
2204 		DHD_ERROR(("%s(): Clocks are already turned off \r\n",
2205 			__FUNCTION__));
2206 		return ret;
2207 	}
2208 
2209 	bus->bt_use_count--;
2210 
2211 	/*
2212 	 * When the SDIO Bus is shared between BT & WLAN, we turn Off the clock
2213 	 * once the last user has relinqushed the same. But there are two schemes
2214 	 * in that too. We consider WLAN as the  bus master (even if its not
2215 	 * active). Even when the WLAN is OFF the DHD Watchdog is active.
2216 	 * So this Bus Watchdog is the context whill put the Bus to sleep.
2217 	 * Refer dhd_bus_watchdog function
2218 	 */
2219 
2220 	ret = BCME_OK;
2221 	DHD_INFO(("%s():bt_use_count %d \r\n", __FUNCTION__,
2222 		bus->bt_use_count));
2223 	return ret;
2224 }
2225 
dhdsdio_reset_bt_use_count(struct dhd_bus * bus)2226 void dhdsdio_reset_bt_use_count(struct dhd_bus *bus)
2227 {
2228 	/* reset bt use count */
2229 	bus->bt_use_count = 0;
2230 }
2231 #endif /* BT_OVER_SDIO */
2232 
2233 #ifdef USE_DYNAMIC_F2_BLKSIZE
dhdsdio_func_blocksize(dhd_pub_t * dhd,int function_num,int block_size)2234 int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
2235 {
2236 	int func_blk_size = function_num;
2237 	int bcmerr = 0;
2238 	int result;
2239 
2240 	bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size,
2241 		sizeof(int), &result, sizeof(int), IOV_GET);
2242 
2243 	if (bcmerr != BCME_OK) {
2244 		DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num));
2245 		return BCME_ERROR;
2246 	}
2247 
2248 	if (result != block_size) {
2249 		DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n",
2250 			__FUNCTION__, function_num, result, block_size));
2251 		func_blk_size = function_num << 16 | block_size;
2252 		bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL,
2253 			0, &func_blk_size, sizeof(int32), IOV_SET);
2254 		if (bcmerr != BCME_OK) {
2255 			DHD_ERROR(("%s: Set F2 Block size error\n", __FUNCTION__));
2256 			return BCME_ERROR;
2257 		}
2258 	}
2259 
2260 	return BCME_OK;
2261 }
2262 #endif /* USE_DYNAMIC_F2_BLKSIZE */
2263 
2264 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) || defined(FORCE_WOWLAN)
2265 void
dhd_enable_oob_intr(struct dhd_bus * bus,bool enable)2266 dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
2267 {
2268 #if defined(BCMSPI_ANDROID)
2269 	bcmsdh_intr_enable(bus->sdh);
2270 #elif defined(HW_OOB) || defined(FORCE_WOWLAN)
2271 	bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
2272 #else
2273 	sdpcmd_regs_t *regs = bus->regs;
2274 	uint retries = 0;
2275 
2276 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
2277 	if (enable == TRUE) {
2278 
2279 		/* Tell device to start using OOB wakeup */
2280 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
2281 		if (retries > retry_limit)
2282 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
2283 
2284 	} else {
2285 		/* Send misc interrupt to indicate OOB not needed */
2286 		W_SDREG(0, &regs->tosbmailboxdata, retries);
2287 		if (retries <= retry_limit)
2288 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
2289 	}
2290 
2291 	/* Turn off our contribution to the HT clock request */
2292 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
2293 #endif /* !defined(HW_OOB) */
2294 }
2295 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
2296 
2297 int
dhd_bus_txdata(struct dhd_bus * bus,void * pkt)2298 dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
2299 {
2300 	int ret = BCME_ERROR;
2301 	osl_t *osh;
2302 	uint datalen, prec;
2303 
2304 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2305 
2306 	osh = bus->dhd->osh;
2307 	datalen = PKTLEN(osh, pkt);
2308 
2309 #ifdef SDTEST
2310 	/* Push the test header if doing loopback */
2311 	if (bus->ext_loop) {
2312 		uint8* data;
2313 		PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
2314 		data = PKTDATA(osh, pkt);
2315 		*data++ = SDPCM_TEST_ECHOREQ;
2316 		*data++ = (uint8)bus->loopid++;
2317 		*data++ = (datalen >> 0);
2318 		*data++ = (datalen >> 8);
2319 		datalen += SDPCM_TEST_HDRLEN;
2320 	}
2321 #else /* SDTEST */
2322 	BCM_REFERENCE(datalen);
2323 #endif /* SDTEST */
2324 
2325 	prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
2326 
2327 	/* move from dhdsdio_sendfromq(), try to orphan skb early */
2328 	if (bus->dhd->conf->orphan_move == 1)
2329 		PKTORPHAN(pkt, bus->dhd->conf->tsq);
2330 
2331 	/* Check for existing queue, current flow-control, pending event, or pending clock */
2332 	if (dhd_deferred_tx || bus->fcstate || pktq_n_pkts_tot(&bus->txq) || bus->dpc_sched ||
2333 	    (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
2334 	    (bus->clkstate != CLK_AVAIL)) {
2335 		bool deq_ret;
2336 		int pkq_len = 0;
2337 
2338 		DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
2339 			pktq_n_pkts_tot(&bus->txq)));
2340 #ifdef BCMINTERNAL
2341 		if (!bus->fcstate)
2342 			bus->tx_deferred++;
2343 #endif /* BCMINTERNAL */
2344 		bus->fcqueued++;
2345 
2346 		/* Priority based enq */
2347 		dhd_os_sdlock_txq(bus->dhd);
2348 		deq_ret = dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec);
2349 		dhd_os_sdunlock_txq(bus->dhd);
2350 
2351 		if (!deq_ret) {
2352 #ifdef PROP_TXSTATUS
2353 			if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) == 0)
2354 #endif /* PROP_TXSTATUS */
2355 			{
2356 #ifdef DHDTCPACK_SUPPRESS
2357 				if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
2358 					DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using\n",
2359 						__FUNCTION__, __LINE__));
2360 					dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
2361 				}
2362 #endif /* DHDTCPACK_SUPPRESS */
2363 				dhd_txcomplete(bus->dhd, pkt, FALSE);
2364 				PKTFREE(osh, pkt, TRUE);	/* XXX update counter */
2365 			}
2366 			ret = BCME_NORESOURCE;
2367 		} else
2368 			ret = BCME_OK;
2369 
2370 		/* XXX Possible race since check and action are not locked? */
2371 		if (dhd_doflow) {
2372 			dhd_os_sdlock_txq(bus->dhd);
2373 			pkq_len = pktq_n_pkts_tot(&bus->txq);
2374 			dhd_os_sdunlock_txq(bus->dhd);
2375 		}
2376 		if (dhd_doflow && pkq_len >= FCHI) {
2377 			bool wlfc_enabled = FALSE;
2378 #ifdef PROP_TXSTATUS
2379 			wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) !=
2380 				WLFC_UNSUPPORTED);
2381 #endif
2382 			if (!wlfc_enabled && dhd_doflow) {
2383 				dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
2384 			}
2385 		}
2386 
2387 #ifdef DHD_DEBUG
2388 		dhd_os_sdlock_txq(bus->dhd);
2389 		if (pktqprec_n_pkts(&bus->txq, prec) > qcount[prec])
2390 			qcount[prec] = pktqprec_n_pkts(&bus->txq, prec);
2391 		dhd_os_sdunlock_txq(bus->dhd);
2392 #endif
2393 
2394 		/* Schedule DPC if needed to send queued packet(s) */
2395 		/* XXX Also here, since other deferral conditions may no longer hold? */
2396 		if (dhd_deferred_tx && !bus->dpc_sched) {
2397 			if (bus->dhd->conf->deferred_tx_len) {
2398 				if(dhd_os_wd_timer_enabled(bus->dhd) == FALSE) {
2399 					bus->dpc_sched = TRUE;
2400 					dhd_sched_dpc(bus->dhd);
2401 				}
2402 				if(pktq_n_pkts_tot(&bus->txq) >= bus->dhd->conf->deferred_tx_len &&
2403 						dhd_os_wd_timer_enabled(bus->dhd) == FALSE) {
2404 					bus->dpc_sched = TRUE;
2405 					dhd_sched_dpc(bus->dhd);
2406 				}
2407 			} else {
2408 				bus->dpc_sched = TRUE;
2409 				dhd_sched_dpc(bus->dhd);
2410 			}
2411 		}
2412 	} else {
2413 		int chan = SDPCM_DATA_CHANNEL;
2414 
2415 #ifdef SDTEST
2416 		chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL);
2417 #endif
2418 		/* Lock: we're about to use shared data/code (and SDIO) */
2419 		dhd_os_sdlock(bus->dhd);
2420 
2421 		/* Otherwise, send it now */
2422 		BUS_WAKE(bus);
2423 		/* Make sure back plane ht clk is on, no pending allowed */
2424 		dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
2425 
2426 		ret = dhdsdio_txpkt(bus, chan, &pkt, 1, TRUE);
2427 
2428 		if (ret != BCME_OK)
2429 			bus->dhd->tx_errors++;
2430 		else
2431 			bus->dhd->dstats.tx_bytes += datalen;
2432 
2433 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
2434 				NO_OTHER_ACTIVE_BUS_USER(bus)) {
2435 			bus->activity = FALSE;
2436 			dhdsdio_bussleep(bus, TRUE);
2437 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
2438 		}
2439 
2440 		dhd_os_sdunlock(bus->dhd);
2441 	}
2442 
2443 	return ret;
2444 }
2445 
2446 /* align packet data pointer and packet length to n-byte boundary, process packet headers,
2447  * a new packet may be allocated if there is not enough head and/or tail from for padding.
2448  * the caller is responsible for updating the glom size in the head packet (when glom is
2449  * used)
2450  *
2451  * pad_pkt_len: returns the length of extra padding needed from the padding packet, this parameter
2452  * is taken in tx glom mode only
2453  *
2454  * new_pkt: out, pointer of the new packet allocated due to insufficient head room for alignment
2455  * padding, NULL if not needed, the caller is responsible for freeing the new packet
2456  *
2457  * return: positive value - length of the packet, including head and tail padding
2458  *		   negative value - errors
2459  */
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)2460 static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
2461 	int prev_chain_total_len, bool last_chained_pkt,
2462 	int *pad_pkt_len, void **new_pkt
2463 #if defined(BCMSDIOH_TXGLOM_EXT)
2464 	, int first_frame
2465 #endif
2466 )
2467 {
2468 	osl_t *osh;
2469 	uint8 *frame;
2470 	int pkt_len;
2471 	int modulo;
2472 	int head_padding;
2473 	int tail_padding = 0;
2474 	uint32 swheader;
2475 	uint32 swhdr_offset;
2476 	bool alloc_new_pkt = FALSE;
2477 	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
2478 #ifdef PKT_STATICS
2479 	uint16 len;
2480 #endif
2481 
2482 	*new_pkt = NULL;
2483 	osh = bus->dhd->osh;
2484 
2485 #ifdef DHDTCPACK_SUPPRESS
2486 	if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
2487 		DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
2488 			__FUNCTION__, __LINE__));
2489 		dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
2490 	}
2491 #endif /* DHDTCPACK_SUPPRESS */
2492 
2493 	/* Add space for the SDPCM hardware/software headers */
2494 	PKTPUSH(osh, pkt, sdpcm_hdrlen);
2495 	ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
2496 
2497 	frame = (uint8*)PKTDATA(osh, pkt);
2498 	pkt_len = (uint16)PKTLEN(osh, pkt);
2499 
2500 #ifdef PKT_STATICS
2501 	len = (uint16)PKTLEN(osh, pkt);
2502 	switch(chan) {
2503 		case SDPCM_CONTROL_CHANNEL:
2504 			bus->tx_statics.ctrl_count++;
2505 			bus->tx_statics.ctrl_size += len;
2506 			break;
2507 		case SDPCM_DATA_CHANNEL:
2508 			bus->tx_statics.data_count++;
2509 			bus->tx_statics.data_size += len;
2510 			break;
2511 		case SDPCM_GLOM_CHANNEL:
2512 			bus->tx_statics.glom_count++;
2513 			bus->tx_statics.glom_size += len;
2514 			break;
2515 		case SDPCM_EVENT_CHANNEL:
2516 			bus->tx_statics.event_count++;
2517 			bus->tx_statics.event_size += len;
2518 			break;
2519 		case SDPCM_TEST_CHANNEL:
2520 			bus->tx_statics.test_count++;
2521 			bus->tx_statics.test_size += len;
2522 			break;
2523 
2524 		default:
2525 			break;
2526 	}
2527 #endif /* PKT_STATICS */
2528 #ifdef DHD_DEBUG
2529 	if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets))
2530 		tx_packets[PKTPRIO(pkt)]++;
2531 #endif /* DHD_DEBUG */
2532 
2533 	/* align the data pointer, allocate a new packet if there is not enough space (new
2534 	 * packet data pointer will be aligned thus no padding will be needed)
2535 	 */
2536 	head_padding = (uintptr)frame % DHD_SDALIGN;
2537 	if (PKTHEADROOM(osh, pkt) < head_padding) {
2538 		head_padding = 0;
2539 		alloc_new_pkt = TRUE;
2540 	} else {
2541 		uint cur_chain_total_len;
2542 		int chain_tail_padding = 0;
2543 
2544 		/* All packets need to be aligned by DHD_SDALIGN */
2545 		modulo = (pkt_len + head_padding) % DHD_SDALIGN;
2546 		tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
2547 
2548 		/* Total pkt chain length needs to be aligned by block size,
2549 		 * unless it is a single pkt chain with total length less than one block size,
2550 		 * which we prefer sending by byte mode.
2551 		 *
2552 		 * Do the chain alignment here if
2553 		 * 1. This is the last pkt of the chain of multiple pkts or a single pkt.
2554 		 * 2-1. This chain is of multiple pkts, or
2555 		 * 2-2. This is a single pkt whose size is longer than one block size.
2556 		 */
2557 		cur_chain_total_len = prev_chain_total_len +
2558 			(head_padding + pkt_len + tail_padding);
2559 		if (last_chained_pkt && bus->blocksize != 0 &&
2560 			(cur_chain_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
2561 			modulo = cur_chain_total_len % bus->blocksize;
2562 			chain_tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
2563 		}
2564 
2565 #ifdef DHDENABLE_TAILPAD
2566 		if (PKTTAILROOM(osh, pkt) < tail_padding) {
2567 			/* We don't have tail room to align by DHD_SDALIGN */
2568 			alloc_new_pkt = TRUE;
2569 			bus->tx_tailpad_pktget++;
2570 		} else if (PKTTAILROOM(osh, pkt) < tail_padding + chain_tail_padding) {
2571 			/* We have tail room for tail_padding of this pkt itself, but not for
2572 			 * total pkt chain alignment by block size.
2573 			 * Use the padding packet to avoid memory copy if applicable,
2574 			 * otherwise, just allocate a new pkt.
2575 			 */
2576 			if (bus->pad_pkt) {
2577 				*pad_pkt_len = chain_tail_padding;
2578 				bus->tx_tailpad_chain++;
2579 			} else {
2580 				alloc_new_pkt = TRUE;
2581 				bus->tx_tailpad_pktget++;
2582 			}
2583 		} else
2584 		/* This last pkt's tailroom is sufficient to hold both tail_padding
2585 		 * of the pkt itself and chain_tail_padding of total pkt chain
2586 		 */
2587 #endif /* DHDENABLE_TAILPAD */
2588 		tail_padding += chain_tail_padding;
2589 	}
2590 
2591 	DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n",
2592 		__FUNCTION__, pkt_len, head_padding, tail_padding, *pad_pkt_len));
2593 
2594 	if (alloc_new_pkt) {
2595 		void *tmp_pkt;
2596 		int newpkt_size;
2597 		int cur_total_len;
2598 
2599 		ASSERT(*pad_pkt_len == 0);
2600 
2601 		DHD_INFO(("%s allocating new packet for padding\n", __FUNCTION__));
2602 
2603 		/* head pointer is aligned now, no padding needed */
2604 		head_padding = 0;
2605 
2606 		/* update the tail padding as it depends on the head padding, since a new packet is
2607 		 * allocated, the head padding is non longer needed and packet length is chagned
2608 		 */
2609 
2610 		cur_total_len = prev_chain_total_len + pkt_len;
2611 		if (last_chained_pkt && bus->blocksize != 0 &&
2612 			(cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
2613 			modulo = cur_total_len % bus->blocksize;
2614 			tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
2615 		} else {
2616 			modulo = pkt_len % DHD_SDALIGN;
2617 			tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
2618 		}
2619 
2620 		newpkt_size = PKTLEN(osh, pkt) + bus->blocksize + DHD_SDALIGN;
2621 		bus->dhd->tx_realloc++;
2622 		tmp_pkt = PKTGET(osh, newpkt_size, TRUE);
2623 		if (tmp_pkt == NULL) {
2624 			DHD_ERROR(("failed to alloc new %d byte packet\n", newpkt_size));
2625 			return BCME_NOMEM;
2626 		}
2627 		PKTALIGN(osh, tmp_pkt, PKTLEN(osh, pkt), DHD_SDALIGN);
2628 		bcopy(PKTDATA(osh, pkt), PKTDATA(osh, tmp_pkt), PKTLEN(osh, pkt));
2629 		*new_pkt = tmp_pkt;
2630 		pkt = tmp_pkt;
2631 	}
2632 
2633 	if (head_padding)
2634 		PKTPUSH(osh, pkt, head_padding);
2635 
2636 	frame = (uint8*)PKTDATA(osh, pkt);
2637 	bzero(frame, head_padding + sdpcm_hdrlen);
2638 	pkt_len = (uint16)PKTLEN(osh, pkt);
2639 
2640 	/* the header has the followming format
2641 	 * 4-byte HW frame tag: length, ~length (for glom this is the total length)
2642 	 *
2643 	 * 8-byte HW extesion flags (glom mode only) as the following:
2644 	 *			2-byte packet length, excluding HW tag and padding
2645 	 *			2-byte frame channel and frame flags (e.g. next frame following)
2646 	 *			2-byte header length
2647 	 *			2-byte tail padding size
2648 	 *
2649 	 * 8-byte SW frame tags as the following
2650 	 *			4-byte flags: host tx seq, channel, data offset
2651 	 *			4-byte flags: TBD
2652 	 */
2653 
2654 	swhdr_offset = SDPCM_FRAMETAG_LEN;
2655 
2656 	/* hardware frame tag:
2657 	 *
2658 	 * in tx-glom mode, dongle only checks the hardware frame tag in the first
2659 	 * packet and sees it as the total lenght of the glom (including tail padding),
2660 	 * for each packet in the glom, the packet length needs to be updated, (see
2661 	 * below PKTSETLEN)
2662 	 *
2663 	 * in non tx-glom mode, PKTLEN still need to include tail padding as to be
2664 	 * referred to in sdioh_request_buffer(). The tail length will be excluded in
2665 	 * dhdsdio_txpkt_postprocess().
2666 	 */
2667 #if defined(BCMSDIOH_TXGLOM_EXT)
2668 	if (bus->dhd->conf->txglom_bucket_size)
2669 		tail_padding = 0;
2670 #endif
2671 	*(uint16*)frame = (uint16)htol16(pkt_len);
2672 	*(((uint16*)frame) + 1) = (uint16)htol16(~pkt_len);
2673 	pkt_len += tail_padding;
2674 
2675 	/* hardware extesion flags */
2676 	if (bus->txglom_enable) {
2677 		uint32 hwheader1;
2678 		uint32 hwheader2;
2679 #ifdef BCMSDIOH_TXGLOM_EXT
2680 		uint32 act_len = pkt_len - tail_padding;
2681 		uint32 real_pad = 0;
2682 		if(bus->dhd->conf->txglom_ext && !last_chained_pkt) {
2683 			tail_padding = 0;
2684 			if(first_frame == 0) {
2685 				// first pkt, add pad to bucket size - recv offset
2686 				pkt_len = bus->dhd->conf->txglom_bucket_size - TXGLOM_RECV_OFFSET;
2687 			} else {
2688 				// add pad to bucket size
2689 				pkt_len = bus->dhd->conf->txglom_bucket_size;
2690 			}
2691 			swhdr_offset += SDPCM_HWEXT_LEN;
2692 			hwheader1 = (act_len - SDPCM_FRAMETAG_LEN) | (last_chained_pkt << 24);
2693 			hwheader2 = (pkt_len - act_len) << 16;
2694 			htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
2695 			htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
2696 			real_pad = pkt_len - act_len;
2697 
2698 			if (PKTTAILROOM(osh, pkt) < real_pad) {
2699 				DHD_INFO(("%s : insufficient tailroom %d for %d real_pad\n",
2700 					__func__, (int)PKTTAILROOM(osh, pkt), real_pad));
2701 				if (PKTPADTAILROOM(osh, pkt, real_pad)) {
2702 					DHD_ERROR(("CHK1: padding error size %d\n", real_pad));
2703 				} else
2704 					frame = (uint8 *)PKTDATA(osh, pkt);
2705 			}
2706 		} else
2707 #endif
2708 		{
2709 			swhdr_offset += SDPCM_HWEXT_LEN;
2710 			hwheader1 = (pkt_len - SDPCM_FRAMETAG_LEN - tail_padding) |
2711 				(last_chained_pkt << 24);
2712 			hwheader2 = (tail_padding) << 16;
2713 			htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
2714 			htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
2715 		}
2716 	}
2717 	PKTSETLEN((osh), (pkt), (pkt_len));
2718 
2719 	/* software frame tags */
2720 	swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
2721 		| (txseq % SDPCM_SEQUENCE_WRAP) |
2722 		(((head_padding + sdpcm_hdrlen) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
2723 	htol32_ua_store(swheader, frame + swhdr_offset);
2724 	htol32_ua_store(0, frame + swhdr_offset + sizeof(swheader));
2725 
2726 	return pkt_len;
2727 }
2728 
dhdsdio_txpkt_postprocess(dhd_bus_t * bus,void * pkt)2729 static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt)
2730 {
2731 	osl_t *osh;
2732 	uint8 *frame;
2733 	int data_offset;
2734 	int tail_padding;
2735 	int swhdr_offset = SDPCM_FRAMETAG_LEN + (bus->txglom_enable ? SDPCM_HWEXT_LEN : 0);
2736 
2737 	(void)osh;
2738 	osh = bus->dhd->osh;
2739 
2740 	/* restore pkt buffer pointer, but keeps the header pushed by dhd_prot_hdrpush */
2741 	frame = (uint8*)PKTDATA(osh, pkt);
2742 
2743 	DHD_INFO(("%s PKTLEN before postprocess %d\n",
2744 		__FUNCTION__, PKTLEN(osh, pkt)));
2745 
2746 	/* PKTLEN still includes tail_padding, so exclude it.
2747 	 * We shall have head_padding + original pkt_len for PKTLEN afterwards.
2748 	 */
2749 	if (bus->txglom_enable) {
2750 		/* txglom pkts have tail_padding length in HW ext header */
2751 		tail_padding = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16;
2752 		PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - tail_padding);
2753 		DHD_INFO((" txglom pkt: tail_padding %d PKTLEN %d\n",
2754 			tail_padding, PKTLEN(osh, pkt)));
2755 	} else {
2756 		/* non-txglom pkts have head_padding + original pkt length in HW frame tag.
2757 		 * We cannot refer to this field for txglom pkts as the first pkt of the chain will
2758 		 * have the field for the total length of the chain.
2759 		 */
2760 		PKTSETLEN(osh, pkt, *(uint16*)frame);
2761 		DHD_INFO((" non-txglom pkt: HW frame tag len %d after PKTLEN %d\n",
2762 			*(uint16*)frame, PKTLEN(osh, pkt)));
2763 	}
2764 
2765 	data_offset = ltoh32_ua(frame + swhdr_offset);
2766 	data_offset = (data_offset & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT;
2767 	/* Get rid of sdpcm header + head_padding */
2768 	PKTPULL(osh, pkt, data_offset);
2769 
2770 	DHD_INFO(("%s data_offset %d, PKTLEN %d\n",
2771 		__FUNCTION__, data_offset, PKTLEN(osh, pkt)));
2772 
2773 	return BCME_OK;
2774 }
2775 
dhdsdio_txpkt(dhd_bus_t * bus,uint chan,void ** pkts,int num_pkt,bool free_pkt)2776 static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt)
2777 {
2778 	int i;
2779 	int ret = 0;
2780 	osl_t *osh;
2781 	bcmsdh_info_t *sdh;
2782 	void *pkt = NULL;
2783 	void *pkt_chain;
2784 	int total_len = 0;
2785 	void *head_pkt = NULL;
2786 	void *prev_pkt = NULL;
2787 	int pad_pkt_len = 0;
2788 	int new_pkt_num = 0;
2789 	void *new_pkts[MAX_TX_PKTCHAIN_CNT];
2790 	bool wlfc_enabled = FALSE;
2791 
2792 	if (bus->dhd->dongle_reset)
2793 		return BCME_NOTREADY;
2794 
2795 	if (num_pkt <= 0)
2796 		return BCME_BADARG;
2797 
2798 	sdh = bus->sdh;
2799 	osh = bus->dhd->osh;
2800 	/* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */
2801 	new_pkts[0] = NULL;
2802 
2803 	for (i = 0; i < num_pkt; i++) {
2804 		int pkt_len;
2805 		bool last_pkt;
2806 		void *new_pkt = NULL;
2807 
2808 		pkt = pkts[i];
2809 		ASSERT(pkt);
2810 		last_pkt = (i == num_pkt - 1);
2811 		pkt_len = dhdsdio_txpkt_preprocess(bus, pkt, chan, bus->tx_seq + i,
2812 			total_len, last_pkt, &pad_pkt_len, &new_pkt
2813 #if defined(BCMSDIOH_TXGLOM_EXT)
2814 			, i
2815 #endif
2816 		);
2817 		if (pkt_len <= 0)
2818 			goto done;
2819 		if (new_pkt) {
2820 			pkt = new_pkt;
2821 			new_pkts[new_pkt_num++] = new_pkt;
2822 		}
2823 		total_len += pkt_len;
2824 
2825 		PKTSETNEXT(osh, pkt, NULL);
2826 		/* insert the packet into the list */
2827 		head_pkt ? PKTSETNEXT(osh, prev_pkt, pkt) : (head_pkt = pkt);
2828 		prev_pkt = pkt;
2829 
2830 	}
2831 
2832 	/* Update the HW frame tag (total length) in the first pkt of the glom */
2833 	if (bus->txglom_enable) {
2834 		uint8 *frame;
2835 
2836 		total_len += pad_pkt_len;
2837 		frame = (uint8*)PKTDATA(osh, head_pkt);
2838 		*(uint16*)frame = (uint16)htol16(total_len);
2839 		*(((uint16*)frame) + 1) = (uint16)htol16(~total_len);
2840 
2841 	}
2842 
2843 #ifdef DHDENABLE_TAILPAD
2844 	/* if a padding packet if needed, insert it to the end of the link list */
2845 	if (pad_pkt_len) {
2846 		PKTSETLEN(osh, bus->pad_pkt, pad_pkt_len);
2847 		PKTSETNEXT(osh, pkt, bus->pad_pkt);
2848 	}
2849 #endif /* DHDENABLE_TAILPAD */
2850 
2851 	/* dhd_bcmsdh_send_buf ignores the buffer pointer if he packet
2852 	 * parameter is not NULL, for non packet chian we pass NULL pkt pointer
2853 	 * so it will take the aligned length and buffer pointer.
2854 	 */
2855 	pkt_chain = PKTNEXT(osh, head_pkt) ? head_pkt : NULL;
2856 #ifdef TPUT_MONITOR
2857 	if ((bus->dhd->conf->data_drop_mode == TXPKT_DROP) && (total_len > 500))
2858 		ret = BCME_OK;
2859 	else
2860 #endif
2861 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
2862 		PKTDATA(osh, head_pkt), total_len, pkt_chain, NULL, NULL, TXRETRIES);
2863 	if (ret == BCME_OK)
2864 		bus->tx_seq = (bus->tx_seq + num_pkt) % SDPCM_SEQUENCE_WRAP;
2865 
2866 	/* if a padding packet was needed, remove it from the link list as it not a data pkt */
2867 	if (pad_pkt_len && pkt)
2868 		PKTSETNEXT(osh, pkt, NULL);
2869 
2870 done:
2871 	pkt = head_pkt;
2872 	while (pkt) {
2873 		void *pkt_next = PKTNEXT(osh, pkt);
2874 		PKTSETNEXT(osh, pkt, NULL);
2875 		dhdsdio_txpkt_postprocess(bus, pkt);
2876 		pkt = pkt_next;
2877 	}
2878 
2879 	/* new packets might be allocated due to insufficient room for padding, but we
2880 	 * still have to indicate the original packets to upper layer
2881 	 */
2882 	for (i = 0; i < num_pkt; i++) {
2883 		pkt = pkts[i];
2884 		wlfc_enabled = FALSE;
2885 #ifdef PROP_TXSTATUS
2886 		if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt))) {
2887 			wlfc_enabled = (dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0) !=
2888 				WLFC_UNSUPPORTED);
2889 		}
2890 #endif /* PROP_TXSTATUS */
2891 		if (!wlfc_enabled) {
2892 			PKTSETNEXT(osh, pkt, NULL);
2893 			dhd_txcomplete(bus->dhd, pkt, ret != 0);
2894 			if (free_pkt)
2895 				PKTFREE(osh, pkt, TRUE);
2896 		}
2897 	}
2898 
2899 	for (i = 0; i < new_pkt_num; i++)
2900 		PKTFREE(osh, new_pkts[i], TRUE);
2901 
2902 	return ret;
2903 }
2904 
2905 static uint
dhdsdio_sendfromq(dhd_bus_t * bus,uint maxframes)2906 dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
2907 {
2908 	uint cnt = 0;
2909 	uint8 tx_prec_map;
2910 	uint16 txpktqlen = 0;
2911 	uint32 intstatus = 0;
2912 	uint retries = 0;
2913 	osl_t *osh;
2914 	dhd_pub_t *dhd = bus->dhd;
2915 	sdpcmd_regs_t *regs = bus->regs;
2916 #if defined(DHD_LOSSLESS_ROAMING) || defined(DHD_PKTDUMP_TOFW)
2917 	uint8 *pktdata;
2918 	struct ether_header *eh;
2919 #ifdef BDC
2920 	struct bdc_header *bdc_header;
2921 	uint8 data_offset;
2922 #endif
2923 #endif /* DHD_LOSSLESS_ROAMING */
2924 
2925 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
2926 
2927 	if (!KSO_ENAB(bus)) {
2928 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
2929 		return BCME_NODEVICE;
2930 	}
2931 
2932 	osh = dhd->osh;
2933 	tx_prec_map = ~bus->flowcontrol;
2934 #ifdef DHD_LOSSLESS_ROAMING
2935 	tx_prec_map &= dhd->dequeue_prec_map;
2936 #endif /* DHD_LOSSLESS_ROAMING */
2937 	for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) {
2938 		int i;
2939 		int num_pkt = 1;
2940 		void *pkts[MAX_TX_PKTCHAIN_CNT];
2941 		int prec_out;
2942 		uint datalen = 0;
2943 
2944 		dhd_os_sdlock_txq(bus->dhd);
2945 		if (bus->txglom_enable) {
2946 			uint32 glomlimit = (uint32)bus->txglomsize;
2947 #if defined(BCMSDIOH_STD)
2948 			if (bus->blocksize == 64) {
2949 				glomlimit = MIN((uint32)bus->txglomsize, BLK_64_MAXTXGLOM);
2950 			}
2951 #endif /* BCMSDIOH_STD */
2952 			num_pkt = MIN((uint32)DATABUFCNT(bus), glomlimit);
2953 			num_pkt = MIN(num_pkt, ARRAYSIZE(pkts));
2954 		}
2955 		num_pkt = MIN(num_pkt, pktq_mlen(&bus->txq, tx_prec_map));
2956 		for (i = 0; i < num_pkt; i++) {
2957 			pkts[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
2958 			if (!pkts[i]) {
2959 				DHD_ERROR(("%s: pktq_mlen non-zero when no pkt\n",
2960 					__FUNCTION__));
2961 				ASSERT(0);
2962 				break;
2963 			}
2964 #if defined(DHD_LOSSLESS_ROAMING) || defined(DHD_PKTDUMP_TOFW)
2965 			pktdata = (uint8 *)PKTDATA(osh, pkts[i]);
2966 #ifdef BDC
2967 			/* Skip BDC header */
2968 			bdc_header = (struct bdc_header *)pktdata;
2969 			data_offset = bdc_header->dataOffset;
2970 			pktdata += BDC_HEADER_LEN + (data_offset << 2);
2971 #endif
2972 			eh = (struct ether_header *)pktdata;
2973 #ifdef DHD_LOSSLESS_ROAMING
2974 			if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
2975 				uint8 prio = (uint8)PKTPRIO(pkts[i]);
2976 
2977 				/* Restore to original priority for 802.1X packet */
2978 				if (prio == PRIO_8021D_NC) {
2979 					PKTSETPRIO(pkts[i], dhd->prio_8021x);
2980 #ifdef BDC
2981 					/* Restore to original priority in BDC header */
2982 					bdc_header->priority =
2983 						(dhd->prio_8021x & BDC_PRIORITY_MASK);
2984 #endif
2985 				}
2986 			}
2987 #endif /* DHD_LOSSLESS_ROAMING */
2988 #ifdef DHD_PKTDUMP_TOFW
2989 			dhd_dump_pkt(bus->dhd, BDC_GET_IF_IDX(bdc_header), pktdata,
2990 				(uint32)PKTLEN(bus->dhd->osh, pkts[i]), TRUE, NULL, NULL);
2991 #endif
2992 #endif /* DHD_LOSSLESS_ROAMING || DHD_8021X_DUMP */
2993 			if (!bus->dhd->conf->orphan_move)
2994 				PKTORPHAN(pkts[i], bus->dhd->conf->tsq);
2995 			datalen += PKTLEN(osh, pkts[i]);
2996 		}
2997 		dhd_os_sdunlock_txq(bus->dhd);
2998 
2999 		if (i == 0)
3000 			break;
3001 		if (dhdsdio_txpkt(bus, SDPCM_DATA_CHANNEL, pkts, i, TRUE) != BCME_OK)
3002 			dhd->tx_errors++;
3003 		else {
3004 			dhd->dstats.tx_bytes += datalen;
3005 			bus->txglomframes++;
3006 			bus->txglompkts += num_pkt;
3007 #ifdef PKT_STATICS
3008 			bus->tx_statics.glom_cnt_us[num_pkt-1] =
3009 				(bus->tx_statics.glom_cnt[num_pkt-1]*bus->tx_statics.glom_cnt_us[num_pkt-1]
3010 				+ bcmsdh_get_spend_time(bus->sdh))/(bus->tx_statics.glom_cnt[num_pkt-1] + 1);
3011 #endif
3012 		}
3013 		cnt += i;
3014 #ifdef PKT_STATICS
3015 		if (num_pkt) {
3016 			bus->tx_statics.glom_cnt[num_pkt-1]++;
3017 			if (num_pkt > bus->tx_statics.glom_max)
3018 				bus->tx_statics.glom_max = num_pkt;
3019 		}
3020 #endif
3021 
3022 		/* In poll mode, need to check for other events */
3023 		if (!bus->intr && cnt)
3024 		{
3025 			/* Check device status, signal pending interrupt */
3026 			R_SDREG(intstatus, &regs->intstatus, retries);
3027 			bus->f2txdata++;
3028 			if (bcmsdh_regfail(bus->sdh))
3029 				break;
3030 			if (intstatus & bus->hostintmask)
3031 				bus->ipend = TRUE;
3032 		}
3033 
3034 	}
3035 
3036 	if (dhd_doflow) {
3037 		dhd_os_sdlock_txq(bus->dhd);
3038 		txpktqlen = pktq_n_pkts_tot(&bus->txq);
3039 		dhd_os_sdunlock_txq(bus->dhd);
3040 	}
3041 
3042 	/* Do flow-control if needed */
3043 	if (dhd->up && (dhd->busstate == DHD_BUS_DATA) && (txpktqlen < FCLOW)) {
3044 		bool wlfc_enabled = FALSE;
3045 #ifdef PROP_TXSTATUS
3046 		wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED);
3047 #endif
3048 		if (!wlfc_enabled && dhd_doflow && dhd->txoff) {
3049 			dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
3050 		}
3051 	}
3052 
3053 	return cnt;
3054 }
3055 
3056 static void
dhdsdio_sendpendctl(dhd_bus_t * bus)3057 dhdsdio_sendpendctl(dhd_bus_t *bus)
3058 {
3059 	bcmsdh_info_t *sdh = bus->sdh;
3060 	int ret;
3061 	uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN;
3062 
3063 	if (bus->txglom_enable)
3064 		frame_seq += SDPCM_HWEXT_LEN;
3065 
3066 	if (*frame_seq != bus->tx_seq) {
3067 		DHD_INFO(("%s IOCTL frame seq lag detected!"
3068 			" frm_seq:%d != bus->tx_seq:%d, corrected\n",
3069 			__FUNCTION__, *frame_seq, bus->tx_seq));
3070 		*frame_seq = bus->tx_seq;
3071 	}
3072 
3073 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
3074 		(uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len,
3075 		NULL, NULL, NULL, 1);
3076 	if (ret == BCME_OK)
3077 		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
3078 
3079 	bus->ctrl_frame_stat = FALSE;
3080 	dhd_wait_event_wakeup(bus->dhd);
3081 }
3082 
3083 int
dhd_bus_txctl(struct dhd_bus * bus,uchar * msg,uint msglen)3084 dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
3085 {
3086 	static int err_nodevice = 0;
3087 	uint8 *frame;
3088 	uint16 len;
3089 	uint32 swheader;
3090 	uint8 doff = 0;
3091 	int ret = -1;
3092 	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
3093 
3094 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
3095 
3096 	if (bus->dhd->dongle_reset)
3097 		return -EIO;
3098 
3099 	/* Back the pointer to make a room for bus header */
3100 	frame = msg - sdpcm_hdrlen;
3101 	len = (msglen += sdpcm_hdrlen);
3102 
3103 	/* Add alignment padding (optional for ctl frames) */
3104 	if (dhd_alignctl) {
3105 		if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
3106 			frame -= doff;
3107 			len += doff;
3108 			msglen += doff;
3109 			bzero(frame, doff + sdpcm_hdrlen);
3110 		}
3111 		ASSERT(doff < DHD_SDALIGN);
3112 	}
3113 	doff += sdpcm_hdrlen;
3114 
3115 #ifndef BCMSPI
3116 	/* Round send length to next SDIO block */
3117 	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
3118 		uint16 pad = bus->blocksize - (len % bus->blocksize);
3119 		if ((pad <= bus->roundup) && (pad < bus->blocksize))
3120 			len += pad;
3121 	} else if (len % DHD_SDALIGN) {
3122 		len += DHD_SDALIGN - (len % DHD_SDALIGN);
3123 	}
3124 #endif /* BCMSPI */
3125 
3126 	/* Satisfy length-alignment requirements */
3127 	if (forcealign && (len & (ALIGNMENT - 1)))
3128 		len = ROUNDUP(len, ALIGNMENT);
3129 
3130 	ASSERT(ISALIGNED((uintptr)frame, 2));
3131 
3132 	/* Need to lock here to protect txseq and SDIO tx calls */
3133 	dhd_os_sdlock(bus->dhd);
3134 	if (bus->dhd->conf->txctl_tmo_fix > 0 && !TXCTLOK(bus)) {
3135 		bus->ctrl_wait = TRUE;
3136 		dhd_os_sdunlock(bus->dhd);
3137 		wait_event_interruptible_timeout(bus->ctrl_tx_wait, TXCTLOK(bus),
3138 			msecs_to_jiffies(bus->dhd->conf->txctl_tmo_fix));
3139 		dhd_os_sdlock(bus->dhd);
3140 		bus->ctrl_wait = FALSE;
3141 	}
3142 
3143 	BUS_WAKE(bus);
3144 
3145 	/* Make sure backplane clock is on */
3146 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
3147 
3148 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
3149 	*(uint16*)frame = htol16((uint16)msglen);
3150 	*(((uint16*)frame) + 1) = htol16(~msglen);
3151 
3152 	if (bus->txglom_enable) {
3153 		uint32 hwheader1, hwheader2;
3154 		/* Software tag: channel, sequence number, data offset */
3155 		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
3156 				| bus->tx_seq
3157 				| ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
3158 		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN);
3159 		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN
3160 			+ SDPCM_HWEXT_LEN + sizeof(swheader));
3161 
3162 		hwheader1 = (msglen - SDPCM_FRAMETAG_LEN) | (1 << 24);
3163 		hwheader2 = (len - (msglen)) << 16;
3164 		htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
3165 		htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
3166 
3167 		*(uint16*)frame = htol16(len);
3168 		*(((uint16*)frame) + 1) = htol16(~(len));
3169 	} else {
3170 		/* Software tag: channel, sequence number, data offset */
3171 		swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
3172 		        | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
3173 		htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
3174 		htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
3175 	}
3176 
3177 	if (!TXCTLOK(bus))
3178 	{
3179 		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
3180 			__FUNCTION__, bus->tx_max, bus->tx_seq));
3181 		bus->ctrl_frame_stat = TRUE;
3182 		/* Send from dpc */
3183 		bus->ctrl_frame_buf = frame;
3184 		bus->ctrl_frame_len = len;
3185 
3186 #if defined(NDIS)
3187 		dhd_os_sdunlock(bus->dhd);
3188 		dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
3189 		dhd_os_sdlock(bus->dhd);
3190 #else
3191 		if (!bus->dpc_sched) {
3192 			bus->dpc_sched = TRUE;
3193 			dhd_sched_dpc(bus->dhd);
3194 		}
3195 		if (bus->ctrl_frame_stat) {
3196 			dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
3197 		}
3198 #endif /* NDIS */
3199 
3200 		if (bus->ctrl_frame_stat == FALSE) {
3201 			DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
3202 			ret = 0;
3203 		} else {
3204 			bus->dhd->txcnt_timeout++;
3205 			if (!bus->dhd->hang_was_sent) {
3206 #ifdef CUSTOMER_HW4_DEBUG
3207 				/* XXX Add Debug code for find root cause from CSP:565333 */
3208 				uint32 status, retry = 0;
3209 				R_SDREG(status, &bus->regs->intstatus, retry);
3210 				DHD_TRACE_HW4(("%s: txcnt_timeout, INT status=0x%08X\n",
3211 					__FUNCTION__, status));
3212 				DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n",
3213 					__FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate));
3214 #endif /* CUSTOMER_HW4_DEBUG */
3215 				DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
3216 					__FUNCTION__, bus->dhd->txcnt_timeout));
3217 #ifdef BCMSDIO_RXLIM_POST
3218 				DHD_ERROR(("%s: rxlim_en=%d, rxlim enable=%d, rxlim_addr=%d\n",
3219 					__FUNCTION__,
3220 					bus->dhd->conf->rxlim_en, bus->rxlim_en, bus->rxlim_addr));
3221 #endif /* BCMSDIO_RXLIM_POST */
3222 			}
3223 #ifdef DHD_FW_COREDUMP
3224 			/* Collect socram dump */
3225 			if ((bus->dhd->memdump_enabled) &&
3226 				(bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT)) {
3227 				/* collect core dump */
3228 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_TX;
3229 				dhd_os_sdunlock(bus->dhd);
3230 				dhd_bus_mem_dump(bus->dhd);
3231 				dhd_os_sdlock(bus->dhd);
3232 			}
3233 #endif /* DHD_FW_COREDUMP */
3234 			ret = -1;
3235 			bus->ctrl_frame_stat = FALSE;
3236 			goto done;
3237 		}
3238 	}
3239 
3240 	bus->dhd->txcnt_timeout = 0;
3241 	bus->ctrl_frame_stat = TRUE;
3242 
3243 	if (ret == -1) {
3244 #ifdef DHD_DEBUG
3245 		if (DHD_BYTES_ON() && DHD_CTL_ON()) {
3246 			prhex("Tx Frame", frame, len);
3247 		} else if (DHD_HDRS_ON()) {
3248 			prhex("TxHdr", frame, MIN(len, 16));
3249 		}
3250 #endif
3251 #ifdef PKT_STATICS
3252 		bus->tx_statics.ctrl_count++;
3253 		bus->tx_statics.ctrl_size += len;
3254 #endif
3255 		ret = dhd_bcmsdh_send_buffer(bus, frame, len);
3256 	}
3257 	bus->ctrl_frame_stat = FALSE;
3258 
3259 done:
3260 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
3261 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
3262 		bus->activity = FALSE;
3263 		dhdsdio_bussleep(bus, TRUE);
3264 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
3265 	}
3266 
3267 	dhd_os_sdunlock(bus->dhd);
3268 
3269 	/* XXX Need to validate return code (ranges) */
3270 	if (ret)
3271 		bus->dhd->tx_ctlerrs++;
3272 	else
3273 		bus->dhd->tx_ctlpkts++;
3274 
3275 	if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT) {
3276 #ifdef DHD_PM_CONTROL_FROM_FILE
3277 		if (g_pm_control == TRUE) {
3278 			return -BCME_ERROR;
3279 		} else {
3280 		return -ETIMEDOUT;
3281 		}
3282 #else
3283 		return -ETIMEDOUT;
3284 #endif /* DHD_PM_CONTROL_FROM_FILE */
3285 	}
3286 	if (ret == BCME_NODEVICE)
3287 		err_nodevice++;
3288 	else
3289 		err_nodevice = 0;
3290 
3291 	return ret ? err_nodevice >= ERROR_BCME_NODEVICE_MAX ? -ETIMEDOUT : -EIO : 0;
3292 }
3293 
3294 int
dhd_bus_rxctl(struct dhd_bus * bus,uchar * msg,uint msglen)3295 dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
3296 {
3297 	int timeleft;
3298 	uint rxlen = 0;
3299 	static uint cnt = 0;
3300 	uint max_rxcnt;
3301 
3302 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
3303 
3304 	if (bus->dhd->dongle_reset)
3305 		return -EIO;
3306 
3307 	/* Wait until control frame is available */
3308 	timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen);
3309 
3310 	dhd_os_sdlock(bus->dhd);
3311 	rxlen = bus->rxlen;
3312 	bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
3313 	bus->rxlen = 0;
3314 	dhd_os_sdunlock(bus->dhd);
3315 
3316 	if (bus->dhd->conf->ctrl_resched > 0 && !rxlen && timeleft == 0) {
3317 		cnt++;
3318 		if (cnt <= bus->dhd->conf->ctrl_resched) {
3319 			uint32 status, retry = 0;
3320 			R_SDREG(status, &bus->regs->intstatus, retry);
3321 			if ((status & I_HMB_HOST_INT) || PKT_AVAILABLE(bus, status)) {
3322 				DHD_ERROR(("%s: reschedule dhd_dpc, cnt=%d, status=0x%x\n",
3323 					__FUNCTION__, cnt, status));
3324 				bus->ipend = TRUE;
3325 				bus->dpc_sched = TRUE;
3326 				dhd_sched_dpc(bus->dhd);
3327 
3328 				/* Wait until control frame is available */
3329 				timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen);
3330 
3331 				dhd_os_sdlock(bus->dhd);
3332 				rxlen = bus->rxlen;
3333 				bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
3334 				bus->rxlen = 0;
3335 				dhd_os_sdunlock(bus->dhd);
3336 			}
3337 		}
3338 	} else {
3339 		cnt = 0;
3340 	}
3341 
3342 	if (rxlen) {
3343 		DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
3344 			__FUNCTION__, rxlen, msglen));
3345 	} else {
3346 		if (timeleft == 0) {
3347 #ifdef DHD_DEBUG
3348 			uint32 status, retry = 0;
3349 			R_SDREG(status, &bus->regs->intstatus, retry);
3350 			DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n",
3351 				__FUNCTION__, status));
3352 #else
3353 			DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
3354 #endif /* DHD_DEBUG */
3355 			if (!bus->dhd->dongle_trap_occured) {
3356 #ifdef DHD_FW_COREDUMP
3357 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT;
3358 #endif /* DHD_FW_COREDUMP */
3359 				dhd_os_sdlock(bus->dhd);
3360 				dhdsdio_checkdied(bus, NULL, 0);
3361 				dhd_os_sdunlock(bus->dhd);
3362 			}
3363 		} else {
3364 			DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
3365 			if (!bus->dhd->dongle_trap_occured) {
3366 #ifdef DHD_FW_COREDUMP
3367 				bus->dhd->memdump_type = DUMP_TYPE_RESUMED_UNKNOWN;
3368 #endif /* DHD_FW_COREDUMP */
3369 				dhd_os_sdlock(bus->dhd);
3370 				dhdsdio_checkdied(bus, NULL, 0);
3371 				dhd_os_sdunlock(bus->dhd);
3372 			}
3373 		}
3374 #ifdef DHD_FW_COREDUMP
3375 		/* Dump the ram image */
3376 		if (bus->dhd->memdump_enabled && !bus->dhd->dongle_trap_occured)
3377 			dhdsdio_mem_dump(bus);
3378 #endif /* DHD_FW_COREDUMP */
3379 	}
3380 	if (timeleft == 0) {
3381 		if (rxlen == 0)
3382 			bus->dhd->rxcnt_timeout++;
3383 		DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__,
3384 			bus->dhd->rxcnt_timeout, rxlen));
3385 #ifdef DHD_FW_COREDUMP
3386 		/* collect socram dump */
3387 		if (bus->dhd->memdump_enabled) {
3388 			bus->dhd->memdump_type = DUMP_TYPE_RESUMED_ON_TIMEOUT_RX;
3389 			dhd_bus_mem_dump(bus->dhd);
3390 		}
3391 #endif /* DHD_FW_COREDUMP */
3392 	} else {
3393 		bus->dhd->rxcnt_timeout = 0;
3394 	}
3395 
3396 	if (rxlen)
3397 		bus->dhd->rx_ctlpkts++;
3398 	else
3399 		bus->dhd->rx_ctlerrs++;
3400 
3401 	if (bus->dhd->conf->rxcnt_timeout)
3402 		max_rxcnt = bus->dhd->conf->rxcnt_timeout;
3403 	else
3404 		max_rxcnt = MAX_CNTL_RX_TIMEOUT;
3405 	if (bus->dhd->rxcnt_timeout >= max_rxcnt) {
3406 #ifdef DHD_PM_CONTROL_FROM_FILE
3407 		if (g_pm_control == TRUE) {
3408 			return -BCME_ERROR;
3409 		} else {
3410 			return -ETIMEDOUT;
3411 		}
3412 #else
3413 		return -ETIMEDOUT;
3414 #endif /* DHD_PM_CONTROL_FROM_FILE */
3415 	}
3416 	if (bus->dhd->dongle_trap_occured)
3417 		return -EREMOTEIO;
3418 
3419 	return rxlen ? (int)rxlen : -EIO; /* XXX Returns EIO error  */
3420 }
3421 
3422 /* IOVar table */
3423 enum {
3424 	IOV_INTR = 1,
3425 	IOV_POLLRATE,
3426 	IOV_SDREG,
3427 	IOV_SBREG,
3428 	IOV_SDCIS,
3429 #ifdef DHD_BUS_MEM_ACCESS
3430 	IOV_MEMBYTES,
3431 #endif /* DHD_BUS_MEM_ACCESS */
3432 	IOV_RAMSIZE,
3433 	IOV_RAMSTART,
3434 #ifdef DHD_DEBUG
3435 	IOV_CHECKDIED,
3436 	IOV_SERIALCONS,
3437 #endif /* DHD_DEBUG */
3438 	IOV_SET_DOWNLOAD_STATE,
3439 	IOV_SOCRAM_STATE,
3440 	IOV_FORCEEVEN,
3441 	IOV_SDIOD_DRIVE,
3442 	IOV_READAHEAD,
3443 	IOV_SDRXCHAIN,
3444 	IOV_ALIGNCTL,
3445 	IOV_SDALIGN,
3446 	IOV_DEVRESET,
3447 	IOV_CPU,
3448 #if defined(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL)
3449 	IOV_WATERMARK,
3450 	IOV_MESBUSYCTRL,
3451 #endif /* USE_SDIOFIFO_IOVAR */
3452 #ifdef BCMINTERNAL
3453 	IOV_SDRESET,
3454 	IOV_SDABORT,
3455 	IOV_FIRSTREAD,
3456 	IOV_TSTOPH,
3457 	IOV_RETRYDATA,
3458 	IOV_CHECKFIFO,
3459 	IOV_DOFLOW,
3460 	IOV_SDF2,
3461 	IOV_CLOCKPOLL,
3462 	IOV_MAXRAMSIZE,
3463 	IOV_SIALL,
3464 #endif /* BCMINTERNAL */
3465 #ifdef SDTEST
3466 	IOV_PKTGEN,
3467 	IOV_EXTLOOP,
3468 #endif /* SDTEST */
3469 	IOV_SPROM,
3470 	IOV_TXBOUND,
3471 	IOV_RXBOUND,
3472 	IOV_TXMINMAX,
3473 	IOV_IDLETIME,
3474 	IOV_IDLECLOCK,
3475 	IOV_SD1IDLE,
3476 	IOV_SLEEP,
3477 	IOV_DONGLEISOLATION,
3478 	IOV_KSO,
3479 	IOV_DEVSLEEP,
3480 	IOV_DEVCAP,
3481 	IOV_VARS,
3482 #ifdef SOFTAP
3483 	IOV_FWPATH,
3484 #endif
3485 	IOV_TXGLOMSIZE,
3486 	IOV_TXGLOMMODE,
3487 	IOV_HANGREPORT,
3488 	IOV_TXINRX_THRES,
3489 	IOV_SDIO_SUSPEND
3490 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
3491 	IOV_GDB_SERVER,  /**< starts gdb server on given interface */
3492 #endif /* DEBUGGER || DHD_DSCOPE */
3493 };
3494 
3495 const bcm_iovar_t dhdsdio_iovars[] = {
3496 	{"intr",	IOV_INTR,	0, 0,	IOVT_BOOL,	0 },
3497 	{"sleep",	IOV_SLEEP,	0, 0,	IOVT_BOOL,	0 },
3498 	{"pollrate",	IOV_POLLRATE,	0, 0,	IOVT_UINT32,	0 },
3499 	{"idletime",	IOV_IDLETIME,	0, 0,	IOVT_INT32,	0 },
3500 	{"idleclock",	IOV_IDLECLOCK,	0, 0,	IOVT_INT32,	0 },
3501 	{"sd1idle",	IOV_SD1IDLE,	0, 0,	IOVT_BOOL,	0 },
3502 #ifdef DHD_BUS_MEM_ACCESS
3503 	{"membytes",	IOV_MEMBYTES,	0, 0,	IOVT_BUFFER,	2 * sizeof(int) },
3504 #endif /* DHD_BUS_MEM_ACCESS */
3505 	{"ramsize",	IOV_RAMSIZE,	0, 0,	IOVT_UINT32,	0 },
3506 	{"ramstart",	IOV_RAMSTART,	0, 0,	IOVT_UINT32,	0 },
3507 	{"dwnldstate",	IOV_SET_DOWNLOAD_STATE,	0, 0,	IOVT_BOOL,	0 },
3508 	{"socram_state",	IOV_SOCRAM_STATE,	0, 0,	IOVT_BOOL,	0 },
3509 	{"vars",	IOV_VARS,	0, 0,	IOVT_BUFFER,	0 },
3510 	{"sdiod_drive",	IOV_SDIOD_DRIVE, 0, 0,	IOVT_UINT32,	0 },
3511 	{"readahead",	IOV_READAHEAD,	0, 0,	IOVT_BOOL,	0 },
3512 	{"sdrxchain",	IOV_SDRXCHAIN,	0, 0,	IOVT_BOOL,	0 },
3513 	{"alignctl",	IOV_ALIGNCTL,	0, 0,	IOVT_BOOL,	0 },
3514 	{"sdalign",	IOV_SDALIGN,	0, 0,	IOVT_BOOL,	0 },
3515 	{"devreset",	IOV_DEVRESET,	0, 0,	IOVT_BOOL,	0 },
3516 #ifdef DHD_DEBUG
3517 	{"sdreg",	IOV_SDREG,	0, 0,	IOVT_BUFFER,	sizeof(sdreg_t) },
3518 	{"sbreg",	IOV_SBREG,	0, 0,	IOVT_BUFFER,	sizeof(sdreg_t) },
3519 	{"sd_cis",	IOV_SDCIS,	0, 0,	IOVT_BUFFER,	DHD_IOCTL_MAXLEN },
3520 	{"forcealign",	IOV_FORCEEVEN,	0, 0,	IOVT_BOOL,	0 },
3521 	{"txbound",	IOV_TXBOUND,	0, 0,	IOVT_UINT32,	0 },
3522 	{"rxbound",	IOV_RXBOUND,	0, 0,	IOVT_UINT32,	0 },
3523 	{"txminmax",	IOV_TXMINMAX,	0, 0,	IOVT_UINT32,	0 },
3524 	{"cpu",		IOV_CPU,	0, 0,	IOVT_BOOL,	0 },
3525 #ifdef DHD_DEBUG
3526 	{"checkdied",	IOV_CHECKDIED,	0, 0,	IOVT_BUFFER,	0 },
3527 	{"serial",	IOV_SERIALCONS,	0, 0,	IOVT_UINT32,	0 },
3528 #endif /* DHD_DEBUG  */
3529 #ifdef BCMINTERNAL
3530 	{"siregall",	IOV_SIALL,	0, 0,	IOVT_UINT32,	0 },
3531 #endif /* BCMINTERNAL */
3532 #endif /* DHD_DEBUG */
3533 #if defined(BCMINTERNAL) || defined(DHD_SPROM)
3534 	{"sprom",	IOV_SPROM,	0, 0,	IOVT_BUFFER,	2 * sizeof(int) },
3535 #endif /* BCMINTERNAL || DHD_SPROM */
3536 #ifdef SDTEST
3537 	{"extloop",	IOV_EXTLOOP,	0, 0,	IOVT_BOOL,	0 },
3538 	{"pktgen",	IOV_PKTGEN,	0, 0,	IOVT_BUFFER,	sizeof(dhd_pktgen_t) },
3539 #endif /* SDTEST */
3540 #if defined(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL)
3541 	{"watermark",	IOV_WATERMARK,	0, 0,	IOVT_UINT32,	0 },
3542 	{"mesbusyctrl",	IOV_MESBUSYCTRL,	0, 0,	IOVT_UINT32,	0 },
3543 #endif /* USE_SDIOFIFO_IOVAR */
3544 #ifdef BCMINTERNAL
3545 	{"firstread",	IOV_FIRSTREAD,	0, 0,	IOVT_UINT32,	0 }, /* INTERNAL */
3546 	{"tstoph",	IOV_TSTOPH,	0, 0,	IOVT_BOOL,	0 },
3547 	{"retrydata",	IOV_RETRYDATA,	0, 0,	IOVT_BOOL,	0 },
3548 	{"checkfifo",	IOV_CHECKFIFO,	0, 0,	IOVT_BOOL,	0 },
3549 	{"sdf2",	IOV_SDF2,	0, 0,	IOVT_UINT32,	0 },
3550 	{"sdreset",	IOV_SDRESET,	0, 0,	IOVT_VOID,	0 },
3551 	{"sdabort",	IOV_SDABORT,	0, 0,	IOVT_UINT32,	0 },
3552 	{"doflow",	IOV_DOFLOW,	0, 0,	IOVT_BOOL,	0 },
3553 	{"clockpoll",	IOV_CLOCKPOLL,	0, 0,	IOVT_BOOL,	0 },
3554 	{"maxsocram",	IOV_MAXRAMSIZE,	0, 0,	IOVT_UINT32,	0 },
3555 #ifdef DHD_DEBUG
3556 	{"serial",	IOV_SERIALCONS,	0, 0,	IOVT_UINT32,	0 },
3557 #endif /* DHD_DEBUG */
3558 #endif /* BCMINTERNAL */
3559 	{"devcap", IOV_DEVCAP,	0, 0,	IOVT_UINT32,	0 },
3560 	{"dngl_isolation", IOV_DONGLEISOLATION,	0, 0,	IOVT_UINT32,	0 },
3561 	{"kso",	IOV_KSO,	0, 0,	IOVT_UINT32,	0 },
3562 	{"devsleep", IOV_DEVSLEEP,	0, 0,	IOVT_UINT32,	0 },
3563 #ifdef SOFTAP
3564 	{"fwpath", IOV_FWPATH, 0, 0, IOVT_BUFFER, 0 },
3565 #endif
3566 	{"txglomsize", IOV_TXGLOMSIZE, 0, 0, IOVT_UINT32, 0 },
3567 	{"fw_hang_report", IOV_HANGREPORT, 0, 0, IOVT_BOOL, 0 },
3568 	{"txinrx_thres", IOV_TXINRX_THRES, 0, 0, IOVT_INT32, 0 },
3569 	{"sdio_suspend", IOV_SDIO_SUSPEND, 0, 0, IOVT_UINT32, 0 },
3570 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
3571 	{"gdb_server", IOV_GDB_SERVER,    0, 0,      IOVT_UINT32,    0 },
3572 #endif /* DEBUGGER || DHD_DSCOPE */
3573 	{NULL, 0, 0, 0, 0, 0 }
3574 };
3575 
3576 static void
dhd_dump_pct(struct bcmstrbuf * strbuf,char * desc,uint num,uint div)3577 dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
3578 {
3579 	uint q1, q2;
3580 
3581 	if (!div) {
3582 		bcm_bprintf(strbuf, "%s N/A", desc);
3583 	} else {
3584 		q1 = num / div;
3585 		q2 = (100 * (num - (q1 * div))) / div;
3586 		bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
3587 	}
3588 }
3589 
3590 void
dhd_bus_dump(dhd_pub_t * dhdp,struct bcmstrbuf * strbuf)3591 dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
3592 {
3593 	dhd_bus_t *bus = dhdp->bus;
3594 #if defined(DHD_WAKE_STATUS) && defined(DHD_WAKE_EVENT_STATUS)
3595 	int i;
3596 #endif
3597 
3598 	bcm_bprintf(strbuf, "Bus SDIO structure:\n");
3599 	bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
3600 	            bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
3601 	bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n",
3602 	            bus->fcstate, pktq_n_pkts_tot(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
3603 	            bus->rxlen, bus->rx_seq);
3604 	bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
3605 	            bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
3606 
3607 #ifdef DHD_WAKE_STATUS
3608 	bcm_bprintf(strbuf, "wake %u rxwake %u readctrlwake %u\n",
3609 		bcmsdh_get_total_wake(bus->sdh), bus->wake_counts.rxwake,
3610 		bus->wake_counts.rcwake);
3611 #ifdef DHD_WAKE_RX_STATUS
3612 	bcm_bprintf(strbuf, " unicast %u multicast %u broadcast %u arp %u\n",
3613 		bus->wake_counts.rx_ucast, bus->wake_counts.rx_mcast,
3614 		bus->wake_counts.rx_bcast, bus->wake_counts.rx_arp);
3615 	bcm_bprintf(strbuf, " multi4 %u multi6 %u icmp6 %u multiother %u\n",
3616 		bus->wake_counts.rx_multi_ipv4, bus->wake_counts.rx_multi_ipv6,
3617 		bus->wake_counts.rx_icmpv6, bus->wake_counts.rx_multi_other);
3618 	bcm_bprintf(strbuf, " icmp6_ra %u, icmp6_na %u, icmp6_ns %u\n",
3619 		bus->wake_counts.rx_icmpv6_ra, bus->wake_counts.rx_icmpv6_na,
3620 		bus->wake_counts.rx_icmpv6_ns);
3621 #endif /* DHD_WAKE_RX_STATUS */
3622 #ifdef DHD_WAKE_EVENT_STATUS
3623 	for (i = 0; i < WLC_E_LAST; i++)
3624 		if (bus->wake_counts.rc_event[i] != 0)
3625 			bcm_bprintf(strbuf, " %s = %u\n", bcmevent_get_name(i),
3626 				bus->wake_counts.rc_event[i]);
3627 	bcm_bprintf(strbuf, "\n");
3628 #endif /* DHD_WAKE_EVENT_STATUS */
3629 #endif /* DHD_WAKE_STATUS */
3630 
3631 	bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
3632 	            bus->pollrate, bus->pollcnt, bus->regfails);
3633 
3634 	bcm_bprintf(strbuf, "\nAdditional counters:\n");
3635 #ifdef DHDENABLE_TAILPAD
3636 	bcm_bprintf(strbuf, "tx_tailpad_chain %u tx_tailpad_pktget %u\n",
3637 	            bus->tx_tailpad_chain, bus->tx_tailpad_pktget);
3638 #endif /* DHDENABLE_TAILPAD */
3639 	bcm_bprintf(strbuf, "tx_sderrs %u fcqueued %u rxrtx %u rx_toolong %u rxc_errors %u\n",
3640 	            bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
3641 	            bus->rxc_errors);
3642 	bcm_bprintf(strbuf, "rx_hdrfail %u badhdr %u badseq %u\n",
3643 	            bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
3644 	bcm_bprintf(strbuf, "fc_rcvd %u, fc_xoff %u, fc_xon %u\n",
3645 	            bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
3646 	bcm_bprintf(strbuf, "rxglomfail %u, rxglomframes %u, rxglompkts %u\n",
3647 	            bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
3648 	bcm_bprintf(strbuf, "f2rx (hdrs/data) %u (%u/%u), f2tx %u f1regs %u\n",
3649 	            (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
3650 	            bus->f2txdata, bus->f1regdata);
3651 	{
3652 		dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
3653 		             (bus->f2rxhdrs + bus->f2rxdata));
3654 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
3655 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
3656 		             (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
3657 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
3658 		bcm_bprintf(strbuf, "\n");
3659 
3660 		dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
3661 		             bus->dhd->rx_packets);
3662 		dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
3663 		bcm_bprintf(strbuf, "\n");
3664 
3665 		dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
3666 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
3667 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
3668 		             (bus->f2txdata + bus->f1regdata));
3669 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
3670 		bcm_bprintf(strbuf, "\n");
3671 
3672 		dhd_dump_pct(strbuf, "Total: pkts/f2rw",
3673 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
3674 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
3675 		dhd_dump_pct(strbuf, ", pkts/f1sd",
3676 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
3677 		dhd_dump_pct(strbuf, ", pkts/sd",
3678 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
3679 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
3680 		dhd_dump_pct(strbuf, ", pkts/int",
3681 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
3682 		bcm_bprintf(strbuf, "\n\n");
3683 	}
3684 
3685 #ifdef SDTEST
3686 	/* XXX Add new stats, include pktq len */
3687 	if (bus->pktgen_count) {
3688 		bcm_bprintf(strbuf, "pktgen config and count:\n");
3689 		bcm_bprintf(strbuf, "freq %u count %u print %u total %u min %u len %u\n",
3690 		            bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
3691 		            bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
3692 		bcm_bprintf(strbuf, "send attempts %u rcvd %u fail %u\n",
3693 		            bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
3694 	}
3695 #endif /* SDTEST */
3696 #ifdef DHD_DEBUG
3697 	bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
3698 	            bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
3699 	bcm_bprintf(strbuf, "blocksize %u roundup %u\n", bus->blocksize, bus->roundup);
3700 #endif /* DHD_DEBUG */
3701 	bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
3702 	            bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
3703 #ifdef BCMINTERNAL
3704 	bcm_bprintf(strbuf, "tx_deferred %d, fc 0x%x\n", bus->tx_deferred, bus->flowcontrol);
3705 #ifdef DHD_DEBUG
3706 	{
3707 		int i;
3708 		bcm_bprintf(strbuf, "qcount: ");
3709 		for (i = 0; i < 8; i++)
3710 			bcm_bprintf(strbuf, " %d , ", qcount[i]);
3711 		bcm_bprintf(strbuf, "\n");
3712 		bcm_bprintf(strbuf, "tx_packets: ");
3713 		for (i = 0; i < 8; i++)
3714 			bcm_bprintf(strbuf, " %d , ", tx_packets[i]);
3715 		bcm_bprintf(strbuf, "\n");
3716 	}
3717 #endif /* DHD_DEBUG */
3718 #endif /* BCMINTERNAL */
3719 	dhd_dump_pct(strbuf, "Tx: glom pct", (100 * bus->txglompkts), bus->dhd->tx_packets);
3720 	dhd_dump_pct(strbuf, ", pkts/glom", bus->txglompkts, bus->txglomframes);
3721 	bcm_bprintf(strbuf, "\n");
3722 	bcm_bprintf(strbuf, "txglomframes %u, txglompkts %u\n", bus->txglomframes, bus->txglompkts);
3723 	bcm_bprintf(strbuf, "\n");
3724 }
3725 
3726 void
dhd_bus_clearcounts(dhd_pub_t * dhdp)3727 dhd_bus_clearcounts(dhd_pub_t *dhdp)
3728 {
3729 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
3730 
3731 	bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
3732 	bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
3733 	bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
3734 #ifdef DHDENABLE_TAILPAD
3735 	bus->tx_tailpad_chain = bus->tx_tailpad_pktget = 0;
3736 #endif /* DHDENABLE_TAILPAD */
3737 	bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
3738 	bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
3739 	bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
3740 #ifdef BCMINTERNAL
3741 	bus->tx_deferred = bus->flowcontrol = 0;
3742 #endif
3743 	bus->txglomframes = bus->txglompkts = 0;
3744 }
3745 
3746 #ifdef SDTEST
3747 static int
dhdsdio_pktgen_get(dhd_bus_t * bus,uint8 * arg)3748 dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
3749 {
3750 	dhd_pktgen_t pktgen;
3751 
3752 	pktgen.version = DHD_PKTGEN_VERSION;
3753 	pktgen.freq = bus->pktgen_freq;
3754 	pktgen.count = bus->pktgen_count;
3755 	pktgen.print = bus->pktgen_print;
3756 	pktgen.total = bus->pktgen_total;
3757 	pktgen.minlen = bus->pktgen_minlen;
3758 	pktgen.maxlen = bus->pktgen_maxlen;
3759 	pktgen.numsent = bus->pktgen_sent;
3760 	pktgen.numrcvd = bus->pktgen_rcvd;
3761 	pktgen.numfail = bus->pktgen_fail;
3762 	pktgen.mode = bus->pktgen_mode;
3763 	pktgen.stop = bus->pktgen_stop;
3764 
3765 	bcopy(&pktgen, arg, sizeof(pktgen));
3766 
3767 	return 0;
3768 }
3769 
3770 static int
dhdsdio_pktgen_set(dhd_bus_t * bus,uint8 * arg)3771 dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
3772 {
3773 	dhd_pktgen_t pktgen;
3774 	uint oldcnt, oldmode;
3775 
3776 	bcopy(arg, &pktgen, sizeof(pktgen));
3777 	if (pktgen.version != DHD_PKTGEN_VERSION)
3778 		return BCME_BADARG;
3779 
3780 	oldcnt = bus->pktgen_count;
3781 	oldmode = bus->pktgen_mode;
3782 
3783 	bus->pktgen_freq = pktgen.freq;
3784 	bus->pktgen_count = pktgen.count;
3785 	bus->pktgen_print = pktgen.print;
3786 	bus->pktgen_total = pktgen.total;
3787 	bus->pktgen_minlen = pktgen.minlen;
3788 	bus->pktgen_maxlen = pktgen.maxlen;
3789 	bus->pktgen_mode = pktgen.mode;
3790 	bus->pktgen_stop = pktgen.stop;
3791 
3792 	bus->pktgen_tick = bus->pktgen_ptick = 0;
3793 #if defined(LINUX)
3794 	bus->pktgen_prev_time = jiffies;
3795 #endif /* LINUX */
3796 	bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
3797 	bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
3798 
3799 	/* Clear counts for a new pktgen (mode change, or was stopped) */
3800 	if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) {
3801 		bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0;
3802 		bus->pktgen_prev_rcvd = bus->pktgen_fail = 0;
3803 	}
3804 
3805 	return 0;
3806 }
3807 #endif /* SDTEST */
3808 
3809 static int
dhdsdio_membytes(dhd_bus_t * bus,bool write,uint32 address,uint8 * data,uint size)3810 dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
3811 {
3812 	int bcmerror = 0;
3813 	uint32 sdaddr;
3814 	uint dsize;
3815 	uint8 *pdata;
3816 
3817 	/* In remap mode, adjust address beyond socram and redirect
3818 	 * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
3819 	 * is not backplane accessible
3820 	 */
3821 	if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address)) {
3822 		address -= bus->orig_ramsize;
3823 		address += SOCDEVRAM_BP_ADDR;
3824 	}
3825 
3826 	/* Determine initial transfer parameters */
3827 	sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
3828 	if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
3829 		dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
3830 	else
3831 		dsize = size;
3832 
3833 	/* Set the backplane window to include the start address */
3834 	if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
3835 		DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
3836 		goto xfer_done;
3837 	}
3838 
3839 	/* Do the transfer(s) */
3840 	while (size) {
3841 		DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
3842 		          __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
3843 		          (address & SBSDIO_SBWINDOW_MASK)));
3844 		if (dsize <= MAX_MEM_BUF) {
3845 			pdata = bus->membuf;
3846 			if (write)
3847 				memcpy(bus->membuf, data, dsize);
3848 		} else {
3849 			pdata = data;
3850 		}
3851 		if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, pdata, dsize))) {
3852 			DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
3853 			break;
3854 		}
3855 		if (dsize <= MAX_MEM_BUF && !write)
3856 			memcpy(data, bus->membuf, dsize);
3857 
3858 		/* Adjust for next transfer (if any) */
3859 		if ((size -= dsize)) {
3860 			data += dsize;
3861 			address += dsize;
3862 			if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
3863 				DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
3864 				break;
3865 			}
3866 			sdaddr = 0;
3867 			dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
3868 		}
3869 
3870 	}
3871 
3872 xfer_done:
3873 	/* Return the window to backplane enumeration space for core access */
3874 	if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
3875 		DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
3876 			bcmsdh_cur_sbwad(bus->sdh)));
3877 	}
3878 
3879 	return bcmerror;
3880 }
3881 
3882 #if defined(BCMSDIO_RXLIM_POST) || defined(BCMSDIO_TXSEQ_SYNC)
3883 static void
dhdsdio_txseq_sync(dhd_bus_t * bus,sdpcm_shared_t * sh)3884 dhdsdio_txseq_sync(dhd_bus_t *bus, sdpcm_shared_t *sh)
3885 {
3886 	struct dhd_conf *conf = bus->dhd->conf;
3887 
3888 	if (sh->flags & SDPCM_SHARED_RXLIM_POST) {
3889 #ifdef BCMSDIO_RXLIM_POST
3890 		if (conf->rxlim_en) {
3891 			if (sh->msgtrace_addr) {
3892 				bus->rxlim_en = TRUE;
3893 				bus->rxlim_addr = sh->msgtrace_addr;
3894 				DHD_INFO(("%s: RXLIM_POST enabled with rxlim_addr=0x%x\n",
3895 					__FUNCTION__, bus->rxlim_addr));
3896 			} else {
3897 				DHD_INFO(("%s: RXLIM_POST not enabled in fw\n", __FUNCTION__));
3898 			}
3899 		} else
3900 #endif /* BCMSDIO_RXLIM_POST */
3901 #ifdef BCMSDIO_TXSEQ_SYNC
3902 		if (conf->txseq_sync) {
3903 			uint8 val = 0;
3904 			sh->txseq_sync_addr = ltoh32(sh->txseq_sync_addr);
3905 			DHD_INFO(("%s: TXSEQ_SYNC enabled\n", __FUNCTION__));
3906 			if (0 == dhdsdio_membytes(bus, FALSE, sh->txseq_sync_addr, (uint8 *)&val, 1)) {
3907 				if (bus->tx_seq != val) {
3908 					DHD_INFO(("%s: Sync tx_seq from %d to %d\n",
3909 						__FUNCTION__, bus->tx_seq, val));
3910 					bus->tx_seq = val;
3911 					bus->tx_max = bus->tx_seq + 4;
3912 				}
3913 			}
3914 		} else
3915 #endif /* BCMSDIO_TXSEQ_SYNC */
3916 		{
3917 			DHD_INFO(("%s: rxlim_en and txseq_sync not enabled in config.txt\n", __FUNCTION__));
3918 		}
3919 		sh->flags &= ~SDPCM_SHARED_RXLIM_POST;
3920 	}
3921 	else {
3922 #ifdef BCMSDIO_RXLIM_POST
3923 		bus->rxlim_en = 0;
3924 #endif /* BCMSDIO_RXLIM_POST */
3925 #ifdef BCMSDIO_TXSEQ_SYNC
3926 		conf->txseq_sync = FALSE;
3927 #endif /* BCMSDIO_TXSEQ_SYNC */
3928 		DHD_INFO(("%s: TXSEQ_SYNC and RXLIM_POST not supported in fw\n", __FUNCTION__));
3929 	}
3930 }
3931 #endif /* BCMSDIO_RXLIM_POST || BCMSDIO_TXSEQ_SYNC */
3932 
3933 static int
dhdsdio_readshared(dhd_bus_t * bus,sdpcm_shared_t * sh)3934 dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
3935 {
3936 	uint32 addr;
3937 	int rv, i;
3938 	uint32 shaddr = 0;
3939 
3940 	if (bus->sih == NULL) {
3941 		if (bus->dhd && bus->dhd->dongle_reset) {
3942 			DHD_ERROR(("%s: Dongle is in reset state\n", __FUNCTION__));
3943 			return BCME_NOTREADY;
3944 		} else {
3945 			ASSERT(bus->dhd);
3946 			ASSERT(bus->sih);
3947 			DHD_ERROR(("%s: The address of sih is invalid\n", __FUNCTION__));
3948 			return BCME_ERROR;
3949 		}
3950 	}
3951 	/*
3952 	 * If SR is not implemented in 43430 FW we should not adjust shaddr
3953 	 * XXX Should be REMOVED after SR will be implemented in 43430 FW
3954 	 */
3955 	if ((CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
3956 		CHIPID(bus->sih->chip) == BCM43018_CHIP_ID) && !dhdsdio_sr_cap(bus))
3957 		bus->srmemsize = 0;
3958 
3959 	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
3960 	i = 0;
3961 	do {
3962 		/* Read last word in memory to determine address of sdpcm_shared structure */
3963 		if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
3964 			return rv;
3965 
3966 		addr = ltoh32(addr);
3967 
3968 		DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
3969 
3970 		/*
3971 		 * Check if addr is valid.
3972 		 * NVRAM length at the end of memory should have been overwritten.
3973 		 */
3974 		if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
3975 			if ((bus->srmemsize > 0) && (i++ == 0)) {
3976 				shaddr -= bus->srmemsize;
3977 			} else {
3978 				DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
3979 					__FUNCTION__, addr));
3980 				return BCME_ERROR;
3981 			}
3982 		} else
3983 			break;
3984 	} while (i < 2);
3985 
3986 	/* Read hndrte_shared structure */
3987 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
3988 		return rv;
3989 
3990 	/* Endianness */
3991 	sh->flags = ltoh32(sh->flags);
3992 	sh->trap_addr = ltoh32(sh->trap_addr);
3993 	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
3994 	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
3995 	sh->assert_line = ltoh32(sh->assert_line);
3996 	sh->console_addr = ltoh32(sh->console_addr);
3997 	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
3998 
3999 #if defined(BCMSDIO_RXLIM_POST) || defined(BCMSDIO_TXSEQ_SYNC)
4000 	dhdsdio_txseq_sync(bus, sh);
4001 #endif
4002 
4003 	/*
4004 	 * XXX - Allow a sdpcm_shared_t version mismatch between dhd structure
4005 	 * version 1 and firmware structure version 3.
4006 	 * The sdpcm_shared_t stucture fields used in this function are in the
4007 	 * same positions in these two structure versions.
4008 	 * For some chips in the FALCON release, the dhd driver is from the
4009 	 * FALCON branch (sdpcm_shared_t structure version 1) and the firmware
4010 	 * comes from the ROMTERM3 branch (sdpcm_shared_t structure version 1).
4011 	*/
4012 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
4013 		return BCME_OK;
4014 
4015 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
4016 		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
4017 		           "is different than sdpcm_shared version %d in dongle\n",
4018 		           __FUNCTION__, SDPCM_SHARED_VERSION,
4019 		           sh->flags & SDPCM_SHARED_VERSION_MASK));
4020 		return BCME_ERROR;
4021 	}
4022 
4023 	return BCME_OK;
4024 }
4025 
4026 #define CONSOLE_LINE_MAX	192
4027 
4028 #ifdef DHD_DEBUG
4029 static int
dhdsdio_readconsole(dhd_bus_t * bus)4030 dhdsdio_readconsole(dhd_bus_t *bus)
4031 {
4032 	dhd_console_t *c = &bus->console;
4033 	uint8 line[CONSOLE_LINE_MAX], ch;
4034 	uint32 n, idx, addr;
4035 	int rv;
4036 
4037 	/* Don't do anything until FWREADY updates console address */
4038 	if (bus->console_addr == 0)
4039 		return 0;
4040 
4041 	if (!KSO_ENAB(bus))
4042 		return 0;
4043 
4044 	/* Read console log struct */
4045 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, log);
4046 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
4047 		return rv;
4048 
4049 	/* Allocate console buffer (one time only) */
4050 	if (c->buf == NULL) {
4051 		c->bufsize = ltoh32(c->log.buf_size);
4052 		if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
4053 			return BCME_NOMEM;
4054 	}
4055 
4056 	idx = ltoh32(c->log.idx);
4057 
4058 	/* Protect against corrupt value */
4059 	if (idx > c->bufsize)
4060 		return BCME_ERROR;
4061 
4062 	/* Skip reading the console buffer if the index pointer has not moved */
4063 	if (idx == c->last)
4064 		return BCME_OK;
4065 
4066 	/* Read the console buffer */
4067 	/* xxx this could optimize and read only the portion of the buffer needed, but
4068 	 * it would also have to handle wrap-around.
4069 	 */
4070 	addr = ltoh32(c->log.buf);
4071 	if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
4072 		return rv;
4073 
4074 	while (c->last != idx) {
4075 		for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
4076 			if (c->last == idx) {
4077 				/* This would output a partial line.  Instead, back up
4078 				 * the buffer pointer and output this line next time around.
4079 				 */
4080 				if (c->last >= n)
4081 					c->last -= n;
4082 				else
4083 					c->last = c->bufsize - n;
4084 				goto break2;
4085 			}
4086 			ch = c->buf[c->last];
4087 			c->last = (c->last + 1) % c->bufsize;
4088 			if (ch == '\n')
4089 				break;
4090 			line[n] = ch;
4091 		}
4092 
4093 		if (n > 0) {
4094 			if (line[n - 1] == '\r')
4095 				n--;
4096 			line[n] = 0;
4097 			printf("CONSOLE: %s\n", line);
4098 #ifdef LOG_INTO_TCPDUMP
4099 			dhd_sendup_log(bus->dhd, line, n);
4100 #endif /* LOG_INTO_TCPDUMP */
4101 		}
4102 	}
4103 break2:
4104 
4105 	return BCME_OK;
4106 }
4107 #endif /* DHD_DEBUG */
4108 
4109 static int
dhdsdio_checkdied(dhd_bus_t * bus,char * data,uint size)4110 dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size)
4111 {
4112 	int bcmerror = 0;
4113 	uint msize = 512;
4114 	char *mbuffer = NULL;
4115 	char *console_buffer = NULL;
4116 	uint maxstrlen = 256;
4117 	char *str = NULL;
4118 	sdpcm_shared_t l_sdpcm_shared;
4119 	struct bcmstrbuf strbuf;
4120 	uint32 console_ptr, console_size, console_index;
4121 	uint8 line[CONSOLE_LINE_MAX], ch;
4122 	uint32 n, i, addr;
4123 	int rv;
4124 
4125 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
4126 
4127 	if (DHD_NOCHECKDIED_ON())
4128 		return 0;
4129 
4130 	if (data == NULL) {
4131 		/*
4132 		 * Called after a rx ctrl timeout. "data" is NULL.
4133 		 * allocate memory to trace the trap or assert.
4134 		 */
4135 		size = msize;
4136 		mbuffer = data = MALLOC(bus->dhd->osh, msize);
4137 		if (mbuffer == NULL) {
4138 			DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
4139 			bcmerror = BCME_NOMEM;
4140 			goto done;
4141 		}
4142 	}
4143 
4144 	if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
4145 		DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
4146 		bcmerror = BCME_NOMEM;
4147 		goto done;
4148 	}
4149 
4150 	if ((bcmerror = dhdsdio_readshared(bus, &l_sdpcm_shared)) < 0)
4151 		goto done;
4152 
4153 	bcm_binit(&strbuf, data, size);
4154 
4155 	bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
4156 	            l_sdpcm_shared.msgtrace_addr, l_sdpcm_shared.console_addr);
4157 
4158 	if ((l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
4159 		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
4160 		 * (Avoids conflict with real asserts for programmatic parsing of output.)
4161 		 */
4162 		bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
4163 	}
4164 
4165 	if ((l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
4166 		/* NOTE: Misspelled assert is intentional - DO NOT FIX.
4167 		 * (Avoids conflict with real asserts for programmatic parsing of output.)
4168 		 */
4169 		bcm_bprintf(&strbuf, "No trap%s in dongle",
4170 		          (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
4171 		          ?"/assrt" :"");
4172 	} else {
4173 		if (l_sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
4174 			/* Download assert */
4175 			bcm_bprintf(&strbuf, "Dongle assert");
4176 			if (l_sdpcm_shared.assert_exp_addr != 0) {
4177 				str[0] = '\0';
4178 				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
4179 				                                 l_sdpcm_shared.assert_exp_addr,
4180 				                                 (uint8 *)str, maxstrlen)) < 0)
4181 					goto done;
4182 
4183 				str[maxstrlen - 1] = '\0';
4184 				bcm_bprintf(&strbuf, " expr \"%s\"", str);
4185 			}
4186 
4187 			if (l_sdpcm_shared.assert_file_addr != 0) {
4188 				str[0] = '\0';
4189 				if ((bcmerror = dhdsdio_membytes(bus, FALSE,
4190 				                   l_sdpcm_shared.assert_file_addr,
4191 				                                 (uint8 *)str, maxstrlen)) < 0)
4192 					goto done;
4193 
4194 				str[maxstrlen - 1] = '\0';
4195 				bcm_bprintf(&strbuf, " file \"%s\"", str);
4196 			}
4197 
4198 			bcm_bprintf(&strbuf, " line %d ", l_sdpcm_shared.assert_line);
4199 		}
4200 
4201 		if (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
4202 			trap_t *tr = &bus->dhd->last_trap_info;
4203 			bus->dhd->dongle_trap_occured = TRUE;
4204 			if ((bcmerror = dhdsdio_membytes(bus, FALSE,
4205 			                                 l_sdpcm_shared.trap_addr,
4206 			                                 (uint8*)tr, sizeof(trap_t))) < 0)
4207 				goto done;
4208 
4209 			bus->dongle_trap_addr = ltoh32(l_sdpcm_shared.trap_addr);
4210 
4211 			dhd_bus_dump_trap_info(bus, &strbuf);
4212 
4213 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log);
4214 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
4215 				(uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
4216 				goto printbuf;
4217 
4218 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.buf_size);
4219 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
4220 				(uint8 *)&console_size, sizeof(console_size))) < 0)
4221 				goto printbuf;
4222 
4223 			addr = l_sdpcm_shared.console_addr + OFFSETOF(hnd_cons_t, log.idx);
4224 			if ((rv = dhdsdio_membytes(bus, FALSE, addr,
4225 				(uint8 *)&console_index, sizeof(console_index))) < 0)
4226 				goto printbuf;
4227 
4228 			console_ptr = ltoh32(console_ptr);
4229 			console_size = ltoh32(console_size);
4230 			console_index = ltoh32(console_index);
4231 
4232 			if (console_size > CONSOLE_BUFFER_MAX ||
4233 				!(console_buffer = MALLOC(bus->dhd->osh, console_size)))
4234 				goto printbuf;
4235 
4236 			if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr,
4237 				(uint8 *)console_buffer, console_size)) < 0)
4238 				goto printbuf;
4239 
4240 			for (i = 0, n = 0; i < console_size; i += n + 1) {
4241 				for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
4242 					ch = console_buffer[(console_index + i + n) % console_size];
4243 					if (ch == '\n')
4244 						break;
4245 					line[n] = ch;
4246 				}
4247 
4248 				if (n > 0) {
4249 					if (line[n - 1] == '\r')
4250 						n--;
4251 					line[n] = 0;
4252 					/* Don't use DHD_ERROR macro since we print
4253 					 * a lot of information quickly. The macro
4254 					 * will truncate a lot of the printfs
4255 					 */
4256 
4257 					if (dhd_msg_level & DHD_ERROR_VAL)
4258 						printf("CONSOLE: %s\n", line);
4259 				}
4260 			}
4261 		}
4262 	}
4263 
4264 printbuf:
4265 	if (l_sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
4266 		DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
4267 	}
4268 
4269 #if defined(DHD_FW_COREDUMP)
4270 	if (bus->dhd->memdump_enabled && (l_sdpcm_shared.flags & SDPCM_SHARED_TRAP)) {
4271 		/* Mem dump to a file on device */
4272 		bus->dhd->memdump_type = DUMP_TYPE_DONGLE_TRAP;
4273 		/* xxx this sdunlock has been put as a WAR here. We tried to come up
4274 		  * with a better solution but with the current structure of sdlocks it is very
4275 		  * unlikely to have a better fix for now. The better Rearch of sdio bus
4276 		  * locking has been put up as a cleanup activity and a thorough
4277 		  * code walkthrough is needed.
4278 		  */
4279 		dhd_os_sdunlock(bus->dhd);
4280 		dhdsdio_mem_dump(bus);
4281 		dhd_os_sdlock(bus->dhd);
4282 #ifdef NDIS
4283 		/* Windows would like to crash and collect memory dump for analysis */
4284 		ASSERT(0 && "Dongle firmware died.");
4285 
4286 		/* For free drivers ASSERT will not bugcheck */
4287 		KeBugCheckEx(__LINE__, 0, 0, 0, 0);
4288 #endif
4289 	}
4290 #endif /* #if defined(DHD_FW_COREDUMP) */
4291 
4292 done:
4293 	if (mbuffer)
4294 		MFREE(bus->dhd->osh, mbuffer, msize);
4295 	if (str)
4296 		MFREE(bus->dhd->osh, str, maxstrlen);
4297 	if (console_buffer)
4298 		MFREE(bus->dhd->osh, console_buffer, console_size);
4299 
4300 	return bcmerror;
4301 }
4302 
4303 #if defined(DHD_FW_COREDUMP)
4304 int
dhd_bus_mem_dump(dhd_pub_t * dhdp)4305 dhd_bus_mem_dump(dhd_pub_t *dhdp)
4306 {
4307 	dhd_bus_t *bus = dhdp->bus;
4308 	if (dhdp->busstate == DHD_BUS_SUSPEND) {
4309 		DHD_ERROR(("%s: Bus is suspend so skip\n", __FUNCTION__));
4310 		return 0;
4311 	}
4312 	return dhdsdio_mem_dump(bus);
4313 }
4314 
4315 int
dhd_bus_get_mem_dump(dhd_pub_t * dhdp)4316 dhd_bus_get_mem_dump(dhd_pub_t *dhdp)
4317 {
4318 	if (!dhdp) {
4319 		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
4320 		return BCME_ERROR;
4321 	}
4322 
4323 	return dhdsdio_get_mem_dump(dhdp->bus);
4324 }
4325 
4326 static int
dhdsdio_get_mem_dump(dhd_bus_t * bus)4327 dhdsdio_get_mem_dump(dhd_bus_t *bus)
4328 {
4329 	int ret = BCME_ERROR;
4330 	int size = bus->ramsize;		/* Full mem size */
4331 	uint32 start = bus->dongle_ram_base;	/* Start address */
4332 	uint read_size = 0;			/* Read size of each iteration */
4333 	uint8 *p_buf = NULL, *databuf = NULL;
4334 
4335 	/* Get full mem size */
4336 	p_buf = dhd_get_fwdump_buf(bus->dhd, size);
4337 	if (!p_buf) {
4338 		DHD_ERROR(("%s: Out of memory (%d bytes)\n",
4339 			__FUNCTION__, size));
4340 		return BCME_ERROR;
4341 	}
4342 
4343 	dhd_os_sdlock(bus->dhd);
4344 	BUS_WAKE(bus);
4345 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
4346 
4347 	/* Read mem content */
4348 	DHD_ERROR(("Dump dongle memory\n"));
4349 	databuf = p_buf;
4350 	while (size) {
4351 		read_size = MIN(MEMBLOCK, size);
4352 		ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size);
4353 		if (ret) {
4354 			DHD_ERROR(("%s: Error membytes %d\n", __FUNCTION__, ret));
4355 			ret = BCME_ERROR;
4356 			break;
4357 		}
4358 		/* Decrement size and increment start address */
4359 		size -= read_size;
4360 		start += read_size;
4361 		databuf += read_size;
4362 	}
4363 
4364 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
4365 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
4366 		bus->activity = FALSE;
4367 		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
4368 	}
4369 
4370 	dhd_os_sdunlock(bus->dhd);
4371 
4372 	return ret;
4373 }
4374 
4375 static int
dhdsdio_mem_dump(dhd_bus_t * bus)4376 dhdsdio_mem_dump(dhd_bus_t *bus)
4377 {
4378 	dhd_pub_t *dhdp;
4379 	int ret = BCME_ERROR;
4380 
4381 	dhdp = bus->dhd;
4382 	if (!dhdp) {
4383 		DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
4384 		return ret;
4385 	}
4386 
4387 	ret = dhdsdio_get_mem_dump(bus);
4388 	if (ret) {
4389 		DHD_ERROR(("%s: failed to get mem dump, err=%d\n",
4390 			__FUNCTION__, ret));
4391 	} else {
4392 		/* schedule a work queue to perform actual memdump.
4393 		 * dhd_mem_dump() performs the job
4394 		 */
4395 		dhd_schedule_memdump(dhdp, dhdp->soc_ram, dhdp->soc_ram_length);
4396 		/* soc_ram free handled in dhd_{free,clear} */
4397 	}
4398 
4399 	return ret;
4400 }
4401 #endif /* DHD_FW_COREDUMP */
4402 
4403 int
dhd_socram_dump(dhd_bus_t * bus)4404 dhd_socram_dump(dhd_bus_t * bus)
4405 {
4406 #if defined(DHD_FW_COREDUMP)
4407 	return (dhdsdio_mem_dump(bus));
4408 #else
4409 	return -1;
4410 #endif
4411 }
4412 
4413 int
dhdsdio_downloadvars(dhd_bus_t * bus,void * arg,int len)4414 dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
4415 {
4416 	int bcmerror = BCME_OK;
4417 
4418 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
4419 
4420 	if (bus->dhd->up &&
4421 		1) {
4422 		bcmerror = BCME_NOTDOWN;
4423 		goto err;
4424 	}
4425 	if (!len) {
4426 		bcmerror = BCME_BUFTOOSHORT;
4427 		goto err;
4428 	}
4429 
4430 	/* Free the old ones and replace with passed variables */
4431 	if (bus->vars)
4432 		MFREE(bus->dhd->osh, bus->vars, bus->varsz);
4433 
4434 	bus->vars = MALLOC(bus->dhd->osh, len);
4435 	bus->varsz = bus->vars ? len : 0;
4436 	if (bus->vars == NULL) {
4437 		bcmerror = BCME_NOMEM;
4438 		goto err;
4439 	}
4440 
4441 	/* Copy the passed variables, which should include the terminating double-null */
4442 	bcopy(arg, bus->vars, bus->varsz);
4443 err:
4444 	return bcmerror;
4445 }
4446 
4447 #ifdef DHD_DEBUG
4448 static int
dhd_serialconsole(dhd_bus_t * bus,bool set,bool enable,int * bcmerror)4449 dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror)
4450 {
4451 	int int_val;
4452 	uint32 addr, data, uart_enab = 0;
4453 
4454 	addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr);
4455 	data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data);
4456 	*bcmerror = 0;
4457 
4458 	bcmsdh_reg_write(bus->sdh, addr, 4, 1);
4459 	if (bcmsdh_regfail(bus->sdh)) {
4460 		*bcmerror = BCME_SDIO_ERROR;
4461 		return -1;
4462 	}
4463 	int_val = bcmsdh_reg_read(bus->sdh, data, 4);
4464 	if (bcmsdh_regfail(bus->sdh)) {
4465 		*bcmerror = BCME_SDIO_ERROR;
4466 		return -1;
4467 	}
4468 
4469 	if (!set)
4470 		return (int_val & uart_enab);
4471 	if (enable)
4472 		int_val |= uart_enab;
4473 	else
4474 		int_val &= ~uart_enab;
4475 	bcmsdh_reg_write(bus->sdh, data, 4, int_val);
4476 	if (bcmsdh_regfail(bus->sdh)) {
4477 		*bcmerror = BCME_SDIO_ERROR;
4478 		return -1;
4479 	}
4480 
4481 	return (int_val & uart_enab);
4482 }
4483 #endif /* BCMINTERNAL */
4484 
4485 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)4486 dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
4487                 void *params, uint plen, void *arg, uint len, uint val_size)
4488 {
4489 	int bcmerror = 0;
4490 	int32 int_val = 0;
4491 	bool bool_val = 0;
4492 
4493 	DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
4494 	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
4495 
4496 	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
4497 		goto exit;
4498 
4499 	if (plen >= sizeof(int_val))
4500 		bcopy(params, &int_val, sizeof(int_val));
4501 
4502 	bool_val = (int_val != 0) ? TRUE : FALSE;
4503 
4504 	/* Some ioctls use the bus */
4505 	dhd_os_sdlock(bus->dhd);
4506 
4507 	/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
4508 	if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
4509 	                                actionid == IOV_GVAL(IOV_DEVRESET))) {
4510 		bcmerror = BCME_NOTREADY;
4511 		goto exit;
4512 	}
4513 
4514 	/*
4515 	 * Special handling for keepSdioOn: New SDIO Wake-up Mechanism
4516 	 */
4517 	if ((vi->varid == IOV_KSO) && (IOV_ISSET(actionid))) {
4518 		dhdsdio_clk_kso_iovar(bus, bool_val);
4519 		goto exit;
4520 	} else if ((vi->varid == IOV_DEVSLEEP) && (IOV_ISSET(actionid))) {
4521 #ifdef BCMINTERNAL
4522 		/* XXX: Temp for debugging devsleep */
4523 		if (int_val == 2) {
4524 			bus->dpc_sched = TRUE;
4525 			dhd_sched_dpc(bus->dhd);
4526 		} else if (int_val == 3) {
4527 			bus->_slpauto = FALSE;
4528 		} else if (int_val == 4) {
4529 			bus->_slpauto = TRUE;
4530 		} else if (int_val == 5) {
4531 			bus->kso = TRUE;
4532 		} else if (int_val == 6) {
4533 			bus->kso = FALSE;
4534 		} else
4535 #endif
4536 		{
4537 			dhdsdio_clk_devsleep_iovar(bus, bool_val);
4538 			if (!SLPAUTO_ENAB(bus) && (bool_val == FALSE) && (bus->ipend)) {
4539 				DHD_ERROR(("INT pending in devsleep 1, dpc_sched: %d\n",
4540 					bus->dpc_sched));
4541 				if (!bus->dpc_sched) {
4542 					bus->dpc_sched = TRUE;
4543 					dhd_sched_dpc(bus->dhd);
4544 				}
4545 			}
4546 		}
4547 		goto exit;
4548 	}
4549 
4550 	/* Handle sleep stuff before any clock mucking */
4551 	if (vi->varid == IOV_SLEEP) {
4552 		if (IOV_ISSET(actionid)) {
4553 			bcmerror = dhdsdio_bussleep(bus, bool_val);
4554 		} else {
4555 			int_val = (int32)bus->sleeping;
4556 			bcopy(&int_val, arg, val_size);
4557 		}
4558 		goto exit;
4559 	}
4560 
4561 	/* Request clock to allow SDIO accesses */
4562 	if (!bus->dhd->dongle_reset) {
4563 		BUS_WAKE(bus);
4564 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
4565 	}
4566 
4567 	switch (actionid) {
4568 	case IOV_GVAL(IOV_INTR):
4569 		int_val = (int32)bus->intr;
4570 		bcopy(&int_val, arg, val_size);
4571 		break;
4572 
4573 	case IOV_SVAL(IOV_INTR):
4574 		bus->intr = bool_val;
4575 		bus->intdis = FALSE;
4576 		if (bus->dhd->up) {
4577 			if (bus->intr) {
4578 				DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
4579 				// terence 20141207: enbale intdis
4580 				bus->intdis = TRUE;
4581 				bcmsdh_intr_enable(bus->sdh);
4582 			} else {
4583 				DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
4584 				bcmsdh_intr_disable(bus->sdh);
4585 			}
4586 		}
4587 		break;
4588 
4589 	case IOV_GVAL(IOV_POLLRATE):
4590 		int_val = (int32)bus->pollrate;
4591 		bcopy(&int_val, arg, val_size);
4592 		break;
4593 
4594 	case IOV_SVAL(IOV_POLLRATE):
4595 		bus->pollrate = (uint)int_val;
4596 		bus->poll = (bus->pollrate != 0);
4597 		break;
4598 
4599 	case IOV_GVAL(IOV_IDLETIME):
4600 		int_val = bus->idletime;
4601 		bcopy(&int_val, arg, val_size);
4602 		break;
4603 
4604 	case IOV_SVAL(IOV_IDLETIME):
4605 		if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
4606 			bcmerror = BCME_BADARG;
4607 		} else {
4608 			bus->idletime = int_val;
4609 		}
4610 		break;
4611 
4612 	case IOV_GVAL(IOV_IDLECLOCK):
4613 		int_val = (int32)bus->idleclock;
4614 		bcopy(&int_val, arg, val_size);
4615 		break;
4616 
4617 	case IOV_SVAL(IOV_IDLECLOCK):
4618 		bus->idleclock = int_val;
4619 		break;
4620 
4621 	case IOV_GVAL(IOV_SD1IDLE):
4622 		int_val = (int32)sd1idle;
4623 		bcopy(&int_val, arg, val_size);
4624 		break;
4625 
4626 	case IOV_SVAL(IOV_SD1IDLE):
4627 		sd1idle = bool_val;
4628 		break;
4629 
4630 #ifdef DHD_DEBUG
4631 	case IOV_GVAL(IOV_CHECKDIED):
4632 		bcmerror = dhdsdio_checkdied(bus, arg, len);
4633 		break;
4634 #endif /* DHD_DEBUG */
4635 
4636 #ifdef DHD_BUS_MEM_ACCESS
4637 	case IOV_SVAL(IOV_MEMBYTES):
4638 	case IOV_GVAL(IOV_MEMBYTES):
4639 	{
4640 		uint32 address;
4641 		uint size, dsize;
4642 		uint8 *data;
4643 
4644 		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
4645 
4646 		ASSERT(plen >= 2*sizeof(int));
4647 
4648 		address = (uint32)int_val;
4649 		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
4650 		size = (uint)int_val;
4651 
4652 		/* Do some validation */
4653 		dsize = set ? plen - (2 * sizeof(int)) : len;
4654 		if (dsize < size) {
4655 			DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
4656 			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
4657 			bcmerror = BCME_BADARG;
4658 			break;
4659 		}
4660 
4661 		DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
4662 		          (set ? "write" : "read"), size, address));
4663 
4664 		/* check if CR4 */
4665 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
4666 			/*
4667 			 * If address is start of RAM (i.e. a downloaded image),
4668 			 * store the reset instruction to be written in 0
4669 			 */
4670 			if (set && address == bus->dongle_ram_base) {
4671 				bus->resetinstr = *(((uint32*)params) + 2);
4672 			}
4673 		}
4674 
4675 		/* Generate the actual data pointer */
4676 		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
4677 
4678 		/* Call to do the transfer */
4679 		bcmerror = dhdsdio_membytes(bus, set, address, data, size);
4680 
4681 		break;
4682 	}
4683 #endif /* DHD_BUS_MEM_ACCESS */
4684 
4685 	case IOV_GVAL(IOV_RAMSIZE):
4686 		int_val = (int32)bus->ramsize;
4687 		bcopy(&int_val, arg, val_size);
4688 		break;
4689 
4690 	case IOV_GVAL(IOV_RAMSTART):
4691 		int_val = (int32)bus->dongle_ram_base;
4692 		bcopy(&int_val, arg, val_size);
4693 		break;
4694 
4695 	case IOV_GVAL(IOV_SDIOD_DRIVE):
4696 		int_val = (int32)dhd_sdiod_drive_strength;
4697 		bcopy(&int_val, arg, val_size);
4698 		break;
4699 
4700 	case IOV_SVAL(IOV_SDIOD_DRIVE):
4701 		dhd_sdiod_drive_strength = int_val;
4702 		si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
4703 		break;
4704 
4705 	case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
4706 		bcmerror = dhdsdio_download_state(bus, bool_val);
4707 		break;
4708 
4709 	case IOV_SVAL(IOV_SOCRAM_STATE):
4710 		bcmerror = dhdsdio_download_state(bus, bool_val);
4711 		break;
4712 
4713 	case IOV_SVAL(IOV_VARS):
4714 		bcmerror = dhdsdio_downloadvars(bus, arg, len);
4715 		break;
4716 
4717 	case IOV_GVAL(IOV_READAHEAD):
4718 		int_val = (int32)dhd_readahead;
4719 		bcopy(&int_val, arg, val_size);
4720 		break;
4721 
4722 	case IOV_SVAL(IOV_READAHEAD):
4723 		if (bool_val && !dhd_readahead)
4724 			bus->nextlen = 0;
4725 		dhd_readahead = bool_val;
4726 		break;
4727 
4728 	case IOV_GVAL(IOV_SDRXCHAIN):
4729 		int_val = (int32)bus->use_rxchain;
4730 		bcopy(&int_val, arg, val_size);
4731 		break;
4732 
4733 	case IOV_SVAL(IOV_SDRXCHAIN):
4734 		if (bool_val && !bus->sd_rxchain)
4735 			bcmerror = BCME_UNSUPPORTED;
4736 		else
4737 			bus->use_rxchain = bool_val;
4738 		break;
4739 #ifndef BCMSPI
4740 	case IOV_GVAL(IOV_ALIGNCTL):
4741 		int_val = (int32)dhd_alignctl;
4742 		bcopy(&int_val, arg, val_size);
4743 		break;
4744 
4745 	case IOV_SVAL(IOV_ALIGNCTL):
4746 		dhd_alignctl = bool_val;
4747 		break;
4748 #endif /* BCMSPI */
4749 
4750 	case IOV_GVAL(IOV_SDALIGN):
4751 		int_val = DHD_SDALIGN;
4752 		bcopy(&int_val, arg, val_size);
4753 		break;
4754 
4755 #ifdef DHD_DEBUG
4756 	case IOV_GVAL(IOV_VARS):
4757 		if (bus->varsz < (uint)len)
4758 			bcopy(bus->vars, arg, bus->varsz);
4759 		else
4760 			bcmerror = BCME_BUFTOOSHORT;
4761 		break;
4762 #endif /* DHD_DEBUG */
4763 
4764 #ifdef DHD_DEBUG
4765 	/* XXX Until these return BCME ranges, make assumptions here */
4766 	case IOV_GVAL(IOV_SDREG):
4767 	{
4768 		sdreg_t *sd_ptr;
4769 		uintptr addr;
4770 		uint size;
4771 
4772 		sd_ptr = (sdreg_t *)params;
4773 
4774 		addr = ((uintptr)bus->regs + sd_ptr->offset);
4775 		size = sd_ptr->func;
4776 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
4777 		if (bcmsdh_regfail(bus->sdh))
4778 			bcmerror = BCME_SDIO_ERROR;
4779 		bcopy(&int_val, arg, sizeof(int32));
4780 		break;
4781 	}
4782 
4783 	case IOV_SVAL(IOV_SDREG):
4784 	{
4785 		sdreg_t *sd_ptr;
4786 		uintptr addr;
4787 		uint size;
4788 
4789 		sd_ptr = (sdreg_t *)params;
4790 
4791 		addr = ((uintptr)bus->regs + sd_ptr->offset);
4792 		size = sd_ptr->func;
4793 		bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
4794 		if (bcmsdh_regfail(bus->sdh))
4795 			bcmerror = BCME_SDIO_ERROR;
4796 		break;
4797 	}
4798 
4799 	/* XXX Same as above */
4800 	/* Same as above, but offset is not backplane (not SDIO core) */
4801 	case IOV_GVAL(IOV_SBREG):
4802 	{
4803 		sdreg_t sdreg;
4804 		uint32 addr, size;
4805 
4806 		bcopy(params, &sdreg, sizeof(sdreg));
4807 
4808 		addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
4809 		size = sdreg.func;
4810 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
4811 		if (bcmsdh_regfail(bus->sdh))
4812 			bcmerror = BCME_SDIO_ERROR;
4813 		bcopy(&int_val, arg, sizeof(int32));
4814 		break;
4815 	}
4816 
4817 	case IOV_SVAL(IOV_SBREG):
4818 	{
4819 		sdreg_t sdreg;
4820 		uint32 addr, size;
4821 
4822 		bcopy(params, &sdreg, sizeof(sdreg));
4823 
4824 		addr = SI_ENUM_BASE(bus->sih) + sdreg.offset;
4825 		size = sdreg.func;
4826 		bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
4827 		if (bcmsdh_regfail(bus->sdh))
4828 			bcmerror = BCME_SDIO_ERROR;
4829 		break;
4830 	}
4831 
4832 	case IOV_GVAL(IOV_SDCIS):
4833 	{
4834 		*(char *)arg = 0;
4835 
4836 		/* XXX Ignoring return codes, should be evident from printed results */
4837 		bcmstrcat(arg, "\nFunc 0\n");
4838 		bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4839 		bcmstrcat(arg, "\nFunc 1\n");
4840 		bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4841 		bcmstrcat(arg, "\nFunc 2\n");
4842 		bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
4843 		break;
4844 	}
4845 
4846 	case IOV_GVAL(IOV_FORCEEVEN):
4847 		int_val = (int32)forcealign;
4848 		bcopy(&int_val, arg, val_size);
4849 		break;
4850 
4851 	case IOV_SVAL(IOV_FORCEEVEN):
4852 		forcealign = bool_val;
4853 		break;
4854 
4855 	case IOV_GVAL(IOV_TXBOUND):
4856 		int_val = (int32)dhd_txbound;
4857 		bcopy(&int_val, arg, val_size);
4858 		break;
4859 
4860 	case IOV_SVAL(IOV_TXBOUND):
4861 		dhd_txbound = (uint)int_val;
4862 		break;
4863 
4864 	case IOV_GVAL(IOV_RXBOUND):
4865 		int_val = (int32)dhd_rxbound;
4866 		bcopy(&int_val, arg, val_size);
4867 		break;
4868 
4869 	case IOV_SVAL(IOV_RXBOUND):
4870 		dhd_rxbound = (uint)int_val;
4871 		break;
4872 
4873 	case IOV_GVAL(IOV_TXMINMAX):
4874 		int_val = (int32)dhd_txminmax;
4875 		bcopy(&int_val, arg, val_size);
4876 		break;
4877 
4878 	case IOV_SVAL(IOV_TXMINMAX):
4879 		dhd_txminmax = (uint)int_val;
4880 		break;
4881 
4882 #ifdef DHD_DEBUG
4883 	case IOV_GVAL(IOV_SERIALCONS):
4884 		int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror);
4885 		if (bcmerror != 0)
4886 			break;
4887 
4888 		bcopy(&int_val, arg, val_size);
4889 		break;
4890 
4891 	case IOV_SVAL(IOV_SERIALCONS):
4892 		dhd_serialconsole(bus, TRUE, bool_val, &bcmerror);
4893 		break;
4894 #endif /* DHD_DEBUG */
4895 
4896 #if defined(BCMINTERNAL) && defined(BCMDBG)
4897 	case IOV_SVAL(IOV_SIALL):
4898 		DHD_ERROR(("Dumping all the Backplane registers\n"));
4899 		si_viewall(bus->sih, TRUE);
4900 		break;
4901 #endif /* defined(BCMINTERNAL) && defined(BCMDBG) */
4902 
4903 #endif /* DHD_DEBUG */
4904 
4905 #if defined(DHD_SPROM)
4906 	case IOV_SVAL(IOV_SPROM):
4907 	case IOV_GVAL(IOV_SPROM):
4908 	{
4909 		uint32 offset;
4910 		uint size, dsize;
4911 
4912 		bool set = (actionid == IOV_SVAL(IOV_SPROM));
4913 
4914 		ASSERT(plen >= 2*sizeof(int));
4915 
4916 		offset = (uint32)int_val;
4917 		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
4918 		size = (uint)int_val;
4919 
4920 		/* Avoid bigger size of srom reads that may be requested from app.
4921 		 * gSPI has only F1 OTP visible from CC.  There is no CIS in gSPI.
4922 		 */
4923 		if (bus->bus == SPI_BUS)
4924 			size = SBSDIO_CIS_SIZE_LIMIT;
4925 
4926 		/* Do some validation */
4927 		dsize = set ? plen - (2 * sizeof(int)) : len;
4928 		if (dsize < size) {
4929 			DHD_ERROR(("%s: error on srom %s, addr 0x%08x size %d dsize %d\n",
4930 			           __FUNCTION__, (set ? "write" : "read"), offset, size, dsize));
4931 			bcmerror = BCME_BADARG;
4932 			break;
4933 		}
4934 
4935 		if ((offset > SROM_MAX) || ((offset + size) > SROM_MAX)) {
4936 			DHD_ERROR(("%s: error on srom %s, offset %d size %d exceeds limit %d\n",
4937 			           __FUNCTION__, (set ? "write" : "read"), offset, size, SROM_MAX));
4938 			bcmerror = BCME_BADARG;
4939 			break;
4940 		}
4941 
4942 		if (!set) {
4943 			if (!ISALIGNED((uintptr)arg, sizeof(uint16))) {
4944 				DHD_ERROR(("%s: srom data pointer %p not word-aligned\n",
4945 				           __FUNCTION__, arg));
4946 				bcmerror = BCME_BADARG;
4947 				break;
4948 			}
4949 
4950 			GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
4951 			bcmerror = srom_read(bus->sih, DHD_BUS, (void*)bus->regs, bus->dhd->osh,
4952 			                     offset, size, (uint16*)arg, FALSE);
4953 			GCC_DIAGNOSTIC_POP();
4954 
4955 		} else {
4956 			arg = (void*)((uintptr)arg + 2 * sizeof(int));
4957 			if (!ISALIGNED((uintptr)arg, sizeof(uint16))) {
4958 				DHD_ERROR(("%s: srom data pointer %p not word-aligned\n",
4959 				           __FUNCTION__, arg));
4960 				bcmerror = BCME_BADARG;
4961 				break;
4962 			}
4963 			GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
4964 			bcmerror = srom_write(bus->sih, DHD_BUS, (void*)bus->regs, bus->dhd->osh,
4965 			                      offset, size, (uint16*)arg);
4966 			GCC_DIAGNOSTIC_POP();
4967 		}
4968 		break;
4969 	}
4970 #endif /* DHD_SPROM */
4971 
4972 #ifdef SDTEST
4973 	case IOV_GVAL(IOV_EXTLOOP):
4974 		int_val = (int32)bus->ext_loop;
4975 		bcopy(&int_val, arg, val_size);
4976 		break;
4977 
4978 	case IOV_SVAL(IOV_EXTLOOP):
4979 		bus->ext_loop = bool_val;
4980 		break;
4981 
4982 	case IOV_GVAL(IOV_PKTGEN):
4983 		bcmerror = dhdsdio_pktgen_get(bus, arg);
4984 		break;
4985 
4986 	case IOV_SVAL(IOV_PKTGEN):
4987 		bcmerror = dhdsdio_pktgen_set(bus, arg);
4988 		break;
4989 #endif /* SDTEST */
4990 
4991 #if defined(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL)
4992 	case IOV_GVAL(IOV_WATERMARK):
4993 		int_val = (int32)watermark;
4994 		bcopy(&int_val, arg, val_size);
4995 		break;
4996 
4997 	case IOV_SVAL(IOV_WATERMARK):
4998 		watermark = (uint)int_val;
4999 		watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark;
5000 		DHD_ERROR(("Setting watermark as 0x%x.\n", watermark));
5001 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL);
5002 		break;
5003 
5004 	case IOV_GVAL(IOV_MESBUSYCTRL):
5005 		int_val = (int32)mesbusyctrl;
5006 		bcopy(&int_val, arg, val_size);
5007 		break;
5008 
5009 	case IOV_SVAL(IOV_MESBUSYCTRL):
5010 		mesbusyctrl = (uint)int_val;
5011 		mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK)
5012 			? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl;
5013 		DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl));
5014 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
5015 			((uint8)mesbusyctrl | 0x80), NULL);
5016 		break;
5017 #endif /* define(USE_SDIOFIFO_IOVAR) || defined(BCMINTERNAL) */
5018 
5019 #ifdef BCMINTERNAL
5020 	case IOV_GVAL(IOV_FIRSTREAD):
5021 		int_val = (int32)firstread;
5022 		bcopy(&int_val, arg, val_size);
5023 		break;
5024 
5025 	case IOV_SVAL(IOV_FIRSTREAD):
5026 		if ((int_val < 12) || (int_val > 32)) {
5027 			bcmerror = BCME_BADARG;
5028 			break;
5029 		}
5030 		firstread = (uint)int_val;
5031 		break;
5032 
5033 	case IOV_GVAL(IOV_TSTOPH):
5034 		int_val = tstoph;
5035 		bcopy(&int_val, arg, val_size);
5036 		break;
5037 
5038 	case IOV_SVAL(IOV_TSTOPH):
5039 		if (tstoph && bus->dhd->busstate == DHD_BUS_DOWN) {
5040 			tstoph = bool_val;
5041 			bus->dhd->busstate = DHD_BUS_DATA;
5042 			if (bus->intr) {
5043 				bus->intdis = FALSE;
5044 				bcmsdh_intr_enable(bus->sdh);
5045 			}
5046 		} else {
5047 			tstoph = bool_val;
5048 		}
5049 		break;
5050 
5051 	case IOV_GVAL(IOV_RETRYDATA):
5052 		int_val = (int32)retrydata;
5053 		bcopy(&int_val, arg, val_size);
5054 		break;
5055 
5056 	case IOV_SVAL(IOV_RETRYDATA):
5057 		retrydata = bool_val;
5058 		break;
5059 
5060 	case IOV_GVAL(IOV_CHECKFIFO):
5061 		int_val = (int32)checkfifo;
5062 		bcopy(&int_val, arg, val_size);
5063 		break;
5064 
5065 	case IOV_SVAL(IOV_CHECKFIFO):
5066 		checkfifo = bool_val;
5067 		break;
5068 
5069 	case IOV_GVAL(IOV_SDF2):
5070 	case IOV_SVAL(IOV_SDF2):
5071 	{
5072 		uint8 *buf;
5073 		int ret = BCME_OK;
5074 
5075 		if (!(buf = MALLOC(bus->dhd->osh, int_val))) {
5076 			bcmerror = BCME_NOMEM;
5077 			break;
5078 		}
5079 
5080 		if (actionid == IOV_SVAL(IOV_SDF2)) {
5081 			ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
5082 				F2SYNC, buf, int_val, NULL, NULL, NULL, 1);
5083 		} else {
5084 			ret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
5085 				F2SYNC, buf, int_val, NULL, NULL, NULL);
5086 		}
5087 		if (ret != BCME_OK) {
5088 			bcmerror = BCME_SDIO_ERROR;
5089 		}
5090 
5091 		MFREE(bus->dhd->osh, buf, int_val);
5092 
5093 		break;
5094 	}
5095 
5096 	case IOV_SVAL(IOV_CPU):
5097 		/* Go to the ARM core */
5098 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5099 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5100 			DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5101 			bcmerror = BCME_ERROR;
5102 			break;
5103 		}
5104 
5105 		/* Take the request action */
5106 		if (bool_val)
5107 			si_core_reset(bus->sih, 0, 0);
5108 		else
5109 			si_core_disable(bus->sih, 0);
5110 
5111 		if (bcmsdh_regfail(bus->sdh))
5112 			bcmerror = BCME_SDIO_ERROR;
5113 
5114 		/* Return to the SDIO core */
5115 		if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
5116 			si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5117 		break;
5118 
5119 	case IOV_GVAL(IOV_CPU):
5120 		/* Go to the ARM core */
5121 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5122 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5123 			DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5124 			bcmerror = BCME_ERROR;
5125 			break;
5126 		}
5127 
5128 		/* Get its status */
5129 		int_val = (int32)si_iscoreup(bus->sih);
5130 		bcopy(&int_val, arg, val_size);
5131 
5132 		/* Return to the SDIO core */
5133 		if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
5134 			si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5135 		break;
5136 
5137 	case IOV_SVAL(IOV_SDRESET):
5138 		bcmsdh_reset(bus->sdh);
5139 		break;
5140 
5141 	case IOV_SVAL(IOV_SDABORT):
5142 		if (int_val == 1 || int_val == 2)
5143 			bcmsdh_abort(bus->sdh, int_val);
5144 		else
5145 			bcmerror = BCME_BADARG;
5146 		break;
5147 
5148 	case IOV_GVAL(IOV_DOFLOW):
5149 		int_val = (int32)dhd_doflow;
5150 		bcopy(&int_val, arg, val_size);
5151 		break;
5152 
5153 	case IOV_SVAL(IOV_DOFLOW):
5154 		dhd_doflow = bool_val;
5155 		/* De flowcontrol if turning off flowcontrol */
5156 		if (!dhd_doflow)
5157 			dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
5158 		break;
5159 
5160 	case IOV_GVAL(IOV_CLOCKPOLL):
5161 		int_val = (int32)bus->clockpoll;
5162 		bcopy(&int_val, arg, val_size);
5163 		break;
5164 
5165 	case IOV_GVAL(IOV_MAXRAMSIZE):
5166 		int_val = (int32)bus->ramsize;
5167 		bcopy(&int_val, arg, val_size);
5168 		break;
5169 
5170 	case IOV_SVAL(IOV_MAXRAMSIZE):
5171 		dhd_dongle_ramsize = int_val;
5172 		dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
5173 		break;
5174 
5175 	case IOV_SVAL(IOV_CLOCKPOLL):
5176 		bus->clockpoll = bool_val;
5177 		break;
5178 #endif /* BCMINTERNAL */
5179 
5180 	case IOV_GVAL(IOV_DONGLEISOLATION):
5181 		int_val = bus->dhd->dongle_isolation;
5182 		bcopy(&int_val, arg, val_size);
5183 		break;
5184 
5185 	case IOV_SVAL(IOV_DONGLEISOLATION):
5186 		bus->dhd->dongle_isolation = bool_val;
5187 		break;
5188 
5189 	case IOV_SVAL(IOV_DEVRESET):
5190 		DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
5191 		           __FUNCTION__, bool_val, bus->dhd->dongle_reset,
5192 		           bus->dhd->busstate));
5193 
5194 		ASSERT(bus->dhd->osh);
5195 		/* ASSERT(bus->cl_devid); */
5196 
5197 		/* must release sdlock, since devreset also acquires it */
5198 		dhd_os_sdunlock(bus->dhd);
5199 		dhd_bus_devreset(bus->dhd, (uint8)bool_val);
5200 		dhd_os_sdlock(bus->dhd);
5201 		break;
5202 	/*
5203 	 * softap firmware is updated through module parameter or android private command
5204 	 */
5205 
5206 	case IOV_GVAL(IOV_DEVRESET):
5207 		DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
5208 
5209 		/* Get its status */
5210 		int_val = (bool) bus->dhd->dongle_reset;
5211 		bcopy(&int_val, arg, val_size);
5212 
5213 		break;
5214 
5215 	case IOV_GVAL(IOV_KSO):
5216 		int_val = dhdsdio_sleepcsr_get(bus);
5217 		bcopy(&int_val, arg, val_size);
5218 		break;
5219 
5220 	case IOV_GVAL(IOV_DEVCAP):
5221 		int_val = dhdsdio_devcap_get(bus);
5222 		bcopy(&int_val, arg, val_size);
5223 		break;
5224 
5225 	case IOV_SVAL(IOV_DEVCAP):
5226 		dhdsdio_devcap_set(bus, (uint8) int_val);
5227 		break;
5228 	case IOV_GVAL(IOV_TXGLOMSIZE):
5229 		int_val = (int32)bus->txglomsize;
5230 		bcopy(&int_val, arg, val_size);
5231 		break;
5232 
5233 	case IOV_SVAL(IOV_TXGLOMSIZE):
5234 		if (int_val > SDPCM_MAXGLOM_SIZE) {
5235 			bcmerror = BCME_ERROR;
5236 		} else {
5237 			bus->txglomsize = (uint)int_val;
5238 		}
5239 		break;
5240 	case IOV_SVAL(IOV_HANGREPORT):
5241 		bus->dhd->hang_report = bool_val;
5242 		DHD_ERROR(("%s: Set hang_report as %d\n", __FUNCTION__, bus->dhd->hang_report));
5243 		break;
5244 
5245 	case IOV_GVAL(IOV_HANGREPORT):
5246 		int_val = (int32)bus->dhd->hang_report;
5247 		bcopy(&int_val, arg, val_size);
5248 		break;
5249 
5250 	case IOV_GVAL(IOV_TXINRX_THRES):
5251 		int_val = bus->txinrx_thres;
5252 		bcopy(&int_val, arg, val_size);
5253 		break;
5254 	case IOV_SVAL(IOV_TXINRX_THRES):
5255 		if (int_val < 0) {
5256 			bcmerror = BCME_BADARG;
5257 		} else {
5258 			bus->txinrx_thres = int_val;
5259 		}
5260 		break;
5261 
5262 	case IOV_GVAL(IOV_SDIO_SUSPEND):
5263 		int_val = (bus->dhd->busstate == DHD_BUS_SUSPEND) ? 1 : 0;
5264 		bcopy(&int_val, arg, val_size);
5265 		break;
5266 
5267 	case IOV_SVAL(IOV_SDIO_SUSPEND):
5268 		if (bool_val) { /* Suspend */
5269 			dhdsdio_suspend(bus);
5270 		}
5271 		else { /* Resume */
5272 			dhdsdio_resume(bus);
5273 		}
5274 		break;
5275 
5276 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
5277 	case IOV_SVAL(IOV_GDB_SERVER):
5278 		if (bool_val == TRUE) {
5279 			debugger_init((void *) bus, &bus_ops, int_val, SI_ENUM_BASE(bus->sih));
5280 		} else {
5281 			debugger_close();
5282 		}
5283 		break;
5284 #endif /* DEBUGGER || DHD_DSCOPE */
5285 
5286 	default:
5287 		bcmerror = BCME_UNSUPPORTED;
5288 		break;
5289 	}
5290 
5291 exit:
5292 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
5293 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
5294 		bus->activity = FALSE;
5295 		dhdsdio_bussleep(bus, TRUE);
5296 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
5297 	}
5298 
5299 	dhd_os_sdunlock(bus->dhd);
5300 
5301 	return bcmerror;
5302 }
5303 
5304 static int
dhdsdio_write_vars(dhd_bus_t * bus)5305 dhdsdio_write_vars(dhd_bus_t *bus)
5306 {
5307 	int bcmerror = 0;
5308 	uint32 varsize, phys_size;
5309 	uint32 varaddr;
5310 	uint8 *vbuffer;
5311 	uint32 varsizew;
5312 #ifdef DHD_DEBUG
5313 	uint8 *nvram_ularray;
5314 #endif /* DHD_DEBUG */
5315 
5316 	/* Even if there are no vars are to be written, we still need to set the ramsize. */
5317 	varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
5318 	varaddr = (bus->ramsize - 4) - varsize;
5319 
5320 	// terence 20150412: fix for nvram failed to download
5321 	if (bus->dhd->conf->chip == BCM43340_CHIP_ID ||
5322 			bus->dhd->conf->chip == BCM43341_CHIP_ID) {
5323 		varsize = varsize ? ROUNDUP(varsize, 64) : 0;
5324 		varaddr = (bus->ramsize - 64) - varsize;
5325 	}
5326 
5327 	varaddr += bus->dongle_ram_base;
5328 
5329 	if (bus->vars) {
5330 		/* XXX: WAR for PR85623 */
5331 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 7)) {
5332 			if (((varaddr & 0x3C) == 0x3C) && (varsize > 4)) {
5333 				DHD_ERROR(("PR85623WAR in place\n"));
5334 				varsize += 4;
5335 				varaddr -= 4;
5336 			}
5337 		}
5338 
5339 		/* XXX In case the controller has trouble with odd bytes... */
5340 		vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
5341 		if (!vbuffer)
5342 			return BCME_NOMEM;
5343 
5344 		bzero(vbuffer, varsize);
5345 		bcopy(bus->vars, vbuffer, bus->varsz);
5346 
5347 		/* Write the vars list */
5348 		bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize);
5349 		if (bcmerror) {
5350 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
5351 				__FUNCTION__, bcmerror, varsize, varaddr));
5352 			return bcmerror;
5353 		}
5354 
5355 #ifdef DHD_DEBUG
5356 		/* Verify NVRAM bytes */
5357 		DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
5358 		nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
5359 		if (!nvram_ularray) {
5360 			MFREE(bus->dhd->osh, vbuffer, varsize);
5361 			return BCME_NOMEM;
5362 		}
5363 
5364 		/* Upload image to verify downloaded contents. */
5365 		memset(nvram_ularray, 0xaa, varsize);
5366 
5367 		/* Read the vars list to temp buffer for comparison */
5368 		bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
5369 		if (bcmerror) {
5370 				DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
5371 					__FUNCTION__, bcmerror, varsize, varaddr));
5372 		}
5373 		/* Compare the org NVRAM with the one read from RAM */
5374 		if (memcmp(vbuffer, nvram_ularray, varsize)) {
5375 			DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
5376 		} else
5377 			DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
5378 			__FUNCTION__));
5379 
5380 		MFREE(bus->dhd->osh, nvram_ularray, varsize);
5381 #endif /* DHD_DEBUG */
5382 
5383 		MFREE(bus->dhd->osh, vbuffer, varsize);
5384 	}
5385 
5386 #ifdef MINIME
5387 	phys_size = bus->ramsize;
5388 #else
5389 	phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
5390 #endif
5391 
5392 	phys_size += bus->dongle_ram_base;
5393 
5394 	/* adjust to the user specified RAM */
5395 	DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
5396 		phys_size, bus->ramsize));
5397 	DHD_INFO(("Vars are at %d, orig varsize is %d\n",
5398 		varaddr, varsize));
5399 	varsize = ((phys_size - 4) - varaddr);
5400 
5401 	/*
5402 	 * Determine the length token:
5403 	 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
5404 	 */
5405 #ifdef DHD_DEBUG
5406 	if (bcmerror) {
5407 		varsizew = 0;
5408 	} else
5409 #endif /* DHD_DEBUG */
5410 	{
5411 		varsizew = varsize / 4;
5412 		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
5413 		varsizew = htol32(varsizew);
5414 	}
5415 
5416 	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
5417 
5418 	/* Write the length token to the last word */
5419 	bcmerror = dhdsdio_membytes(bus, TRUE, (phys_size - 4),
5420 		(uint8*)&varsizew, 4);
5421 
5422 	return bcmerror;
5423 }
5424 
5425 bool
dhd_bus_is_multibp_capable(struct dhd_bus * bus)5426 dhd_bus_is_multibp_capable(struct dhd_bus *bus)
5427 {
5428 	return MULTIBP_CAP(bus->sih);
5429 }
5430 
5431 static int
dhdsdio_download_state(dhd_bus_t * bus,bool enter)5432 dhdsdio_download_state(dhd_bus_t *bus, bool enter)
5433 {
5434 	uint retries;
5435 	int bcmerror = 0;
5436 	int foundcr4 = 0;
5437 
5438 	if (!bus->sih)
5439 		return BCME_ERROR;
5440 	/* To enter download state, disable ARM and reset SOCRAM.
5441 	 * To exit download state, simply reset ARM (default is RAM boot).
5442 	 */
5443 	if (enter) {
5444 		bus->alp_only = TRUE;
5445 
5446 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5447 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5448 			if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
5449 				foundcr4 = 1;
5450 			} else {
5451 				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5452 				bcmerror = BCME_ERROR;
5453 				goto fail;
5454 			}
5455 		}
5456 
5457 		if (!foundcr4) {
5458 			si_core_disable(bus->sih, 0);
5459 			if (bcmsdh_regfail(bus->sdh)) {
5460 				bcmerror = BCME_SDIO_ERROR;
5461 				goto fail;
5462 			}
5463 
5464 			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
5465 				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
5466 				bcmerror = BCME_ERROR;
5467 				goto fail;
5468 			}
5469 
5470 			si_core_reset(bus->sih, 0, 0);
5471 			if (bcmsdh_regfail(bus->sdh)) {
5472 				DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n",
5473 				           __FUNCTION__));
5474 				bcmerror = BCME_SDIO_ERROR;
5475 				goto fail;
5476 			}
5477 
5478 			if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID ||
5479 				CHIPID(bus->sih->chip) == BCM43018_CHIP_ID) {
5480 				/* Disabling Remap for SRAM_3 */
5481 				si_socram_set_bankpda(bus->sih, 0x3, 0x0);
5482 			}
5483 
5484 			/* Clear the top bit of memory */
5485 			if (bus->ramsize) {
5486 				uint32 zeros = 0;
5487 				if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4,
5488 				                     (uint8*)&zeros, 4) < 0) {
5489 					bcmerror = BCME_SDIO_ERROR;
5490 					goto fail;
5491 				}
5492 			}
5493 		} else {
5494 			/* For CR4,
5495 			 * Halt ARM
5496 			 * Remove ARM reset
5497 			 * Read RAM base address [0x18_0000]
5498 			 * [next] Download firmware
5499 			 * [done at else] Populate the reset vector
5500 			 * [done at else] Remove ARM halt
5501 			*/
5502 			/* Halt ARM & remove reset */
5503 			si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
5504 		}
5505 	} else {
5506 		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
5507 			if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
5508 				DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
5509 				bcmerror = BCME_ERROR;
5510 				goto fail;
5511 			}
5512 
5513 			if (!si_iscoreup(bus->sih)) {
5514 				DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
5515 				bcmerror = BCME_ERROR;
5516 				goto fail;
5517 			}
5518 
5519 			if ((bcmerror = dhdsdio_write_vars(bus))) {
5520 				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
5521 				goto fail;
5522 			}
5523 
5524 #ifdef BCMSDIOLITE
5525 			if (!si_setcore(bus->sih, CC_CORE_ID, 0)) {
5526 				DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__));
5527 				bcmerror = BCME_ERROR;
5528 				goto fail;
5529 			}
5530 #else
5531 			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
5532 			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
5533 				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
5534 				bcmerror = BCME_ERROR;
5535 				goto fail;
5536 			}
5537 #endif
5538 			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
5539 
5540 			/* XXX Change standby configuration here if necessary */
5541 
5542 			if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
5543 			    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
5544 				DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
5545 				bcmerror = BCME_ERROR;
5546 				goto fail;
5547 			}
5548 		} else {
5549 			/* cr4 has no socram, but tcm's */
5550 			/* write vars */
5551 			if ((bcmerror = dhdsdio_write_vars(bus))) {
5552 				DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
5553 				goto fail;
5554 			}
5555 #ifdef BCMSDIOLITE
5556 			if (!si_setcore(bus->sih, CC_CORE_ID, 0)) {
5557 				DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__));
5558 				bcmerror = BCME_ERROR;
5559 				goto fail;
5560 			}
5561 #else
5562 			if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
5563 			    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
5564 				DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
5565 				bcmerror = BCME_ERROR;
5566 				goto fail;
5567 			}
5568 #endif
5569 			W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
5570 
5571 			/* switch back to arm core again */
5572 			if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
5573 				DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
5574 				bcmerror = BCME_ERROR;
5575 				goto fail;
5576 			}
5577 			/* write address 0 with reset instruction */
5578 			bcmerror = dhdsdio_membytes(bus, TRUE, 0,
5579 				(uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
5580 
5581 			if (bcmerror == BCME_OK) {
5582 				uint32 tmp;
5583 
5584 				/* verify write */
5585 				bcmerror = dhdsdio_membytes(bus, FALSE, 0,
5586 				                            (uint8 *)&tmp, sizeof(tmp));
5587 
5588 				if (bcmerror == BCME_OK && tmp != bus->resetinstr) {
5589 					DHD_ERROR(("%s: Failed to write 0x%08x to addr 0\n",
5590 					          __FUNCTION__, bus->resetinstr));
5591 					DHD_ERROR(("%s: contents of addr 0 is 0x%08x\n",
5592 					          __FUNCTION__, tmp));
5593 					bcmerror = BCME_SDIO_ERROR;
5594 					goto fail;
5595 				}
5596 			}
5597 
5598 			/* now remove reset and halt and continue to run CR4 */
5599 		}
5600 
5601 		si_core_reset(bus->sih, 0, 0);
5602 		if (bcmsdh_regfail(bus->sdh)) {
5603 			DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
5604 			bcmerror = BCME_SDIO_ERROR;
5605 			goto fail;
5606 		}
5607 
5608 		/* Allow HT Clock now that the ARM is running. */
5609 		bus->alp_only = FALSE;
5610 
5611 		bus->dhd->busstate = DHD_BUS_LOAD;
5612 	}
5613 
5614 fail:
5615 	/* Always return to SDIOD core */
5616 	if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
5617 		si_setcore(bus->sih, SDIOD_CORE_ID, 0);
5618 
5619 	return bcmerror;
5620 }
5621 
5622 int
dhd_bus_iovar_op(dhd_pub_t * dhdp,const char * name,void * params,uint plen,void * arg,uint len,bool set)5623 dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
5624                  void *params, uint plen, void *arg, uint len, bool set)
5625 {
5626 	dhd_bus_t *bus = dhdp->bus;
5627 	const bcm_iovar_t *vi = NULL;
5628 	int bcmerror = 0;
5629 	uint val_size;
5630 	uint32 actionid;
5631 
5632 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5633 
5634 	ASSERT(name);
5635 
5636 	/* Get MUST have return space */
5637 	ASSERT(set || (arg && len));
5638 
5639 	/* Set does NOT take qualifiers */
5640 	ASSERT(!set || (!params && !plen));
5641 
5642 	/* Look up var locally; if not found pass to host driver */
5643 	if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
5644 		dhd_os_sdlock(bus->dhd);
5645 
5646 		BUS_WAKE(bus);
5647 
5648 		/* Turn on clock in case SD command needs backplane */
5649 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5650 
5651 		bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
5652 
5653 		/* Check for bus configuration changes of interest */
5654 
5655 		/* If it was divisor change, read the new one */
5656 		if (set && strcmp(name, "sd_divisor") == 0) {
5657 			if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
5658 			                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
5659 				bus->sd_divisor = -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_divisor));
5664 			}
5665 		}
5666 		/* If it was a mode change, read the new one */
5667 		if (set && strcmp(name, "sd_mode") == 0) {
5668 			if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
5669 			                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
5670 				bus->sd_mode = -1;
5671 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
5672 			} else {
5673 				DHD_INFO(("%s: noted %s update, value now %d\n",
5674 				          __FUNCTION__, name, bus->sd_mode));
5675 			}
5676 		}
5677 		/* Similar check for blocksize change */
5678 		if (set && strcmp(name, "sd_blocksize") == 0) {
5679 			int32 fnum = 2;
5680 			if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
5681 			                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
5682 				bus->blocksize = 0;
5683 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
5684 			} else {
5685 				DHD_INFO(("%s: noted %s update, value now %d\n",
5686 				          __FUNCTION__, "sd_blocksize", bus->blocksize));
5687 
5688 				dhdsdio_tune_fifoparam(bus);
5689 			}
5690 		}
5691 		bus->roundup = MIN(max_roundup, bus->blocksize);
5692 
5693 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
5694 			NO_OTHER_ACTIVE_BUS_USER(bus)) {
5695 			bus->activity = FALSE;
5696 			dhdsdio_bussleep(bus, TRUE);
5697 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
5698 		}
5699 
5700 		dhd_os_sdunlock(bus->dhd);
5701 		goto exit;
5702 	}
5703 
5704 	DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
5705 	         name, (set ? "set" : "get"), len, plen));
5706 
5707 	/* set up 'params' pointer in case this is a set command so that
5708 	 * the convenience int and bool code can be common to set and get
5709 	 */
5710 	if (params == NULL) {
5711 		params = arg;
5712 		plen = len;
5713 	}
5714 
5715 	if (vi->type == IOVT_VOID)
5716 		val_size = 0;
5717 	else if (vi->type == IOVT_BUFFER)
5718 		val_size = len;
5719 	else
5720 		/* all other types are integer sized */
5721 		val_size = sizeof(int);
5722 
5723 	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
5724 	bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
5725 
5726 exit:
5727 	return bcmerror;
5728 }
5729 
5730 void
dhd_bus_stop(struct dhd_bus * bus,bool enforce_mutex)5731 dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
5732 {
5733 	osl_t *osh;
5734 	uint32 local_hostintmask;
5735 	uint8 saveclk;
5736 	uint retries;
5737 	int err;
5738 	bool wlfc_enabled = FALSE;
5739 	unsigned long flags;
5740 
5741 	if (!bus->dhd)
5742 		return;
5743 
5744 	osh = bus->dhd->osh;
5745 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5746 
5747 	bcmsdh_waitlockfree(bus->sdh);
5748 
5749 	if (enforce_mutex)
5750 		dhd_os_sdlock(bus->dhd);
5751 
5752 	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) {
5753 		/* if Firmware already hangs disbale any interrupt */
5754 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
5755 		bus->dhd->busstate = DHD_BUS_DOWN;
5756 		bus->hostintmask = 0;
5757 		bcmsdh_intr_disable(bus->sdh);
5758 	} else {
5759 
5760 		BUS_WAKE(bus);
5761 
5762 		if (KSO_ENAB(bus)) {
5763 
5764 		/* Enable clock for device interrupts */
5765 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5766 
5767 		/* Disable and clear interrupts at the chip level also */
5768 		W_SDREG(0, &bus->regs->hostintmask, retries);
5769 		local_hostintmask = bus->hostintmask;
5770 		bus->hostintmask = 0;
5771 
5772 		/* Force clocks on backplane to be sure F2 interrupt propagates */
5773 		saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
5774 		if (!err) {
5775 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5776 			                 (saveclk | SBSDIO_FORCE_HT), &err);
5777 		}
5778 		if (err) {
5779 			DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
5780 			            __FUNCTION__, err));
5781 		}
5782 
5783 		/* Turn off the bus (F2), free any pending packets */
5784 		/* XXX How to wake up any waiting processes? */
5785 		/* XXX New API: bcmsdh_fn_set(bus->sdh, SDIO_FUNC_2, FALSE); */
5786 		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
5787 #if !defined(NDIS)
5788 		bcmsdh_intr_disable(bus->sdh); /* XXX bcmsdh_intr_mask(bus->sdh); */
5789 #endif /* !defined(NDIS) */
5790 #ifndef BCMSPI
5791 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
5792 #endif /* !BCMSPI */
5793 
5794 		/* Clear any pending interrupts now that F2 is disabled */
5795 		W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
5796 		}
5797 
5798 		/* Turn off the backplane clock (only) */
5799 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
5800 
5801 		/* Change our idea of bus state */
5802 		DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
5803 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
5804 		bus->dhd->busstate = DHD_BUS_DOWN;
5805 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
5806 	}
5807 
5808 #ifdef PROP_TXSTATUS
5809 	wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED);
5810 #endif
5811 	if (!wlfc_enabled) {
5812 #ifdef DHDTCPACK_SUPPRESS
5813 		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
5814 		 * when there is a newly coming packet from network stack.
5815 		 */
5816 		dhd_tcpack_info_tbl_clean(bus->dhd);
5817 #endif /* DHDTCPACK_SUPPRESS */
5818 		dhd_os_sdlock_txq(bus->dhd);
5819 		/* Clear the data packet queues */
5820 		pktq_flush(osh, &bus->txq, TRUE);
5821 		dhd_os_sdunlock_txq(bus->dhd);
5822 	}
5823 
5824 	/* Clear any held glomming stuff */
5825 	if (bus->glomd)
5826 		PKTFREE(osh, bus->glomd, FALSE);
5827 
5828 	if (bus->glom)
5829 		PKTFREE(osh, bus->glom, FALSE);
5830 
5831 	bus->glom = bus->glomd = NULL;
5832 
5833 	/* Clear rx control and wake any waiters */
5834 	/* XXX More important in disconnect, but no context? */
5835 	bus->rxlen = 0;
5836 	dhd_os_ioctl_resp_wake(bus->dhd);
5837 
5838 	/* Reset some F2 state stuff */
5839 	bus->rxskip = FALSE;
5840 	bus->tx_seq = bus->rx_seq = 0;
5841 
5842 	/* Initializing tx_max to a reasonable value to start xfer
5843 	 * Gets updated to correct value after receving the first
5844 	 * packet from firmware
5845 	 * XXX - Need to find a right mechanism to querry from
5846 	 * firmware when the device is coming up
5847 	 */
5848 	bus->tx_max = 4;
5849 
5850 	if (enforce_mutex)
5851 		dhd_os_sdunlock(bus->dhd);
5852 }
5853 
5854 #if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD)
5855 extern uint sd_txglom;
5856 #endif
5857 void
dhd_txglom_enable(dhd_pub_t * dhdp,bool enable)5858 dhd_txglom_enable(dhd_pub_t *dhdp, bool enable)
5859 {
5860 	/* can't enable host txglom by default, some platforms have no
5861 	 * (or crappy) ADMA support and txglom will cause kernel assertions (e.g.
5862 	 * panda board)
5863 	 */
5864 	dhd_bus_t *bus = dhdp->bus;
5865 #ifdef BCMSDIOH_TXGLOM
5866 	uint32 rxglom;
5867 	int32 ret;
5868 
5869 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5870 
5871 #ifdef BCMSDIOH_STD
5872 	if (enable)
5873 		enable = sd_txglom;
5874 #endif /* BCMSDIOH_STD */
5875 
5876 	if (enable) {
5877 		rxglom = 1;
5878 		ret = dhd_iovar(dhdp, 0, "bus:rxglom", (char *)&rxglom, sizeof(rxglom), NULL, 0,
5879 				TRUE);
5880 		if (ret >= 0)
5881 			bus->txglom_enable = TRUE;
5882 		else {
5883 #ifdef BCMSDIOH_STD
5884 			sd_txglom = 0;
5885 #endif /* BCMSDIOH_STD */
5886 			bus->txglom_enable = FALSE;
5887 		}
5888 	} else
5889 #endif /* BCMSDIOH_TXGLOM */
5890 		bus->txglom_enable = FALSE;
5891 	printf("%s: enable %d\n",  __FUNCTION__, bus->txglom_enable);
5892 	dhd_conf_set_txglom_params(bus->dhd, bus->txglom_enable);
5893 	bcmsdh_set_mode(bus->sdh, bus->dhd->conf->txglom_mode);
5894 }
5895 
5896 int
dhd_bus_init(dhd_pub_t * dhdp,bool enforce_mutex)5897 dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
5898 {
5899 	dhd_bus_t *bus = dhdp->bus;
5900 	dhd_timeout_t tmo;
5901 	uint retries = 0;
5902 	uint8 ready, enable;
5903 	int err, ret = 0;
5904 #ifdef BCMSPI
5905 	uint32 dstatus = 0;	/* gSPI device-status bits */
5906 #else /* BCMSPI */
5907 	uint8 saveclk;
5908 #endif /* BCMSPI */
5909 #if defined(SDIO_ISR_THREAD)
5910 	int intr_extn;
5911 #endif
5912 
5913 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
5914 
5915 	ASSERT(bus->dhd);
5916 	if (!bus->dhd)
5917 		return 0;
5918 
5919 	if (enforce_mutex)
5920 		dhd_os_sdlock(bus->dhd);
5921 
5922 	if (bus->sih->chip == BCM43362_CHIP_ID) {
5923 		printf("%s: delay 100ms for BCM43362\n", __FUNCTION__);
5924 		OSL_DELAY(100000); // terence 20131209: delay for 43362
5925 	}
5926 
5927 	/* Make sure backplane clock is on, needed to generate F2 interrupt */
5928 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
5929 	if (bus->clkstate != CLK_AVAIL) {
5930 		DHD_ERROR(("%s: clock state is wrong. state = %d\n", __FUNCTION__, bus->clkstate));
5931 		ret = -1;
5932 		goto exit;
5933 	}
5934 
5935 #ifdef BCMSPI
5936 	/* fake "ready" for spi, wake-wlan would have already enabled F1 and F2 */
5937 	ready = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
5938 	enable = 0;
5939 
5940 	/* Give the dongle some time to do its thing and set IOR2 */
5941 	dhd_timeout_start(&tmo, WAIT_F2RXFIFORDY * WAIT_F2RXFIFORDY_DELAY * 1000);
5942 	while (!enable && !dhd_timeout_expired(&tmo)) {
5943 		dstatus = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL);
5944 		if (dstatus & STATUS_F2_RX_READY)
5945 			enable = TRUE;
5946 	}
5947 
5948 	if (enable) {
5949 		DHD_ERROR(("Took %u usec before dongle is ready\n", tmo.elapsed));
5950 		enable = ready;
5951 	} else {
5952 		DHD_ERROR(("dstatus when timed out on f2-fifo not ready = 0x%x\n", dstatus));
5953 		DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed));
5954 		ret = -1;
5955 		goto exit;
5956 	}
5957 
5958 #else /* !BCMSPI */
5959 	/* Force clocks on backplane to be sure F2 interrupt propagates */
5960 	saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
5961 
5962 	if (!err) {
5963 #ifndef BCMQT
5964 		/* QT requires HT clock */
5965 		if (bus->sih->chip == BCM43012_CHIP_ID ||
5966 			bus->sih->chip == BCM43013_CHIP_ID ||
5967 			bus->sih->chip == BCM43014_CHIP_ID) {
5968 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5969 				(saveclk | SBSDIO_HT_AVAIL_REQ), &err);
5970 		} else
5971 #endif /* BCMQT */
5972 		{
5973 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5974 				(saveclk | SBSDIO_FORCE_HT), &err);
5975 		}
5976 	}
5977 
5978 	if (err) {
5979 		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
5980 		ret = -1;
5981 		goto exit;
5982 	}
5983 
5984 	/* Enable function 2 (frame transfers) */
5985 	/* XXX New API: change to bcmsdh_fn_set(sdh, SDIO_FUNC_2, TRUE); */
5986 	W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
5987 	        &bus->regs->tosbmailboxdata, retries);
5988 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
5989 
5990 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
5991 
5992 	/* Give the dongle some time to do its thing and set IOR2 */
5993 #ifdef BCMSLTGT
5994 	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000 * htclkratio);
5995 #else
5996 	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
5997 #endif /* BCMSLTGT */
5998 
5999 	ready = 0;
6000 	while (ready != enable && !dhd_timeout_expired(&tmo))
6001 	        ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
6002 
6003 #endif /* !BCMSPI */
6004 
6005 	DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
6006 	          __FUNCTION__, enable, ready, tmo.elapsed));
6007 
6008 #if defined(SDIO_ISR_THREAD)
6009 	if (dhdp->conf->intr_extn) {
6010 		intr_extn = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTR_EXTN, NULL);
6011 		if (intr_extn & 0x1) {
6012 			intr_extn |= 0x2;
6013 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTR_EXTN, intr_extn, NULL);
6014 		}
6015 	}
6016 #endif
6017 
6018 	/* XXX For simplicity, fail and await next call if F2 not ready.
6019 	 * XXX Should really set timer to poll, and/or enable interrupt;
6020 	 * XXX then put this process in wait until a result...
6021 	 */
6022 
6023 	/* If F2 successfully enabled, set core and enable interrupts */
6024 	if (ready == enable) {
6025 		/* Make sure we're talking to the core. */
6026 #ifdef BCMSDIOLITE
6027 		bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0);
6028 		ASSERT(bus->regs != NULL);
6029 #else
6030 		if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
6031 			bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
6032 		ASSERT(bus->regs != NULL);
6033 #endif
6034 		/* Set up the interrupt mask and enable interrupts */
6035 		bus->hostintmask = HOSTINTMASK;
6036 		/* corerev 4 could use the newer interrupt logic to detect the frames */
6037 #ifndef BCMSPI
6038 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) &&
6039 			(bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) {
6040 			bus->hostintmask &= ~I_HMB_FRAME_IND;
6041 			bus->hostintmask |= I_XMTDATA_AVAIL;
6042 		}
6043 #endif /* BCMSPI */
6044 		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
6045 
6046 		/* PR47410 - Lower F2 Watermark to avoid DMA Hang
6047 		 * in F2 when SD Clock is stopped.
6048 		 */
6049 		if (bus->sih->buscorerev < 15) {
6050 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
6051 				(uint8)watermark, &err);
6052 		}
6053 
6054 		/* Set bus state according to enable result */
6055 		dhdp->busstate = DHD_BUS_DATA;
6056 
6057 		/* Need to set fn2 block size to match fn1 block size.
6058 		 * Requests to fn2 go thru fn1. *
6059 		 * faltwig has this code contitioned with #if !BCMSPI_ANDROID.
6060 		 * It would be cleaner to use the ->sdh->block_sz[fno] instead of
6061 		 * 64, but this layer has no access to sdh types.
6062 		 */
6063 #if defined(NDIS)
6064 	{
6065 		uint8 *ptr = NULL;
6066 		uint16 block_sz = 64;
6067 		ptr = (uint8*) &block_sz;
6068 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0,
6069 			(SDIOD_FBR_BASE(SDIO_FUNC_2) + SDIOD_CCCR_BLKSIZE_0),
6070 			*ptr++, &err);
6071 		if (err == BCME_OK)
6072 			bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0,
6073 			(SDIOD_FBR_BASE(SDIO_FUNC_2) + SDIOD_CCCR_BLKSIZE_1),
6074 			*ptr++, &err);
6075 		if (err != BCME_OK) {
6076 			printf("%s: set block size for func 2 failed\n",
6077 				__FUNCTION__);
6078 			ret = -1;
6079 			goto exit;
6080 		}
6081 	}
6082 #endif /* NDIS */
6083 
6084 		/* XXX These need to change w/API updates */
6085 		/* bcmsdh_intr_unmask(bus->sdh); */
6086 
6087 		bus->intdis = FALSE;
6088 		if (bus->intr) {
6089 			DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
6090 #ifndef BCMSPI_ANDROID
6091 			bcmsdh_intr_enable(bus->sdh);
6092 #endif /* !BCMSPI_ANDROID */
6093 		} else {
6094 			DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
6095 			bcmsdh_intr_disable(bus->sdh);
6096 		}
6097 
6098 #ifdef DEBUG_LOST_INTERRUPTS
6099 		{
6100 			uint32 intstatus;
6101 			bool hostpending;
6102 			uint8 devena, devpend;
6103 			uint sdr_retries = 0;
6104 
6105 			hostpending = bcmsdh_intr_pending(bus->sdh);
6106 			devena = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL);
6107 			devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTPEND, NULL);
6108 
6109 			R_SDREG(intstatus, &bus->regs->intstatus, sdr_retries);
6110 			intstatus &= bus->hostintmask;
6111 
6112 			DHD_ERROR(("%s: interrupts -- host %s device ena/pend 0x%02x/0x%02x\n"
6113 			           "intstatus 0x%08x, hostmask 0x%08x\n", __FUNCTION__,
6114 			           (hostpending ? "PENDING" : "NOT PENDING"),
6115 			           devena, devpend, intstatus, bus->hostintmask));
6116 		}
6117 #endif /* DEBUG_LOST_INTERRUPTS */
6118 	}
6119 
6120 #ifndef BCMSPI
6121 
6122 	else {
6123 		if (dhdp->conf->chip == BCM4354_CHIP_ID) {
6124 			ret = -1;
6125 			goto exit;
6126 		}
6127 		/* Disable F2 again */
6128 		enable = SDIO_FUNC_ENABLE_1;
6129 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
6130 	}
6131 
6132 	if (dhdsdio_sr_cap(bus)) {
6133 		dhdsdio_sr_init(bus);
6134 		/* Masking the chip active interrupt  permanantly */
6135 		bus->hostintmask &= ~I_CHIPACTIVE;
6136 		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
6137 		DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
6138 		__FUNCTION__, bus->hostintmask));
6139 	} else {
6140 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
6141 			SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
6142 	}
6143 #endif /* !BCMSPI */
6144 
6145 	/* If we didn't come up, turn off backplane clock */
6146 	if (dhdp->busstate != DHD_BUS_DATA)
6147 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
6148 
6149 exit:
6150 	if (enforce_mutex)
6151 		dhd_os_sdunlock(bus->dhd);
6152 
6153 	/* XXX Temp errnum workaround: return ok, caller checks bus state */
6154 	return ret;
6155 }
6156 
6157 static void
dhdsdio_rxfail(dhd_bus_t * bus,bool abort,bool rtx)6158 dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
6159 {
6160 	bcmsdh_info_t *sdh = bus->sdh;
6161 	sdpcmd_regs_t *regs = bus->regs;
6162 	uint retries = 0;
6163 	uint16 lastrbc;
6164 	uint8 hi, lo;
6165 	int err;
6166 
6167 	DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
6168 	           (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
6169 
6170 	if (!KSO_ENAB(bus)) {
6171 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
6172 		return;
6173 	}
6174 
6175 	if (abort) {
6176 		bcmsdh_abort(sdh, SDIO_FUNC_2);
6177 	}
6178 
6179 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
6180 	if (err) {
6181 		DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__));
6182 		goto fail;
6183 	}
6184 	bus->f1regdata++;
6185 
6186 	/* Wait until the packet has been flushed (device/FIFO stable) */
6187 	for (lastrbc = retries = 0xffff; retries > 0; retries--) {
6188 		hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
6189 		lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, &err);
6190 		if (err) {
6191 			DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__));
6192 			goto fail;
6193 		}
6194 
6195 		bus->f1regdata += 2;
6196 
6197 		if ((hi == 0) && (lo == 0))
6198 			break;
6199 
6200 		if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
6201 			DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
6202 			           __FUNCTION__, lastrbc, ((hi << 8) + lo)));
6203 		}
6204 		lastrbc = (hi << 8) + lo;
6205 	}
6206 
6207 	if (!retries) {
6208 		DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
6209 	} else {
6210 		DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
6211 	}
6212 
6213 	if (rtx) {
6214 		bus->rxrtx++;
6215 		W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
6216 		bus->f1regdata++;
6217 		if (retries <= retry_limit) {
6218 			bus->rxskip = TRUE;
6219 		}
6220 	}
6221 
6222 	/* Clear partial in any case */
6223 	bus->nextlen = 0;
6224 
6225 fail:
6226 	/* If we can't reach the device, signal failure */
6227 	if (err || bcmsdh_regfail(sdh)) {
6228 		DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
6229 		bus->dhd->busstate = DHD_BUS_DOWN;
6230 	}
6231 }
6232 
6233 static void
dhdsdio_read_control(dhd_bus_t * bus,uint8 * hdr,uint len,uint doff)6234 dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
6235 {
6236 	bcmsdh_info_t *sdh = bus->sdh;
6237 	uint rdlen, pad;
6238 
6239 	int sdret;
6240 
6241 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
6242 
6243 	/* Control data already received in aligned rxctl */
6244 	if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
6245 		goto gotpkt;
6246 
6247 	ASSERT(bus->rxbuf);
6248 	/* Set rxctl for frame (w/optional alignment) */
6249 	bus->rxctl = bus->rxbuf;
6250 	if (dhd_alignctl) {
6251 		bus->rxctl += firstread;
6252 		if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
6253 			bus->rxctl += (DHD_SDALIGN - pad);
6254 		bus->rxctl -= firstread;
6255 	}
6256 	ASSERT(bus->rxctl >= bus->rxbuf);
6257 
6258 	/* Copy the already-read portion over */
6259 	bcopy(hdr, bus->rxctl, firstread);
6260 	if (len <= firstread)
6261 		goto gotpkt;
6262 
6263 	/* Copy the full data pkt in gSPI case and process ioctl. */
6264 	if (bus->bus == SPI_BUS) {
6265 		bcopy(hdr, bus->rxctl, len);
6266 		goto gotpkt;
6267 	}
6268 
6269 	/* Raise rdlen to next SDIO block to avoid tail command */
6270 	rdlen = len - firstread;
6271 	if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
6272 		pad = bus->blocksize - (rdlen % bus->blocksize);
6273 		if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
6274 		    ((len + pad) < bus->dhd->maxctl))
6275 			rdlen += pad;
6276 	} else if (rdlen % DHD_SDALIGN) {
6277 		rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
6278 	}
6279 
6280 	/* Satisfy length-alignment requirements */
6281 	if (forcealign && (rdlen & (ALIGNMENT - 1)))
6282 		rdlen = ROUNDUP(rdlen, ALIGNMENT);
6283 
6284 	/* Drop if the read is too big or it exceeds our maximum */
6285 	if ((rdlen + firstread) > bus->dhd->maxctl) {
6286 		DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
6287 		           __FUNCTION__, rdlen, bus->dhd->maxctl));
6288 		bus->dhd->rx_errors++;
6289 		dhdsdio_rxfail(bus, FALSE, FALSE);
6290 		goto done;
6291 	}
6292 
6293 	if ((len - doff) > bus->dhd->maxctl) {
6294 		DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
6295 		           __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
6296 		bus->dhd->rx_errors++; bus->rx_toolong++;
6297 		dhdsdio_rxfail(bus, FALSE, FALSE);
6298 		goto done;
6299 	}
6300 
6301 	/* XXX Could block readers with rxlen=0? */
6302 
6303 	/* Read remainder of frame body into the rxctl buffer */
6304 	sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
6305 	                            (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
6306 	bus->f2rxdata++;
6307 	ASSERT(sdret != BCME_PENDING);
6308 
6309 	/* Control frame failures need retransmission */
6310 	if (sdret < 0) {
6311 		DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
6312 		bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
6313 		dhdsdio_rxfail(bus, TRUE, TRUE);
6314 		goto done;
6315 	}
6316 
6317 gotpkt:
6318 
6319 #ifdef DHD_DEBUG
6320 	if (DHD_BYTES_ON() && DHD_CTL_ON()) {
6321 		prhex("RxCtrl", bus->rxctl, len);
6322 	}
6323 #endif
6324 
6325 	/* Point to valid data and indicate its length */
6326 	bus->rxctl += doff;
6327 	bus->rxlen = len - doff;
6328 
6329 done:
6330 	/* Awake any waiters */
6331 	dhd_os_ioctl_resp_wake(bus->dhd);
6332 }
6333 int
6334 dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
6335 	void **pkt, uint32 *pkt_count);
6336 
6337 static uint8
dhdsdio_rxglom(dhd_bus_t * bus,uint8 rxseq)6338 dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
6339 {
6340 	uint16 dlen, totlen;
6341 	uint8 *dptr, num = 0;
6342 
6343 	uint16 sublen, check;
6344 	void *pfirst, *plast, *pnext;
6345 	void * list_tail[DHD_MAX_IFS] = { NULL };
6346 	void * list_head[DHD_MAX_IFS] = { NULL };
6347 	uint8 idx;
6348 	osl_t *osh = bus->dhd->osh;
6349 
6350 	int errcode;
6351 	uint8 chan, seq, doff, sfdoff;
6352 	uint8 txmax;
6353 	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
6354 	uint reorder_info_len;
6355 
6356 	int ifidx = 0;
6357 	bool usechain = bus->use_rxchain;
6358 
6359 	/* If packets, issue read(s) and send up packet chain */
6360 	/* Return sequence numbers consumed? */
6361 
6362 	DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
6363 
6364 	/* If there's a descriptor, generate the packet chain */
6365 	if (bus->glomd) {
6366 		dhd_os_sdlock_rxq(bus->dhd);
6367 
6368 		pfirst = plast = pnext = NULL;
6369 		dlen = (uint16)PKTLEN(osh, bus->glomd);
6370 		dptr = PKTDATA(osh, bus->glomd);
6371 		if (!dlen || (dlen & 1)) {
6372 			DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
6373 			           __FUNCTION__, dlen));
6374 			dlen = 0;
6375 		}
6376 
6377 		for (totlen = num = 0; dlen; num++) {
6378 			/* Get (and move past) next length */
6379 			sublen = ltoh16_ua(dptr);
6380 			dlen -= sizeof(uint16);
6381 			dptr += sizeof(uint16);
6382 			if ((sublen < SDPCM_HDRLEN) ||
6383 			    ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
6384 				DHD_ERROR(("%s: descriptor len %d bad: %d\n",
6385 				           __FUNCTION__, num, sublen));
6386 				pnext = NULL;
6387 				break;
6388 			}
6389 			if (sublen % DHD_SDALIGN) {
6390 				DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
6391 				           __FUNCTION__, sublen, DHD_SDALIGN));
6392 				usechain = FALSE;
6393 			}
6394 			totlen += sublen;
6395 
6396 			/* For last frame, adjust read len so total is a block multiple */
6397 			if (!dlen) {
6398 				sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
6399 				totlen = ROUNDUP(totlen, bus->blocksize);
6400 			}
6401 
6402 			/* Allocate/chain packet for next subframe */
6403 			if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
6404 				DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
6405 				           __FUNCTION__, num, sublen));
6406 				break;
6407 			}
6408 			ASSERT(!PKTLINK(pnext));
6409 			if (!pfirst) {
6410 				ASSERT(!plast);
6411 				pfirst = plast = pnext;
6412 			} else {
6413 				ASSERT(plast);
6414 				PKTSETNEXT(osh, plast, pnext);
6415 				plast = pnext;
6416 			}
6417 
6418 			/* Adhere to start alignment requirements */
6419 			PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
6420 		}
6421 
6422 		/* If all allocations succeeded, save packet chain in bus structure */
6423 		if (pnext) {
6424 			DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
6425 			          __FUNCTION__, totlen, num));
6426 			if (DHD_GLOM_ON() && bus->nextlen) {
6427 				if (totlen != bus->nextlen) {
6428 					DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
6429 					          "rxseq %d\n", __FUNCTION__, bus->nextlen,
6430 					          totlen, rxseq));
6431 				}
6432 			}
6433 			bus->glom = pfirst;
6434 			pfirst = pnext = NULL;
6435 		} else {
6436 			if (pfirst)
6437 				PKTFREE(osh, pfirst, FALSE);
6438 			bus->glom = NULL;
6439 			num = 0;
6440 		}
6441 
6442 		/* Done with descriptor packet */
6443 		PKTFREE(osh, bus->glomd, FALSE);
6444 		bus->glomd = NULL;
6445 		bus->nextlen = 0;
6446 
6447 		dhd_os_sdunlock_rxq(bus->dhd);
6448 	}
6449 
6450 	/* Ok -- either we just generated a packet chain, or had one from before */
6451 	if (bus->glom) {
6452 		if (DHD_GLOM_ON()) {
6453 			DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
6454 			for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
6455 				DHD_GLOM(("    %p: %p len 0x%04x (%d)\n",
6456 				          pnext, (uint8*)PKTDATA(osh, pnext),
6457 				          PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
6458 			}
6459 		}
6460 
6461 		pfirst = bus->glom;
6462 		dlen = (uint16)pkttotlen(osh, pfirst);
6463 
6464 		/* Do an SDIO read for the superframe.  Configurable iovar to
6465 		 * read directly into the chained packet, or allocate a large
6466 		 * packet and and copy into the chain.
6467 		 */
6468 		if (usechain) {
6469 			errcode = dhd_bcmsdh_recv_buf(bus,
6470 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
6471 			                              F2SYNC, (uint8*)PKTDATA(osh, pfirst),
6472 			                              dlen, pfirst, NULL, NULL);
6473 		} else if (bus->dataptr) {
6474 			errcode = dhd_bcmsdh_recv_buf(bus,
6475 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
6476 			                              F2SYNC, bus->dataptr,
6477 			                              dlen, NULL, NULL, NULL);
6478 			sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
6479 			if (sublen != dlen) {
6480 				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
6481 				           __FUNCTION__, dlen, sublen));
6482 				errcode = -1;
6483 			}
6484 			pnext = NULL;
6485 			BCM_REFERENCE(pnext);
6486 		} else {
6487 			DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
6488 			errcode = -1;
6489 		}
6490 		bus->f2rxdata++;
6491 		ASSERT(errcode != BCME_PENDING);
6492 
6493 		/* On failure, kill the superframe, allow a couple retries */
6494 		if (errcode < 0) {
6495 			DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
6496 			           __FUNCTION__, dlen, errcode));
6497 			bus->dhd->rx_errors++; /* XXX Account for rtx?? */
6498 
6499 			if (bus->glomerr++ < 3) {
6500 				dhdsdio_rxfail(bus, TRUE, TRUE);
6501 			} else {
6502 				bus->glomerr = 0;
6503 				dhdsdio_rxfail(bus, TRUE, FALSE);
6504 				dhd_os_sdlock_rxq(bus->dhd);
6505 				PKTFREE(osh, bus->glom, FALSE);
6506 				dhd_os_sdunlock_rxq(bus->dhd);
6507 				bus->rxglomfail++;
6508 				bus->glom = NULL;
6509 			}
6510 			return 0;
6511 		}
6512 
6513 #ifdef DHD_DEBUG
6514 		if (DHD_GLOM_ON()) {
6515 			prhex("SUPERFRAME", PKTDATA(osh, pfirst),
6516 			      MIN(PKTLEN(osh, pfirst), 48));
6517 		}
6518 #endif
6519 
6520 		/* Validate the superframe header */
6521 		dptr = (uint8 *)PKTDATA(osh, pfirst);
6522 		sublen = ltoh16_ua(dptr);
6523 		check = ltoh16_ua(dptr + sizeof(uint16));
6524 
6525 		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6526 		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
6527 		bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
6528 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
6529 			DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
6530 			          __FUNCTION__, bus->nextlen, seq));
6531 			bus->nextlen = 0;
6532 		}
6533 		doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6534 		txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6535 
6536 		errcode = 0;
6537 		if ((uint16)~(sublen^check)) {
6538 			DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
6539 			           __FUNCTION__, sublen, check));
6540 			errcode = -1;
6541 		} else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
6542 			DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
6543 			           __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
6544 			errcode = -1;
6545 		} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
6546 			DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
6547 			           SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
6548 			errcode = -1;
6549 		} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
6550 			DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
6551 			errcode = -1;
6552 		} else if ((doff < SDPCM_HDRLEN) ||
6553 		           (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
6554 			DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
6555 				__FUNCTION__, doff, sublen, PKTLEN(osh, pfirst),
6556 				SDPCM_HDRLEN));
6557 			errcode = -1;
6558 		}
6559 
6560 		/* Check sequence number of superframe SW header */
6561 		if (rxseq != seq) {
6562 			DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
6563 			          __FUNCTION__, seq, rxseq));
6564 			bus->rx_badseq++;
6565 			rxseq = seq;
6566 		}
6567 
6568 		/* Check window for sanity */
6569 		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
6570 			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
6571 			           __FUNCTION__, txmax, bus->tx_seq));
6572 			txmax = bus->tx_max;
6573 		}
6574 		bus->tx_max = txmax;
6575 
6576 		/* Remove superframe header, remember offset */
6577 		PKTPULL(osh, pfirst, doff);
6578 		sfdoff = doff;
6579 
6580 		/* Validate all the subframe headers */
6581 		for (num = 0, pnext = pfirst; pnext && !errcode;
6582 		     num++, pnext = PKTNEXT(osh, pnext)) {
6583 			dptr = (uint8 *)PKTDATA(osh, pnext);
6584 			dlen = (uint16)PKTLEN(osh, pnext);
6585 			sublen = ltoh16_ua(dptr);
6586 			check = ltoh16_ua(dptr + sizeof(uint16));
6587 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6588 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6589 #ifdef DHD_DEBUG
6590 			if (DHD_GLOM_ON()) {
6591 				prhex("subframe", dptr, 32);
6592 			}
6593 #endif
6594 
6595 			if ((uint16)~(sublen^check)) {
6596 				DHD_ERROR(("%s (subframe %d): HW hdr error: "
6597 				           "len/check 0x%04x/0x%04x\n",
6598 				           __FUNCTION__, num, sublen, check));
6599 				errcode = -1;
6600 			} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
6601 				DHD_ERROR(("%s (subframe %d): length mismatch: "
6602 				           "len 0x%04x, expect 0x%04x\n",
6603 				           __FUNCTION__, num, sublen, dlen));
6604 				errcode = -1;
6605 			} else if ((chan != SDPCM_DATA_CHANNEL) &&
6606 			           (chan != SDPCM_EVENT_CHANNEL)) {
6607 				DHD_ERROR(("%s (subframe %d): bad channel %d\n",
6608 				           __FUNCTION__, num, chan));
6609 				errcode = -1;
6610 			} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
6611 				DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
6612 				           __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
6613 				errcode = -1;
6614 			}
6615 		}
6616 
6617 		if (errcode) {
6618 			/* Terminate frame on error, request a couple retries */
6619 			if (bus->glomerr++ < 3) {
6620 				/* Restore superframe header space */
6621 				PKTPUSH(osh, pfirst, sfdoff);
6622 				dhdsdio_rxfail(bus, TRUE, TRUE);
6623 			} else {
6624 				bus->glomerr = 0;
6625 				dhdsdio_rxfail(bus, TRUE, FALSE);
6626 				dhd_os_sdlock_rxq(bus->dhd);
6627 				PKTFREE(osh, bus->glom, FALSE);
6628 				dhd_os_sdunlock_rxq(bus->dhd);
6629 				bus->rxglomfail++;
6630 				bus->glom = NULL;
6631 			}
6632 			bus->nextlen = 0;
6633 			return 0;
6634 		}
6635 
6636 		/* Basic SD framing looks ok - process each packet (header) */
6637 		bus->glom = NULL;
6638 		plast = NULL;
6639 
6640 		dhd_os_sdlock_rxq(bus->dhd);
6641 		for (num = 0; pfirst; rxseq++, pfirst = pnext) {
6642 			pnext = PKTNEXT(osh, pfirst);
6643 			PKTSETNEXT(osh, pfirst, NULL);
6644 
6645 			dptr = (uint8 *)PKTDATA(osh, pfirst);
6646 			sublen = ltoh16_ua(dptr);
6647 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
6648 			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
6649 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
6650 
6651 			DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
6652 			          __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
6653 			          PKTLEN(osh, pfirst), sublen, chan, seq));
6654 
6655 			ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
6656 
6657 			if (rxseq != seq) {
6658 				DHD_GLOM(("%s: rx_seq %d, expected %d\n",
6659 				          __FUNCTION__, seq, rxseq));
6660 				bus->rx_badseq++;
6661 				rxseq = seq;
6662 			}
6663 
6664 #ifdef DHD_DEBUG
6665 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
6666 				prhex("Rx Subframe Data", dptr, dlen);
6667 			}
6668 #endif
6669 
6670 			PKTSETLEN(osh, pfirst, sublen);
6671 			PKTPULL(osh, pfirst, doff);
6672 
6673 			reorder_info_len = sizeof(reorder_info_buf);
6674 
6675 			if (PKTLEN(osh, pfirst) == 0) {
6676 				PKTFREE(bus->dhd->osh, pfirst, FALSE);
6677 				continue;
6678 			} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf,
6679 				&reorder_info_len) != 0) {
6680 				DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
6681 				bus->dhd->rx_errors++;
6682 				PKTFREE(osh, pfirst, FALSE);
6683 				continue;
6684 			}
6685 			if (reorder_info_len) {
6686 				uint32 free_buf_count;
6687 				void *ppfirst;
6688 
6689 				ppfirst = pfirst;
6690 				/* Reordering info from the firmware */
6691 				dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf,
6692 					reorder_info_len, &ppfirst, &free_buf_count);
6693 
6694 				if (free_buf_count == 0) {
6695 					continue;
6696 				} else {
6697 					void *temp;
6698 
6699 					/*  go to the end of the chain and attach the pnext there */
6700 					temp = ppfirst;
6701 					while (PKTNEXT(osh, temp) != NULL) {
6702 						temp = PKTNEXT(osh, temp);
6703 					}
6704 					pfirst = temp;
6705 					if (list_tail[ifidx] == NULL)
6706 						list_head[ifidx] = ppfirst;
6707 					else
6708 						PKTSETNEXT(osh, list_tail[ifidx], ppfirst);
6709 					list_tail[ifidx] = pfirst;
6710 				}
6711 
6712 				num += (uint8)free_buf_count;
6713 			} else {
6714 				/* this packet will go up, link back into chain and count it */
6715 
6716 				if (list_tail[ifidx] == NULL) {
6717 					list_head[ifidx] = list_tail[ifidx] = pfirst;
6718 				} else {
6719 					PKTSETNEXT(osh, list_tail[ifidx], pfirst);
6720 					list_tail[ifidx] = pfirst;
6721 				}
6722 				num++;
6723 			}
6724 #ifdef DHD_DEBUG
6725 			if (DHD_GLOM_ON()) {
6726 				DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
6727 				          __FUNCTION__, num, pfirst,
6728 				          PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
6729 				          PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
6730 				prhex("", (uint8 *)PKTDATA(osh, pfirst),
6731 				      MIN(PKTLEN(osh, pfirst), 32));
6732 			}
6733 #endif /* DHD_DEBUG */
6734 		}
6735 		dhd_os_sdunlock_rxq(bus->dhd);
6736 
6737 		for (idx = 0; idx < DHD_MAX_IFS; idx++) {
6738 			if (list_head[idx]) {
6739 				void *temp;
6740 				uint8 cnt = 0;
6741 				temp = list_head[idx];
6742 				do {
6743 					temp = PKTNEXT(osh, temp);
6744 					cnt++;
6745 				} while (temp);
6746 				if (cnt) {
6747 					dhd_os_sdunlock(bus->dhd);
6748 					dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
6749 					dhd_os_sdlock(bus->dhd);
6750 				}
6751 			}
6752 		}
6753 		bus->rxglomframes++;
6754 		bus->rxglompkts += num;
6755 	}
6756 	return num;
6757 }
6758 
6759 /* Return TRUE if there may be more frames to read */
6760 static uint
dhdsdio_readframes(dhd_bus_t * bus,uint maxframes,bool * finished)6761 dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
6762 {
6763 	osl_t *osh = bus->dhd->osh;
6764 	bcmsdh_info_t *sdh = bus->sdh;
6765 
6766 	uint16 len, check;	/* Extracted hardware header fields */
6767 	uint8 chan, seq, doff;	/* Extracted software header fields */
6768 	uint8 fcbits;		/* Extracted fcbits from software header */
6769 	uint8 delta;
6770 
6771 	void *pkt;	/* Packet for event or data frames */
6772 	uint16 pad;	/* Number of pad bytes to read */
6773 	uint16 rdlen;	/* Total number of bytes to read */
6774 	uint8 rxseq;	/* Next sequence number to expect */
6775 	uint rxleft = 0;	/* Remaining number of frames allowed */
6776 	int sdret;	/* Return code from bcmsdh calls */
6777 	uint8 txmax;	/* Maximum tx sequence offered */
6778 #ifdef BCMSPI
6779 	uint32 dstatus = 0;	/* gSPI device status bits of */
6780 #endif /* BCMSPI */
6781 	bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
6782 	uint8 *rxbuf;
6783 	int ifidx = 0;
6784 	uint rxcount = 0; /* Total frames read */
6785 	uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
6786 	uint reorder_info_len;
6787 	uint pkt_count;
6788 
6789 #if defined(DHD_DEBUG) || defined(SDTEST)
6790 	bool sdtest = FALSE;	/* To limit message spew from test mode */
6791 #endif
6792 
6793 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
6794 	bus->readframes = TRUE;
6795 
6796 	if (!KSO_ENAB(bus)) {
6797 		DHD_ERROR(("%s: KSO off\n", __FUNCTION__));
6798 		bus->readframes = FALSE;
6799 		return 0;
6800 	}
6801 
6802 	ASSERT(maxframes);
6803 
6804 #ifdef SDTEST
6805 	/* Allow pktgen to override maxframes */
6806 	if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
6807 		maxframes = bus->pktgen_count;
6808 		sdtest = TRUE;
6809 	}
6810 #endif
6811 
6812 	/* Not finished unless we encounter no more frames indication */
6813 	*finished = FALSE;
6814 
6815 #ifdef BCMSPI
6816 	/* Get pktlen from gSPI device F0 reg. */
6817 	if (bus->bus == SPI_BUS) {
6818 		/* Peek in dstatus bits and find out size to do rx-read. */
6819 		dstatus = bcmsdh_get_dstatus(bus->sdh);
6820 		if (dstatus == 0)
6821 			DHD_ERROR(("%s:ZERO spi dstatus, a case observed in PR61352 hit !!!\n",
6822 			           __FUNCTION__));
6823 
6824 		DHD_TRACE(("Device status from regread = 0x%x\n", dstatus));
6825 		DHD_TRACE(("Device status from bit-reconstruction = 0x%x\n",
6826 		          bcmsdh_get_dstatus((void *)bus->sdh)));
6827 
6828 		/* Check underflow also, WAR for PR55150 */
6829 		if ((dstatus & STATUS_F2_PKT_AVAILABLE) && (((dstatus & STATUS_UNDERFLOW)) == 0)) {
6830 			bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
6831 			                STATUS_F2_PKT_LEN_SHIFT);
6832 			/* '0' size with pkt-available interrupt is eqvt to 2048 bytes */
6833 			bus->nextlen = (bus->nextlen == 0) ? SPI_MAX_PKT_LEN : bus->nextlen;
6834 			if (bus->dwordmode)
6835 				bus->nextlen = bus->nextlen << 2;
6836 			DHD_TRACE(("Entering %s: length to be read from gSPI = %d\n",
6837 			          __FUNCTION__, bus->nextlen));
6838 		} else {
6839 			if (dstatus & STATUS_F2_PKT_AVAILABLE)
6840 				DHD_ERROR(("Underflow during %s.\n", __FUNCTION__));
6841 			else
6842 				DHD_ERROR(("False pkt-available intr.\n"));
6843 			*finished = TRUE;
6844 			return (maxframes - rxleft);
6845 		}
6846 	}
6847 #endif /* BCMSPI */
6848 
6849 	for (rxseq = bus->rx_seq, rxleft = maxframes;
6850 	     !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
6851 	     rxseq++, rxleft--) {
6852 #ifdef DHDTCPACK_SUP_DBG
6853 		if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_DELAYTX) {
6854 			if (bus->dotxinrx == FALSE)
6855 				DHD_ERROR(("%s %d: dotxinrx FALSE with tcpack_sub_mode %d\n",
6856 					__FUNCTION__, __LINE__, bus->dhd->tcpack_sup_mode));
6857 		}
6858 #ifdef DEBUG_COUNTER
6859 		else if (pktq_mlen(&bus->txq, ~bus->flowcontrol) > 0) {
6860 			tack_tbl.cnt[bus->dotxinrx ? 6 : 7]++;
6861 		}
6862 #endif /* DEBUG_COUNTER */
6863 #endif /* DHDTCPACK_SUP_DBG */
6864 		/* tx more to improve rx performance */
6865 		if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
6866 			dhdsdio_sendpendctl(bus);
6867 		} else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
6868 			!bus->fcstate && DATAOK(bus) &&
6869 			(pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
6870 			dhdsdio_sendfromq(bus, dhd_txbound);
6871 #ifdef DHDTCPACK_SUPPRESS
6872 			/* In TCPACK_SUP_DELAYTX mode, do txinrx only if
6873 			 * 1. Any DATA packet to TX
6874 			 * 2. TCPACK to TCPDATA PSH packets.
6875 			 * in bus txq.
6876 			 */
6877 			bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ?
6878 				FALSE : TRUE;
6879 #endif
6880 		}
6881 
6882 		/* Handle glomming separately */
6883 		if (bus->glom || bus->glomd) {
6884 			uint8 cnt;
6885 			DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
6886 			          __FUNCTION__, bus->glomd, bus->glom));
6887 			cnt = dhdsdio_rxglom(bus, rxseq);
6888 			DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
6889 			rxseq += cnt - 1;
6890 			rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
6891 			continue;
6892 		}
6893 
6894 		/* Try doing single read if we can */
6895 		if (dhd_readahead && bus->nextlen) {
6896 			uint16 nextlen = bus->nextlen;
6897 			bus->nextlen = 0;
6898 
6899 			if (bus->bus == SPI_BUS) {
6900 				rdlen = len = nextlen;
6901 			} else {
6902 				rdlen = len = nextlen << 4;
6903 
6904 				/* Pad read to blocksize for efficiency */
6905 				if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
6906 					pad = bus->blocksize - (rdlen % bus->blocksize);
6907 					if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
6908 						((rdlen + pad + firstread) < MAX_RX_DATASZ))
6909 						rdlen += pad;
6910 				} else if (rdlen % DHD_SDALIGN) {
6911 					rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
6912 				}
6913 			}
6914 
6915 			/* We use bus->rxctl buffer in WinXP for initial control pkt receives.
6916 			 * Later we use buffer-poll for data as well as control packets.
6917 			 * This is required because dhd receives full frame in gSPI unlike SDIO.
6918 			 * After the frame is received we have to distinguish whether it is data
6919 			 * or non-data frame.
6920 			 */
6921 			/* Allocate a packet buffer */
6922 			dhd_os_sdlock_rxq(bus->dhd);
6923 			if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
6924 				if (bus->bus == SPI_BUS) {
6925 					bus->usebufpool = FALSE;
6926 					bus->rxctl = bus->rxbuf;
6927 					if (dhd_alignctl) {
6928 						bus->rxctl += firstread;
6929 						if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
6930 							bus->rxctl += (DHD_SDALIGN - pad);
6931 						bus->rxctl -= firstread;
6932 					}
6933 					ASSERT(bus->rxctl >= bus->rxbuf);
6934 					rxbuf = bus->rxctl;
6935 					/* Read the entire frame */
6936 					sdret = dhd_bcmsdh_recv_buf(bus,
6937 					                            bcmsdh_cur_sbwad(sdh),
6938 					                            SDIO_FUNC_2,
6939 					                            F2SYNC, rxbuf, rdlen,
6940 					                            NULL, NULL, NULL);
6941 					bus->f2rxdata++;
6942 					ASSERT(sdret != BCME_PENDING);
6943 
6944 #ifdef BCMSPI
6945 					/* PR55150 WAR: Wait for next pkt-available interrupt for
6946 					 * further processing
6947 					 */
6948 					if (bcmsdh_get_dstatus((void *)bus->sdh) &
6949 					                STATUS_UNDERFLOW) {
6950 						bus->nextlen = 0;
6951 						*finished = TRUE;
6952 						DHD_ERROR(("%s: read %d control bytes failed "
6953 						           "due to spi underflow\n",
6954 						           __FUNCTION__, rdlen));
6955 						/* dhd.rx_ctlerrs is higher level */
6956 						bus->rxc_errors++;
6957 						dhd_os_sdunlock_rxq(bus->dhd);
6958 						continue;
6959 					}
6960 #endif /* BCMSPI */
6961 
6962 					/* Control frame failures need retransmission */
6963 					if (sdret < 0) {
6964 						DHD_ERROR(("%s: read %d control bytes failed: %d\n",
6965 						   __FUNCTION__, rdlen, sdret));
6966 						/* dhd.rx_ctlerrs is higher level */
6967 						bus->rxc_errors++;
6968 						dhd_os_sdunlock_rxq(bus->dhd);
6969 						dhdsdio_rxfail(bus, TRUE,
6970 						    (bus->bus == SPI_BUS) ? FALSE : TRUE);
6971 						continue;
6972 					}
6973 				} else {
6974 					/* Give up on data, request rtx of events */
6975 					DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
6976 					           "expected rxseq %d\n",
6977 					           __FUNCTION__, len, rdlen, rxseq));
6978 					/* XXX Can't issue retry (NAK), frame not started. */
6979 					/* Just go try again w/normal header read */
6980 					dhd_os_sdunlock_rxq(bus->dhd);
6981 					continue;
6982 				}
6983 			} else {
6984 				if (bus->bus == SPI_BUS)
6985 					bus->usebufpool = TRUE;
6986 
6987 				ASSERT(!PKTLINK(pkt));
6988 				PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
6989 				rxbuf = (uint8 *)PKTDATA(osh, pkt);
6990 				/* Read the entire frame */
6991 				sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
6992 				                            SDIO_FUNC_2,
6993 				                            F2SYNC, rxbuf, rdlen,
6994 				                            pkt, NULL, NULL);
6995 				bus->f2rxdata++;
6996 				ASSERT(sdret != BCME_PENDING);
6997 #ifdef BCMSPI
6998 				/* PR55150 WAR: Wait for next pkt-available interrupt for further
6999 				 * processing
7000 				 */
7001 				if (bcmsdh_get_dstatus((void *)bus->sdh) & STATUS_UNDERFLOW) {
7002 					bus->nextlen = 0;
7003 					*finished = TRUE;
7004 					DHD_ERROR(("%s (nextlen): read %d bytes failed due "
7005 					           "to spi underflow\n",
7006 					           __FUNCTION__, rdlen));
7007 					PKTFREE(bus->dhd->osh, pkt, FALSE);
7008 					bus->dhd->rx_errors++;
7009 					dhd_os_sdunlock_rxq(bus->dhd);
7010 					continue;
7011 				}
7012 #endif /* BCMSPI */
7013 
7014 				if (sdret < 0) {
7015 					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
7016 					   __FUNCTION__, rdlen, sdret));
7017 					PKTFREE(bus->dhd->osh, pkt, FALSE);
7018 					bus->dhd->rx_errors++; /* XXX Account for rtx?? */
7019 					dhd_os_sdunlock_rxq(bus->dhd);
7020 					/* Force retry w/normal header read.  Don't attempt NAK for
7021 					 * gSPI
7022 					 */
7023 					dhdsdio_rxfail(bus, TRUE,
7024 					      (bus->bus == SPI_BUS) ? FALSE : TRUE);
7025 					continue;
7026 				}
7027 			}
7028 			dhd_os_sdunlock_rxq(bus->dhd);
7029 
7030 			/* Now check the header */
7031 			bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
7032 
7033 			/* Extract hardware header fields */
7034 			len = ltoh16_ua(bus->rxhdr);
7035 			check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
7036 
7037 			/* All zeros means readahead info was bad */
7038 			if (!(len|check)) {
7039 				DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
7040 				           __FUNCTION__));
7041 				dhd_os_sdlock_rxq(bus->dhd);
7042 				PKTFREE2();
7043 				dhd_os_sdunlock_rxq(bus->dhd);
7044 				GSPI_PR55150_BAILOUT;
7045 				continue;
7046 			}
7047 
7048 			/* Validate check bytes */
7049 			if ((uint16)~(len^check)) {
7050 				DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
7051 				           " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
7052 				           len, check));
7053 				dhd_os_sdlock_rxq(bus->dhd);
7054 				PKTFREE2();
7055 				dhd_os_sdunlock_rxq(bus->dhd);
7056 				bus->rx_badhdr++;
7057 				dhdsdio_rxfail(bus, FALSE, FALSE);
7058 				GSPI_PR55150_BAILOUT;
7059 				continue;
7060 			}
7061 
7062 			/* Validate frame length */
7063 			if (len < SDPCM_HDRLEN) {
7064 				/* XXX Might choose to allow length 4 for signaling */
7065 				DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
7066 				           __FUNCTION__, len));
7067 				dhd_os_sdlock_rxq(bus->dhd);
7068 				PKTFREE2();
7069 				dhd_os_sdunlock_rxq(bus->dhd);
7070 				GSPI_PR55150_BAILOUT;
7071 				continue;
7072 			}
7073 
7074 			/* Check for consistency with readahead info */
7075 #ifdef BCMSPI
7076 			if (bus->bus == SPI_BUS) {
7077 				if (bus->dwordmode) {
7078 					uint16 spilen;
7079 					spilen = ROUNDUP(len, 4);
7080 					len_consistent = (nextlen != spilen);
7081 				} else
7082 					len_consistent = (nextlen != len);
7083 			} else
7084 #endif  /* BCMSPI */
7085 				len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
7086 			if (len_consistent) {
7087 				/* Mismatch, force retry w/normal header (may be >4K) */
7088 				DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
7089 				           "expected rxseq %d\n",
7090 				           __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
7091 				dhd_os_sdlock_rxq(bus->dhd);
7092 				PKTFREE2();
7093 				dhd_os_sdunlock_rxq(bus->dhd);
7094 				dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
7095 				GSPI_PR55150_BAILOUT;
7096 				continue;
7097 			}
7098 
7099 			/* Extract software header fields */
7100 			chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7101 			seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7102 			doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7103 			txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7104 
7105 #ifdef BCMSPI
7106 			/* Save the readahead length if there is one */
7107 			if (bus->bus == SPI_BUS) {
7108 				/* Use reconstructed dstatus bits and find out readahead size */
7109 				dstatus = bcmsdh_get_dstatus((void *)bus->sdh);
7110 				DHD_INFO(("Device status from bit-reconstruction = 0x%x\n",
7111 				bcmsdh_get_dstatus((void *)bus->sdh)));
7112 				if (dstatus & STATUS_F2_PKT_AVAILABLE) {
7113 					bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
7114 					                STATUS_F2_PKT_LEN_SHIFT);
7115 					bus->nextlen = (bus->nextlen == 0) ?
7116 					           SPI_MAX_PKT_LEN : bus->nextlen;
7117 					if (bus->dwordmode)
7118 						bus->nextlen = bus->nextlen << 2;
7119 					DHD_INFO(("readahead len from gSPI = %d \n",
7120 					           bus->nextlen));
7121 					bus->dhd->rx_readahead_cnt ++;
7122 				} else {
7123 					bus->nextlen = 0;
7124 					*finished = TRUE;
7125 				}
7126 			} else {
7127 #endif /* BCMSPI */
7128 				bus->nextlen =
7129 				         bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
7130 				if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
7131 					DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
7132 					          " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
7133 					          seq));
7134 					bus->nextlen = 0;
7135 				}
7136 
7137 				bus->dhd->rx_readahead_cnt ++;
7138 #ifdef BCMSPI
7139 			}
7140 #endif /* BCMSPI */
7141 			/* Handle Flow Control */
7142 			fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7143 
7144 			delta = 0;
7145 			if (~bus->flowcontrol & fcbits) {
7146 				bus->fc_xoff++;
7147 				delta = 1;
7148 			}
7149 			if (bus->flowcontrol & ~fcbits) {
7150 				bus->fc_xon++;
7151 				delta = 1;
7152 			}
7153 
7154 			if (delta) {
7155 				bus->fc_rcvd++;
7156 				bus->flowcontrol = fcbits;
7157 			}
7158 
7159 			/* Check and update sequence number */
7160 			if (rxseq != seq) {
7161 				DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
7162 				          __FUNCTION__, seq, rxseq));
7163 				bus->rx_badseq++;
7164 				rxseq = seq;
7165 			}
7166 
7167 			/* Check window for sanity */
7168 			if ((uint8)(txmax - bus->tx_seq) > 0x70) {
7169 #ifdef BCMSPI
7170 				if ((bus->bus == SPI_BUS) && !(dstatus & STATUS_F2_RX_READY)) {
7171 					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
7172 						__FUNCTION__, txmax, bus->tx_seq));
7173 					txmax = bus->tx_seq + 2;
7174 				} else {
7175 #endif /* BCMSPI */
7176 					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
7177 						__FUNCTION__, txmax, bus->tx_seq));
7178 					txmax = bus->tx_max;
7179 #ifdef BCMSPI
7180 				}
7181 #endif /* BCMSPI */
7182 			}
7183 			bus->tx_max = txmax;
7184 
7185 #ifdef DHD_DEBUG
7186 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
7187 				prhex("Rx Data", rxbuf, len);
7188 			} else if (DHD_HDRS_ON()) {
7189 				prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
7190 			}
7191 #endif
7192 
7193 			if (chan == SDPCM_CONTROL_CHANNEL) {
7194 				if (bus->bus == SPI_BUS) {
7195 					dhdsdio_read_control(bus, rxbuf, len, doff);
7196 					if (bus->usebufpool) {
7197 						dhd_os_sdlock_rxq(bus->dhd);
7198 						PKTFREE(bus->dhd->osh, pkt, FALSE);
7199 						dhd_os_sdunlock_rxq(bus->dhd);
7200 					}
7201 					continue;
7202 				} else {
7203 					DHD_ERROR(("%s (nextlen): readahead on control"
7204 					           " packet %d?\n", __FUNCTION__, seq));
7205 					/* Force retry w/normal header read */
7206 					bus->nextlen = 0;
7207 					dhdsdio_rxfail(bus, FALSE, TRUE);
7208 					dhd_os_sdlock_rxq(bus->dhd);
7209 					PKTFREE2();
7210 					dhd_os_sdunlock_rxq(bus->dhd);
7211 					continue;
7212 				}
7213 			}
7214 
7215 			if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
7216 				DHD_ERROR(("Received %d bytes on %d channel. Running out of "
7217 				           "rx pktbuf's or not yet malloced.\n", len, chan));
7218 				continue;
7219 			}
7220 
7221 			/* Validate data offset */
7222 			if ((doff < SDPCM_HDRLEN) || (doff > len)) {
7223 				DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
7224 				           __FUNCTION__, doff, len, SDPCM_HDRLEN));
7225 				dhd_os_sdlock_rxq(bus->dhd);
7226 				PKTFREE2();
7227 				dhd_os_sdunlock_rxq(bus->dhd);
7228 				ASSERT(0);
7229 				dhdsdio_rxfail(bus, FALSE, FALSE);
7230 				continue;
7231 			}
7232 
7233 			/* All done with this one -- now deliver the packet */
7234 			goto deliver;
7235 		}
7236 		/* gSPI frames should not be handled in fractions */
7237 		if (bus->bus == SPI_BUS) {
7238 			break;
7239 		}
7240 
7241 		/* Read frame header (hardware and software) */
7242 		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
7243 		                            bus->rxhdr, firstread, NULL, NULL, NULL);
7244 		bus->f2rxhdrs++;
7245 		ASSERT(sdret != BCME_PENDING);
7246 
7247 		if (sdret < 0) {
7248 			DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
7249 			bus->rx_hdrfail++;
7250 #ifdef BCMINTERNAL
7251 			if (tstoph) {
7252 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7253 				bus->dhd->busstate = DHD_BUS_DOWN;
7254 				continue;
7255 			}
7256 #endif
7257 			dhdsdio_rxfail(bus, TRUE, TRUE);
7258 			continue;
7259 		}
7260 
7261 #ifdef DHD_DEBUG
7262 		if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
7263 			prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
7264 		}
7265 #endif
7266 
7267 		/* Extract hardware header fields */
7268 		len = ltoh16_ua(bus->rxhdr);
7269 		check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
7270 
7271 		/* All zeros means no more frames */
7272 		if (!(len|check)) {
7273 			*finished = TRUE;
7274 			break;
7275 		}
7276 
7277 		/* Validate check bytes */
7278 		if ((uint16)~(len^check)) {
7279 			DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
7280 			           __FUNCTION__, len, check));
7281 			bus->rx_badhdr++;
7282 			dhdsdio_rxfail(bus, FALSE, FALSE);
7283 			continue;
7284 		}
7285 
7286 		/* Validate frame length */
7287 		if (len < SDPCM_HDRLEN) {
7288 			/* XXX Might choose to allow length 4 for signaling */
7289 			DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len));
7290 			continue;
7291 		}
7292 
7293 		/* Extract software header fields */
7294 		chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7295 		seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7296 		doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7297 		txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7298 
7299 		/* Validate data offset */
7300 		if ((doff < SDPCM_HDRLEN) || (doff > len)) {
7301 			DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
7302 			           __FUNCTION__, doff, len, SDPCM_HDRLEN, seq));
7303 			bus->rx_badhdr++;
7304 			ASSERT(0);
7305 			dhdsdio_rxfail(bus, FALSE, FALSE);
7306 			continue;
7307 		}
7308 
7309 		/* Save the readahead length if there is one */
7310 		bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
7311 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
7312 			DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
7313 			          __FUNCTION__, bus->nextlen, seq));
7314 			bus->nextlen = 0;
7315 		}
7316 
7317 		/* Handle Flow Control */
7318 		fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
7319 
7320 		delta = 0;
7321 		if (~bus->flowcontrol & fcbits) {
7322 			bus->fc_xoff++;
7323 			delta = 1;
7324 		}
7325 		if (bus->flowcontrol & ~fcbits) {
7326 			bus->fc_xon++;
7327 			delta = 1;
7328 		}
7329 
7330 		if (delta) {
7331 			bus->fc_rcvd++;
7332 			bus->flowcontrol = fcbits;
7333 		}
7334 
7335 		/* Check and update sequence number */
7336 		if (rxseq != seq) {
7337 			DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq));
7338 			bus->rx_badseq++;
7339 			rxseq = seq;
7340 		}
7341 
7342 		/* Check window for sanity */
7343 		if ((uint8)(txmax - bus->tx_seq) > 0x70) {
7344 			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
7345 			           __FUNCTION__, txmax, bus->tx_seq));
7346 			txmax = bus->tx_max;
7347 		}
7348 		bus->tx_max = txmax;
7349 
7350 		/* Call a separate function for control frames */
7351 		if (chan == SDPCM_CONTROL_CHANNEL) {
7352 			dhdsdio_read_control(bus, bus->rxhdr, len, doff);
7353 			continue;
7354 		}
7355 
7356 		ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) ||
7357 		       (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL));
7358 
7359 		/* Length to read */
7360 		rdlen = (len > firstread) ? (len - firstread) : 0;
7361 
7362 		/* May pad read to blocksize for efficiency */
7363 		if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
7364 			pad = bus->blocksize - (rdlen % bus->blocksize);
7365 			if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
7366 			    ((rdlen + pad + firstread) < MAX_RX_DATASZ))
7367 				rdlen += pad;
7368 		} else if (rdlen % DHD_SDALIGN) {
7369 			rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
7370 		}
7371 
7372 		/* Satisfy length-alignment requirements */
7373 		if (forcealign && (rdlen & (ALIGNMENT - 1)))
7374 			rdlen = ROUNDUP(rdlen, ALIGNMENT);
7375 
7376 		if ((rdlen + firstread) > MAX_RX_DATASZ) {
7377 			/* Too long -- skip this frame */
7378 			DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen));
7379 			bus->dhd->rx_errors++; bus->rx_toolong++;
7380 			dhdsdio_rxfail(bus, FALSE, FALSE);
7381 			continue;
7382 		}
7383 
7384 		dhd_os_sdlock_rxq(bus->dhd);
7385 		if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) {
7386 			/* Give up on data, request rtx of events */
7387 			DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n",
7388 			           __FUNCTION__, rdlen, chan));
7389 			bus->dhd->rx_dropped++;
7390 			dhd_os_sdunlock_rxq(bus->dhd);
7391 			dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan));
7392 			continue;
7393 		}
7394 		dhd_os_sdunlock_rxq(bus->dhd);
7395 
7396 		ASSERT(!PKTLINK(pkt));
7397 
7398 		/* XXX Should check len for small packets in case we're done? */
7399 		/* Leave room for what we already read, and align remainder */
7400 		ASSERT(firstread < (PKTLEN(osh, pkt)));
7401 		PKTPULL(osh, pkt, firstread);
7402 		PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
7403 
7404 		/* Read the remaining frame data */
7405 		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
7406 		                            ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL);
7407 		bus->f2rxdata++;
7408 		ASSERT(sdret != BCME_PENDING);
7409 
7410 		if (sdret < 0) {
7411 			DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen,
7412 			           ((chan == SDPCM_EVENT_CHANNEL) ? "event" :
7413 			            ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret));
7414 			dhd_os_sdlock_rxq(bus->dhd);
7415 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7416 			dhd_os_sdunlock_rxq(bus->dhd);
7417 			bus->dhd->rx_errors++; /* XXX Account for rtx?? */
7418 			dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan));
7419 			continue;
7420 		}
7421 
7422 		/* Copy the already-read portion */
7423 		PKTPUSH(osh, pkt, firstread);
7424 		bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread);
7425 
7426 #ifdef DHD_DEBUG
7427 		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
7428 			prhex("Rx Data", PKTDATA(osh, pkt), len);
7429 		}
7430 #endif
7431 
7432 deliver:
7433 		/* Save superframe descriptor and allocate packet frame */
7434 		if (chan == SDPCM_GLOM_CHANNEL) {
7435 			if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
7436 				DHD_GLOM(("%s: got glom descriptor, %d bytes:\n",
7437 				          __FUNCTION__, len));
7438 #ifdef DHD_DEBUG
7439 				if (DHD_GLOM_ON()) {
7440 					prhex("Glom Data", PKTDATA(osh, pkt), len);
7441 				}
7442 #endif
7443 				PKTSETLEN(osh, pkt, len);
7444 				ASSERT(doff == SDPCM_HDRLEN);
7445 				PKTPULL(osh, pkt, SDPCM_HDRLEN);
7446 				bus->glomd = pkt;
7447 			} else {
7448 				DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__));
7449 				dhdsdio_rxfail(bus, FALSE, FALSE);
7450 			}
7451 			continue;
7452 		}
7453 
7454 		/* Fill in packet len and prio, deliver upward */
7455 		PKTSETLEN(osh, pkt, len);
7456 		PKTPULL(osh, pkt, doff);
7457 
7458 #ifdef SDTEST
7459 		/* Test channel packets are processed separately */
7460 		if (chan == SDPCM_TEST_CHANNEL) {
7461 			dhdsdio_testrcv(bus, pkt, seq);
7462 			continue;
7463 		}
7464 #endif /* SDTEST */
7465 
7466 		if (PKTLEN(osh, pkt) == 0) {
7467 			dhd_os_sdlock_rxq(bus->dhd);
7468 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7469 			dhd_os_sdunlock_rxq(bus->dhd);
7470 			continue;
7471 		} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt, reorder_info_buf,
7472 			&reorder_info_len) != 0) {
7473 			DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
7474 			dhd_os_sdlock_rxq(bus->dhd);
7475 			PKTFREE(bus->dhd->osh, pkt, FALSE);
7476 			dhd_os_sdunlock_rxq(bus->dhd);
7477 			bus->dhd->rx_errors++;
7478 			continue;
7479 		}
7480 
7481 		if (reorder_info_len) {
7482 			/* Reordering info from the firmware */
7483 			dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len,
7484 				&pkt, &pkt_count);
7485 			if (pkt_count == 0)
7486 				continue;
7487 		} else {
7488 			pkt_count = 1;
7489 		}
7490 
7491 		/* XXX Release the lock around the rx delivery: an OS (like Windows)
7492 		 * might call tx in the same thread context, resulting in deadlock.
7493 		 */
7494 		/* Unlock during rx call */
7495 		dhd_os_sdunlock(bus->dhd);
7496 		dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
7497 		dhd_os_sdlock(bus->dhd);
7498 #if defined(SDIO_ISR_THREAD)
7499 		/* terence 20150615: fix for below error due to bussleep in watchdog after dhd_os_sdunlock here,
7500 		  * so call BUS_WAKE to wake up bus again
7501 		  * dhd_bcmsdh_recv_buf: Device asleep
7502 		  * dhdsdio_readframes: RXHEADER FAILED: -40
7503 		  * dhdsdio_rxfail: abort command, terminate frame, send NAK
7504 		*/
7505 		BUS_WAKE(bus);
7506 #endif
7507 	}
7508 	rxcount = maxframes - rxleft;
7509 #ifdef DHD_DEBUG
7510 	/* Message if we hit the limit */
7511 	if (!rxleft && !sdtest)
7512 		DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
7513 	else
7514 #endif /* DHD_DEBUG */
7515 	DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
7516 	/* Back off rxseq if awaiting rtx, update rx_seq */
7517 	if (bus->rxskip)
7518 		rxseq--;
7519 	bus->rx_seq = rxseq;
7520 
7521 	if (bus->reqbussleep)
7522 	{
7523 		dhdsdio_bussleep(bus, TRUE);
7524 		bus->reqbussleep = FALSE;
7525 	}
7526 	bus->readframes = FALSE;
7527 
7528 	return rxcount;
7529 }
7530 
7531 static uint32
dhdsdio_hostmail(dhd_bus_t * bus,uint32 * hmbd)7532 dhdsdio_hostmail(dhd_bus_t *bus, uint32 *hmbd)
7533 {
7534 	sdpcmd_regs_t *regs = bus->regs;
7535 	uint32 intstatus = 0;
7536 	uint32 hmb_data;
7537 	uint8 fcbits;
7538 	uint retries = 0;
7539 
7540 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7541 
7542 	/* Read mailbox data and ack that we did so */
7543 	R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
7544 	if (retries <= retry_limit)
7545 		W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
7546 	bus->f1regdata += 2;
7547 
7548 	/* Dongle recomposed rx frames, accept them again */
7549 	if (hmb_data & HMB_DATA_NAKHANDLED) {
7550 		DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq));
7551 		/* XXX ASSERT(bus->rxskip); */
7552 		if (!bus->rxskip) {
7553 			DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__));
7554 		}
7555 		bus->rxskip = FALSE;
7556 		intstatus |= FRAME_AVAIL_MASK(bus);
7557 	}
7558 
7559 	/*
7560 	 * DEVREADY does not occur with gSPI.
7561 	 */
7562 	if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
7563 		bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT;
7564 		if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
7565 			DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n",
7566 			           bus->sdpcm_ver, SDPCM_PROT_VERSION));
7567 		else
7568 			DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
7569 #ifndef BCMSPI
7570 		/* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */
7571 		if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
7572 		    (bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1)) {
7573 			uint32 val;
7574 
7575 			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
7576 			val &= ~CC_XMTDATAAVAIL_MODE;
7577 			val |= CC_XMTDATAAVAIL_CTRL;
7578 			W_REG(bus->dhd->osh, &bus->regs->corecontrol, val);
7579 
7580 			val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
7581 		}
7582 #endif /* BCMSPI */
7583 
7584 #ifdef DHD_DEBUG
7585 		/* Retrieve console state address now that firmware should have updated it */
7586 		{
7587 			sdpcm_shared_t shared;
7588 			if (dhdsdio_readshared(bus, &shared) == 0)
7589 				bus->console_addr = shared.console_addr;
7590 		}
7591 #endif /* DHD_DEBUG */
7592 	}
7593 
7594 	/*
7595 	 * Flow Control has been moved into the RX headers and this out of band
7596 	 * method isn't used any more.  Leave this here for possibly remaining backward
7597 	 * compatible with older dongles
7598 	 */
7599 	if (hmb_data & HMB_DATA_FC) {
7600 		fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT;
7601 
7602 		if (fcbits & ~bus->flowcontrol)
7603 			bus->fc_xoff++;
7604 		if (bus->flowcontrol & ~fcbits)
7605 			bus->fc_xon++;
7606 
7607 		bus->fc_rcvd++;
7608 		bus->flowcontrol = fcbits;
7609 	}
7610 
7611 	/* At least print a message if FW halted */
7612 	if (hmb_data & HMB_DATA_FWHALT) {
7613 		DHD_ERROR(("FIRMWARE HALTED\n"));
7614 		dhdsdio_checkdied(bus, NULL, 0);
7615 	}
7616 
7617 	/* Shouldn't be any others */
7618 	if (hmb_data & ~(HMB_DATA_DEVREADY |
7619 	                 HMB_DATA_FWHALT |
7620 	                 HMB_DATA_NAKHANDLED |
7621 	                 HMB_DATA_FC |
7622 	                 HMB_DATA_FWREADY |
7623 	                 HMB_DATA_FCDATA_MASK |
7624 	                 HMB_DATA_VERSION_MASK)) {
7625 		DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
7626 	}
7627 
7628 	if (hmbd) {
7629 		*hmbd = hmb_data;
7630 	}
7631 
7632 	return intstatus;
7633 }
7634 
7635 #ifdef BCMSDIO_INTSTATUS_WAR
7636 static uint32
dhdsdio_read_intstatus_byte(dhd_bus_t * bus)7637 dhdsdio_read_intstatus_byte(dhd_bus_t *bus)
7638 {
7639 	bcmsdh_info_t *sdh = bus->sdh;
7640 	sdpcmd_regs_t *regs = bus->regs;
7641 	uint32 newstatus = 0, intstatus_byte = 0;
7642 	uint retries = 0;
7643 	int err1 = 0, err2 = 0, err3 = 0, err4 = 0;
7644 
7645 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7646 
7647 	/* read_intr_mode:
7648 	  * 0: word mode only (default)
7649 	  * 1: byte mode after read word failed
7650 	  * 2: byte mode only
7651 	*/
7652 	if (bus->dhd->conf->read_intr_mode) {
7653 		if (bus->dhd->conf->read_intr_mode == 1) {
7654 			R_SDREG(newstatus, &regs->intstatus, retries);
7655 			if (!bcmsdh_regfail(bus->sdh)) {
7656 				goto exit;
7657 			}
7658 		}
7659 		intstatus_byte = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7660 			((unsigned long)&regs->intstatus & 0xffff) + 0, &err1);
7661 		if (!err1)
7662 			newstatus |= intstatus_byte;
7663 		intstatus_byte = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7664 			((unsigned long)&regs->intstatus & 0xffff) + 1, &err2) << 8;
7665 		if (!err2)
7666 			newstatus |= intstatus_byte;
7667 		intstatus_byte |= bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7668 			((unsigned long)&regs->intstatus & 0xffff) + 2, &err3) << 16;
7669 		if (!err3)
7670 			newstatus |= intstatus_byte;
7671 		intstatus_byte |= bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
7672 			((unsigned long)&regs->intstatus & 0xffff) + 3, &err4) << 24;
7673 		if (!err4)
7674 			newstatus |= intstatus_byte;
7675 
7676 		if (!err1 || !err2 || !err3 || !err4)
7677 			sdh->regfail = FALSE;
7678 	}
7679 	else {
7680 		R_SDREG(newstatus, &regs->intstatus, retries);
7681 	}
7682 
7683 exit:
7684 	return newstatus;
7685 }
7686 #endif
7687 
7688 static bool
dhdsdio_dpc(dhd_bus_t * bus)7689 dhdsdio_dpc(dhd_bus_t *bus)
7690 {
7691 	bcmsdh_info_t *sdh = bus->sdh;
7692 	sdpcmd_regs_t *regs = bus->regs;
7693 	uint32 intstatus, newstatus = 0;
7694 	uint retries = 0;
7695 	uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
7696 	uint txlimit = dhd_txbound; /* Tx frames to send before resched */
7697 	uint framecnt = 0;		  /* Temporary counter of tx/rx frames */
7698 	bool rxdone = TRUE;		  /* Flag for no more read data */
7699 	bool resched = FALSE;	  /* Flag indicating resched wanted */
7700 	unsigned long flags;
7701 #ifdef DEBUG_DPC_THREAD_WATCHDOG
7702 	bool is_resched_by_readframe = FALSE;
7703 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
7704 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
7705 
7706 	dhd_os_sdlock(bus->dhd);
7707 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
7708 	if (bus->dhd->busstate == DHD_BUS_DOWN) {
7709 		DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
7710 		bus->intstatus = 0;
7711 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
7712 		dhd_os_sdunlock(bus->dhd);
7713 		return 0;
7714 	}
7715 
7716 	DHD_BUS_BUSY_SET_IN_DPC(bus->dhd);
7717 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
7718 
7719 	/* Start with leftover status bits */
7720 	intstatus = bus->intstatus;
7721 
7722 	if (!SLPAUTO_ENAB(bus) && !KSO_ENAB(bus)) {
7723 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
7724 		goto exit;
7725 	}
7726 
7727 	/* If waiting for HTAVAIL, check status */
7728 	if (!SLPAUTO_ENAB(bus) && (bus->clkstate == CLK_PENDING)) {
7729 		int err;
7730 		uint8 clkctl, devctl = 0;
7731 
7732 #ifdef DHD_DEBUG
7733 		/* Check for inconsistent device control */
7734 		devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
7735 		if (err) {
7736 			DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
7737 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7738 			bus->dhd->busstate = DHD_BUS_DOWN;
7739 		} else {
7740 			ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
7741 		}
7742 #endif /* DHD_DEBUG */
7743 
7744 		/* Read CSR, if clock on switch to AVAIL, else ignore */
7745 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
7746 		if (err) {
7747 			DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
7748 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7749 			bus->dhd->busstate = DHD_BUS_DOWN;
7750 		}
7751 
7752 		DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl));
7753 
7754 		if (SBSDIO_HTAV(clkctl)) {
7755 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
7756 			if (err) {
7757 				DHD_ERROR(("%s: error reading DEVCTL: %d\n",
7758 				           __FUNCTION__, err));
7759 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7760 				bus->dhd->busstate = DHD_BUS_DOWN;
7761 			}
7762 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
7763 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
7764 			if (err) {
7765 				DHD_ERROR(("%s: error writing DEVCTL: %d\n",
7766 				           __FUNCTION__, err));
7767 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
7768 				bus->dhd->busstate = DHD_BUS_DOWN;
7769 			}
7770 			bus->clkstate = CLK_AVAIL;
7771 		} else {
7772 			goto clkwait;
7773 		}
7774 	}
7775 
7776 	BUS_WAKE(bus);
7777 
7778 	/* Make sure backplane clock is on */
7779 	dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
7780 	if (bus->clkstate != CLK_AVAIL)
7781 		goto clkwait;
7782 
7783 	/* Pending interrupt indicates new device status */
7784 	if (bus->ipend) {
7785 		bus->ipend = FALSE;
7786 #if defined(BT_OVER_SDIO)
7787 	bcmsdh_btsdio_process_f3_intr();
7788 #endif /* defined (BT_OVER_SDIO) */
7789 
7790 #ifdef BCMSDIO_INTSTATUS_WAR
7791 		newstatus = dhdsdio_read_intstatus_byte(bus);
7792 #else
7793 		R_SDREG(newstatus, &regs->intstatus, retries);
7794 #endif
7795 		bus->f1regdata++;
7796 		if (bcmsdh_regfail(bus->sdh))
7797 			newstatus = 0;
7798 		newstatus &= bus->hostintmask;
7799 		bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
7800 		if (newstatus) {
7801 			bus->f1regdata++;
7802 #ifndef BCMSPI
7803 			if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) &&
7804 				(newstatus == I_XMTDATA_AVAIL)) {
7805 			} else
7806 #endif /* BCMSPI */
7807 				W_SDREG(newstatus, &regs->intstatus, retries);
7808 		}
7809 	}
7810 
7811 	/* Merge new bits with previous */
7812 	intstatus |= newstatus;
7813 	bus->intstatus = 0;
7814 
7815 	/* Handle flow-control change: read new state in case our ack
7816 	 * crossed another change interrupt.  If change still set, assume
7817 	 * FC ON for safety, let next loop through do the debounce.
7818 	 */
7819 	if (intstatus & I_HMB_FC_CHANGE) {
7820 		intstatus &= ~I_HMB_FC_CHANGE;
7821 		W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
7822 		R_SDREG(newstatus, &regs->intstatus, retries);
7823 		bus->f1regdata += 2;
7824 		bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
7825 		intstatus |= (newstatus & bus->hostintmask);
7826 	}
7827 
7828 	/* Handle host mailbox indication */
7829 	if (intstatus & I_HMB_HOST_INT) {
7830 		uint32 hmbdata = 0;
7831 
7832 		intstatus &= ~I_HMB_HOST_INT;
7833 		intstatus |= dhdsdio_hostmail(bus, &hmbdata);
7834 
7835 	}
7836 
7837 #ifdef DHD_UCODE_DOWNLOAD
7838 exit_ucode:
7839 #endif /* DHD_UCODE_DOWNLOAD */
7840 
7841 	/* Just being here means nothing more to do for chipactive */
7842 	if (intstatus & I_CHIPACTIVE) {
7843 		/* ASSERT(bus->clkstate == CLK_AVAIL); */
7844 		intstatus &= ~I_CHIPACTIVE;
7845 	}
7846 
7847 	/* Handle host mailbox indication */
7848 	if (intstatus & I_HMB_HOST_INT) {
7849 		intstatus &= ~I_HMB_HOST_INT;
7850 		intstatus |= dhdsdio_hostmail(bus, NULL);
7851 	}
7852 
7853 	/* Generally don't ask for these, can get CRC errors... */
7854 	/* XXX Besides noting the error, should we ABORT/TERM? */
7855 	if (intstatus & I_WR_OOSYNC) {
7856 		DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
7857 		intstatus &= ~I_WR_OOSYNC;
7858 	}
7859 
7860 	if (intstatus & I_RD_OOSYNC) {
7861 		DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
7862 		intstatus &= ~I_RD_OOSYNC;
7863 	}
7864 
7865 	/* XXX Should reset or something here... */
7866 	if (intstatus & I_SBINT) {
7867 		DHD_ERROR(("Dongle reports SBINT\n"));
7868 		intstatus &= ~I_SBINT;
7869 	}
7870 
7871 	/* Would be active due to wake-wlan in gSPI */
7872 	if (intstatus & I_CHIPACTIVE) {
7873 		DHD_INFO(("Dongle reports CHIPACTIVE\n"));
7874 		intstatus &= ~I_CHIPACTIVE;
7875 	}
7876 
7877 	if (intstatus & I_HMB_FC_STATE) {
7878 		DHD_INFO(("Dongle reports HMB_FC_STATE\n"));
7879 		intstatus &= ~I_HMB_FC_STATE;
7880 	}
7881 
7882 	/* Ignore frame indications if rxskip is set */
7883 	if (bus->rxskip) {
7884 		intstatus &= ~FRAME_AVAIL_MASK(bus);
7885 	}
7886 
7887 	/* On frame indication, read available frames */
7888 	if (PKT_AVAILABLE(bus, intstatus)) {
7889 #ifdef BCMINTERNAL
7890 		if (checkfifo) {
7891 			int count, regerrs = 0;
7892 			uint32 fifoaddr, rdptr, rdoffs, endptrs;
7893 			uint32 datalow[8], datahigh[8];
7894 			uint coretype = bus->sih->buscoretype;
7895 			uint corerev = bus->sdpcmrev;
7896 
7897 			/* set fifoaddr to fetch xmt fifo pointers */
7898 			fifoaddr = (0xB << 16);
7899 			W_SDREG(fifoaddr, &SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr, retries);
7900 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7901 			R_SDREG(rdptr, &SDPCMFIFOREG(bus, coretype, corerev)->fifodatalow, retries);
7902 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7903 
7904 			/* Read the first 8 words out of the FIFO */
7905 			for (count = 0, rdoffs = (rdptr & 0x7F); count < 8; count++) {
7906 				fifoaddr = (0xA << 16) | rdoffs;
7907 				W_SDREG(fifoaddr,
7908 					&SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr,
7909 					retries);
7910 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7911 				R_SDREG(datalow[count],
7912 					&SDPCMFIFOREG(bus, coretype, corerev)->fifodatalow,
7913 					retries);
7914 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7915 				W_SDREG(fifoaddr,
7916 					&SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr,
7917 					retries);
7918 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7919 				R_SDREG(datahigh[count],
7920 					&SDPCMFIFOREG(bus, coretype, corerev)->fifodatahigh,
7921 					retries);
7922 				if (bcmsdh_regfail(bus->sdh)) regerrs++;
7923 				rdoffs = (rdoffs + 1) & 0x7F;
7924 			}
7925 
7926 			/* For the heck of it, read the pointers again */
7927 			fifoaddr = (0xB << 16);
7928 			W_SDREG(fifoaddr,
7929 				&SDPCMFIFOREG(bus, coretype, corerev)->fifoaddr, retries);
7930 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7931 			R_SDREG(endptrs,
7932 				&SDPCMFIFOREG(bus, coretype, corerev)->fifodatalow, retries);
7933 			if (bcmsdh_regfail(bus->sdh)) regerrs++;
7934 
7935 			printf("Initial read of Transmit DMA Pointers: 0x%08x\n", rdptr);
7936 			printf("Transmit DMA Data\n");
7937 			for (count = 0, rdoffs = (rdptr & 0x7F); count < 8; count++) {
7938 				printf("0x%08x: 0x%08x 0x%08x\n", rdoffs,
7939 				       datahigh[count], datalow[count]);
7940 				rdoffs = (rdoffs + 1) & 0x7F;
7941 			}
7942 			printf("Final read of Transmit DMA Pointers: 0x%08x\n", endptrs);
7943 			printf("Register errors: %d\n", regerrs);
7944 
7945 			checkfifo = FALSE;
7946 		}
7947 #endif /* BCMINTERNAL */
7948 
7949 		framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
7950 		if (rxdone || bus->rxskip)
7951 			intstatus  &= ~FRAME_AVAIL_MASK(bus);
7952 		rxlimit -= MIN(framecnt, rxlimit);
7953 	}
7954 
7955 	/* Keep still-pending events for next scheduling */
7956 	bus->intstatus = intstatus;
7957 
7958 clkwait:
7959 	/* Re-enable interrupts to detect new device events (mailbox, rx frame)
7960 	 * or clock availability.  (Allows tx loop to check ipend if desired.)
7961 	 * (Unless register access seems hosed, as we may not be able to ACK...)
7962 	 */
7963 	if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) &&
7964 			!(bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) {
7965 		DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
7966 		          __FUNCTION__, rxdone, framecnt));
7967 		bus->intdis = FALSE;
7968 #if defined(OOB_INTR_ONLY)
7969 		bcmsdh_oob_intr_set(bus->sdh, TRUE);
7970 #endif /* defined(OOB_INTR_ONLY) */
7971 #if !defined(NDIS)
7972 		bcmsdh_intr_enable(sdh);
7973 #endif /* !defined(NDIS) */
7974 #ifdef BCMSPI_ANDROID
7975 		if (*dhd_spi_lockcount == 0)
7976 			bcmsdh_oob_intr_set(bus->sdh, TRUE);
7977 #endif /* BCMSPI_ANDROID */
7978 	}
7979 
7980 #if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
7981 	/* In case of SW-OOB(using edge trigger),
7982 	 * Check interrupt status in the dongle again after enable irq on the host.
7983 	 * and rechedule dpc if interrupt is pended in the dongle.
7984 	 * There is a chance to miss OOB interrupt while irq is disabled on the host.
7985 	 * No need to do this with HW-OOB(level trigger)
7986 	 */
7987 	R_SDREG(newstatus, &regs->intstatus, retries);
7988 	if (bcmsdh_regfail(bus->sdh))
7989 		newstatus = 0;
7990 	if (newstatus & bus->hostintmask) {
7991 		bus->ipend = TRUE;
7992 		resched = TRUE;
7993 	}
7994 #endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */
7995 
7996 #ifdef BCMSDIO_RXLIM_POST
7997 	if (!DATAOK(bus) && bus->rxlim_en) {
7998 		uint8 rxlim = 0;
7999 		if (0 == dhdsdio_membytes(bus, FALSE, bus->rxlim_addr, (uint8 *)&rxlim, 1)) {
8000 			if (bus->tx_max != rxlim) {
8001 				DHD_INFO(("%s: bus->tx_max/rxlim=%d/%d\n", __FUNCTION__,
8002 					bus->tx_max, rxlim));
8003 				bus->tx_max = rxlim;
8004 			}
8005 		}
8006 	}
8007 #endif /* BCMSDIO_RXLIM_POST */
8008 
8009 #ifdef PROP_TXSTATUS
8010 	dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
8011 #endif
8012 
8013 	if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
8014 		dhdsdio_sendpendctl(bus);
8015 #ifdef CONSOLE_DPC
8016 	else if (DATAOK(bus) && strlen(bus->cons_cmd) && (bus->clkstate == CLK_AVAIL) &&
8017 			!bus->fcstate) {
8018 		dhd_bus_console_in(bus->dhd, bus->cons_cmd, strlen(bus->cons_cmd));
8019 	}
8020 #endif
8021 
8022 	/* Send queued frames (limit 1 if rx may still be pending) */
8023 	else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
8024 	    pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
8025 
8026 			if (bus->dhd->conf->dhd_txminmax < 0)
8027 				framecnt = rxdone ? txlimit : MIN(txlimit, DATABUFCNT(bus));
8028 			else
8029 				framecnt = rxdone ? txlimit : MIN(txlimit, bus->dhd->conf->dhd_txminmax);
8030 			framecnt = dhdsdio_sendfromq(bus, framecnt);
8031 			txlimit -= framecnt;
8032 	}
8033 	/* Resched the DPC if ctrl cmd is pending on bus credit */
8034 	if (bus->ctrl_frame_stat) {
8035 		if (bus->dhd->conf->txctl_tmo_fix) {
8036 			set_current_state(TASK_INTERRUPTIBLE);
8037 			if (!kthread_should_stop())
8038 				schedule_timeout(1);
8039 			set_current_state(TASK_RUNNING);
8040 		}
8041 		resched = TRUE;
8042 	}
8043 
8044 	/* Resched if events or tx frames are pending, else await next interrupt */
8045 	/* On failed register access, all bets are off: no resched or interrupts */
8046 	if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
8047 		if ((bus->sih && bus->sih->buscorerev >= 12) && !(dhdsdio_sleepcsr_get(bus) &
8048 			SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
8049 			/* Bus failed because of KSO */
8050 			DHD_ERROR(("%s: Bus failed due to KSO\n", __FUNCTION__));
8051 			bus->kso = FALSE;
8052 		} else {
8053 			DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
8054 				__FUNCTION__));
8055 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
8056 			bus->dhd->busstate = DHD_BUS_DOWN;
8057 			bus->intstatus = 0;
8058 			/* XXX Under certain conditions it may be reasonable to enable interrupts.
8059 			 * E.g. if we get occasional 'bcmsdh_regfail' we should be able to continue
8060 			 * operation. May want to make the decision to enable or not based on count
8061 			 * of failures, so in case of bus lock up we avoid continuous interrupt.
8062 			 */
8063 		}
8064 	} else if (bus->clkstate == CLK_PENDING) {
8065 		/* Awaiting I_CHIPACTIVE; don't resched */
8066 	} else if (bus->intstatus || bus->ipend ||
8067 			(!bus->fcstate && (pktq_mlen(&bus->txq, ((~bus->flowcontrol)
8068 #ifdef DHD_LOSSLESS_ROAMING
8069 			& bus->dhd->dequeue_prec_map
8070 #endif /* DHD_LOSSLESS_ROAMING */
8071 			))) && DATAOK(bus)) ||
8072 			PKT_AVAILABLE(bus, bus->intstatus)) {  /* Read multiple frames */
8073 		resched = TRUE;
8074 	}
8075 
8076 	bus->dpc_sched = resched;
8077 
8078 	/* If we're done for now, turn off clock request. */
8079 	/* XXX Leave request on if just waiting for new credit? */
8080 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING) &&
8081 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8082 		bus->activity = FALSE;
8083 		dhdsdio_bussleep(bus, TRUE);
8084 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8085 	}
8086 
8087 exit:
8088 
8089 	if (!resched) {
8090 		/* Re-enable interrupts to detect new device events (mailbox, rx frame)
8091 		 * or clock availability.  (Allows tx loop to check ipend if desired.)
8092 		 * (Unless register access seems hosed, as we may not be able to ACK...)
8093 		 */
8094 		if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh) &&
8095 				(bus->dhd->conf->oob_enabled_later && !bus->ctrl_frame_stat)) {
8096 			DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
8097 					  __FUNCTION__, rxdone, framecnt));
8098 			bus->intdis = FALSE;
8099 #if defined(OOB_INTR_ONLY)
8100 			bcmsdh_oob_intr_set(bus->sdh, TRUE);
8101 #endif /* defined(OOB_INTR_ONLY) */
8102 			bcmsdh_intr_enable(sdh);
8103 		}
8104 		if (dhd_dpcpoll) {
8105 			if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) {
8106 				resched = TRUE;
8107 #ifdef DEBUG_DPC_THREAD_WATCHDOG
8108 				is_resched_by_readframe = TRUE;
8109 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
8110 			}
8111 		}
8112 	}
8113 
8114 #ifdef TPUT_MONITOR
8115 	dhd_conf_tput_monitor(bus->dhd);
8116 #endif
8117 
8118 	if (bus->ctrl_wait && TXCTLOK(bus))
8119 		wake_up_interruptible(&bus->ctrl_tx_wait);
8120 	dhd_os_sdunlock(bus->dhd);
8121 #ifdef DEBUG_DPC_THREAD_WATCHDOG
8122 	if (bus->dhd->dhd_bug_on) {
8123 		DHD_INFO(("%s: resched = %d ctrl_frame_stat = %d intstatus 0x%08x"
8124 			" ipend = %d pktq_mlen = %d is_resched_by_readframe = %d \n",
8125 			__FUNCTION__, resched, bus->ctrl_frame_stat,
8126 			bus->intstatus, bus->ipend,
8127 			pktq_mlen(&bus->txq, ~bus->flowcontrol), is_resched_by_readframe));
8128 
8129 			bus->dhd->dhd_bug_on = FALSE;
8130 	}
8131 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
8132 
8133 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
8134 	DHD_BUS_BUSY_CLEAR_IN_DPC(bus->dhd);
8135 	dhd_os_busbusy_wake(bus->dhd);
8136 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
8137 
8138 	return resched;
8139 }
8140 
8141 bool
dhd_bus_dpc(struct dhd_bus * bus)8142 dhd_bus_dpc(struct dhd_bus *bus)
8143 {
8144 	bool resched;
8145 
8146 	/* Call the DPC directly. */
8147 	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
8148 	resched = dhdsdio_dpc(bus);
8149 
8150 	return resched;
8151 }
8152 
8153 void
dhdsdio_isr(void * arg)8154 dhdsdio_isr(void *arg)
8155 {
8156 	dhd_bus_t *bus = (dhd_bus_t*)arg;
8157 	bcmsdh_info_t *sdh;
8158 
8159 	if (!bus) {
8160 		DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
8161 		return;
8162 	}
8163 	sdh = bus->sdh;
8164 
8165 	if (bus->dhd->busstate == DHD_BUS_DOWN) {
8166 		DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
8167 		return;
8168 	}
8169 	/* XXX Overall operation:
8170 	 * XXX   - Mask further interrupts
8171 	 * XXX   - Read/ack intstatus
8172 	 * XXX   - Take action based on bits and state
8173 	 * XXX   - Reenable interrupts (as per state)
8174 	 */
8175 
8176 	DHD_INTR(("%s: Enter\n", __FUNCTION__));
8177 
8178 	/* Count the interrupt call */
8179 	bus->intrcount++;
8180 	bus->ipend = TRUE;
8181 
8182 	/* Shouldn't get this interrupt if we're sleeping? */
8183 	if (!SLPAUTO_ENAB(bus)) {
8184 		if (bus->sleeping) {
8185 			DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
8186 			return;
8187 		} else if (!KSO_ENAB(bus)) {
8188 			DHD_ERROR(("ISR in devsleep 1\n"));
8189 		}
8190 	}
8191 
8192 	/* Disable additional interrupts (is this needed now)? */
8193 	if (bus->intr) {
8194 		DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
8195 	} else {
8196 		DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
8197 	}
8198 
8199 #ifdef BCMSPI_ANDROID
8200 	bcmsdh_oob_intr_set(bus->sdh, FALSE);
8201 #endif /* BCMSPI_ANDROID */
8202 #if !defined(NDIS)
8203 	bcmsdh_intr_disable(sdh); /* XXX New API: bcmsdh_intr_mask()? */
8204 #endif /* !defined(NDIS) */
8205 	bus->intdis = TRUE;
8206 
8207 #if defined(SDIO_ISR_THREAD)
8208 	DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
8209 	DHD_OS_WAKE_LOCK(bus->dhd);
8210 	/* terence 20150209: dpc should be scheded again if dpc_sched is TRUE or dhd_bus_txdata can
8211 	    not schedule anymore because dpc_sched is TRUE now.
8212 	 */
8213 	if (dhdsdio_dpc(bus)) {
8214 		bus->dpc_sched = TRUE;
8215 		dhd_sched_dpc(bus->dhd);
8216 	}
8217 	DHD_OS_WAKE_UNLOCK(bus->dhd);
8218 #else
8219 #if !defined(NDIS)
8220 	bus->dpc_sched = TRUE;
8221 	dhd_sched_dpc(bus->dhd);
8222 #endif /* !defined(NDIS) */
8223 #endif /* defined(SDIO_ISR_THREAD) */
8224 
8225 }
8226 
8227 #ifdef PKT_STATICS
8228 void
dhd_bus_dump_txpktstatics(dhd_pub_t * dhdp)8229 dhd_bus_dump_txpktstatics(dhd_pub_t *dhdp)
8230 {
8231 	dhd_bus_t *bus = dhdp->bus;
8232 	uint32 total = 0;
8233 	uint i;
8234 
8235 	printf("%s: TYPE EVENT: %d pkts (size=%d) transfered\n",
8236 		__FUNCTION__, bus->tx_statics.event_count, bus->tx_statics.event_size);
8237 	printf("%s: TYPE CTRL:  %d pkts (size=%d) transfered\n",
8238 		__FUNCTION__, bus->tx_statics.ctrl_count, bus->tx_statics.ctrl_size);
8239 	printf("%s: TYPE DATA:  %d pkts (size=%d) transfered\n",
8240 		__FUNCTION__, bus->tx_statics.data_count, bus->tx_statics.data_size);
8241 	printf("%s: Glom size distribution:\n", __FUNCTION__);
8242 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8243 		total += bus->tx_statics.glom_cnt[i];
8244 	}
8245 	printk(KERN_CONT DHD_LOG_PREFIXS);
8246 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8247 		printk(KERN_CONT "%02d: %5d", i+1, bus->tx_statics.glom_cnt[i]);
8248 		if ((i+1)%8)
8249 			printk(KERN_CONT ", ");
8250 		else {
8251 			printk("\n");
8252 			printk(KERN_CONT DHD_LOG_PREFIXS);
8253 		}
8254 	}
8255 	printk("\n");
8256 	printk(KERN_CONT DHD_LOG_PREFIXS);
8257 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8258 		printk(KERN_CONT "%02d:%5d%%", i+1, (bus->tx_statics.glom_cnt[i]*100)/total);
8259 		if ((i+1)%8)
8260 			printk(KERN_CONT ", ");
8261 		else {
8262 			printk("\n");
8263 			printk(KERN_CONT DHD_LOG_PREFIXS);
8264 		}
8265 	}
8266 	printk("\n");
8267 	printf("%s: Glom spend time distribution(us):\n", __FUNCTION__);
8268 	printk(KERN_CONT DHD_LOG_PREFIXS);
8269 	for (i=0;i<bus->tx_statics.glom_max;i++) {
8270 		printk(KERN_CONT "%02d: %5u", i+1, bus->tx_statics.glom_cnt_us[i]);
8271 		if ((i+1)%8)
8272 			printk(KERN_CONT ", ");
8273 		else {
8274 			printk("\n");
8275 			printk(KERN_CONT DHD_LOG_PREFIXS);
8276 		}
8277 	}
8278 	printk("\n");
8279 	if (total) {
8280 		printf("%s: data(%d)/glom(%d)=%d, glom_max=%d\n",
8281 			__FUNCTION__, bus->tx_statics.data_count, total,
8282 			bus->tx_statics.data_count/total, bus->tx_statics.glom_max);
8283 	}
8284 	printf("%s: TYPE RX GLOM: %d pkts (size=%d) transfered\n",
8285 		__FUNCTION__, bus->tx_statics.glom_count, bus->tx_statics.glom_size);
8286 	printf("%s: TYPE TEST: %d pkts (size=%d) transfered\n",
8287 		__FUNCTION__, bus->tx_statics.test_count, bus->tx_statics.test_size);
8288 
8289 #ifdef KSO_DEBUG
8290 	printf("%s: kso try distribution(us):\n", __FUNCTION__);
8291 	printk(KERN_CONT DHD_LOG_PREFIXS);
8292 	for (i=0; i<10; i++) {
8293 		printk(KERN_CONT "[%d]: %d, ", i, dhdp->conf->kso_try_array[i]);
8294 	}
8295 	printk("\n");
8296 #endif
8297 }
8298 
8299 void
dhd_bus_clear_txpktstatics(dhd_pub_t * dhdp)8300 dhd_bus_clear_txpktstatics(dhd_pub_t *dhdp)
8301 {
8302 	dhd_bus_t *bus = dhdp->bus;
8303 	memset((uint8*) &bus->tx_statics, 0, sizeof(pkt_statics_t));
8304 }
8305 #endif
8306 
8307 #ifdef SDTEST
8308 static void
dhdsdio_pktgen_init(dhd_bus_t * bus)8309 dhdsdio_pktgen_init(dhd_bus_t *bus)
8310 {
8311 	/* Default to specified length, or full range */
8312 	if (dhd_pktgen_len) {
8313 		bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN);
8314 		bus->pktgen_minlen = bus->pktgen_maxlen;
8315 	} else {
8316 		bus->pktgen_maxlen = MAX_PKTGEN_LEN;
8317 		bus->pktgen_minlen = 0;
8318 	}
8319 	bus->pktgen_len = (uint16)bus->pktgen_minlen;
8320 
8321 	/* Default to per-watchdog burst with 10s print time */
8322 	bus->pktgen_freq = 1;
8323 	bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0;
8324 	bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
8325 
8326 	/* Default to echo mode */
8327 	bus->pktgen_mode = DHD_PKTGEN_ECHO;
8328 	bus->pktgen_stop = 1;
8329 }
8330 
8331 static void
dhdsdio_pktgen(dhd_bus_t * bus)8332 dhdsdio_pktgen(dhd_bus_t *bus)
8333 {
8334 	void *pkt;
8335 	uint8 *data;
8336 	uint pktcount;
8337 	uint fillbyte;
8338 	osl_t *osh = bus->dhd->osh;
8339 	uint16 len;
8340 #if defined(LINUX)
8341 	ulong time_lapse;
8342 	uint sent_pkts;
8343 	uint rcvd_pkts;
8344 #endif /* LINUX */
8345 
8346 	/* Display current count if appropriate */
8347 	if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
8348 		bus->pktgen_ptick = 0;
8349 		printf("%s: send attempts %d, rcvd %d, errors %d\n",
8350 		       __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
8351 
8352 #if defined(LINUX)
8353 		/* Print throughput stats only for constant length packet runs */
8354 		if (bus->pktgen_minlen == bus->pktgen_maxlen) {
8355 			time_lapse = jiffies - bus->pktgen_prev_time;
8356 			bus->pktgen_prev_time = jiffies;
8357 			sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent;
8358 			bus->pktgen_prev_sent = bus->pktgen_sent;
8359 			rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd;
8360 			bus->pktgen_prev_rcvd = bus->pktgen_rcvd;
8361 
8362 			printf("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n",
8363 			  __FUNCTION__,
8364 			  (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8,
8365 			  (rcvd_pkts * bus->pktgen_len  / jiffies_to_msecs(time_lapse)) * 8);
8366 		}
8367 #endif /* LINUX */
8368 	}
8369 
8370 	/* For recv mode, just make sure dongle has started sending */
8371 	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
8372 		if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) {
8373 			bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING;
8374 			dhdsdio_sdtest_set(bus, bus->pktgen_total);
8375 		}
8376 		return;
8377 	}
8378 
8379 	/* Otherwise, generate or request the specified number of packets */
8380 	for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
8381 		/* Stop if total has been reached */
8382 		if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) {
8383 			bus->pktgen_count = 0;
8384 			break;
8385 		}
8386 
8387 		/* Allocate an appropriate-sized packet */
8388 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
8389 			len = SDPCM_TEST_PKT_CNT_FLD_LEN;
8390 		} else {
8391 			len = bus->pktgen_len;
8392 		}
8393 		if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
8394 		                   TRUE))) {;
8395 			DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
8396 			break;
8397 		}
8398 		PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
8399 		data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
8400 
8401 		/* Write test header cmd and extra based on mode */
8402 		switch (bus->pktgen_mode) {
8403 		case DHD_PKTGEN_ECHO:
8404 			*data++ = SDPCM_TEST_ECHOREQ;
8405 			*data++ = (uint8)bus->pktgen_sent;
8406 			break;
8407 
8408 		case DHD_PKTGEN_SEND:
8409 			*data++ = SDPCM_TEST_DISCARD;
8410 			*data++ = (uint8)bus->pktgen_sent;
8411 			break;
8412 
8413 		case DHD_PKTGEN_RXBURST:
8414 			*data++ = SDPCM_TEST_BURST;
8415 			*data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */
8416 			break;
8417 
8418 		default:
8419 			DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode));
8420 			PKTFREE(osh, pkt, TRUE);
8421 			bus->pktgen_count = 0;
8422 			return;
8423 		}
8424 
8425 		/* Write test header length field */
8426 		*data++ = (bus->pktgen_len >> 0);
8427 		*data++ = (bus->pktgen_len >> 8);
8428 
8429 		/* Write frame count in a 4 byte field adjucent to SDPCM test header for
8430 		 * burst mode
8431 		 */
8432 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
8433 			*data++ = (uint8)(bus->pktgen_count >> 0);
8434 			*data++ = (uint8)(bus->pktgen_count >> 8);
8435 			*data++ = (uint8)(bus->pktgen_count >> 16);
8436 			*data++ = (uint8)(bus->pktgen_count >> 24);
8437 		} else {
8438 
8439 			/* Then fill in the remainder -- N/A for burst */
8440 			for (fillbyte = 0; fillbyte < len; fillbyte++)
8441 				*data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent);
8442 		}
8443 
8444 #ifdef DHD_DEBUG
8445 		if (DHD_BYTES_ON() && DHD_DATA_ON()) {
8446 			data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
8447 			prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
8448 		}
8449 #endif
8450 
8451 		/* Send it */
8452 		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) {
8453 			bus->pktgen_fail++;
8454 			if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail)
8455 				bus->pktgen_count = 0;
8456 		}
8457 		bus->pktgen_sent++;
8458 
8459 		/* Bump length if not fixed, wrap at max */
8460 		if (++bus->pktgen_len > bus->pktgen_maxlen)
8461 			bus->pktgen_len = (uint16)bus->pktgen_minlen;
8462 
8463 		/* Special case for burst mode: just send one request! */
8464 		if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
8465 			break;
8466 	}
8467 }
8468 
8469 static void
dhdsdio_sdtest_set(dhd_bus_t * bus,uint count)8470 dhdsdio_sdtest_set(dhd_bus_t *bus, uint count)
8471 {
8472 	void *pkt;
8473 	uint8 *data;
8474 	osl_t *osh = bus->dhd->osh;
8475 
8476 	/* Allocate the packet */
8477 	if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
8478 		SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) {
8479 		DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
8480 		return;
8481 	}
8482 	PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
8483 		SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN);
8484 	data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
8485 
8486 	/* Fill in the test header */
8487 	*data++ = SDPCM_TEST_SEND;
8488 	*data++ = (count > 0)?TRUE:FALSE;
8489 	*data++ = (bus->pktgen_maxlen >> 0);
8490 	*data++ = (bus->pktgen_maxlen >> 8);
8491 	*data++ = (uint8)(count >> 0);
8492 	*data++ = (uint8)(count >> 8);
8493 	*data++ = (uint8)(count >> 16);
8494 	*data++ = (uint8)(count >> 24);
8495 
8496 	/* Send it */
8497 	if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK)
8498 		bus->pktgen_fail++;
8499 }
8500 
8501 static void
dhdsdio_testrcv(dhd_bus_t * bus,void * pkt,uint seq)8502 dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
8503 {
8504 	osl_t *osh = bus->dhd->osh;
8505 	uint8 *data;
8506 	uint pktlen;
8507 
8508 	uint8 cmd;
8509 	uint8 extra;
8510 	uint16 len;
8511 	uint16 offset;
8512 
8513 	/* Check for min length */
8514 	if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) {
8515 		DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen));
8516 		PKTFREE(osh, pkt, FALSE);
8517 		return;
8518 	}
8519 
8520 	/* Extract header fields */
8521 	data = PKTDATA(osh, pkt);
8522 	cmd = *data++;
8523 	extra = *data++;
8524 	len = *data++; len += *data++ << 8;
8525 	DHD_TRACE(("%s:cmd:%d, xtra:%d,len:%d\n", __FUNCTION__, cmd, extra, len));
8526 	/* Check length for relevant commands */
8527 	if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) {
8528 		if (pktlen != len + SDPCM_TEST_HDRLEN) {
8529 			DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d"
8530 			           " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
8531 			PKTFREE(osh, pkt, FALSE);
8532 			return;
8533 		}
8534 	}
8535 
8536 	/* Process as per command */
8537 	switch (cmd) {
8538 	case SDPCM_TEST_ECHOREQ:
8539 		/* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
8540 		*(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP;
8541 		if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) == BCME_OK) {
8542 			bus->pktgen_sent++;
8543 		} else {
8544 			bus->pktgen_fail++;
8545 			PKTFREE(osh, pkt, FALSE);
8546 		}
8547 		bus->pktgen_rcvd++;
8548 		break;
8549 
8550 	case SDPCM_TEST_ECHORSP:
8551 		if (bus->ext_loop) {
8552 			PKTFREE(osh, pkt, FALSE);
8553 			bus->pktgen_rcvd++;
8554 			break;
8555 		}
8556 
8557 		for (offset = 0; offset < len; offset++, data++) {
8558 			if (*data != SDPCM_TEST_FILL(offset, extra)) {
8559 				DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: "
8560 				           "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
8561 				           offset, len, SDPCM_TEST_FILL(offset, extra), *data));
8562 				break;
8563 			}
8564 		}
8565 		PKTFREE(osh, pkt, FALSE);
8566 		bus->pktgen_rcvd++;
8567 		break;
8568 
8569 	case SDPCM_TEST_DISCARD:
8570 		{
8571 			int i = 0;
8572 			uint8 *prn = data;
8573 			uint8 testval = extra;
8574 			for (i = 0; i < len; i++) {
8575 				if (*prn != testval) {
8576 					DHD_ERROR(("DIErr@Pkt#:%d,Ix:%d, expected:0x%x, got:0x%x\n",
8577 						i, bus->pktgen_rcvd_rcvsession, testval, *prn));
8578 					prn++; testval++;
8579 				}
8580 			}
8581 		}
8582 		PKTFREE(osh, pkt, FALSE);
8583 		bus->pktgen_rcvd++;
8584 		break;
8585 
8586 	case SDPCM_TEST_BURST:
8587 	case SDPCM_TEST_SEND:
8588 	default:
8589 		DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
8590 		          " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
8591 		PKTFREE(osh, pkt, FALSE);
8592 		break;
8593 	}
8594 
8595 	/* For recv mode, stop at limit (and tell dongle to stop sending) */
8596 	if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
8597 		if (bus->pktgen_rcv_state != PKTGEN_RCV_IDLE) {
8598 			bus->pktgen_rcvd_rcvsession++;
8599 
8600 			if (bus->pktgen_total &&
8601 				(bus->pktgen_rcvd_rcvsession >= bus->pktgen_total)) {
8602 			bus->pktgen_count = 0;
8603 			DHD_ERROR(("Pktgen:rcv test complete!\n"));
8604 			bus->pktgen_rcv_state = PKTGEN_RCV_IDLE;
8605 			dhdsdio_sdtest_set(bus, FALSE);
8606 				bus->pktgen_rcvd_rcvsession = 0;
8607 			}
8608 		}
8609 	}
8610 }
8611 #endif /* SDTEST */
8612 
dhd_bus_oob_intr_register(dhd_pub_t * dhdp)8613 int dhd_bus_oob_intr_register(dhd_pub_t *dhdp)
8614 {
8615 	int err = 0;
8616 
8617 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8618 	err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus);
8619 #endif
8620 	return err;
8621 }
8622 
dhd_bus_oob_intr_unregister(dhd_pub_t * dhdp)8623 void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
8624 {
8625 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8626 	bcmsdh_oob_intr_unregister(dhdp->bus->sdh);
8627 #endif
8628 }
8629 
dhd_bus_oob_intr_set(dhd_pub_t * dhdp,bool enable)8630 void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
8631 {
8632 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8633 	bcmsdh_oob_intr_set(dhdp->bus->sdh, enable);
8634 #endif
8635 }
8636 
dhd_bus_get_oob_irq_num(dhd_pub_t * dhdp)8637 int dhd_bus_get_oob_irq_num(dhd_pub_t *dhdp)
8638 {
8639 	int irq_num = 0;
8640 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
8641 	irq_num = bcmsdh_get_oob_intr_num(dhdp->bus->sdh);
8642 #endif /* OOB_INTR_ONLY || BCMSPI_ANDROID */
8643 	return irq_num;
8644 }
8645 
8646 #ifdef LINUX
dhd_bus_to_dev(struct dhd_bus * bus)8647 struct device *dhd_bus_to_dev(struct dhd_bus *bus)
8648 {
8649 	return (struct device *)bcmsdh_get_dev(bus->sdh);
8650 }
8651 #endif /* LINUX */
8652 
dhd_bus_dev_pm_stay_awake(dhd_pub_t * dhdpub)8653 void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
8654 {
8655 #ifdef LINUX
8656 	bcmsdh_dev_pm_stay_awake(dhdpub->bus->sdh);
8657 #endif
8658 }
8659 
dhd_bus_dev_pm_relax(dhd_pub_t * dhdpub)8660 void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub)
8661 {
8662 #ifdef LINUX
8663 	bcmsdh_dev_relax(dhdpub->bus->sdh);
8664 #endif
8665 }
8666 
dhd_bus_dev_pm_enabled(dhd_pub_t * dhdpub)8667 bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub)
8668 {
8669 	bool enabled = FALSE;
8670 
8671 #ifdef LINUX
8672 	enabled = bcmsdh_dev_pm_enabled(dhdpub->bus->sdh);
8673 #endif
8674 	return enabled;
8675 }
8676 
8677 extern bool
dhd_bus_watchdog(dhd_pub_t * dhdp)8678 dhd_bus_watchdog(dhd_pub_t *dhdp)
8679 {
8680 	dhd_bus_t *bus;
8681 	unsigned long flags;
8682 
8683 	DHD_TIMER(("%s: Enter\n", __FUNCTION__));
8684 
8685 	bus = dhdp->bus;
8686 
8687 	if (bus->dhd->dongle_reset)
8688 		return FALSE;
8689 
8690 	if (bus->dhd->hang_was_sent) {
8691 		dhd_os_wd_timer(bus->dhd, 0);
8692 		return FALSE;
8693 	}
8694 
8695 	/* Ignore the timer if simulating bus down */
8696 	if (!SLPAUTO_ENAB(bus) && bus->sleeping)
8697 		return FALSE;
8698 
8699 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
8700 	if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp) ||
8701 			DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp)) {
8702 		DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8703 		return FALSE;
8704 	}
8705 	DHD_BUS_BUSY_SET_IN_WD(dhdp);
8706 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8707 
8708 	dhd_os_sdlock(bus->dhd);
8709 
8710 	/* Poll period: check device if appropriate. */
8711 	// terence 20160615: remove !SLPAUTO_ENAB(bus) to fix not able to polling if sr supported
8712 	if (1 && (bus->poll && (++bus->polltick >= bus->pollrate))) {
8713 		uint32 intstatus = 0;
8714 
8715 		/* Reset poll tick */
8716 		bus->polltick = 0;
8717 
8718 		/* Check device if no interrupts */
8719 		if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
8720 #ifdef DEBUG_LOST_INTERRUPTS
8721 			uint retries = 0;
8722 			bool hostpending;
8723 			uint8 devena, devpend;
8724 
8725 			/* Make sure backplane clock is on */
8726 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8727 
8728 			hostpending = bcmsdh_intr_pending(bus->sdh);
8729 			devena = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL);
8730 			devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTPEND, NULL);
8731 
8732 			R_SDREG(intstatus, &bus->regs->intstatus, retries);
8733 			intstatus &= bus->hostintmask;
8734 
8735 			if (intstatus && !hostpending) {
8736 				DHD_ERROR(("%s: !hpend: ena 0x%02x pend 0x%02x intstatus 0x%08x\n",
8737 				           __FUNCTION__, devena, devpend, intstatus));
8738 			}
8739 #endif /* DEBUG_LOST_INTERRUPTS */
8740 
8741 #ifndef BCMSPI
8742 			/* XXX Needs to be fixed for polling operation (in CE) */
8743 			if (!bus->dpc_sched) {
8744 				uint8 devpend;
8745 				devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
8746 				                          SDIOD_CCCR_INTPEND, NULL);
8747 				intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
8748 			}
8749 #else
8750 			if (!bus->dpc_sched) {
8751 				uint32 devpend;
8752 				devpend = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0,
8753 					SPID_STATUS_REG, NULL);
8754 				intstatus = devpend & STATUS_F2_PKT_AVAILABLE;
8755 			}
8756 #endif /* !BCMSPI */
8757 
8758 			/* If there is something, make like the ISR and schedule the DPC */
8759 			if (intstatus) {
8760 				bus->pollcnt++;
8761 				bus->ipend = TRUE;
8762 				if (bus->intr) {
8763 					bcmsdh_intr_disable(bus->sdh);
8764 				}
8765 				bus->dpc_sched = TRUE;
8766 				dhd_sched_dpc(bus->dhd);
8767 			}
8768 		}
8769 
8770 		/* Update interrupt tracking */
8771 		bus->lastintrs = bus->intrcount;
8772 	}
8773 
8774 	if ((!bus->dpc_sched) && pktq_n_pkts_tot(&bus->txq)) {
8775 		bus->dpc_sched = TRUE;
8776 		dhd_sched_dpc(bus->dhd);
8777 	}
8778 
8779 #ifdef DHD_DEBUG
8780 	/* Poll for console output periodically */
8781 	if (dhdp->busstate == DHD_BUS_DATA && dhdp->dhd_console_ms != 0) {
8782 		bus->console.count += dhd_watchdog_ms;
8783 		if (bus->console.count >= dhdp->dhd_console_ms) {
8784 			bus->console.count -= dhdp->dhd_console_ms;
8785 			/* Make sure backplane clock is on */
8786 			if (SLPAUTO_ENAB(bus))
8787 				dhdsdio_bussleep(bus, FALSE);
8788 			else
8789 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8790 			if (dhdsdio_readconsole(bus) < 0)
8791 				dhdp->dhd_console_ms = 0;	/* On error, stop trying */
8792 		}
8793 	}
8794 #endif /* DHD_DEBUG */
8795 
8796 #ifdef SDTEST
8797 	/* Generate packets if configured */
8798 	if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
8799 		/* Make sure backplane clock is on */
8800 		if (SLPAUTO_ENAB(bus))
8801 			dhdsdio_bussleep(bus, FALSE);
8802 		else
8803 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8804 		bus->pktgen_tick = 0;
8805 		dhdsdio_pktgen(bus);
8806 	}
8807 #endif
8808 
8809 	/* On idle timeout clear activity flag and/or turn off clock */
8810 #ifdef DHD_USE_IDLECOUNT
8811 	if (bus->activity)
8812 		bus->activity = FALSE;
8813 	else {
8814 		bus->idlecount++;
8815 
8816 		/*
8817 		 * If the condition to switch off the clock is reached And if
8818 		 * BT is inactive (in case of BT_OVER_SDIO build) turn off clk.
8819 		 *
8820 		 * Consider the following case, DHD is configured with
8821 		 * 1) idletime == DHD_IDLE_IMMEDIATE
8822 		 * 2) BT is the last user of the clock
8823 		 * We cannot disable the clock from __dhdsdio_clk_disable
8824 		 * since WLAN might be using it. If WLAN is active then
8825 		 * from the respective function/context after doing the job
8826 		 * the clk is turned off.
8827 		 * But if WLAN is actually inactive then the watchdog should
8828 		 * disable the clock. So the condition check below should be
8829 		 * bus->idletime != 0 instead of idletime == 0
8830 		 */
8831 		if ((bus->idletime != 0) && (bus->idlecount >= bus->idletime) &&
8832 			NO_OTHER_ACTIVE_BUS_USER(bus)) {
8833 			DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
8834 			if (!bus->poll && SLPAUTO_ENAB(bus)) {
8835 				if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
8836 					dhd_os_wd_timer(bus->dhd, 0);
8837 			} else
8838 				dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8839 
8840 			bus->idlecount = 0;
8841 		}
8842 	}
8843 #else
8844 	if ((bus->idletime != 0) && (bus->clkstate == CLK_AVAIL) &&
8845 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8846 		if (++bus->idlecount >= bus->idletime) {
8847 			bus->idlecount = 0;
8848 			if (bus->activity) {
8849 				bus->activity = FALSE;
8850 #if !defined(OEM_ANDROID) && !defined(NDIS)
8851 /* XXX
8852  * For Android turn off clocks as soon as possible, to improve power
8853  * efficiency. For non-android, extend clock-active period for voice
8854  * quality reasons (see PR84690/Jira:SWWLAN-7650).
8855  */
8856 			} else {
8857 #endif /* !defined(OEM_ANDROID) && !defined(NDIS) */
8858 				if (!bus->poll && SLPAUTO_ENAB(bus)) {
8859 					if (!bus->readframes)
8860 						dhdsdio_bussleep(bus, TRUE);
8861 					else
8862 						bus->reqbussleep = TRUE;
8863 				} else {
8864 					dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8865 				}
8866 			}
8867 		}
8868 	}
8869 #endif /* DHD_USE_IDLECOUNT */
8870 
8871 	dhd_os_sdunlock(bus->dhd);
8872 
8873 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
8874 	DHD_BUS_BUSY_CLEAR_IN_WD(dhdp);
8875 	dhd_os_busbusy_wake(dhdp);
8876 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
8877 
8878 	return bus->ipend;
8879 }
8880 
8881 extern int
dhd_bus_console_in(dhd_pub_t * dhdp,uchar * msg,uint msglen)8882 dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
8883 {
8884 	dhd_bus_t *bus = dhdp->bus;
8885 	uint32 addr, val;
8886 	int rv;
8887 	void *pkt;
8888 
8889 #ifndef CONSOLE_DPC
8890 	/* Exclusive bus access */
8891 	dhd_os_sdlock(bus->dhd);
8892 #endif
8893 
8894 	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
8895 	if (bus->console_addr == 0) {
8896 		rv = BCME_UNSUPPORTED;
8897 		goto exit;
8898 	}
8899 
8900 	/* Don't allow input if dongle is in reset */
8901 	if (bus->dhd->dongle_reset) {
8902 		rv = BCME_NOTREADY;
8903 		goto exit;
8904 	}
8905 
8906 #ifndef CONSOLE_DPC
8907 	if (!DATAOK(bus)) {
8908 		DHD_CTL(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d, pktq_len %d\n",
8909 			__FUNCTION__, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
8910 		rv = BCME_NOTREADY;
8911 		goto exit;
8912 	}
8913 
8914 	/* Request clock to allow SDIO accesses */
8915 	BUS_WAKE(bus);
8916 	/* No pend allowed since txpkt is called later, ht clk has to be on */
8917 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
8918 #endif
8919 
8920 	/* Zero cbuf_index */
8921 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx);
8922 	/* handle difference in definition of hnd_log_t in certain branches */
8923 	if (dhdp->wlc_ver_major < 14) {
8924 		addr -= sizeof(uint32);
8925 	}
8926 	val = htol32(0);
8927 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
8928 		goto done;
8929 
8930 	/* Write message into cbuf */
8931 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf);
8932 	/* handle difference in definition of hnd_log_t in certain branches */
8933 	if (dhdp->wlc_ver_major < 14) {
8934 		addr -= sizeof(uint32);
8935 	}
8936 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
8937 		goto done;
8938 
8939 	/* Write length into vcons_in */
8940 	addr = bus->console_addr + OFFSETOF(hnd_cons_t, vcons_in);
8941 	val = htol32(msglen);
8942 	if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
8943 		goto done;
8944 
8945 	/* Bump dongle by sending an empty packet on the event channel.
8946 	 * sdpcm_sendup (RX) checks for virtual console input.
8947 	 */
8948 	if ((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL)
8949 		rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
8950 
8951 done:
8952 #ifndef CONSOLE_DPC
8953 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
8954 		NO_OTHER_ACTIVE_BUS_USER(bus)) {
8955 		bus->activity = FALSE;
8956 		dhdsdio_bussleep(bus, TRUE);
8957 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
8958 	}
8959 #endif
8960 
8961 exit:
8962 #ifdef CONSOLE_DPC
8963 	memset(bus->cons_cmd, 0, sizeof(bus->cons_cmd));
8964 #else
8965 	dhd_os_sdunlock(bus->dhd);
8966 #endif
8967 	return rv;
8968 }
8969 
8970 #ifdef CONSOLE_DPC
8971 extern int
dhd_bus_txcons(dhd_pub_t * dhdp,uchar * msg,uint msglen)8972 dhd_bus_txcons(dhd_pub_t *dhdp, uchar *msg, uint msglen)
8973 {
8974 	dhd_bus_t *bus = dhdp->bus;
8975 	int ret = BCME_OK;
8976 
8977 	dhd_os_sdlock(bus->dhd);
8978 
8979 	/* Address could be zero if CONSOLE := 0 in dongle Makefile */
8980 	if (bus->console_addr == 0) {
8981 		ret = BCME_UNSUPPORTED;
8982 		goto exit;
8983 	}
8984 
8985 	/* Don't allow input if dongle is in reset */
8986 	if (bus->dhd->dongle_reset) {
8987 		ret = BCME_NOTREADY;
8988 		goto exit;
8989 	}
8990 
8991 	if (msglen >= sizeof(bus->cons_cmd)) {
8992 		DHD_ERROR(("%s: \"%s\"(%d) too long\n", __FUNCTION__, msg, msglen));
8993 		ret = BCME_BADARG;
8994 		goto exit;
8995 	}
8996 
8997 	if (!strlen(bus->cons_cmd)) {
8998 		strncpy(bus->cons_cmd, msg, sizeof(bus->cons_cmd));
8999 		DHD_CTL(("%s: \"%s\" delay send, tx_max %d, tx_seq %d, pktq_len %d\n",
9000 			__FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
9001 		if (!bus->dpc_sched) {
9002 			bus->dpc_sched = TRUE;
9003 			dhd_sched_dpc(bus->dhd);
9004 		}
9005 	} else {
9006 		DHD_CTL(("%s: \"%s\" is pending, tx_max %d, tx_seq %d, pktq_len %d\n",
9007 			__FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
9008 		ret = BCME_NOTREADY;
9009 	}
9010 
9011 exit:
9012 	dhd_os_sdunlock(bus->dhd);
9013 
9014 	return ret;
9015 }
9016 #endif
9017 
9018 #if defined(DHD_DEBUG) && !defined(BCMSDIOLITE)
9019 static void
dhd_dump_cis(uint fn,uint8 * cis)9020 dhd_dump_cis(uint fn, uint8 *cis)
9021 {
9022 	uint byte, tag, tdata;
9023 	DHD_INFO(("Function %d CIS:\n", fn));
9024 
9025 	for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
9026 		if ((byte % 16) == 0)
9027 			DHD_INFO(("    "));
9028 		DHD_INFO(("%02x ", cis[byte]));
9029 		if ((byte % 16) == 15)
9030 			DHD_INFO(("\n"));
9031 		if (!tdata--) {
9032 			tag = cis[byte];
9033 			if (tag == 0xff)
9034 				break;
9035 			else if (!tag)
9036 				tdata = 0;
9037 			else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
9038 				tdata = cis[byte + 1] + 1;
9039 			else
9040 				DHD_INFO(("]"));
9041 		}
9042 	}
9043 	if ((byte % 16) != 15)
9044 		DHD_INFO(("\n"));
9045 }
9046 #endif /* DHD_DEBUG */
9047 
9048 static bool
dhdsdio_chipmatch(uint16 chipid)9049 dhdsdio_chipmatch(uint16 chipid)
9050 {
9051 	if (chipid == BCM4330_CHIP_ID)
9052 		return TRUE;
9053 	if (chipid == BCM43362_CHIP_ID)
9054 		return TRUE;
9055 	if (chipid == BCM43340_CHIP_ID)
9056 		return TRUE;
9057 	if (chipid == BCM43341_CHIP_ID)
9058 		return TRUE;
9059 	if (chipid == BCM4334_CHIP_ID)
9060 		return TRUE;
9061 	if (chipid == BCM4324_CHIP_ID)
9062 		return TRUE;
9063 	if (chipid == BCM4335_CHIP_ID)
9064 		return TRUE;
9065 	if (chipid == BCM4339_CHIP_ID)
9066 		return TRUE;
9067 	if (BCM4345_CHIP(chipid))
9068 		return TRUE;
9069 	if (chipid == BCM4350_CHIP_ID)
9070 		return TRUE;
9071 	if (chipid == BCM4354_CHIP_ID)
9072 		return TRUE;
9073 	if (chipid == BCM4358_CHIP_ID)
9074 		return TRUE;
9075 	if (chipid == BCM43569_CHIP_ID)
9076 		return TRUE;
9077 	if (chipid == BCM4371_CHIP_ID)
9078 		return TRUE;
9079 	if (chipid == BCM43430_CHIP_ID)
9080 		return TRUE;
9081 	if (chipid == BCM43018_CHIP_ID)
9082 		return TRUE;
9083 	if (BCM4349_CHIP(chipid))
9084 		return TRUE;
9085 #ifdef UNRELEASEDCHIP
9086 	if ((chipid == BCM4347_CHIP_ID) ||
9087 		(chipid == BCM4357_CHIP_ID) ||
9088 		(chipid == BCM4361_CHIP_ID))
9089 		return TRUE;
9090 #endif
9091 	if (chipid == BCM4364_CHIP_ID)
9092 			return TRUE;
9093 
9094 	if (chipid == BCM43012_CHIP_ID)
9095 		return TRUE;
9096 
9097 	if (chipid == BCM43014_CHIP_ID)
9098 		return TRUE;
9099 
9100 	if (chipid == BCM43013_CHIP_ID)
9101 		return TRUE;
9102 
9103 	if (chipid == BCM4369_CHIP_ID)
9104 		return TRUE;
9105 
9106 	if (BCM4378_CHIP(chipid)) {
9107 		return TRUE;
9108 	}
9109 
9110 	if (chipid == BCM4362_CHIP_ID)
9111 		return TRUE;
9112 	if (chipid == BCM43751_CHIP_ID)
9113 		return TRUE;
9114 	if (chipid == BCM43752_CHIP_ID)
9115 		return TRUE;
9116 
9117 	return FALSE;
9118 }
9119 
9120 static void *
dhdsdio_probe(uint16 venid,uint16 devid,uint16 bus_no,uint16 slot,uint16 func,uint bustype,void * regsva,osl_t * osh,void * sdh)9121 dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
9122 	uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
9123 {
9124 	int ret;
9125 	dhd_bus_t *bus;
9126 
9127 	DHD_MUTEX_LOCK();
9128 
9129 	/* Init global variables at run-time, not as part of the declaration.
9130 	 * This is required to support init/de-init of the driver. Initialization
9131 	 * of globals as part of the declaration results in non-deterministic
9132 	 * behavior since the value of the globals may be different on the
9133 	 * first time that the driver is initialized vs subsequent initializations.
9134 	 */
9135 	dhd_txbound = DHD_TXBOUND;
9136 	dhd_rxbound = DHD_RXBOUND;
9137 #ifdef BCMSPI
9138 	dhd_alignctl = FALSE;
9139 #else
9140 	dhd_alignctl = TRUE;
9141 #endif /* BCMSPI */
9142 	sd1idle = TRUE;
9143 	dhd_readahead = TRUE;
9144 	retrydata = FALSE;
9145 
9146 #ifdef DISABLE_FLOW_CONTROL
9147 	dhd_doflow = FALSE;
9148 #endif /* DISABLE_FLOW_CONTROL */
9149 	dhd_dongle_ramsize = 0;
9150 	dhd_txminmax = DHD_TXMINMAX;
9151 
9152 #ifdef BCMSPI
9153 	forcealign = FALSE;
9154 #else
9155 	forcealign = TRUE;
9156 #endif /* !BCMSPI */
9157 
9158 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9159 	DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
9160 
9161 	/* We make assumptions about address window mappings */
9162 	ASSERT((uintptr)regsva == si_enum_base(devid));
9163 
9164 	/* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
9165 	 * means early parse could fail, so here we should get either an ID
9166 	 * we recognize OR (-1) indicating we must request power first.
9167 	 */
9168 	/* Check the Vendor ID */
9169 	switch (venid) {
9170 		case 0x0000:
9171 		case VENDOR_BROADCOM:
9172 			break;
9173 		default:
9174 			DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
9175 			           __FUNCTION__, venid));
9176 			goto forcereturn;
9177 	}
9178 
9179 	/* Check the Device ID and make sure it's one that we support */
9180 	switch (devid) {
9181 #ifdef BCMINTERNAL
9182 		case SDIOD_FPGA_ID:
9183 			DHD_INFO(("%s: found FPGA Dongle\n", __FUNCTION__));
9184 			break;
9185 #endif /* BCMINTERNAL */
9186 		case 0:
9187 			DHD_INFO(("%s: allow device id 0, will check chip internals\n",
9188 			          __FUNCTION__));
9189 			break;
9190 
9191 		default:
9192 			DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
9193 			           __FUNCTION__, venid, devid));
9194 			goto forcereturn;
9195 	}
9196 
9197 	if (osh == NULL) {
9198 		DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__));
9199 		goto forcereturn;
9200 	}
9201 
9202 	/* Allocate private bus interface state */
9203 	if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
9204 		DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
9205 		goto fail;
9206 	}
9207 	bzero(bus, sizeof(dhd_bus_t));
9208 	bus->sdh = sdh;
9209 	bus->cl_devid = (uint16)devid;
9210 	bus->bus = DHD_BUS;
9211 	bus->bus_num = bus_no;
9212 	bus->slot_num = slot;
9213 	bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
9214 	bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */
9215 #ifdef BT_OVER_SDIO
9216 	bus->bt_use_count = 0;
9217 #endif
9218 
9219 #if defined(LINUX) && defined(SUPPORT_P2P_GO_PS)
9220 	init_waitqueue_head(&bus->bus_sleep);
9221 #endif /* LINUX && SUPPORT_P2P_GO_PS */
9222 	init_waitqueue_head(&bus->ctrl_tx_wait);
9223 
9224 	/* attempt to attach to the dongle */
9225 	if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
9226 		DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__));
9227 		goto fail;
9228 	}
9229 
9230 	/* Attach to the dhd/OS/network interface */
9231 	if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) {
9232 		DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
9233 		goto fail;
9234 	}
9235 
9236 #if defined(GET_OTP_MAC_ENABLE) || defined(GET_OTP_MODULE_NAME)
9237 	dhd_conf_get_otp(bus->dhd, sdh, bus->sih);
9238 #endif
9239 
9240 	/* Allocate buffers */
9241 	if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
9242 		DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
9243 		goto fail;
9244 	}
9245 
9246 	if (!(dhdsdio_probe_init(bus, osh, sdh))) {
9247 		DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__));
9248 		goto fail;
9249 	}
9250 
9251 	if (bus->intr) {
9252 		/* Register interrupt callback, but mask it (not operational yet). */
9253 		DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
9254 		bcmsdh_intr_disable(sdh); /* XXX New API: bcmsdh_intr_mask()? */
9255 		if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
9256 			DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
9257 			           __FUNCTION__, ret));
9258 			goto fail;
9259 		}
9260 		DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
9261 	} else {
9262 		DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
9263 		           __FUNCTION__));
9264 	}
9265 
9266 	DHD_INFO(("%s: completed!!\n", __FUNCTION__));
9267 
9268 	/* if firmware path present try to download and bring up bus */
9269 	bus->dhd->hang_report  = TRUE;
9270 #if 0 // terence 20150325: fix for WPA/WPA2 4-way handshake fail in hostapd
9271 #if defined(LINUX) || defined(linux)
9272 	if (dhd_download_fw_on_driverload) {
9273 #endif /* LINUX || linux */
9274 		if ((ret = dhd_bus_start(bus->dhd)) != 0) {
9275 			DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__));
9276 #if !defined(OEM_ANDROID)
9277 			if (ret == BCME_NOTUP)
9278 #endif /* !OEM_ANDROID */
9279 				goto fail;
9280 		}
9281 #if defined(LINUX) || defined(linux)
9282 	}
9283 	else {
9284 		/* Set random MAC address during boot time */
9285 		get_random_bytes(&bus->dhd->mac.octet[3], 3);
9286 		/* Adding BRCM OUI */
9287 		bus->dhd->mac.octet[0] = 0;
9288 		bus->dhd->mac.octet[1] = 0x90;
9289 		bus->dhd->mac.octet[2] = 0x4C;
9290 	}
9291 #endif /* LINUX || linux */
9292 #endif
9293 #if defined(BT_OVER_SDIO)
9294 	/* At this point Regulators are turned on and iconditionaly sdio bus is started
9295 	 * based upon dhd_download_fw_on_driverload check, so
9296 	 * increase the bus user count, this count will only be disabled inside
9297 	 * dhd_register_if() function if flag dhd_download_fw_on_driverload is set to false,
9298 	 * i.e FW download during insmod is not needed, otherwise it will not be decremented
9299 	 * so that WALN will always hold the bus untill rmmod is done.
9300 	 */
9301 	dhdsdio_bus_usr_cnt_inc(bus->dhd);
9302 #endif /* BT_OVER_SDIO */
9303 
9304 	/* Ok, have the per-port tell the stack we're open for business */
9305 	if (dhd_attach_net(bus->dhd, TRUE) != 0) {
9306 		DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
9307 		goto fail;
9308 	}
9309 
9310 #ifdef BCMHOST_XTAL_PU_TIME_MOD
9311 	bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11);
9312 	bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001);
9313 #endif /* BCMHOST_XTAL_PU_TIME_MOD */
9314 
9315 #if defined(MULTIPLE_SUPPLICANT)
9316 	wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
9317 #endif /* MULTIPLE_SUPPLICANT */
9318 	DHD_MUTEX_UNLOCK();
9319 
9320 	return bus;
9321 
9322 fail:
9323 	dhdsdio_release(bus, osh);
9324 
9325 forcereturn:
9326 	DHD_MUTEX_UNLOCK();
9327 
9328 	return NULL;
9329 }
9330 
9331 static bool
dhdsdio_probe_attach(struct dhd_bus * bus,osl_t * osh,void * sdh,void * regsva,uint16 devid)9332 dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
9333                      uint16 devid)
9334 {
9335 #ifndef BCMSPI
9336 	int err = 0;
9337 	uint8 clkctl = 0;
9338 #endif /* !BCMSPI */
9339 
9340 	bus->alp_only = TRUE;
9341 	bus->sih = NULL;
9342 
9343 	/* Return the window to backplane enumeration space for core access */
9344 	if (dhdsdio_set_siaddr_window(bus, si_enum_base(devid))) {
9345 		DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
9346 	}
9347 
9348 #if defined(DHD_DEBUG) && !defined(CUSTOMER_HW4_DEBUG)
9349 	DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n",
9350 		bcmsdh_reg_read(bus->sdh, si_enum_base(devid), 4)));
9351 #endif /* DHD_DEBUG && !CUSTOMER_HW4_DEBUG */
9352 
9353 #ifndef BCMSPI	/* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */
9354 
9355 	/* Force PLL off until si_attach() programs PLL control regs */
9356 
9357 	/* XXX Ideally should not access F1 power control regs before
9358 	 * reading CIS and confirming device.  But strapping option for
9359 	 * low-power start requires turning on ALP before reading CIS,
9360 	 * and at some point bcmsdh should read the CIS for the ID and
9361 	 * not even tell us if it's some other device.  At this point
9362 	 * (see above) we should know it's us (powered on) or can't read
9363 	 * CIS so we need to power on and try.
9364 	 */
9365 
9366 	/* WAR for PR 39902: must force HT off until PLL programmed. */
9367 	/* WAR for PR43618, PR44891: don't do ALPReq until ALPAvail set */
9368 
9369 	/* XXX Replace write/read sequence with single bcmsdh_cfg_raw() call */
9370 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err);
9371 	if (!err)
9372 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
9373 
9374 	if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
9375 		DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
9376 		           err, DHD_INIT_CLKCTL1, clkctl));
9377 		goto fail;
9378 	}
9379 
9380 #endif /* !BCMSPI */
9381 
9382 #ifdef DHD_DEBUG
9383 	if (DHD_INFO_ON()) {
9384 		uint fn, numfn;
9385 		uint8 *cis = NULL;
9386 		int local_err = 0;
9387 
9388 #ifndef BCMSPI
9389 		numfn = bcmsdh_query_iofnum(sdh);
9390 		ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
9391 
9392 		/* Make sure ALP is available before trying to read CIS */
9393 		SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
9394 		                                    SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
9395 		          !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
9396 
9397 		/* Now request ALP be put on the bus */
9398 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
9399 		                 DHD_INIT_CLKCTL2, &local_err);
9400 		/* XXX Account for possible delay between ALP available and on active */
9401 		OSL_DELAY(65);
9402 #else
9403 		numfn = 0; /* internally func is hardcoded to 1 as gSPI has cis on F1 only */
9404 #endif /* !BCMSPI */
9405 #ifndef BCMSDIOLITE
9406 		if (!(cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
9407 			DHD_INFO(("dhdsdio_probe: cis malloc failed\n"));
9408 			goto fail;
9409 		}
9410 
9411 		for (fn = 0; fn <= numfn; fn++) {
9412 			bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
9413 			if ((err = bcmsdh_cis_read(sdh, fn, cis,
9414 				SBSDIO_CIS_SIZE_LIMIT))) {
9415 				DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n",
9416 					fn, err));
9417 				break;
9418 			}
9419 			dhd_dump_cis(fn, cis);
9420 		}
9421 		MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
9422 #else
9423 	BCM_REFERENCE(cis);
9424 	BCM_REFERENCE(fn);
9425 #endif /* DHD_DEBUG */
9426 		if (local_err) {
9427 			DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n"));
9428 			goto fail;
9429 		}
9430 	}
9431 #endif /* DHD_DEBUG */
9432 
9433 	/* si_attach() will provide an SI handle and scan the backplane */
9434 	if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
9435 	                           &bus->vars, &bus->varsz))) {
9436 		DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
9437 		goto fail;
9438 	}
9439 
9440 #ifdef DHD_DEBUG
9441 	DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n",
9442 		bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg));
9443 #endif /* DHD_DEBUG */
9444 
9445 	/* XXX Let the layers below dhd know the chipid and chiprev for
9446 	 * controlling sw WARs for hw PRs
9447 	 */
9448 	bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
9449 
9450 	if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
9451 		DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
9452 		           __FUNCTION__, bus->sih->chip));
9453 #ifdef BCMINTERNAL
9454 		if (dhd_anychip)
9455 			DHD_ERROR(("Continuing anyway...\n"));
9456 		else
9457 #endif /* BCMINTERNAL */
9458 		goto fail;
9459 	}
9460 
9461 	if (bus->sih->buscorerev >= 12)
9462 		dhdsdio_clk_kso_init(bus);
9463 	else
9464 		bus->kso = TRUE;
9465 
9466 	si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
9467 
9468 #ifdef BCMINTERNAL
9469 	/* Check if there is a PMU in the chip.  The FPGA does not have a PMU. */
9470 	if (!(bus->sih->cccaps & CC_CAP_PMU)) {
9471 		DHD_NOPMU(bus) = 1;
9472 	}
9473 #endif /* BCMINTERNAL */
9474 
9475 	/* Get info on the ARM and SOCRAM cores... */
9476 	/* XXX Should really be qualified by device id */
9477 	if (!DHD_NOPMU(bus)) {
9478 		if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
9479 		    (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
9480 		    (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
9481 			bus->armrev = si_corerev(bus->sih);
9482 		} else {
9483 			DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
9484 			goto fail;
9485 		}
9486 
9487 		if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
9488 			if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
9489 				DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
9490 				goto fail;
9491 			}
9492 		} else {
9493 			/* cr4 has a different way to find the RAM size from TCM's */
9494 			if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
9495 				DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
9496 				goto fail;
9497 			}
9498 			/* also populate base address */
9499 			switch ((uint16)bus->sih->chip) {
9500 			case BCM4335_CHIP_ID:
9501 			case BCM4339_CHIP_ID:
9502 				bus->dongle_ram_base = CR4_4335_RAM_BASE;
9503 				break;
9504 			case BCM4350_CHIP_ID:
9505 			case BCM4354_CHIP_ID:
9506 			case BCM4358_CHIP_ID:
9507 			case BCM43569_CHIP_ID:
9508 			case BCM4371_CHIP_ID:
9509 				bus->dongle_ram_base = CR4_4350_RAM_BASE;
9510 				break;
9511 			case BCM4360_CHIP_ID:
9512 				bus->dongle_ram_base = CR4_4360_RAM_BASE;
9513 				break;
9514 			CASE_BCM4345_CHIP:
9515 				bus->dongle_ram_base = (bus->sih->chiprev < 6)  /* from 4345C0 */
9516 					? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
9517 				break;
9518 			case BCM4349_CHIP_GRPID:
9519 				/* RAM based changed from 4349c0(revid=9) onwards */
9520 				bus->dongle_ram_base = ((bus->sih->chiprev < 9) ?
9521 					CR4_4349_RAM_BASE: CR4_4349_RAM_BASE_FROM_REV_9);
9522 				break;
9523 			case BCM4364_CHIP_ID:
9524 				bus->dongle_ram_base = CR4_4364_RAM_BASE;
9525 				break;
9526 #ifdef UNRELEASEDCHIP
9527 	                case BCM4347_CHIP_ID:
9528 	                case BCM4357_CHIP_ID:
9529 	                case BCM4361_CHIP_ID:
9530 				bus->dongle_ram_base = CR4_4347_RAM_BASE;
9531 				break;
9532 #endif
9533 			case BCM4362_CHIP_ID:
9534 				bus->dongle_ram_base = CR4_4362_RAM_BASE;
9535 				break;
9536 			case BCM43751_CHIP_ID:
9537 				bus->dongle_ram_base = CR4_43751_RAM_BASE;
9538 				break;
9539 			case BCM43752_CHIP_ID:
9540 				bus->dongle_ram_base = CR4_43752_RAM_BASE;
9541 				break;
9542 			case BCM4369_CHIP_ID:
9543 				bus->dongle_ram_base = CR4_4369_RAM_BASE;
9544 				break;
9545 			case BCM4378_CHIP_GRPID:
9546 				bus->dongle_ram_base = CR4_4378_RAM_BASE;
9547 				break;
9548 			default:
9549 				bus->dongle_ram_base = 0;
9550 				DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
9551 				           __FUNCTION__, bus->dongle_ram_base));
9552 			}
9553 		}
9554 		bus->ramsize = bus->orig_ramsize;
9555 		if (dhd_dongle_ramsize)
9556 			dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
9557 
9558 		DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
9559 		           bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
9560 
9561 		bus->srmemsize = si_socram_srmem_size(bus->sih);
9562 	}
9563 
9564 	/* ...but normally deal with the SDPCMDEV core */
9565 #ifdef BCMSDIOLITE
9566 	if (!(bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0))) {
9567 		DHD_ERROR(("%s: failed to find Chip Common core!\n", __FUNCTION__));
9568 		goto fail;
9569 	}
9570 #else
9571 	if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
9572 	    !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
9573 		DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
9574 		goto fail;
9575 	}
9576 #endif
9577 	bus->sdpcmrev = si_corerev(bus->sih);
9578 
9579 	/* Set core control so an SDIO reset does a backplane reset */
9580 	OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
9581 #ifndef BCMSPI
9582 	bus->rxint_mode = SDIO_DEVICE_HMB_RXINT;
9583 
9584 	if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
9585 		(bus->rxint_mode  == SDIO_DEVICE_RXDATAINT_MODE_1))
9586 	{
9587 		uint32 val;
9588 
9589 		val = R_REG(osh, &bus->regs->corecontrol);
9590 		val &= ~CC_XMTDATAAVAIL_MODE;
9591 		val |= CC_XMTDATAAVAIL_CTRL;
9592 		W_REG(osh, &bus->regs->corecontrol, val);
9593 	}
9594 #endif /* BCMSPI */
9595 
9596 	/* XXX Tx needs priority queue, where to determine levels? */
9597 	/* XXX Should it try to do WLC mapping, or just pass through? */
9598 	pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
9599 
9600 	/* Locate an appropriately-aligned portion of hdrbuf */
9601 #ifndef DYNAMIC_MAX_HDR_READ
9602 	bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN);
9603 #endif
9604 
9605 	/* Set the poll and/or interrupt flags */
9606 	bus->intr = (bool)dhd_intr;
9607 	if ((bus->poll = (bool)dhd_poll))
9608 		bus->pollrate = 1;
9609 
9610 	/* Setting default Glom size */
9611 	bus->txglomsize = SDPCM_DEFGLOM_SIZE;
9612 
9613 	return TRUE;
9614 
9615 fail:
9616 	if (bus->sih != NULL) {
9617 		si_detach(bus->sih);
9618 		bus->sih = NULL;
9619 	}
9620 	return FALSE;
9621 }
9622 
9623 static bool
dhdsdio_probe_malloc(dhd_bus_t * bus,osl_t * osh,void * sdh)9624 dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
9625 {
9626 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9627 
9628 	if (bus->dhd->maxctl) {
9629 		bus->rxblen = ROUNDUP((bus->dhd->maxctl+SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
9630 		if (!(bus->rxbuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxblen))) {
9631 			DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
9632 			           __FUNCTION__, bus->rxblen));
9633 			goto fail;
9634 		}
9635 	}
9636 	/* Allocate buffer to receive glomed packet */
9637 	if (!(bus->databuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
9638 		DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
9639 			__FUNCTION__, MAX_DATA_BUF));
9640 		/* release rxbuf which was already located as above */
9641 		if (!bus->rxblen)
9642 			DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen);
9643 		goto fail;
9644 	}
9645 	/* Allocate buffer to membuf */
9646 	bus->membuf = MALLOC(osh, MAX_MEM_BUF);
9647 	if (bus->membuf == NULL) {
9648 		DHD_ERROR(("%s: MALLOC of %d-byte membuf failed\n",
9649 			__FUNCTION__, MAX_MEM_BUF));
9650 		if (bus->databuf) {
9651 #ifndef CONFIG_DHD_USE_STATIC_BUF
9652 			MFREE(osh, bus->databuf, MAX_DATA_BUF);
9653 #endif
9654 			bus->databuf = NULL;
9655 		}
9656 		/* release rxbuf which was already located as above */
9657 		if (!bus->rxblen)
9658 			DHD_OS_PREFREE(bus->dhd, bus->rxbuf, bus->rxblen);
9659 		goto fail;
9660 	}
9661 	memset(bus->membuf, 0, MAX_MEM_BUF);
9662 
9663 	/* Align the buffer */
9664 	if ((uintptr)bus->databuf % DHD_SDALIGN)
9665 		bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
9666 	else
9667 		bus->dataptr = bus->databuf;
9668 
9669 	return TRUE;
9670 
9671 fail:
9672 	return FALSE;
9673 }
9674 
9675 static bool
dhdsdio_probe_init(dhd_bus_t * bus,osl_t * osh,void * sdh)9676 dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
9677 {
9678 	int32 fnum;
9679 
9680 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9681 
9682 	bus->_srenab = FALSE;
9683 
9684 #ifdef SDTEST
9685 	dhdsdio_pktgen_init(bus);
9686 #endif /* SDTEST */
9687 
9688 #ifndef BCMSPI
9689 	/* Disable F2 to clear any intermediate frame state on the dongle */
9690 	/* XXX New API: change to bcmsdh_fn_set(sdh, SDIO_FUNC_2, FALSE); */
9691 	/* XXX Might write SRES instead, or reset ARM (download prep)? */
9692 	bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
9693 #endif /* !BCMSPI */
9694 
9695 	DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
9696 	bus->dhd->busstate = DHD_BUS_DOWN;
9697 	bus->sleeping = FALSE;
9698 	bus->rxflow = FALSE;
9699 	bus->prev_rxlim_hit = 0;
9700 
9701 #ifndef BCMSPI
9702 	/* Done with backplane-dependent accesses, can drop clock... */
9703 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
9704 #endif /* !BCMSPI */
9705 
9706 	/* ...and initialize clock/power states */
9707 	bus->clkstate = CLK_SDONLY;
9708 	bus->idletime = (int32)dhd_idletime;
9709 	bus->idleclock = DHD_IDLE_ACTIVE;
9710 
9711 	/* Query the SD clock speed */
9712 	if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
9713 	                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
9714 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"));
9715 		bus->sd_divisor = -1;
9716 	} else {
9717 		DHD_INFO(("%s: Initial value for %s is %d\n",
9718 		          __FUNCTION__, "sd_divisor", bus->sd_divisor));
9719 	}
9720 
9721 	/* Query the SD bus mode */
9722 	if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
9723 	                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
9724 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode"));
9725 		bus->sd_mode = -1;
9726 	} else {
9727 		DHD_INFO(("%s: Initial value for %s is %d\n",
9728 		          __FUNCTION__, "sd_mode", bus->sd_mode));
9729 	}
9730 
9731 	/* Query the F2 block size, set roundup accordingly */
9732 	fnum = 2;
9733 	if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
9734 	                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
9735 		bus->blocksize = 0;
9736 		DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
9737 	} else {
9738 		DHD_INFO(("%s: Initial value for %s is %d\n",
9739 		          __FUNCTION__, "sd_blocksize", bus->blocksize));
9740 
9741 		dhdsdio_tune_fifoparam(bus);
9742 	}
9743 	bus->roundup = MIN(max_roundup, bus->blocksize);
9744 
9745 #ifdef DHDENABLE_TAILPAD
9746 	if (bus->pad_pkt)
9747 		PKTFREE(osh, bus->pad_pkt, FALSE);
9748 	bus->pad_pkt = PKTGET(osh, SDIO_MAX_BLOCK_SIZE, FALSE);
9749 	if (bus->pad_pkt == NULL)
9750 		DHD_ERROR(("failed to allocate padding packet\n"));
9751 	else {
9752 		int alignment_offset = 0;
9753 		uintptr pktprt = (uintptr)PKTDATA(osh, bus->pad_pkt);
9754 		if (!(pktprt&1) && (pktprt = (pktprt % DHD_SDALIGN)))
9755 			PKTPUSH(osh, bus->pad_pkt, alignment_offset);
9756 		PKTSETNEXT(osh, bus->pad_pkt, NULL);
9757 	}
9758 #endif /* DHDENABLE_TAILPAD */
9759 
9760 	/* Query if bus module supports packet chaining, default to use if supported */
9761 	if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
9762 	                    &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) {
9763 		bus->sd_rxchain = FALSE;
9764 	} else {
9765 		DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
9766 		          __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")));
9767 	}
9768 	bus->use_rxchain = (bool)bus->sd_rxchain;
9769 	bus->txinrx_thres = CUSTOM_TXINRX_THRES;
9770 	/* TX first in dhdsdio_readframes() */
9771 	bus->dotxinrx = TRUE;
9772 
9773 #ifdef PKT_STATICS
9774 	dhd_bus_clear_txpktstatics(bus->dhd);
9775 #endif
9776 
9777 	return TRUE;
9778 }
9779 
9780 int
dhd_bus_download_firmware(struct dhd_bus * bus,osl_t * osh,char * pfw_path,char * pnv_path,char * pclm_path,char * pconf_path)9781 dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
9782                           char *pfw_path, char *pnv_path,
9783                           char *pclm_path, char *pconf_path)
9784 {
9785 	int ret;
9786 
9787 	bus->fw_path = pfw_path;
9788 	bus->nv_path = pnv_path;
9789 	bus->dhd->clm_path = pclm_path;
9790 	bus->dhd->conf_path = pconf_path;
9791 
9792 	ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
9793 
9794 	return ret;
9795 }
9796 
9797 int
dhd_set_bus_params(struct dhd_bus * bus)9798 dhd_set_bus_params(struct dhd_bus *bus)
9799 {
9800 	int ret = 0;
9801 
9802 	if (bus->dhd->conf->dhd_poll >= 0) {
9803 		bus->poll = bus->dhd->conf->dhd_poll;
9804 		if (!bus->pollrate)
9805 			bus->pollrate = 1;
9806 		printf("%s: set polling mode %d\n", __FUNCTION__, bus->dhd->conf->dhd_poll);
9807 	}
9808 	if (bus->dhd->conf->use_rxchain >= 0) {
9809 		bus->use_rxchain = (bool)bus->dhd->conf->use_rxchain;
9810 	}
9811 	if (bus->dhd->conf->txinrx_thres >= 0) {
9812 		bus->txinrx_thres = bus->dhd->conf->txinrx_thres;
9813 	}
9814 	if (bus->dhd->conf->txglomsize >= 0) {
9815 		bus->txglomsize = bus->dhd->conf->txglomsize;
9816 	}
9817 #ifdef MINIME
9818 	if (bus->dhd->conf->fw_type == FW_TYPE_MINIME) {
9819 		bus->ramsize = bus->dhd->conf->ramsize;
9820 		printf("%s: set ramsize 0x%x\n", __FUNCTION__, bus->ramsize);
9821 	}
9822 #endif
9823 #ifdef DYNAMIC_MAX_HDR_READ
9824 	if (bus->dhd->conf->max_hdr_read <= 0) {
9825 		bus->dhd->conf->max_hdr_read = MAX_HDR_READ;
9826 	}
9827 	if (bus->hdrbufp) {
9828 		MFREE(bus->dhd->osh, bus->hdrbufp, bus->dhd->conf->max_hdr_read + DHD_SDALIGN);
9829 	}
9830 	bus->hdrbufp = MALLOC(bus->dhd->osh, bus->dhd->conf->max_hdr_read + DHD_SDALIGN);
9831 	if (bus->hdrbufp == NULL) {
9832 		DHD_ERROR(("%s: MALLOC of %d-byte hdrbufp failed\n",
9833 			__FUNCTION__, bus->dhd->conf->max_hdr_read + DHD_SDALIGN));
9834 		ret = -1;
9835 		goto exit;
9836 	}
9837 	bus->rxhdr = (uint8 *)ROUNDUP((uintptr)bus->hdrbufp, DHD_SDALIGN);
9838 
9839 exit:
9840 #endif
9841 	return ret;
9842 }
9843 
9844 static int
dhdsdio_download_firmware(struct dhd_bus * bus,osl_t * osh,void * sdh)9845 dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
9846 {
9847 	int ret;
9848 
9849 #if defined(SUPPORT_MULTIPLE_REVISION)
9850 	if (concate_revision(bus, bus->fw_path, bus->nv_path) != 0) {
9851 		DHD_ERROR(("%s: fail to concatnate revison \n",
9852 			__FUNCTION__));
9853 		return BCME_BADARG;
9854 	}
9855 #endif /* SUPPORT_MULTIPLE_REVISION */
9856 
9857 #if defined(DHD_BLOB_EXISTENCE_CHECK)
9858 	dhd_set_blob_support(bus->dhd, bus->fw_path);
9859 #endif /* DHD_BLOB_EXISTENCE_CHECK */
9860 
9861 	DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
9862 		__FUNCTION__, bus->fw_path, bus->nv_path));
9863 	DHD_OS_WAKE_LOCK(bus->dhd);
9864 
9865 	dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
9866 	ret = dhd_set_bus_params(bus);
9867 	if (ret) {
9868 		goto exit;
9869 	}
9870 
9871 	/* Download the firmware */
9872 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
9873 
9874 	ret = _dhdsdio_download_firmware(bus);
9875 
9876 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
9877 
9878 exit:
9879 	DHD_OS_WAKE_UNLOCK(bus->dhd);
9880 	return ret;
9881 }
9882 
9883 /* Detach and free everything */
9884 static void
dhdsdio_release(dhd_bus_t * bus,osl_t * osh)9885 dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
9886 {
9887 	bool dongle_isolation = FALSE;
9888 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9889 
9890 	if (bus) {
9891 		ASSERT(osh);
9892 
9893 		if (bus->dhd) {
9894 #if defined(DEBUGGER) || defined(DHD_DSCOPE)
9895 			debugger_close();
9896 #endif /* DEBUGGER || DHD_DSCOPE */
9897 			dongle_isolation = bus->dhd->dongle_isolation;
9898 			dhd_detach(bus->dhd);
9899 		}
9900 
9901 		/* De-register interrupt handler */
9902 		bcmsdh_intr_disable(bus->sdh);
9903 		bcmsdh_intr_dereg(bus->sdh);
9904 
9905 		if (bus->dhd) {
9906 			dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
9907 			dhd_free(bus->dhd);
9908 			bus->dhd = NULL;
9909 		}
9910 
9911 		dhdsdio_release_malloc(bus, osh);
9912 
9913 #ifdef DHD_DEBUG
9914 		if (bus->console.buf != NULL)
9915 			MFREE(osh, bus->console.buf, bus->console.bufsize);
9916 #endif
9917 
9918 #ifdef DHDENABLE_TAILPAD
9919 		if (bus->pad_pkt)
9920 			PKTFREE(osh, bus->pad_pkt, FALSE);
9921 #endif /* DHDENABLE_TAILPAD */
9922 #ifdef DYNAMIC_MAX_HDR_READ
9923 	if (bus->hdrbufp) {
9924 		MFREE(osh, bus->hdrbufp, MAX_HDR_READ + DHD_SDALIGN);
9925 	}
9926 #endif
9927 
9928 		MFREE(osh, bus, sizeof(dhd_bus_t));
9929 	}
9930 
9931 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
9932 }
9933 
9934 static void
dhdsdio_release_malloc(dhd_bus_t * bus,osl_t * osh)9935 dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
9936 {
9937 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
9938 
9939 	if (bus->dhd && bus->dhd->dongle_reset)
9940 		return;
9941 
9942 	if (bus->rxbuf) {
9943 #ifndef CONFIG_DHD_USE_STATIC_BUF
9944 		MFREE(osh, bus->rxbuf, bus->rxblen);
9945 #endif
9946 		bus->rxctl = NULL;
9947 		bus->rxlen = 0;
9948 	}
9949 
9950 	if (bus->databuf) {
9951 #ifndef CONFIG_DHD_USE_STATIC_BUF
9952 		MFREE(osh, bus->databuf, MAX_DATA_BUF);
9953 #endif
9954 	}
9955 
9956 	if (bus->membuf) {
9957 		MFREE(osh, bus->membuf, MAX_MEM_BUF);
9958 		bus->membuf = NULL;
9959 	}
9960 
9961 	if (bus->vars && bus->varsz) {
9962 		MFREE(osh, bus->vars, bus->varsz);
9963 	}
9964 
9965 }
9966 
9967 static void
dhdsdio_release_dongle(dhd_bus_t * bus,osl_t * osh,bool dongle_isolation,bool reset_flag)9968 dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
9969 {
9970 	DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
9971 		bus->dhd, bus->dhd->dongle_reset));
9972 
9973 	if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
9974 		return;
9975 
9976 	if (bus->sih) {
9977 		/* In Win10, system will be BSOD if using "sysprep" to do OS image */
9978 		/* Skip this will not cause the BSOD. */
9979 #if !defined(BCMLXSDMMC) && !defined(NDIS)
9980 		/* XXX - Using the watchdog to reset the chip does not allow
9981 		 * further SDIO communication.  For the SDMMC Driver, this
9982 		 * causes interrupt to not be de-registered properly.
9983 		 */
9984 		/* XXX: dongle isolation mode is on don't reset the chip */
9985 		if (bus->dhd) {
9986 			dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
9987 		}
9988 		if (KSO_ENAB(bus) && (dongle_isolation == FALSE))
9989 			si_watchdog(bus->sih, 4);
9990 #endif /* !defined(BCMLXSDMMC) */
9991 		if (bus->dhd) {
9992 			dhdsdio_clkctl(bus, CLK_NONE, FALSE);
9993 		}
9994 		si_detach(bus->sih);
9995 		bus->sih = NULL;
9996 		if (bus->vars && bus->varsz)
9997 			MFREE(osh, bus->vars, bus->varsz);
9998 		bus->vars = NULL;
9999 	}
10000 
10001 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
10002 }
10003 
10004 static void
dhdsdio_disconnect(void * ptr)10005 dhdsdio_disconnect(void *ptr)
10006 {
10007 	dhd_bus_t *bus = (dhd_bus_t *)ptr;
10008 
10009 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
10010 
10011 	DHD_MUTEX_LOCK();
10012 	if (bus) {
10013 		ASSERT(bus->dhd);
10014 		/* Advertise bus remove during rmmod */
10015 		dhdsdio_advertise_bus_remove(bus->dhd);
10016 		dhdsdio_release(bus, bus->dhd->osh);
10017 	}
10018 	DHD_MUTEX_UNLOCK();
10019 
10020 	DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
10021 }
10022 
10023 static int
dhdsdio_suspend(void * context)10024 dhdsdio_suspend(void *context)
10025 {
10026 	int ret = 0;
10027 #ifdef SUPPORT_P2P_GO_PS
10028 	int wait_time = 0;
10029 #endif /* SUPPORT_P2P_GO_PS */
10030 
10031 #if defined(LINUX)
10032 	dhd_bus_t *bus = (dhd_bus_t*)context;
10033 	unsigned long flags;
10034 
10035 	DHD_ERROR(("%s Enter\n", __FUNCTION__));
10036 	if (bus->dhd == NULL) {
10037 		DHD_ERROR(("bus not inited\n"));
10038 		return BCME_ERROR;
10039 	}
10040 	if (bus->dhd->prot == NULL) {
10041 		DHD_ERROR(("prot is not inited\n"));
10042 		return BCME_ERROR;
10043 	}
10044 
10045 	if (bus->dhd->up == FALSE) {
10046 		return BCME_OK;
10047 	}
10048 
10049 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10050 	if (bus->dhd->busstate != DHD_BUS_DATA && bus->dhd->busstate != DHD_BUS_SUSPEND) {
10051 		DHD_ERROR(("not in a readystate to LPBK  is not inited\n"));
10052 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10053 		return BCME_ERROR;
10054 	}
10055 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10056 	if (bus->dhd->dongle_reset) {
10057 		DHD_ERROR(("Dongle is in reset state.\n"));
10058 		return -EIO;
10059 	}
10060 
10061 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10062 	/* stop all interface network queue. */
10063 	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
10064 	bus->dhd->busstate = DHD_BUS_SUSPEND;
10065 #if defined(LINUX) || defined(linux)
10066 	if (DHD_BUS_BUSY_CHECK_IN_TX(bus->dhd)) {
10067 		DHD_ERROR(("Tx Request is not ended\n"));
10068 		bus->dhd->busstate = DHD_BUS_DATA;
10069 		/* resume all interface network queue. */
10070 		dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
10071 		DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10072 		return -EBUSY;
10073 	}
10074 #endif /* LINUX || linux */
10075 	DHD_BUS_BUSY_SET_SUSPEND_IN_PROGRESS(bus->dhd);
10076 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10077 
10078 #ifdef SUPPORT_P2P_GO_PS
10079 	if (bus->idletime > 0) {
10080 		wait_time = msecs_to_jiffies(bus->idletime * dhd_watchdog_ms);
10081 	}
10082 #endif /* SUPPORT_P2P_GO_PS */
10083 	ret = dhd_os_check_wakelock(bus->dhd);
10084 #ifdef SUPPORT_P2P_GO_PS
10085 	// terence 20141124: fix for suspend issue
10086 	if (SLPAUTO_ENAB(bus) && (!ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) {
10087 		if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) {
10088 			if (!bus->sleeping) {
10089 				ret = 1;
10090 			}
10091 		}
10092 	}
10093 #endif /* SUPPORT_P2P_GO_PS */
10094 
10095 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10096 	if (ret) {
10097 		bus->dhd->busstate = DHD_BUS_DATA;
10098 		/* resume all interface network queue. */
10099 		dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
10100 	}
10101 	bus->dhd->hostsleep = 2;
10102 	DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd);
10103 	dhd_os_busbusy_wake(bus->dhd);
10104 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10105 
10106 #endif /* LINUX */
10107 	return ret;
10108 }
10109 
10110 static int
dhdsdio_resume(void * context)10111 dhdsdio_resume(void *context)
10112 {
10113 	dhd_bus_t *bus = (dhd_bus_t*)context;
10114 	ulong flags;
10115 
10116 	DHD_ERROR(("%s Enter\n", __FUNCTION__));
10117 
10118 	if (bus->dhd->up == FALSE) {
10119 		return BCME_OK;
10120 	}
10121 
10122 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10123 	DHD_BUS_BUSY_SET_RESUME_IN_PROGRESS(bus->dhd);
10124 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10125 
10126 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
10127 	if (dhd_os_check_if_up(bus->dhd))
10128 		bcmsdh_oob_intr_set(bus->sdh, TRUE);
10129 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
10130 
10131 	DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
10132 	DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd);
10133 	bus->dhd->hostsleep = 0;
10134 	bus->dhd->busstate = DHD_BUS_DATA;
10135 	dhd_os_busbusy_wake(bus->dhd);
10136 	/* resume all interface network queue. */
10137 	dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
10138 	DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
10139 
10140 	return 0;
10141 }
10142 
10143 /* Register/Unregister functions are called by the main DHD entry
10144  * point (e.g. module insertion) to link with the bus driver, in
10145  * order to look for or await the device.
10146  */
10147 
10148 static bcmsdh_driver_t dhd_sdio = {
10149 	dhdsdio_probe,
10150 	dhdsdio_disconnect,
10151 	dhdsdio_suspend,
10152 	dhdsdio_resume
10153 };
10154 
10155 int
dhd_bus_register(void)10156 dhd_bus_register(void)
10157 {
10158 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
10159 
10160 	return bcmsdh_register(&dhd_sdio);
10161 }
10162 
10163 void
dhd_bus_unregister(void)10164 dhd_bus_unregister(void)
10165 {
10166 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
10167 
10168 	bcmsdh_unregister();
10169 }
10170 
10171 #if defined(BCMLXSDMMC)
10172 /* Register a dummy SDIO client driver in order to be notified of new SDIO device */
dhd_bus_reg_sdio_notify(void * semaphore)10173 int dhd_bus_reg_sdio_notify(void* semaphore)
10174 {
10175 	return bcmsdh_reg_sdio_notify(semaphore);
10176 }
10177 
dhd_bus_unreg_sdio_notify(void)10178 void dhd_bus_unreg_sdio_notify(void)
10179 {
10180 	bcmsdh_unreg_sdio_notify();
10181 }
10182 #endif /* defined(BCMLXSDMMC) */
10183 
10184 #ifdef BCMEMBEDIMAGE
10185 static int
dhdsdio_download_code_array(struct dhd_bus * bus)10186 dhdsdio_download_code_array(struct dhd_bus *bus)
10187 {
10188 	int bcmerror = -1;
10189 	int offset = 0;
10190 	unsigned char *ularray = NULL;
10191 
10192 	DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__));
10193 
10194 	/* Download image */
10195 	while ((offset + MEMBLOCK) < sizeof(dlarray)) {
10196 		/* check if CR4 */
10197 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
10198 			/* if address is 0, store the reset instruction to be written in 0 */
10199 
10200 			if (offset == 0) {
10201 				bus->resetinstr = *(((uint32*)dlarray));
10202 				/* Add start of RAM address to the address given by user */
10203 				offset += bus->dongle_ram_base;
10204 			}
10205 		}
10206 
10207 		bcmerror = dhdsdio_membytes(bus, TRUE, offset,
10208 			(uint8 *) (dlarray + offset), MEMBLOCK);
10209 		if (bcmerror) {
10210 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10211 			        __FUNCTION__, bcmerror, MEMBLOCK, offset));
10212 			goto err;
10213 		}
10214 
10215 		offset += MEMBLOCK;
10216 	}
10217 
10218 	if (offset < sizeof(dlarray)) {
10219 		bcmerror = dhdsdio_membytes(bus, TRUE, offset,
10220 			(uint8 *) (dlarray + offset), sizeof(dlarray) - offset);
10221 		if (bcmerror) {
10222 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10223 			        __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
10224 			goto err;
10225 		}
10226 	}
10227 
10228 #ifdef DHD_DEBUG
10229 	/* Upload and compare the downloaded code */
10230 	{
10231 		ularray = MALLOC(bus->dhd->osh, bus->ramsize);
10232 		/* Upload image to verify downloaded contents. */
10233 		offset = 0;
10234 		memset(ularray, 0xaa, bus->ramsize);
10235 		while ((offset + MEMBLOCK) < sizeof(dlarray)) {
10236 			bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK);
10237 			if (bcmerror) {
10238 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10239 					__FUNCTION__, bcmerror, MEMBLOCK, offset));
10240 				goto err;
10241 			}
10242 
10243 			offset += MEMBLOCK;
10244 		}
10245 
10246 		if (offset < sizeof(dlarray)) {
10247 			bcmerror = dhdsdio_membytes(bus, FALSE, offset,
10248 				ularray + offset, sizeof(dlarray) - offset);
10249 			if (bcmerror) {
10250 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10251 					__FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
10252 				goto err;
10253 			}
10254 		}
10255 
10256 		if (memcmp(dlarray, ularray, sizeof(dlarray))) {
10257 			DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n",
10258 			           __FUNCTION__, dlimagename, dlimagever, dlimagedate));
10259 			goto err;
10260 		} else
10261 			DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n",
10262 			           __FUNCTION__, dlimagename, dlimagever, dlimagedate));
10263 
10264 	}
10265 #endif /* DHD_DEBUG */
10266 
10267 err:
10268 	if (ularray)
10269 		MFREE(bus->dhd->osh, ularray, bus->ramsize);
10270 	return bcmerror;
10271 }
10272 #endif /* BCMEMBEDIMAGE */
10273 
10274 #ifdef DHD_LINUX_STD_FW_API
10275 static int
dhdsdio_download_code_file(struct dhd_bus * bus,char * pfw_path)10276 dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
10277 {
10278 	int bcmerror = -1;
10279 	int offset = 0;
10280 	int len;
10281 	uint8 *memblock = NULL, *memptr;
10282 #ifdef CHECK_DOWNLOAD_FW
10283 	uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct
10284 #endif
10285 	uint memblock_size = MEMBLOCK;
10286 #ifdef DHD_DEBUG_DOWNLOADTIME
10287 	unsigned long initial_jiffies = 0;
10288 	uint firmware_sz = 0;
10289 #endif
10290 	int offset_end = bus->ramsize;
10291 	const struct firmware *fw = NULL;
10292 	int buf_offset = 0, residual_len = 0;
10293 
10294 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
10295 
10296 	/* XXX: Should succeed in opening image if it is actually given through registry
10297 	 * entry or in module param.
10298 	 */
10299 	bcmerror = dhd_os_get_img_fwreq(&fw, bus->fw_path);
10300 	if (bcmerror < 0) {
10301 		DHD_ERROR(("dhd_os_get_img(Request Firmware API) error : %d\n",
10302 			bcmerror));
10303 		goto err;
10304 	}
10305 	residual_len = fw->size;
10306 
10307 	/* Update the dongle image download block size depending on the F1 block size */
10308 #ifndef NDIS
10309 	if (sd_f1_blocksize == 512)
10310 		memblock_size = MAX_MEMBLOCK;
10311 #endif /* !NDIS */
10312 
10313 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
10314 	if (memblock == NULL) {
10315 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10316 			memblock_size));
10317 		goto err;
10318 	}
10319 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
10320 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
10321 
10322 #ifdef CHECK_DOWNLOAD_FW
10323 		if (bus->dhd->conf->fwchk) {
10324 			memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
10325 			if (memptr_tmp == NULL) {
10326 				DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
10327 				goto err;
10328 			}
10329 		}
10330 #endif
10331 
10332 #ifdef DHD_DEBUG_DOWNLOADTIME
10333 	initial_jiffies = jiffies;
10334 #endif
10335 
10336 	/* Download image */
10337 	while (residual_len) {
10338 		len = MIN(residual_len, memblock_size);
10339 		bcopy((uint8 *)fw->data + buf_offset, (uint8 *)memptr, len);
10340 		/* check if CR4 */
10341 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
10342 			/* if address is 0, store the reset instruction to be written in 0 */
10343 
10344 			if (offset == 0) {
10345 				bus->resetinstr = *(((uint32*)memptr));
10346 				/* Add start of RAM address to the address given by user */
10347 				offset += bus->dongle_ram_base;
10348 				offset_end += offset;
10349 			}
10350 		}
10351 
10352 		bcmerror = dhdsdio_membytes(bus, TRUE, offset, (uint8 *)memptr, len);
10353 		if (bcmerror) {
10354 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10355 			        __FUNCTION__, bcmerror, memblock_size, offset));
10356 			goto err;
10357 		}
10358 
10359 #ifdef CHECK_DOWNLOAD_FW
10360 		if (bus->dhd->conf->fwchk) {
10361 			bcmerror = dhdsdio_membytes(bus, FALSE, offset, memptr_tmp, len);
10362 			if (bcmerror) {
10363 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10364 				        __FUNCTION__, bcmerror, MEMBLOCK, offset));
10365 				goto err;
10366 			}
10367 			if (memcmp(memptr_tmp, memptr, len)) {
10368 				DHD_ERROR(("%s: Downloaded image is corrupted at 0x%08x\n", __FUNCTION__, offset));
10369 				bcmerror = BCME_ERROR;
10370 				goto err;
10371 			} else
10372 				DHD_INFO(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__));
10373 		}
10374 #endif
10375 
10376 		offset += memblock_size;
10377 #ifdef DHD_DEBUG_DOWNLOADTIME
10378 		firmware_sz += len;
10379 #endif
10380 		if (offset >= offset_end) {
10381 			DHD_ERROR(("%s: invalid address access to %x (offset end: %x)\n",
10382 				__FUNCTION__, offset, offset_end));
10383 			bcmerror = BCME_ERROR;
10384 			goto err;
10385 		}
10386 		residual_len -= len;
10387 		buf_offset += len;
10388 	}
10389 
10390 #ifdef DHD_DEBUG_DOWNLOADTIME
10391 	DHD_ERROR(("Firmware download time for %u bytes: %u ms\n",
10392 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
10393 #endif
10394 
10395 err:
10396 	if (memblock)
10397 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
10398 #ifdef CHECK_DOWNLOAD_FW
10399 	if (bus->dhd->conf->fwchk) {
10400 		if (memptr_tmp)
10401 			MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN);
10402 	}
10403 #endif
10404 
10405 	if (fw) {
10406 		dhd_os_close_img_fwreq(fw);
10407 	}
10408 
10409 	return bcmerror;
10410 }
10411 #else
10412 static int
dhdsdio_download_code_file(struct dhd_bus * bus,char * pfw_path)10413 dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
10414 {
10415 	int bcmerror = -1;
10416 	int offset = 0;
10417 	int len;
10418 	void *image = NULL;
10419 	uint8 *memblock = NULL, *memptr;
10420 #ifdef CHECK_DOWNLOAD_FW
10421 	uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct
10422 #endif
10423 	uint memblock_size = MEMBLOCK;
10424 #ifdef DHD_DEBUG_DOWNLOADTIME
10425 	unsigned long initial_jiffies = 0;
10426 	uint firmware_sz = 0;
10427 #endif
10428 
10429 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
10430 
10431 	/* XXX: Should succeed in opening image if it is actually given through registry
10432 	 * entry or in module param.
10433 	 */
10434 	image = dhd_os_open_image1(bus->dhd, pfw_path);
10435 	if (image == NULL) {
10436 		printf("%s: Open firmware file failed %s\n", __FUNCTION__, pfw_path);
10437 		goto err;
10438 	}
10439 
10440 	/* Update the dongle image download block size depending on the F1 block size */
10441 #ifndef NDIS
10442 	if (sd_f1_blocksize == 512)
10443 		memblock_size = MAX_MEMBLOCK;
10444 #endif /* !NDIS */
10445 
10446 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
10447 	if (memblock == NULL) {
10448 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10449 			memblock_size));
10450 		goto err;
10451 	}
10452 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
10453 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
10454 
10455 #ifdef CHECK_DOWNLOAD_FW
10456 	if (bus->dhd->conf->fwchk) {
10457 		memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
10458 		if (memptr_tmp == NULL) {
10459 			DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
10460 			goto err;
10461 		}
10462 	}
10463 #endif
10464 
10465 #ifdef DHD_DEBUG_DOWNLOADTIME
10466 	initial_jiffies = jiffies;
10467 #endif
10468 
10469 	/* Download image */
10470 	while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) {
10471 		// terence 20150412: fix for firmware failed to download
10472 		if (bus->dhd->conf->chip == BCM43340_CHIP_ID ||
10473 				bus->dhd->conf->chip == BCM43341_CHIP_ID) {
10474 			if (len % 64 != 0) {
10475 				memset(memptr+len, 0, len%64);
10476 				len += (64 - len%64);
10477 			}
10478 		}
10479 		if (len < 0) {
10480 			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
10481 			bcmerror = BCME_ERROR;
10482 			goto err;
10483 		}
10484 		/* check if CR4 */
10485 		if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
10486 			/* if address is 0, store the reset instruction to be written in 0 */
10487 
10488 			if (offset == 0) {
10489 				bus->resetinstr = *(((uint32*)memptr));
10490 				/* Add start of RAM address to the address given by user */
10491 				offset += bus->dongle_ram_base;
10492 			}
10493 		}
10494 
10495 		bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
10496 		if (bcmerror) {
10497 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10498 			        __FUNCTION__, bcmerror, memblock_size, offset));
10499 			goto err;
10500 		}
10501 
10502 #ifdef CHECK_DOWNLOAD_FW
10503 		if (bus->dhd->conf->fwchk) {
10504 			bcmerror = dhdsdio_membytes(bus, FALSE, offset, memptr_tmp, len);
10505 			if (bcmerror) {
10506 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
10507 				        __FUNCTION__, bcmerror, MEMBLOCK, offset));
10508 				goto err;
10509 			}
10510 			if (memcmp(memptr_tmp, memptr, len)) {
10511 				DHD_ERROR(("%s: Downloaded image is corrupted at 0x%08x\n", __FUNCTION__, offset));
10512 				bcmerror = BCME_ERROR;
10513 				goto err;
10514 			} else
10515 				DHD_INFO(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__));
10516 		}
10517 #endif
10518 
10519 		offset += memblock_size;
10520 #ifdef DHD_DEBUG_DOWNLOADTIME
10521 		firmware_sz += len;
10522 #endif
10523 	}
10524 
10525 #ifdef DHD_DEBUG_DOWNLOADTIME
10526 	DHD_ERROR(("Firmware download time for %u bytes: %u ms\n",
10527 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
10528 #endif
10529 
10530 err:
10531 	if (memblock)
10532 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
10533 #ifdef CHECK_DOWNLOAD_FW
10534 	if (bus->dhd->conf->fwchk) {
10535 		if (memptr_tmp)
10536 			MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN);
10537 	}
10538 #endif
10539 
10540 	if (image)
10541 		dhd_os_close_image1(bus->dhd, image);
10542 
10543 	return bcmerror;
10544 }
10545 #endif /* DHD_LINUX_STD_FW_API */
10546 
10547 #ifdef DHD_UCODE_DOWNLOAD
10548 /* Currently supported only for the chips in which ucode RAM is AXI addressable */
10549 static uint32
dhdsdio_ucode_base(struct dhd_bus * bus)10550 dhdsdio_ucode_base(struct dhd_bus *bus)
10551 {
10552 	uint32 ucode_base = 0;
10553 
10554 	switch ((uint16)bus->sih->chip) {
10555 	case BCM43012_CHIP_ID:
10556 	case BCM43013_CHIP_ID:
10557 	case BCM43014_CHIP_ID:
10558 		ucode_base = 0xE8020000;
10559 		break;
10560 	default:
10561 		DHD_ERROR(("%s: Unsupported!\n", __func__));
10562 		break;
10563 	}
10564 
10565 	return ucode_base;
10566 }
10567 
10568 static int
dhdsdio_download_ucode_file(struct dhd_bus * bus,char * ucode_path)10569 dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path)
10570 {
10571 	int bcmerror = -1;
10572 	int offset = 0;
10573 	int len;
10574 	uint32 ucode_base;
10575 	void *image = NULL;
10576 	uint8 *memblock = NULL, *memptr;
10577 	uint memblock_size = MEMBLOCK;
10578 #ifdef DHD_DEBUG_DOWNLOADTIME
10579 	unsigned long initial_jiffies = 0;
10580 	uint firmware_sz = 0;
10581 #endif
10582 
10583 	DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, ucode_path));
10584 
10585 	ucode_base = dhdsdio_ucode_base(bus);
10586 
10587 	/* XXX: Should succeed in opening image if it is actually given through registry
10588 	 * entry or in module param.
10589 	 */
10590 	image = dhd_os_open_image1(bus->dhd, ucode_path);
10591 	if (image == NULL)
10592 		goto err;
10593 
10594 	/* Update the dongle image download block size depending on the F1 block size */
10595 	if (sd_f1_blocksize == 512)
10596 		memblock_size = MAX_MEMBLOCK;
10597 
10598 	memptr = memblock = MALLOC(bus->dhd->osh, memblock_size + DHD_SDALIGN);
10599 	if (memblock == NULL) {
10600 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
10601 			memblock_size));
10602 		goto err;
10603 	}
10604 	if ((uint32)(uintptr)memblock % DHD_SDALIGN)
10605 		memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
10606 
10607 #ifdef DHD_DEBUG_DOWNLOADTIME
10608 	initial_jiffies = jiffies;
10609 #endif
10610 
10611 	/* Download image */
10612 	while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) {
10613 		if (len < 0) {
10614 			DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
10615 			bcmerror = BCME_ERROR;
10616 			goto err;
10617 		}
10618 
10619 		bcmerror = dhdsdio_membytes(bus, TRUE, (ucode_base + offset), memptr, len);
10620 		if (bcmerror) {
10621 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
10622 			        __FUNCTION__, bcmerror, memblock_size, offset));
10623 			goto err;
10624 		}
10625 
10626 		offset += memblock_size;
10627 #ifdef DHD_DEBUG_DOWNLOADTIME
10628 		firmware_sz += len;
10629 #endif
10630 	}
10631 
10632 #ifdef DHD_DEBUG_DOWNLOADTIME
10633 	DHD_ERROR(("ucode download time for %u bytes: %u ms\n",
10634 			firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies)));
10635 #endif
10636 
10637 err:
10638 	if (memblock)
10639 		MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN);
10640 
10641 	if (image)
10642 		dhd_os_close_image1(bus->dhd, image);
10643 
10644 	return bcmerror;
10645 } /* dhdsdio_download_ucode_file */
10646 
10647 void
dhd_bus_ucode_download(struct dhd_bus * bus)10648 dhd_bus_ucode_download(struct dhd_bus *bus)
10649 {
10650 	uint32 shaddr = 0, shdata = 0;
10651 
10652 	shaddr = bus->dongle_ram_base + bus->ramsize - 4;
10653 	dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&shdata, 4);
10654 
10655 	DHD_TRACE(("%s: shdata:[0x%08x :0x%08x]\n", __func__, shaddr, shdata));
10656 
10657 	if (shdata == UCODE_DOWNLOAD_REQUEST)
10658 	{
10659 		DHD_ERROR(("%s: Received ucode download request!\n", __func__));
10660 
10661 		/* Download the ucode */
10662 		if (!dhd_get_ucode_path(bus->dhd)) {
10663 			DHD_ERROR(("%s: bus->uc_path not set!\n", __func__));
10664 			return;
10665 		}
10666 		dhdsdio_download_ucode_file(bus, dhd_get_ucode_path(bus->dhd));
10667 
10668 		DHD_ERROR(("%s: Ucode downloaded successfully!\n", __func__));
10669 
10670 		shdata = UCODE_DOWNLOAD_COMPLETE;
10671 		dhdsdio_membytes(bus, TRUE, shaddr, (uint8 *)&shdata, 4);
10672 	}
10673 }
10674 
10675 #endif /* DHD_UCODE_DOWNLOAD */
10676 
10677 static int
dhdsdio_download_nvram(struct dhd_bus * bus)10678 dhdsdio_download_nvram(struct dhd_bus *bus)
10679 {
10680 	int bcmerror = -1;
10681 	uint len, memblock_len = 0;
10682 	char * memblock = NULL;
10683 	char *bufp;
10684 	char *pnv_path;
10685 	bool nvram_file_exists;
10686 
10687 	pnv_path = bus->nv_path;
10688 
10689 	nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
10690 
10691 	len = MAX_NVRAMBUF_SIZE;
10692 	if (nvram_file_exists)
10693 		bcmerror = dhd_get_download_buffer(bus->dhd, pnv_path, NVRAM, &memblock,
10694 			(int *)&len);
10695 	else
10696 		bcmerror = dhd_get_download_buffer(bus->dhd, NULL, NVRAM, &memblock, (int *)&len);
10697 
10698 	if (bcmerror != BCME_OK)
10699 		goto err;
10700 
10701 #ifdef DHD_LINUX_STD_FW_API
10702 	memblock_len = len;
10703 #else
10704 	memblock_len = MAX_NVRAMBUF_SIZE;
10705 #endif /* DHD_LINUX_STD_FW_API */
10706 
10707 	if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
10708 		bufp = (char *)memblock;
10709 		bufp[len] = 0;
10710 		len = process_nvram_vars(bufp, len);
10711 		if (len % 4) {
10712 			len += 4 - (len % 4);
10713 		}
10714 		bufp += len;
10715 		*bufp++ = 0;
10716 		if (len)
10717 			bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
10718 		if (bcmerror) {
10719 			DHD_ERROR(("%s: error downloading vars: %d\n",
10720 			           __FUNCTION__, bcmerror));
10721 		}
10722 	} else {
10723 		DHD_ERROR(("%s: error reading nvram file: %d\n",
10724 		           __FUNCTION__, len));
10725 		bcmerror = BCME_SDIO_ERROR;
10726 	}
10727 
10728 err:
10729 	if (memblock)
10730 		dhd_free_download_buffer(bus->dhd, memblock, memblock_len);
10731 
10732 	return bcmerror;
10733 }
10734 
10735 static int
_dhdsdio_download_firmware(struct dhd_bus * bus)10736 _dhdsdio_download_firmware(struct dhd_bus *bus)
10737 {
10738 	int bcmerror = -1;
10739 
10740 	bool embed = FALSE;	/* download embedded firmware */
10741 	bool dlok = FALSE;	/* download firmware succeeded */
10742 
10743 	/* Out immediately if no image to download */
10744 	if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
10745 #ifdef BCMEMBEDIMAGE
10746 		embed = TRUE;
10747 #else
10748 		return bcmerror;
10749 #endif
10750 	}
10751 
10752 	/* Keep arm in reset */
10753 	if (dhdsdio_download_state(bus, TRUE)) {
10754 		DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
10755 		goto err;
10756 	}
10757 
10758 	/* External image takes precedence if specified */
10759 	if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
10760 		if (dhdsdio_download_code_file(bus, bus->fw_path)) {
10761 			DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
10762 #ifdef BCMEMBEDIMAGE
10763 			embed = TRUE;
10764 #else
10765 			goto err;
10766 #endif
10767 		} else {
10768 			embed = FALSE;
10769 			dlok = TRUE;
10770 		}
10771 	}
10772 
10773 #ifdef BCMEMBEDIMAGE
10774 	if (embed) {
10775 		if (dhdsdio_download_code_array(bus)) {
10776 			DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
10777 			goto err;
10778 		} else {
10779 			dlok = TRUE;
10780 		}
10781 	}
10782 #else
10783 	BCM_REFERENCE(embed);
10784 #endif
10785 	if (!dlok) {
10786 		DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
10787 		goto err;
10788 	}
10789 
10790 	/* External nvram takes precedence if specified */
10791 	if (dhdsdio_download_nvram(bus)) {
10792 		DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
10793 		goto err;
10794 	}
10795 
10796 	/* Take arm out of reset */
10797 	if (dhdsdio_download_state(bus, FALSE)) {
10798 		DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
10799 		goto err;
10800 	}
10801 
10802 	bcmerror = 0;
10803 
10804 err:
10805 	return bcmerror;
10806 }
10807 
10808 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)10809 dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
10810 	void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle)
10811 {
10812 	int status;
10813 
10814 	if (!KSO_ENAB(bus)) {
10815 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
10816 		return BCME_NODEVICE;
10817 	}
10818 
10819 	status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete_fn, handle);
10820 
10821 	return status;
10822 }
10823 
10824 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)10825 dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
10826 	void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle, int max_retry)
10827 {
10828 	int ret;
10829 	int i = 0;
10830 	int retries = 0;
10831 	bcmsdh_info_t *sdh;
10832 
10833 	if (!KSO_ENAB(bus)) {
10834 		DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
10835 		return BCME_NODEVICE;
10836 	}
10837 
10838 	sdh = bus->sdh;
10839 	do {
10840 		ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,
10841 			pkt, complete_fn, handle);
10842 
10843 		bus->f2txdata++;
10844 		ASSERT(ret != BCME_PENDING);
10845 
10846 		if (ret == BCME_NODEVICE) {
10847 			DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__));
10848 		} else if (ret < 0) {
10849 			/* On failure, abort the command and terminate the frame */
10850 			DHD_ERROR(("%s: sdio error %d, abort command and terminate frame.\n",
10851 				__FUNCTION__, ret));
10852 			bus->tx_sderrs++;
10853 			bus->f1regdata++;
10854 			bus->dhd->tx_errors++;
10855 			bcmsdh_abort(sdh, SDIO_FUNC_2);
10856 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
10857 				SFC_WF_TERM, NULL);
10858 			for (i = 0; i < READ_FRM_CNT_RETRIES; i++) {
10859 				uint8 hi, lo;
10860 				hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI,
10861 					NULL);
10862 				lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO,
10863 					NULL);
10864 				bus->f1regdata += 2;
10865 				if ((hi == 0) && (lo == 0))
10866 					break;
10867 			}
10868 		}
10869 	} while ((ret < 0) && retrydata && ++retries < max_retry);
10870 
10871 	return ret;
10872 }
10873 
10874 uint8
dhd_bus_is_ioready(struct dhd_bus * bus)10875 dhd_bus_is_ioready(struct dhd_bus *bus)
10876 {
10877 	uint8 enable;
10878 	bcmsdh_info_t *sdh;
10879 	ASSERT(bus);
10880 	ASSERT(bus->sih != NULL);
10881 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
10882 	sdh = bus->sdh;
10883 	return (enable == bcmsdh_cfg_read(sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL));
10884 }
10885 
10886 uint
dhd_bus_chip(struct dhd_bus * bus)10887 dhd_bus_chip(struct dhd_bus *bus)
10888 {
10889 	ASSERT(bus->sih != NULL);
10890 	return bus->sih->chip;
10891 }
10892 
10893 uint
dhd_bus_chiprev(struct dhd_bus * bus)10894 dhd_bus_chiprev(struct dhd_bus *bus)
10895 {
10896 	ASSERT(bus);
10897 	ASSERT(bus->sih != NULL);
10898 	return bus->sih->chiprev;
10899 }
10900 
10901 void *
dhd_bus_pub(struct dhd_bus * bus)10902 dhd_bus_pub(struct dhd_bus *bus)
10903 {
10904 	return bus->dhd;
10905 }
10906 
10907 void *
dhd_bus_sih(struct dhd_bus * bus)10908 dhd_bus_sih(struct dhd_bus *bus)
10909 {
10910 	return (void *)bus->sih;
10911 }
10912 
10913 void *
dhd_bus_txq(struct dhd_bus * bus)10914 dhd_bus_txq(struct dhd_bus *bus)
10915 {
10916 	return &bus->txq;
10917 }
10918 
10919 uint
dhd_bus_hdrlen(struct dhd_bus * bus)10920 dhd_bus_hdrlen(struct dhd_bus *bus)
10921 {
10922 	return (bus->txglom_enable) ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
10923 }
10924 
10925 void
dhd_bus_set_dotxinrx(struct dhd_bus * bus,bool val)10926 dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val)
10927 {
10928 	bus->dotxinrx = val;
10929 }
10930 
10931 /*
10932  *  dhdsdio_advertise_bus_cleanup advertises that clean up is under progress
10933  * to other bus user contexts like Tx, Rx, IOVAR, WD etc and it waits for other contexts
10934  * to gracefully exit. All the bus usage contexts before marking busstate as busy, will check for
10935  * whether the busstate is DHD_BUS_DOWN or DHD_BUS_DOWN_IN_PROGRESS, if so
10936  * they will exit from there itself without marking dhd_bus_busy_state as BUSY.
10937  */
10938 static void
dhdsdio_advertise_bus_cleanup(dhd_pub_t * dhdp)10939 dhdsdio_advertise_bus_cleanup(dhd_pub_t	 *dhdp)
10940 {
10941 	unsigned long flags;
10942 	int timeleft;
10943 
10944 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
10945 	dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS;
10946 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
10947 
10948 	timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
10949 #ifdef LINUX
10950 	if ((timeleft == 0) || (timeleft == 1))
10951 #else
10952 	if (timeleft == 0)
10953 #endif
10954 	{
10955 		/* XXX This condition ideally should not occur, this means some
10956 		 * bus usage context is not clearing the respective usage bit, print
10957 		 * dhd_bus_busy_state and crash the host for further debugging.
10958 		 */
10959 		DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
10960 				__FUNCTION__, dhdp->dhd_bus_busy_state));
10961 		ASSERT(0);
10962 	}
10963 
10964 	return;
10965 }
10966 
10967 static void
dhdsdio_advertise_bus_remove(dhd_pub_t * dhdp)10968 dhdsdio_advertise_bus_remove(dhd_pub_t	 *dhdp)
10969 {
10970 	unsigned long flags;
10971 	int timeleft;
10972 
10973 	DHD_LINUX_GENERAL_LOCK(dhdp, flags);
10974 	dhdp->busstate = DHD_BUS_REMOVE;
10975 	DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
10976 
10977 	timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
10978 	if ((timeleft == 0) || (timeleft == 1)) {
10979 		DHD_ERROR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
10980 				__FUNCTION__, dhdp->dhd_bus_busy_state));
10981 		ASSERT(0);
10982 	}
10983 
10984 	return;
10985 }
10986 
10987 int
dhd_bus_devreset(dhd_pub_t * dhdp,uint8 flag)10988 dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
10989 {
10990 	int bcmerror = 0;
10991 	dhd_bus_t *bus;
10992 	unsigned long flags;
10993 
10994 	bus = dhdp->bus;
10995 
10996 	if (flag == TRUE) {
10997 		if (!bus->dhd->dongle_reset) {
10998 			DHD_ERROR(("%s: == Power OFF ==\n", __FUNCTION__));
10999 			dhdsdio_advertise_bus_cleanup(bus->dhd);
11000 			dhd_os_sdlock(dhdp);
11001 			dhd_os_wd_timer(dhdp, 0);
11002 #if defined(OEM_ANDROID)
11003 #if !defined(IGNORE_ETH0_DOWN)
11004 			/* Force flow control as protection when stop come before ifconfig_down */
11005 			dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
11006 #endif /* !defined(IGNORE_ETH0_DOWN) */
11007 #endif /* OEM_ANDROID */
11008 			/* Expect app to have torn down any connection before calling */
11009 			/* Stop the bus, disable F2 */
11010 			dhd_bus_stop(bus, FALSE);
11011 
11012 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
11013 			/* Clean up any pending IRQ */
11014 			dhd_enable_oob_intr(bus, FALSE);
11015 			bcmsdh_oob_intr_set(bus->sdh, FALSE);
11016 			bcmsdh_oob_intr_unregister(bus->sdh);
11017 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
11018 
11019 			/* Clean tx/rx buffer pointers, detach from the dongle */
11020 			dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
11021 
11022 			bus->dhd->dongle_reset = TRUE;
11023 			DHD_ERROR(("%s: making dhdpub up FALSE\n", __FUNCTION__));
11024 			bus->dhd->up = FALSE;
11025 			dhd_txglom_enable(dhdp, FALSE);
11026 			dhd_os_sdunlock(dhdp);
11027 
11028 			DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
11029 			DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
11030 			bus->dhd->busstate = DHD_BUS_DOWN;
11031 			DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
11032 
11033 			DHD_TRACE(("%s:  WLAN OFF DONE\n", __FUNCTION__));
11034 			/* App can now remove power from device */
11035 		} else
11036 			bcmerror = BCME_SDIO_ERROR;
11037 	} else {
11038 		/* App must have restored power to device before calling */
11039 
11040 		printf("%s: == Power ON ==\n", __FUNCTION__);
11041 
11042 		if (bus->dhd->dongle_reset) {
11043 			/* Turn on WLAN */
11044 			dhd_os_sdlock(dhdp);
11045 			/* Reset SD client */
11046 			bcmsdh_reset(bus->sdh);
11047 
11048 			/* Attempt to re-attach & download */
11049 			if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
11050 				(uint32 *)(uintptr)si_enum_base(bus->cl_devid),
11051 				bus->cl_devid)) {
11052 
11053 				DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
11054 				DHD_ERROR(("%s: making DHD_BUS_DOWN\n", __FUNCTION__));
11055 				bus->dhd->busstate = DHD_BUS_DOWN;
11056 				DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
11057 				/* Attempt to download binary to the dongle */
11058 				if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
11059 				    dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) {
11060 
11061 					/* Re-init bus, enable F2 transfer */
11062 					bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
11063 					if (bcmerror == BCME_OK) {
11064 #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
11065 						dhd_enable_oob_intr(bus, TRUE);
11066 						bcmsdh_oob_intr_register(bus->sdh,
11067 							dhdsdio_isr, bus);
11068 						bcmsdh_oob_intr_set(bus->sdh, TRUE);
11069 #elif defined(FORCE_WOWLAN)
11070 						dhd_enable_oob_intr(bus, TRUE);
11071 #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
11072 
11073 						bus->dhd->dongle_reset = FALSE;
11074 						bus->dhd->up = TRUE;
11075 
11076 #if defined(OEM_ANDROID) && !defined(IGNORE_ETH0_DOWN)
11077 						/* Restore flow control  */
11078 						dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
11079 #endif /* defined(OEM_ANDROID) &&  (!defined(IGNORE_ETH0_DOWN)) */
11080 						dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
11081 
11082 						DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
11083 					} else {
11084 						dhd_bus_stop(bus, FALSE);
11085 						dhdsdio_release_dongle(bus, bus->dhd->osh,
11086 							TRUE, FALSE);
11087 					}
11088 				} else {
11089 					DHD_ERROR(("%s Failed to download binary to the dongle\n",
11090 						__FUNCTION__));
11091 					if (bus->sih != NULL) {
11092 						si_detach(bus->sih);
11093 						bus->sih = NULL;
11094 					}
11095 					bcmerror = BCME_SDIO_ERROR;
11096 				}
11097 			} else
11098 				bcmerror = BCME_SDIO_ERROR;
11099 
11100 			dhd_os_sdunlock(dhdp);
11101 		} else {
11102 			DHD_INFO(("%s called when dongle is not in reset\n",
11103 				__FUNCTION__));
11104 #if defined(OEM_ANDROID)
11105 			DHD_INFO(("Will call dhd_bus_start instead\n"));
11106 			dhd_bus_resume(dhdp, 1);
11107 #if defined(HW_OOB) || defined(FORCE_WOWLAN)
11108 			dhd_conf_set_hw_oob_intr(bus->sdh, bus->sih); // terence 20120615: fix for OOB initial issue
11109 #endif
11110 			if ((bcmerror = dhd_bus_start(dhdp)) != 0)
11111 				DHD_ERROR(("%s: dhd_bus_start fail with %d\n",
11112 					__FUNCTION__, bcmerror));
11113 #endif /* defined(OEM_ANDROID) */
11114 		}
11115 	}
11116 
11117 #ifdef PKT_STATICS
11118 	dhd_bus_clear_txpktstatics(dhdp);
11119 #endif
11120 	return bcmerror;
11121 }
11122 
11123 #if defined(LINUX)
dhd_bus_suspend(dhd_pub_t * dhdpub)11124 int dhd_bus_suspend(dhd_pub_t *dhdpub)
11125 {
11126 	return bcmsdh_stop(dhdpub->bus->sdh);
11127 }
11128 
dhd_bus_resume(dhd_pub_t * dhdpub,int stage)11129 int dhd_bus_resume(dhd_pub_t *dhdpub, int stage)
11130 {
11131 	return bcmsdh_start(dhdpub->bus->sdh, stage);
11132 }
11133 #endif /* defined(LINUX) */
11134 
11135 /* Get Chip ID version */
dhd_bus_chip_id(dhd_pub_t * dhdp)11136 uint dhd_bus_chip_id(dhd_pub_t *dhdp)
11137 {
11138 	dhd_bus_t *bus = dhdp->bus;
11139 
11140 	if (bus && bus->sih)
11141 		return bus->sih->chip;
11142 	else
11143 		return 0;
11144 }
11145 
11146 /* Get Chip Rev ID version */
dhd_bus_chiprev_id(dhd_pub_t * dhdp)11147 uint dhd_bus_chiprev_id(dhd_pub_t *dhdp)
11148 {
11149 	dhd_bus_t *bus = dhdp->bus;
11150 
11151 	if (bus && bus->sih)
11152 		return bus->sih->chiprev;
11153 	else
11154 		return 0;
11155 }
11156 
11157 /* Get Chip Pkg ID version */
dhd_bus_chippkg_id(dhd_pub_t * dhdp)11158 uint dhd_bus_chippkg_id(dhd_pub_t *dhdp)
11159 {
11160 	dhd_bus_t *bus = dhdp->bus;
11161 
11162 	return bus->sih->chippkg;
11163 }
11164 
dhd_bus_get_ids(struct dhd_bus * bus,uint32 * bus_type,uint32 * bus_num,uint32 * slot_num)11165 int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num, uint32 *slot_num)
11166 {
11167 	*bus_type = bus->bus;
11168 	*bus_num = bus->bus_num;
11169 	*slot_num = bus->slot_num;
11170 	return 0;
11171 }
11172 
11173 int
dhd_bus_membytes(dhd_pub_t * dhdp,bool set,uint32 address,uint8 * data,uint size)11174 dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size)
11175 {
11176 	dhd_bus_t *bus;
11177 
11178 	bus = dhdp->bus;
11179 	return dhdsdio_membytes(bus, set, address, data, size);
11180 }
11181 
11182 #if defined(SUPPORT_MULTIPLE_REVISION)
11183 static int
concate_revision_bcm4335(dhd_bus_t * bus,char * fw_path,char * nv_path)11184 concate_revision_bcm4335(dhd_bus_t *bus, char *fw_path, char *nv_path)
11185 {
11186 
11187 	uint chipver;
11188 #if defined(SUPPORT_MULTIPLE_CHIPS)
11189 	char chipver_tag[10] = "_4335";
11190 #else
11191 	char chipver_tag[4] = {0, };
11192 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11193 
11194 	DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__));
11195 	if (bus->sih->chip != BCM4335_CHIP_ID) {
11196 		DHD_ERROR(("%s:Chip is not BCM4335\n", __FUNCTION__));
11197 		return -1;
11198 	}
11199 	chipver = bus->sih->chiprev;
11200 	DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
11201 	if (chipver == 0x0) {
11202 		DHD_ERROR(("----- CHIP bcm4335_A0 -----\n"));
11203 		strcat(chipver_tag, "_a0");
11204 	} else if (chipver == 0x1) {
11205 		DHD_ERROR(("----- CHIP bcm4335_B0 -----\n"));
11206 #if defined(SUPPORT_MULTIPLE_CHIPS)
11207 		strcat(chipver_tag, "_b0");
11208 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11209 	}
11210 
11211 	strcat(fw_path, chipver_tag);
11212 	strcat(nv_path, chipver_tag);
11213 	return 0;
11214 }
11215 
11216 static int
concate_revision_bcm4339(dhd_bus_t * bus,char * fw_path,char * nv_path)11217 concate_revision_bcm4339(dhd_bus_t *bus, char *fw_path, char *nv_path)
11218 {
11219 
11220 	uint chipver;
11221 #if defined(SUPPORT_MULTIPLE_CHIPS)
11222 	char chipver_tag[10] = "_4339";
11223 #else
11224 	char chipver_tag[4] = {0, };
11225 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11226 
11227 	DHD_TRACE(("%s: BCM4339 Multiple Revision Check\n", __FUNCTION__));
11228 	if (bus->sih->chip != BCM4339_CHIP_ID) {
11229 		DHD_ERROR(("%s:Chip is not BCM4339\n", __FUNCTION__));
11230 		return -1;
11231 	}
11232 	chipver = bus->sih->chiprev;
11233 	DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
11234 	if (chipver == 0x1) {
11235 		DHD_ERROR(("----- CHIP bcm4339_A0 -----\n"));
11236 		strcat(chipver_tag, "_a0");
11237 	} else {
11238 		DHD_ERROR(("----- CHIP bcm4339 unknown revision %d -----\n",
11239 			chipver));
11240 	}
11241 
11242 	strcat(fw_path, chipver_tag);
11243 	strcat(nv_path, chipver_tag);
11244 	return 0;
11245 }
11246 
concate_revision_bcm4350(dhd_bus_t * bus,char * fw_path,char * nv_path)11247 static int concate_revision_bcm4350(dhd_bus_t *bus, char *fw_path, char *nv_path)
11248 {
11249 	uint32 chip_ver;
11250 #if defined(SUPPORT_MULTIPLE_CHIPS)
11251 	char chipver_tag[10] = {0, };
11252 #else
11253 	char chipver_tag[4] = {0, };
11254 #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
11255 	chip_ver = bus->sih->chiprev;
11256 
11257 #if defined(SUPPORT_MULTIPLE_CHIPS)
11258 	if (chip_ver == 3)
11259 		strcat(chipver_tag, "_4354");
11260 	else
11261 		strcat(chipver_tag, "_4350");
11262 #endif
11263 
11264 	if (chip_ver == 3) {
11265 		DHD_ERROR(("----- CHIP 4354 A0 -----\n"));
11266 		strcat(chipver_tag, "_a0");
11267 	} else {
11268 		DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
11269 	}
11270 
11271 	strcat(fw_path, chipver_tag);
11272 	strcat(nv_path, chipver_tag);
11273 	return 0;
11274 }
11275 
concate_revision_bcm4354(dhd_bus_t * bus,char * fw_path,char * nv_path)11276 static int concate_revision_bcm4354(dhd_bus_t *bus, char *fw_path, char *nv_path)
11277 {
11278 	uint32 chip_ver;
11279 #if defined(SUPPORT_MULTIPLE_CHIPS)
11280 	char chipver_tag[10] = "_4354";
11281 #else
11282 #if !defined(CUSTOMER_HW4)
11283 	char chipver_tag[4] = {0, };
11284 #endif /* !CUSTOMER_HW4 */
11285 #endif /* SUPPORT_MULTIPLE_CHIPS */
11286 
11287 	chip_ver = bus->sih->chiprev;
11288 #if !defined(SUPPORT_MULTIPLE_CHIPS) && defined(CUSTOMER_HW4)
11289 	DHD_INFO(("----- CHIP 4354, ver=%x -----\n", chip_ver));
11290 #else
11291 	if (chip_ver == 1) {
11292 		DHD_ERROR(("----- CHIP 4354 A1 -----\n"));
11293 		strcat(chipver_tag, "_a1");
11294 	} else {
11295 		DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
11296 	}
11297 
11298 	strcat(fw_path, chipver_tag);
11299 	strcat(nv_path, chipver_tag);
11300 #endif /* !SUPPORT_MULTIPLE_CHIPS && CUSTOMER_HW4 */
11301 
11302 	return 0;
11303 }
11304 
11305 static int
concate_revision_bcm43454(dhd_bus_t * bus,char * fw_path,char * nv_path)11306 concate_revision_bcm43454(dhd_bus_t *bus, char *fw_path, char *nv_path)
11307 {
11308 	char chipver_tag[10] = {0, };
11309 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
11310 	int base_system_rev_for_nv = 0;
11311 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
11312 
11313 	DHD_TRACE(("%s: BCM43454 Multiple Revision Check\n", __FUNCTION__));
11314 	if (bus->sih->chip != BCM43454_CHIP_ID) {
11315 		DHD_ERROR(("%s:Chip is not BCM43454!\n", __FUNCTION__));
11316 		return -1;
11317 	}
11318 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
11319 	base_system_rev_for_nv = dhd_get_system_rev();
11320 	if (base_system_rev_for_nv > 0) {
11321 		DHD_ERROR(("----- Board Rev  [%d] -----\n", base_system_rev_for_nv));
11322 		sprintf(chipver_tag, "_r%02d", base_system_rev_for_nv);
11323 	}
11324 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
11325 #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW
11326 	DHD_ERROR(("----- Rev [%d] Fot MULTIPLE Board. -----\n", system_hw_rev));
11327 	if ((system_hw_rev >= 8) && (system_hw_rev <= 11)) {
11328 		DHD_ERROR(("This HW is Rev 08 ~ 11. this is For FD-HW\n"));
11329 		strcat(chipver_tag, "_FD");
11330 	}
11331 #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
11332 
11333 	strcat(nv_path, chipver_tag);
11334 	return 0;
11335 }
11336 
11337 int
concate_revision(dhd_bus_t * bus,char * fw_path,char * nv_path)11338 concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path)
11339 {
11340 	int res = 0;
11341 
11342 	if (!bus || !bus->sih) {
11343 		DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
11344 		return -1;
11345 	}
11346 
11347 	switch (bus->sih->chip) {
11348 	case BCM4335_CHIP_ID:
11349 		res = concate_revision_bcm4335(bus, fw_path, nv_path);
11350 
11351 		break;
11352 	case BCM4339_CHIP_ID:
11353 		res = concate_revision_bcm4339(bus, fw_path, nv_path);
11354 		break;
11355 	case BCM4350_CHIP_ID:
11356 		res = concate_revision_bcm4350(bus, fw_path, nv_path);
11357 		break;
11358 	case BCM4354_CHIP_ID:
11359 		res = concate_revision_bcm4354(bus, fw_path, nv_path);
11360 		break;
11361 	case BCM43454_CHIP_ID:
11362 		res = concate_revision_bcm43454(bus, fw_path, nv_path);
11363 		break;
11364 
11365 		/* XXX: Add New Multiple CHIP ID */
11366 	default:
11367 		DHD_ERROR(("REVISION SPECIFIC feature is not required\n"));
11368 		/* XXX: if revision specific feature is not required then return true always */
11369 		return res;
11370 	}
11371 
11372 	if (res == 0) {
11373 #ifdef BCMDBG
11374 		printf("dhd concatenated fw & nv:\n   fw_path:%s\n"
11375 			"   nv_path:%s\n", fw_path, nv_path);
11376 		printf("make sure they exist\n");
11377 #endif
11378 	}
11379 	return res;
11380 }
11381 #endif /* SUPPORT_MULTIPLE_REVISION */
11382 
11383 #if defined(NDIS)
11384 void
dhd_bus_reject_ioreqs(dhd_pub_t * dhdp,bool reject)11385 dhd_bus_reject_ioreqs(dhd_pub_t *dhdp, bool reject)
11386 {
11387 
11388 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
11389 
11390 	bcmsdh_reject_ioreqs(dhdp->bus->sdh, reject);
11391 }
11392 
11393 void
dhd_bus_waitfor_iodrain(dhd_pub_t * dhdp)11394 dhd_bus_waitfor_iodrain(dhd_pub_t *dhdp)
11395 {
11396 
11397 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
11398 
11399 	bcmsdh_waitfor_iodrain(dhdp->bus->sdh);
11400 }
11401 #endif /* (NDIS) */
11402 
11403 void
dhd_bus_update_fw_nv_path(struct dhd_bus * bus,char * pfw_path,char * pnv_path,char * pclm_path,char * pconf_path)11404 dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path,
11405 									char *pclm_path, char *pconf_path)
11406 {
11407 	bus->fw_path = pfw_path;
11408 	bus->nv_path = pnv_path;
11409 	bus->dhd->clm_path = pclm_path;
11410 	bus->dhd->conf_path = pconf_path;
11411 }
11412 
11413 int
dhd_enableOOB(dhd_pub_t * dhd,bool sleep)11414 dhd_enableOOB(dhd_pub_t *dhd, bool sleep)
11415 {
11416 	dhd_bus_t *bus = dhd->bus;
11417 	sdpcmd_regs_t *regs = bus->regs;
11418 	uint retries = 0;
11419 
11420 	if (sleep) {
11421 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11422 		/* Tell device to start using OOB wakeup */
11423 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
11424 		if (retries > retry_limit) {
11425 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
11426 			return BCME_BUSY;
11427 		}
11428 		/* Turn off our contribution to the HT clock request */
11429 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
11430 	} else {
11431 		/* Make sure the controller has the bus up */
11432 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11433 
11434 		/* Send misc interrupt to indicate OOB not needed */
11435 		W_SDREG(0, &regs->tosbmailboxdata, retries);
11436 		if (retries <= retry_limit)
11437 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
11438 
11439 		if (retries > retry_limit)
11440 			DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
11441 
11442 		/* Make sure we have SD bus access */
11443 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
11444 	}
11445 	return BCME_OK;
11446 }
11447 
11448 void
dhd_bus_pktq_flush(dhd_pub_t * dhdp)11449 dhd_bus_pktq_flush(dhd_pub_t *dhdp)
11450 {
11451 	dhd_bus_t *bus = dhdp->bus;
11452 	bool wlfc_enabled = FALSE;
11453 
11454 #ifdef PROP_TXSTATUS
11455 	wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED);
11456 #endif
11457 	if (!wlfc_enabled) {
11458 #ifdef DHDTCPACK_SUPPRESS
11459 		/* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
11460 		 * when there is a newly coming packet from network stack.
11461 		 */
11462 		dhd_tcpack_info_tbl_clean(bus->dhd);
11463 #endif /* DHDTCPACK_SUPPRESS */
11464 		/* Clear the data packet queues */
11465 		pktq_flush(dhdp->osh, &bus->txq, TRUE);
11466 	}
11467 }
11468 
11469 #ifdef BCMSDIO
11470 int
dhd_sr_config(dhd_pub_t * dhd,bool on)11471 dhd_sr_config(dhd_pub_t *dhd, bool on)
11472 {
11473 	dhd_bus_t *bus = dhd->bus;
11474 
11475 	if (!bus->_srenab)
11476 		return -1;
11477 
11478 	return dhdsdio_clk_devsleep_iovar(bus, on);
11479 }
11480 
11481 uint16
dhd_get_chipid(struct dhd_bus * bus)11482 dhd_get_chipid(struct dhd_bus *bus)
11483 {
11484 	if (bus && bus->sih)
11485 		return (uint16)bus->sih->chip;
11486 	else
11487 		return 0;
11488 }
11489 #endif /* BCMSDIO */
11490 
11491 #ifdef DEBUGGER
11492 static uint32
dhd_sdio_reg_read(struct dhd_bus * bus,ulong addr)11493 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr)
11494 {
11495 	uint32 rval;
11496 
11497 	dhd_os_sdlock(bus->dhd);
11498 
11499 	BUS_WAKE(bus);
11500 
11501 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11502 
11503 	rval = bcmsdh_reg_read(bus->sdh, addr, 4);
11504 
11505 	dhd_os_sdunlock(bus->dhd);
11506 
11507 	return rval;
11508 }
11509 
11510 static void
dhd_sdio_reg_write(struct dhd_bus * bus,ulong addr,uint32 val)11511 dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val)
11512 {
11513 	dhd_os_sdlock(bus->dhd);
11514 
11515 	BUS_WAKE(bus);
11516 
11517 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
11518 
11519 	bcmsdh_reg_write(bus->sdh, addr, 4, val);
11520 
11521 	dhd_os_sdunlock(bus->dhd);
11522 }
11523 
11524 #endif /* DEBUGGER */
11525 
11526 #if defined(SOFTAP_TPUT_ENHANCE)
dhd_bus_setidletime(dhd_pub_t * dhdp,int idle_time)11527 void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time)
11528 {
11529 	if (!dhdp || !dhdp->bus) {
11530 		DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
11531 		return;
11532 	}
11533 	dhdp->bus->idletime = idle_time;
11534 }
11535 
dhd_bus_getidletime(dhd_pub_t * dhdp,int * idle_time)11536 void dhd_bus_getidletime(dhd_pub_t *dhdp, int* idle_time)
11537 {
11538 	if (!dhdp || !dhdp->bus) {
11539 		DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
11540 		return;
11541 	}
11542 
11543 	if (!idle_time) {
11544 		DHD_ERROR(("%s:Arg idle_time is NULL\n", __FUNCTION__));
11545 		return;
11546 	}
11547 	*idle_time = dhdp->bus->idletime;
11548 }
11549 #endif /* SOFTAP_TPUT_ENHANCE */
11550 
11551 #if defined(BT_OVER_SDIO)
dhd_bus_cfg_read(void * h,uint fun_num,uint32 addr,int * err)11552 uint8 dhd_bus_cfg_read(void *h, uint fun_num, uint32 addr, int *err)
11553 {
11554 	uint8 intrd;
11555 	dhd_pub_t *dhdp = (dhd_pub_t *)h;
11556 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
11557 
11558 	dhd_os_sdlock(bus->dhd);
11559 
11560 	intrd = bcmsdh_cfg_read(bus->sdh, fun_num, addr, err);
11561 
11562 	dhd_os_sdunlock(bus->dhd);
11563 
11564 	return intrd;
11565 } EXPORT_SYMBOL(dhd_bus_cfg_read);
11566 
dhd_bus_cfg_write(void * h,uint fun_num,uint32 addr,uint8 val,int * err)11567 void dhd_bus_cfg_write(void *h, uint fun_num, uint32 addr, uint8 val, int *err)
11568 {
11569 	dhd_pub_t *dhdp = (dhd_pub_t *)h;
11570 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
11571 
11572 	dhd_os_sdlock(bus->dhd);
11573 
11574 	bcmsdh_cfg_write(bus->sdh, fun_num, addr, val, err);
11575 
11576 	dhd_os_sdunlock(bus->dhd);
11577 
11578 } EXPORT_SYMBOL(dhd_bus_cfg_write);
11579 
11580 static int
extract_hex_field(char * line,uint16 start_pos,uint16 num_chars,uint16 * value)11581 extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value)
11582 {
11583 	char field [8];
11584 
11585 	strlcpy(field, line + start_pos, sizeof(field));
11586 
11587 	return (sscanf (field, "%hX", value) == 1);
11588 }
11589 
11590 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)11591 read_more_btbytes(struct dhd_bus *bus, void * file, char *line, int * addr_mode, uint16 * hi_addr,
11592 	uint32 * dest_addr, uint8 *data_bytes, uint32 * num_bytes)
11593 {
11594 	int		str_len;
11595 	uint16	num_data_bytes, addr, data_pos, type, w, i;
11596 	uint32	abs_base_addr32 = 0;
11597 	*num_bytes = 0;
11598 
11599 	while (!*num_bytes)
11600 	{
11601 		str_len = dhd_os_gets_image(bus->dhd, line, BTFW_MAX_STR_LEN, file);
11602 
11603 		DHD_TRACE(("%s: Len :0x%x  %s\n", __FUNCTION__, str_len, line));
11604 
11605 		if (str_len == 0) {
11606 			break;
11607 		} else if (str_len > 9) {
11608 			extract_hex_field(line, 1, 2, &num_data_bytes);
11609 			extract_hex_field(line, 3, 4, &addr);
11610 			extract_hex_field(line, 7, 2, &type);
11611 
11612 			data_pos = 9;
11613 			for (i = 0; i < num_data_bytes; i++) {
11614 				extract_hex_field(line, data_pos, 2, &w);
11615 				data_bytes [i] = (uint8)(w & 0x00FF);
11616 				data_pos += 2;
11617 			}
11618 
11619 			if (type == BTFW_HEX_LINE_TYPE_EXTENDED_ADDRESS) {
11620 				*hi_addr = (data_bytes [0] << 8) | data_bytes [1];
11621 				*addr_mode = BTFW_ADDR_MODE_EXTENDED;
11622 			} else if (type == BTFW_HEX_LINE_TYPE_EXTENDED_SEGMENT_ADDRESS) {
11623 				*hi_addr = (data_bytes [0] << 8) | data_bytes [1];
11624 				*addr_mode = BTFW_ADDR_MODE_SEGMENT;
11625 			} else if (type == BTFW_HEX_LINE_TYPE_ABSOLUTE_32BIT_ADDRESS) {
11626 				abs_base_addr32 = (data_bytes [0] << 24) | (data_bytes [1] << 16) |
11627 					(data_bytes [2] << 8) | data_bytes [3];
11628 				*addr_mode = BTFW_ADDR_MODE_LINEAR32;
11629 			} else if (type == BTFW_HEX_LINE_TYPE_DATA) {
11630 				*dest_addr = addr;
11631 				if (*addr_mode == BTFW_ADDR_MODE_EXTENDED)
11632 					*dest_addr += (*hi_addr << 16);
11633 				else if (*addr_mode == BTFW_ADDR_MODE_SEGMENT)
11634 					*dest_addr += (*hi_addr << 4);
11635 				else if (*addr_mode == BTFW_ADDR_MODE_LINEAR32)
11636 					*dest_addr += abs_base_addr32;
11637 				*num_bytes = num_data_bytes;
11638 			}
11639 		}
11640 	}
11641 	return (*num_bytes > 0);
11642 }
11643 
11644 static int
_dhdsdio_download_btfw(struct dhd_bus * bus)11645 _dhdsdio_download_btfw(struct dhd_bus *bus)
11646 {
11647 	int	bcm_error = -1;
11648 	void	*image = NULL;
11649 	uint8	*mem_blk = NULL, *mem_ptr = NULL, *data_ptr = NULL;
11650 
11651 	uint32 offset_addr = 0, offset_len = 0, bytes_to_write = 0;
11652 
11653 	char	*line = NULL;
11654 	uint32	dest_addr = 0, num_bytes;
11655 	uint16	hiAddress = 0;
11656 	uint32	start_addr, start_data, end_addr, end_data, i, index, pad,
11657 	bt2wlan_pwrup_adr;
11658 
11659 	int	addr_mode		= BTFW_ADDR_MODE_EXTENDED;
11660 
11661 	/* Out immediately if no image to download */
11662 	if ((bus->btfw_path == NULL) || (bus->btfw_path[0] == '\0')) {
11663 		return 0;
11664 	}
11665 
11666 	/* XXX: Should succeed in opening image if it is actually given through registry
11667 	 * entry or in module param.
11668 	 */
11669 	image = dhd_os_open_image1(bus->dhd, bus->btfw_path);
11670 	if (image == NULL)
11671 		goto err;
11672 
11673 	mem_ptr = mem_blk = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN);
11674 	if (mem_blk == NULL) {
11675 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
11676 			BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN));
11677 		goto err;
11678 	}
11679 	if ((uint32)(uintptr)mem_blk % DHD_SDALIGN)
11680 		mem_ptr += (DHD_SDALIGN - ((uint32)(uintptr)mem_blk % DHD_SDALIGN));
11681 
11682 	data_ptr = MALLOC(bus->dhd->osh, BTFW_DOWNLOAD_BLK_SIZE - 8);
11683 	if (data_ptr == NULL) {
11684 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
11685 			BTFW_DOWNLOAD_BLK_SIZE - 8));
11686 		goto err;
11687 	}
11688 	/* Write to BT register to hold WLAN wake high during BT FW download */
11689 	bt2wlan_pwrup_adr = BTMEM_OFFSET + BT2WLAN_PWRUP_ADDR;
11690 	bcmsdh_reg_write(bus->sdh, bt2wlan_pwrup_adr, 4, BT2WLAN_PWRUP_WAKE);
11691 	/*
11692 	  * Wait for at least 2msec for the clock to be ready/Available.
11693 	  */
11694 	OSL_DELAY(2000);
11695 
11696 	line = MALLOC(bus->dhd->osh, BTFW_MAX_STR_LEN);
11697 	if (line == NULL) {
11698 		DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
11699 			__FUNCTION__, BTFW_MAX_STR_LEN));
11700 		goto err;
11701 	}
11702 	memset(line, 0, BTFW_MAX_STR_LEN);
11703 
11704 	while (read_more_btbytes (bus, image, line, &addr_mode, &hiAddress, &dest_addr,
11705 		data_ptr, &num_bytes)) {
11706 
11707 		DHD_TRACE(("read %d bytes at address %08X\n", num_bytes, dest_addr));
11708 
11709 		start_addr = BTMEM_OFFSET + dest_addr;
11710 		index = 0;
11711 
11712 		/* Make sure the start address is 4 byte aligned to avoid alignment issues
11713 		 * with SD host controllers
11714 		 */
11715 		if (!ISALIGNED(start_addr, 4)) {
11716 			pad = start_addr % 4;
11717 			start_addr = ROUNDDN(start_addr, 4);
11718 			start_data = bcmsdh_reg_read(bus->sdh, start_addr, 4);
11719 			for (i = 0; i < pad; i++, index++) {
11720 			    mem_ptr[index] = (uint8)((uint8 *)&start_data)[i];
11721 			}
11722 		}
11723 		bcopy(data_ptr, &(mem_ptr[index]), num_bytes);
11724 		index += num_bytes;
11725 
11726 		/* Make sure the length is multiple of 4bytes to avoid alignment issues
11727 		 * with SD host controllers
11728 		 */
11729 		end_addr = start_addr + index;
11730 		if (!ISALIGNED(end_addr, 4)) {
11731 			end_addr = ROUNDDN(end_addr, 4);
11732 			end_data = bcmsdh_reg_read(bus->sdh, end_addr, 4);
11733 			for (i = (index % 4); i < 4; i++, index++) {
11734 				mem_ptr[index] = (uint8)((uint8 *)&end_data)[i];
11735 			}
11736 		}
11737 
11738 		offset_addr = start_addr & 0xFFF;
11739 		offset_len =  offset_addr + index;
11740 		if (offset_len <= 0x1000) {
11741 			bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr, index);
11742 			if (bcm_error) {
11743 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
11744 				__FUNCTION__, bcm_error, num_bytes, start_addr));
11745 				goto err;
11746 			}
11747 		}
11748 		else {
11749 			bytes_to_write = 0x1000 - offset_addr;
11750 			bcm_error = dhdsdio_membytes(bus, TRUE, start_addr, mem_ptr,
11751 				bytes_to_write);
11752 			if (bcm_error) {
11753 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
11754 				__FUNCTION__, bcm_error, num_bytes, start_addr));
11755 				goto err;
11756 			}
11757 
11758 			OSL_DELAY(10000);
11759 
11760 			bcm_error = dhdsdio_membytes(bus, TRUE, (start_addr + bytes_to_write),
11761 				(mem_ptr + bytes_to_write), (index - bytes_to_write));
11762 			if (bcm_error) {
11763 				DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
11764 					__FUNCTION__, bcm_error, num_bytes, start_addr));
11765 				goto err;
11766 			}
11767 		}
11768 		memset(line, 0, BTFW_MAX_STR_LEN);
11769 	}
11770 
11771 	bcm_error = 0;
11772 err:
11773 	if (mem_blk)
11774 		MFREE(bus->dhd->osh, mem_blk, BTFW_DOWNLOAD_BLK_SIZE + DHD_SDALIGN);
11775 
11776 	if (data_ptr)
11777 		MFREE(bus->dhd->osh, data_ptr, BTFW_DOWNLOAD_BLK_SIZE - 8);
11778 
11779 	if (line)
11780 		MFREE(bus->dhd->osh, line, BTFW_MAX_STR_LEN);
11781 
11782 	if (image)
11783 		dhd_os_close_image1(bus->dhd, image);
11784 
11785 	return bcm_error;
11786 }
11787 
11788 static int
dhdsdio_download_btfw(struct dhd_bus * bus,osl_t * osh,void * sdh)11789 dhdsdio_download_btfw(struct dhd_bus *bus, osl_t *osh, void *sdh)
11790 {
11791 	int ret;
11792 
11793 	DHD_TRACE(("%s: btfw path=%s\n",
11794 		__FUNCTION__, bus->btfw_path));
11795 	DHD_OS_WAKE_LOCK(bus->dhd);
11796 	dhd_os_sdlock(bus->dhd);
11797 
11798 	/* Download the firmware */
11799 	ret = _dhdsdio_download_btfw(bus);
11800 
11801 	dhd_os_sdunlock(bus->dhd);
11802 	DHD_OS_WAKE_UNLOCK(bus->dhd);
11803 
11804 	return ret;
11805 }
11806 
11807 int
dhd_bus_download_btfw(struct dhd_bus * bus,osl_t * osh,char * pbtfw_path)11808 dhd_bus_download_btfw(struct dhd_bus *bus, osl_t *osh,
11809                           char *pbtfw_path)
11810 {
11811 	int ret;
11812 
11813 	bus->btfw_path = pbtfw_path;
11814 
11815 	ret = dhdsdio_download_btfw(bus, osh, bus->sdh);
11816 
11817 	return ret;
11818 }
11819 #endif /* defined (BT_OVER_SDIO) */
11820 
11821 void
dhd_bus_dump_trap_info(dhd_bus_t * bus,struct bcmstrbuf * strbuf)11822 dhd_bus_dump_trap_info(dhd_bus_t *bus, struct bcmstrbuf *strbuf)
11823 {
11824 	trap_t *tr = &bus->dhd->last_trap_info;
11825 
11826 	bcm_bprintf(strbuf,
11827 		"Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
11828 		"lp 0x%x, rpc 0x%x Trap offset 0x%x, "
11829 		"r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
11830 		"r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
11831 		ltoh32(tr->type), ltoh32(tr->epc), ltoh32(tr->cpsr), ltoh32(tr->spsr),
11832 		ltoh32(tr->r13), ltoh32(tr->r14), ltoh32(tr->pc),
11833 		ltoh32(bus->dongle_trap_addr),
11834 		ltoh32(tr->r0), ltoh32(tr->r1), ltoh32(tr->r2), ltoh32(tr->r3),
11835 		ltoh32(tr->r4), ltoh32(tr->r5), ltoh32(tr->r6), ltoh32(tr->r7));
11836 
11837 }
11838 
11839 static int
dhd_bcmsdh_send_buffer(void * bus,uint8 * frame,uint16 len)11840 dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len)
11841 {
11842 	int ret = -1;
11843 
11844 	ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(((dhd_bus_t*)bus)->sdh),
11845 		SDIO_FUNC_2, F2SYNC, frame, len, NULL, NULL, NULL, TXRETRIES);
11846 
11847 	if (ret == BCME_OK)
11848 		((dhd_bus_t*)bus)->tx_seq = (((dhd_bus_t*)bus)->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
11849 
11850 	return ret;
11851 }
11852 
11853 /* Function to set the min res mask depending on the chip ID used */
11854 bool
dhd_bus_set_default_min_res_mask(struct dhd_bus * bus)11855 dhd_bus_set_default_min_res_mask(struct dhd_bus *bus)
11856 {
11857 	if ((bus == NULL) || (bus->sih == NULL)) {
11858 		DHD_ERROR(("%s(): Invalid Arguments \r\n", __FUNCTION__));
11859 		return FALSE;
11860 	}
11861 
11862 	switch (bus->sih->chip) {
11863 	case BCM4339_CHIP_ID:
11864 		bcmsdh_reg_write(bus->sdh, SI_ENUM_BASE(bus->sih) + 0x618, 4, 0x3fcaf377);
11865 		if (bcmsdh_regfail(bus->sdh)) {
11866 			DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
11867 			return FALSE;
11868 		}
11869 		break;
11870 
11871 	case BCM43012_CHIP_ID:
11872 	case BCM43013_CHIP_ID:
11873 	case BCM43014_CHIP_ID:
11874 		bcmsdh_reg_write(bus->sdh,
11875 			si_get_pmu_reg_addr(bus->sih, OFFSETOF(pmuregs_t, min_res_mask)),
11876 			4, DEFAULT_43012_MIN_RES_MASK);
11877 		if (bcmsdh_regfail(bus->sdh)) {
11878 			DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
11879 			return FALSE;
11880 		}
11881 		break;
11882 
11883 	default:
11884 		DHD_ERROR(("%s: Unhandled chip id\n", __FUNCTION__));
11885 		return FALSE;
11886 	}
11887 
11888 	return TRUE;
11889 }
11890 
11891 /* Function to reset PMU registers */
11892 void
dhd_bus_pmu_reg_reset(dhd_pub_t * dhdp)11893 dhd_bus_pmu_reg_reset(dhd_pub_t *dhdp)
11894 {
11895 	struct dhd_bus *bus = dhdp->bus;
11896 	bcmsdh_reg_write(bus->sdh, si_get_pmu_reg_addr(bus->sih,
11897 		OFFSETOF(pmuregs_t, swscratch)), 4, 0x0);
11898 	if (bcmsdh_regfail(bus->sdh)) {
11899 		DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__));
11900 	}
11901 }
11902 
11903 int
dhd_bus_readwrite_bp_addr(dhd_pub_t * dhdp,uint addr,uint size,uint * data,bool read)11904 dhd_bus_readwrite_bp_addr(dhd_pub_t *dhdp, uint addr, uint size, uint* data, bool read)
11905 {
11906 	int bcmerror = 0;
11907 	struct dhd_bus *bus = dhdp->bus;
11908 
11909 	if (read) {
11910 		*data = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
11911 	} else {
11912 		bcmsdh_reg_write(bus->sdh, addr, size, *data);
11913 	}
11914 
11915 	if (bcmsdh_regfail(bus->sdh))
11916 		bcmerror = BCME_SDIO_ERROR;
11917 
11918 	return bcmerror;
11919 }
11920 
dhd_get_idletime(dhd_pub_t * dhd)11921 int dhd_get_idletime(dhd_pub_t *dhd)
11922 {
11923 	return dhd->bus->idletime;
11924 }
11925 
11926 #ifdef DHD_WAKE_STATUS
11927 wake_counts_t*
dhd_bus_get_wakecount(dhd_pub_t * dhd)11928 dhd_bus_get_wakecount(dhd_pub_t *dhd)
11929 {
11930 	if (!dhd->bus) {
11931 		return NULL;
11932 	}
11933 	return &dhd->bus->wake_counts;
11934 }
11935 int
dhd_bus_get_bus_wake(dhd_pub_t * dhd)11936 dhd_bus_get_bus_wake(dhd_pub_t *dhd)
11937 {
11938 	return bcmsdh_set_get_wake(dhd->bus->sdh, 0);
11939 }
11940 #endif /* DHD_WAKE_STATUS */
11941 
11942 int
dhd_bus_sleep(dhd_pub_t * dhdp,bool sleep,uint32 * intstatus)11943 dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus)
11944 {
11945 	dhd_bus_t *bus = dhdp->bus;
11946 	uint32 retry = 0;
11947 	int ret = 0;
11948 
11949 	if (bus) {
11950 		dhd_os_sdlock(dhdp);
11951 		BUS_WAKE(bus);
11952 		R_SDREG(*intstatus, &bus->regs->intstatus, retry);
11953 		if (sleep) {
11954 			if (SLPAUTO_ENAB(bus)) {
11955 				ret = dhdsdio_bussleep(bus, sleep);
11956 				if (ret != BCME_BUSY)
11957 					dhd_os_wd_timer(bus->dhd, 0);
11958 			} else
11959 				dhdsdio_clkctl(bus, CLK_NONE, FALSE);
11960 		}
11961 		dhd_os_sdunlock(dhdp);
11962 	} else {
11963 		DHD_ERROR(("bus is NULL\n"));
11964 		ret = -1;
11965 	}
11966 
11967 	return ret;
11968 }
11969