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