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