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