Home | History | Annotate | Download | only in sys
      1 /*
      2  * DHD Bus Module for SDIO
      3  *
      4  * Copyright (C) 1999-2010, Broadcom Corporation
      5  *
      6  *      Unless you and Broadcom execute a separate written software license
      7  * agreement governing use of this software, this software is licensed to you
      8  * under the terms of the GNU General Public License version 2 (the "GPL"),
      9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
     10  * following added to such license:
     11  *
     12  *      As a special exception, the copyright holders of this software give you
     13  * permission to link this software with independent modules, and to copy and
     14  * distribute the resulting executable under terms of your choice, provided that
     15  * you also meet, for each linked independent module, the terms and conditions of
     16  * the license of that module.  An independent module is a module which is not
     17  * derived from this software.  The special exception does not apply to any
     18  * modifications of the software.
     19  *
     20  *      Notwithstanding the above, under no circumstances may you combine this
     21  * software in any way with any other Broadcom software provided under a license
     22  * other than the GPL, without Broadcom's express prior written consent.
     23  *
     24  * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.109 2010/04/22 05:52:46 Exp $
     25  */
     26 
     27 #include <typedefs.h>
     28 #include <osl.h>
     29 #include <bcmsdh.h>
     30 
     31 #ifdef BCMEMBEDIMAGE
     32 #include BCMEMBEDIMAGE
     33 #endif /* BCMEMBEDIMAGE */
     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 <sbchipc.h>
     44 #include <sbhnddma.h>
     45 
     46 #include <sdio.h>
     47 #include <sbsdio.h>
     48 #include <sbsdpcmdev.h>
     49 #include <bcmsdpcm.h>
     50 
     51 #include <proto/ethernet.h>
     52 #include <proto/802.1d.h>
     53 #include <proto/802.11.h>
     54 
     55 #include <dngl_stats.h>
     56 #include <dhd.h>
     57 #include <dhd_bus.h>
     58 #include <dhd_proto.h>
     59 #include <dhd_dbg.h>
     60 #include <dhdioctl.h>
     61 #include <sdiovar.h>
     62 
     63 #define QLEN		256	/* bulk rx and tx queue lengths */
     64 #define FCHI		(QLEN - 10)
     65 #define FCLOW		(FCHI / 2)
     66 #define PRIOMASK	7
     67 
     68 #define TXRETRIES	2	/* # of retries for tx frames */
     69 
     70 #if defined(CONFIG_MACH_SANDGATE2G)
     71 #define DHD_RXBOUND	250	/* Default for max rx frames in one scheduling */
     72 #else
     73 #define DHD_RXBOUND	50	/* Default for max rx frames in one scheduling */
     74 #endif /* defined(CONFIG_MACH_SANDGATE2G) */
     75 
     76 #define DHD_TXBOUND	20	/* Default for max tx frames in one scheduling */
     77 
     78 #define DHD_TXMINMAX	1	/* Max tx frames if rx still pending */
     79 
     80 #define MEMBLOCK	2048		/* Block size used for downloading of dongle image */
     81 #define MAX_DATA_BUF	(32 * 1024)	/* Must be large enough to hold biggest possible glom */
     82 
     83 /* Packet alignment for most efficient SDIO (can change based on platform) */
     84 #ifndef DHD_SDALIGN
     85 #define DHD_SDALIGN	32
     86 #endif
     87 #if !ISPOWEROF2(DHD_SDALIGN)
     88 #error DHD_SDALIGN is not a power of 2!
     89 #endif
     90 
     91 #ifndef DHD_FIRSTREAD
     92 #define DHD_FIRSTREAD	32
     93 #endif
     94 #if !ISPOWEROF2(DHD_FIRSTREAD)
     95 #error DHD_FIRSTREAD is not a power of 2!
     96 #endif
     97 
     98 /* Total length of frame header for dongle protocol */
     99 #define SDPCM_HDRLEN	(SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
    100 #ifdef SDTEST
    101 #define SDPCM_RESERVE	(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
    102 #else
    103 #define SDPCM_RESERVE	(SDPCM_HDRLEN + DHD_SDALIGN)
    104 #endif
    105 
    106 /* Space for header read, limit for data packets */
    107 #ifndef MAX_HDR_READ
    108 #define MAX_HDR_READ	32
    109 #endif
    110 #if !ISPOWEROF2(MAX_HDR_READ)
    111 #error MAX_HDR_READ is not a power of 2!
    112 #endif
    113 
    114 #define MAX_RX_DATASZ	2048
    115 
    116 /* Maximum milliseconds to wait for F2 to come up */
    117 #define DHD_WAIT_F2RDY	3000
    118 
    119 /* Bump up limit on waiting for HT to account for first startup;
    120  * if the image is doing a CRC calculation before programming the PMU
    121  * for HT availability, it could take a couple hundred ms more, so
    122  * max out at a half second (500000us).
    123  */
    124 #if (PMU_MAX_TRANSITION_DLY <= 500000)
    125 #undef PMU_MAX_TRANSITION_DLY
    126 #define PMU_MAX_TRANSITION_DLY 500000
    127 #endif
    128 
    129 /* Value for ChipClockCSR during initial setup */
    130 #define DHD_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
    131 #define DHD_INIT_CLKCTL2	(SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
    132 
    133 /* Flags for SDH calls */
    134 #define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
    135 
    136 /* Packet free applicable unconditionally for sdio and sdspi.  Conditional if
    137  * bufpool was present for gspi bus.
    138  */
    139 #define PKTFREE2()		if ((bus->bus != SPI_BUS) || bus->usebufpool) \
    140 					PKTFREE(bus->dhd->osh, pkt, FALSE);
    141 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
    142 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
    143 
    144 
    145 /* Private data for SDIO bus interaction */
    146 typedef struct dhd_bus {
    147 	dhd_pub_t	*dhd;
    148 
    149 	bcmsdh_info_t	*sdh;			/* Handle for BCMSDH calls */
    150 	si_t		*sih;			/* Handle for SI calls */
    151 	char		*vars;			/* Variables (from CIS and/or other) */
    152 	uint		varsz;			/* Size of variables buffer */
    153 	uint32		sbaddr;			/* Current SB window pointer (-1, invalid) */
    154 
    155 	sdpcmd_regs_t	*regs;			/* Registers for SDIO core */
    156 	uint		sdpcmrev;		/* SDIO core revision */
    157 	uint		armrev;			/* CPU core revision */
    158 	uint		ramrev;			/* SOCRAM core revision */
    159 	uint32		ramsize;		/* Size of RAM in SOCRAM (bytes) */
    160 	uint32		orig_ramsize;		/* Size of RAM in SOCRAM (bytes) */
    161 
    162 	uint32		bus;			/* gSPI or SDIO bus */
    163 	uint32		hostintmask;		/* Copy of Host Interrupt Mask */
    164 	uint32		intstatus;		/* Intstatus bits (events) pending */
    165 	bool		dpc_sched;		/* Indicates DPC schedule (intrpt rcvd) */
    166 	bool		fcstate;		/* State of dongle flow-control */
    167 
    168 	uint16		cl_devid;		/* cached devid for dhdsdio_probe_attach() */
    169 	char		*fw_path; /* module_param: path to firmware image */
    170 	char		*nv_path; /* module_param: path to nvram vars file */
    171 	const char      *nvram_params;		/* user specified nvram params. */
    172 
    173 	uint		blocksize;		/* Block size of SDIO transfers */
    174 	uint		roundup;		/* Max roundup limit */
    175 
    176 	struct pktq	txq;			/* Queue length used for flow-control */
    177 	uint8		flowcontrol;		/* per prio flow control bitmask */
    178 	uint8		tx_seq;			/* Transmit sequence number (next) */
    179 	uint8		tx_max;			/* Maximum transmit sequence allowed */
    180 
    181 	uint8		hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
    182 	uint8		*rxhdr;			/* Header of current rx frame (in hdrbuf) */
    183 	uint16		nextlen;		/* Next Read Len from last header */
    184 	uint8		rx_seq;			/* Receive sequence number (expected) */
    185 	bool		rxskip;			/* Skip receive (awaiting NAK ACK) */
    186 
    187 	void		*glomd;			/* Packet containing glomming descriptor */
    188 	void		*glom;			/* Packet chain for glommed superframe */
    189 	uint		glomerr;		/* Glom packet read errors */
    190 
    191 	uint8		*rxbuf;			/* Buffer for receiving control packets */
    192 	uint		rxblen;			/* Allocated length of rxbuf */
    193 	uint8		*rxctl;			/* Aligned pointer into rxbuf */
    194 	uint8		*databuf;		/* Buffer for receiving big glom packet */
    195 	uint8		*dataptr;		/* Aligned pointer into databuf */
    196 	uint		rxlen;			/* Length of valid data in buffer */
    197 
    198 	uint8		sdpcm_ver;		/* Bus protocol reported by dongle */
    199 
    200 	bool		intr;			/* Use interrupts */
    201 	bool		poll;			/* Use polling */
    202 	bool		ipend;			/* Device interrupt is pending */
    203 	bool		intdis;			/* Interrupts disabled by isr */
    204 	uint 		intrcount;		/* Count of device interrupt callbacks */
    205 	uint		lastintrs;		/* Count as of last watchdog timer */
    206 	uint		spurious;		/* Count of spurious interrupts */
    207 	uint		pollrate;		/* Ticks between device polls */
    208 	uint		polltick;		/* Tick counter */
    209 	uint		pollcnt;		/* Count of active polls */
    210 
    211 
    212 	uint		regfails;		/* Count of R_REG/W_REG failures */
    213 
    214 	uint		clkstate;		/* State of sd and backplane clock(s) */
    215 	bool		activity;		/* Activity flag for clock down */
    216 	int32		idletime;		/* Control for activity timeout */
    217 	int32		idlecount;		/* Activity timeout counter */
    218 	int32		idleclock;		/* How to set bus driver when idle */
    219 	int32		sd_divisor;		/* Speed control to bus driver */
    220 	int32		sd_mode;		/* Mode control to bus driver */
    221 	int32		sd_rxchain;		/* If bcmsdh api accepts PKT chains */
    222 	bool		use_rxchain;		/* If dhd should use PKT chains */
    223 	bool		sleeping;		/* Is SDIO bus sleeping? */
    224 	bool		rxflow_mode;	/* Rx flow control mode */
    225 	bool		rxflow;			/* Is rx flow control on */
    226 	uint		prev_rxlim_hit;		/* Is prev rx limit exceeded (per dpc schedule) */
    227 	bool		alp_only;		/* Don't use HT clock (ALP only) */
    228 	/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
    229 	bool		usebufpool;
    230 
    231 #ifdef SDTEST
    232 	/* external loopback */
    233 	bool		ext_loop;
    234 	uint8		loopid;
    235 
    236 	/* pktgen configuration */
    237 	uint		pktgen_freq;		/* Ticks between bursts */
    238 	uint		pktgen_count;		/* Packets to send each burst */
    239 	uint		pktgen_print;		/* Bursts between count displays */
    240 	uint		pktgen_total;		/* Stop after this many */
    241 	uint		pktgen_minlen;		/* Minimum packet data len */
    242 	uint		pktgen_maxlen;		/* Maximum packet data len */
    243 	uint		pktgen_mode;		/* Configured mode: tx, rx, or echo */
    244 	uint		pktgen_stop;		/* Number of tx failures causing stop */
    245 
    246 	/* active pktgen fields */
    247 	uint		pktgen_tick;		/* Tick counter for bursts */
    248 	uint		pktgen_ptick;		/* Burst counter for printing */
    249 	uint		pktgen_sent;		/* Number of test packets generated */
    250 	uint		pktgen_rcvd;		/* Number of test packets received */
    251 	uint		pktgen_fail;		/* Number of failed send attempts */
    252 	uint16		pktgen_len;		/* Length of next packet to send */
    253 #endif /* SDTEST */
    254 
    255 	/* Some additional counters */
    256 	uint		tx_sderrs;		/* Count of tx attempts with sd errors */
    257 	uint		fcqueued;		/* Tx packets that got queued */
    258 	uint		rxrtx;			/* Count of rtx requests (NAK to dongle) */
    259 	uint		rx_toolong;		/* Receive frames too long to receive */
    260 	uint		rxc_errors;		/* SDIO errors when reading control frames */
    261 	uint		rx_hdrfail;		/* SDIO errors on header reads */
    262 	uint		rx_badhdr;		/* Bad received headers (roosync?) */
    263 	uint		rx_badseq;		/* Mismatched rx sequence number */
    264 	uint		fc_rcvd;		/* Number of flow-control events received */
    265 	uint		fc_xoff;		/* Number which turned on flow-control */
    266 	uint		fc_xon;			/* Number which turned off flow-control */
    267 	uint		rxglomfail;		/* Failed deglom attempts */
    268 	uint		rxglomframes;		/* Number of glom frames (superframes) */
    269 	uint		rxglompkts;		/* Number of packets from glom frames */
    270 	uint		f2rxhdrs;		/* Number of header reads */
    271 	uint		f2rxdata;		/* Number of frame data reads */
    272 	uint		f2txdata;		/* Number of f2 frame writes */
    273 	uint		f1regdata;		/* Number of f1 register accesses */
    274 
    275 	uint8		*ctrl_frame_buf;
    276 	uint32		ctrl_frame_len;
    277 	bool		ctrl_frame_stat;
    278 } dhd_bus_t;
    279 
    280 /* clkstate */
    281 #define CLK_NONE	0
    282 #define CLK_SDONLY	1
    283 #define CLK_PENDING	2	/* Not used yet */
    284 #define CLK_AVAIL	3
    285 
    286 #define DHD_NOPMU(dhd)	(FALSE)
    287 
    288 #ifdef DHD_DEBUG
    289 static int qcount[NUMPRIO];
    290 static int tx_packets[NUMPRIO];
    291 #endif /* DHD_DEBUG */
    292 
    293 /* Deferred transmit */
    294 const uint dhd_deferred_tx = 1;
    295 
    296 extern uint dhd_watchdog_ms;
    297 extern void dhd_os_wd_timer(void *bus, uint wdtick);
    298 
    299 /* Tx/Rx bounds */
    300 uint dhd_txbound;
    301 uint dhd_rxbound;
    302 uint dhd_txminmax;
    303 
    304 /* override the RAM size if possible */
    305 #define DONGLE_MIN_MEMSIZE (128 *1024)
    306 int dhd_dongle_memsize;
    307 
    308 static bool dhd_doflow;
    309 static bool dhd_alignctl;
    310 
    311 static bool sd1idle;
    312 
    313 static bool retrydata;
    314 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
    315 
    316 static const uint watermark = 8;
    317 static const uint firstread = DHD_FIRSTREAD;
    318 
    319 #define HDATLEN (firstread - (SDPCM_HDRLEN))
    320 
    321 /* Retry count for register access failures */
    322 static const uint retry_limit = 2;
    323 
    324 /* Force even SD lengths (some host controllers mess up on odd bytes) */
    325 static bool forcealign;
    326 
    327 #define ALIGNMENT  4
    328 
    329 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
    330 extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
    331 #endif
    332 
    333 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
    334 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
    335 #endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
    336 #define PKTALIGN(osh, p, len, align)					\
    337 	do {								\
    338 		uint datalign;						\
    339 		datalign = (uintptr)PKTDATA((osh), (p));		\
    340 		datalign = ROUNDUP(datalign, (align)) - datalign;	\
    341 		ASSERT(datalign < (align));				\
    342 		ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign));	\
    343 		if (datalign)						\
    344 			PKTPULL((osh), (p), datalign);			\
    345 		PKTSETLEN((osh), (p), (len));				\
    346 	} while (0)
    347 
    348 /* Limit on rounding up frames */
    349 static const uint max_roundup = 512;
    350 
    351 /* Try doing readahead */
    352 static bool dhd_readahead;
    353 
    354 
    355 /* To check if there's window offered */
    356 #define DATAOK(bus) \
    357 	(((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
    358 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
    359 
    360 /* Macros to get register read/write status */
    361 /* NOTE: these assume a local dhdsdio_bus_t *bus! */
    362 #define R_SDREG(regvar, regaddr, retryvar) \
    363 do { \
    364 	retryvar = 0; \
    365 	do { \
    366 		regvar = R_REG(bus->dhd->osh, regaddr); \
    367 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
    368 	if (retryvar) { \
    369 		bus->regfails += (retryvar-1); \
    370 		if (retryvar > retry_limit) { \
    371 			DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
    372 			           __FUNCTION__, __LINE__)); \
    373 			regvar = 0; \
    374 		} \
    375 	} \
    376 } while (0)
    377 
    378 #define W_SDREG(regval, regaddr, retryvar) \
    379 do { \
    380 	retryvar = 0; \
    381 	do { \
    382 		W_REG(bus->dhd->osh, regaddr, regval); \
    383 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
    384 	if (retryvar) { \
    385 		bus->regfails += (retryvar-1); \
    386 		if (retryvar > retry_limit) \
    387 			DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
    388 			           __FUNCTION__, __LINE__)); \
    389 	} \
    390 } while (0)
    391 
    392 
    393 #define DHD_BUS			SDIO_BUS
    394 
    395 #define PKT_AVAILABLE()		(intstatus & I_HMB_FRAME_IND)
    396 
    397 #define HOSTINTMASK		(I_HMB_SW_MASK | I_CHIPACTIVE)
    398 
    399 #define GSPI_PR55150_BAILOUT
    400 
    401 
    402 #ifdef SDTEST
    403 static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
    404 static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
    405 #endif
    406 
    407 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
    408 
    409 static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
    410 static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
    411 static void dhdsdio_disconnect(void *ptr);
    412 static bool dhdsdio_chipmatch(uint16 chipid);
    413 static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
    414                                  void * regsva, uint16  devid);
    415 static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
    416 static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
    417 static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh);
    418 
    419 static uint process_nvram_vars(char *varbuf, uint len);
    420 
    421 static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size);
    422 static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
    423 	uint8 *buf, uint nbytes,
    424 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
    425 static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
    426 	uint8 *buf, uint nbytes,
    427 	void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
    428 
    429 static bool dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh);
    430 static int _dhdsdio_download_firmware(struct dhd_bus *bus);
    431 
    432 static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
    433 static int dhdsdio_download_nvram(struct dhd_bus *bus);
    434 #ifdef BCMEMBEDIMAGE
    435 static int dhdsdio_download_code_array(struct dhd_bus *bus);
    436 #endif
    437 
    438 
    439 static void
    440 dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
    441 {
    442 	int32 min_size =  DONGLE_MIN_MEMSIZE;
    443 	/* Restrict the memsize to user specified limit */
    444 	DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
    445 		dhd_dongle_memsize, min_size));
    446 	if ((dhd_dongle_memsize > min_size) &&
    447 		(dhd_dongle_memsize < (int32)bus->orig_ramsize))
    448 		bus->ramsize = dhd_dongle_memsize;
    449 }
    450 
    451 static int
    452 dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
    453 {
    454 	int err = 0;
    455 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
    456 	                 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
    457 	if (!err)
    458 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
    459 		                 (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
    460 	if (!err)
    461 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
    462 		                 (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
    463 	return err;
    464 }
    465 
    466 
    467 /* Turn backplane clock on or off */
    468 static int
    469 dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
    470 {
    471 	int err;
    472 	uint8 clkctl, clkreq, devctl;
    473 	bcmsdh_info_t *sdh;
    474 
    475 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
    476 
    477 #if defined(OOB_INTR_ONLY)
    478 	pendok = FALSE;
    479 #endif
    480 	clkctl = 0;
    481 	sdh = bus->sdh;
    482 
    483 
    484 	if (on) {
    485 		/* Request HT Avail */
    486 		clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
    487 
    488 		if ((bus->sih->chip == BCM4329_CHIP_ID) && (bus->sih->chiprev == 0))
    489 			clkreq |= SBSDIO_FORCE_ALP;
    490 
    491 
    492 
    493 
    494 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
    495 		if (err) {
    496 			DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
    497 			return BCME_ERROR;
    498 		}
    499 
    500 		if (pendok &&
    501 		    ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev == 9))) {
    502 			uint32 dummy, retries;
    503 			R_SDREG(dummy, &bus->regs->clockctlstatus, retries);
    504 		}
    505 
    506 		/* Check current status */
    507 		clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
    508 		if (err) {
    509 			DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
    510 			return BCME_ERROR;
    511 		}
    512 
    513 		/* Go to pending and await interrupt if appropriate */
    514 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
    515 			/* Allow only clock-available interrupt */
    516 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
    517 			if (err) {
    518 				DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
    519 				           __FUNCTION__, err));
    520 				return BCME_ERROR;
    521 			}
    522 
    523 			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
    524 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
    525 			DHD_INFO(("CLKCTL: set PENDING\n"));
    526 			bus->clkstate = CLK_PENDING;
    527 			return BCME_OK;
    528 		} else if (bus->clkstate == CLK_PENDING) {
    529 			/* Cancel CA-only interrupt filter */
    530 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
    531 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
    532 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
    533 		}
    534 
    535 		/* Otherwise, wait here (polling) for HT Avail */
    536 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
    537 			SPINWAIT_SLEEP(sdioh_spinwait_sleep,
    538 				((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
    539 			                                    SBSDIO_FUNC1_CHIPCLKCSR, &err)),
    540 			          !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
    541 		}
    542 		if (err) {
    543 			DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
    544 			return BCME_ERROR;
    545 		}
    546 		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
    547 			DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
    548 			           __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
    549 			return BCME_ERROR;
    550 		}
    551 
    552 
    553 		/* Mark clock available */
    554 		bus->clkstate = CLK_AVAIL;
    555 		DHD_INFO(("CLKCTL: turned ON\n"));
    556 
    557 #if defined(DHD_DEBUG)
    558 		if (bus->alp_only == TRUE) {
    559 #if !defined(BCMLXSDMMC)
    560 			if (!SBSDIO_ALPONLY(clkctl)) {
    561 				DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
    562 			}
    563 #endif /* !defined(BCMLXSDMMC) */
    564 		} else {
    565 			if (SBSDIO_ALPONLY(clkctl)) {
    566 				DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
    567 			}
    568 		}
    569 #endif /* defined (DHD_DEBUG) */
    570 
    571 		bus->activity = TRUE;
    572 	} else {
    573 		clkreq = 0;
    574 
    575 		if (bus->clkstate == CLK_PENDING) {
    576 			/* Cancel CA-only interrupt filter */
    577 			devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
    578 			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
    579 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
    580 		}
    581 
    582 		bus->clkstate = CLK_SDONLY;
    583 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
    584 		DHD_INFO(("CLKCTL: turned OFF\n"));
    585 		if (err) {
    586 			DHD_ERROR(("%s: Failed access turning clock off: %d\n",
    587 			           __FUNCTION__, err));
    588 			return BCME_ERROR;
    589 		}
    590 	}
    591 	return BCME_OK;
    592 }
    593 
    594 /* Change idle/active SD state */
    595 static int
    596 dhdsdio_sdclk(dhd_bus_t *bus, bool on)
    597 {
    598 	int err;
    599 	int32 iovalue;
    600 
    601 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
    602 
    603 	if (on) {
    604 		if (bus->idleclock == DHD_IDLE_STOP) {
    605 			/* Turn on clock and restore mode */
    606 			iovalue = 1;
    607 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
    608 			                      &iovalue, sizeof(iovalue), TRUE);
    609 			if (err) {
    610 				DHD_ERROR(("%s: error enabling sd_clock: %d\n",
    611 				           __FUNCTION__, err));
    612 				return BCME_ERROR;
    613 			}
    614 
    615 			iovalue = bus->sd_mode;
    616 			err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
    617 			                      &iovalue, sizeof(iovalue), TRUE);
    618 			if (err) {
    619 				DHD_ERROR(("%s: error changing sd_mode: %d\n",
    620 				           __FUNCTION__, err));
    621 				return BCME_ERROR;
    622 			}
    623 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
    624 			/* Restore clock speed */
    625 			iovalue = bus->sd_divisor;
    626 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
    627 			                      &iovalue, sizeof(iovalue), TRUE);
    628 			if (err) {
    629 				DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
    630 				           __FUNCTION__, err));
    631 				return BCME_ERROR;
    632 			}
    633 		}
    634 		bus->clkstate = CLK_SDONLY;
    635 	} else {
    636 		/* Stop or slow the SD clock itself */
    637 		if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
    638 			DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
    639 			           __FUNCTION__, bus->sd_divisor, bus->sd_mode));
    640 			return BCME_ERROR;
    641 		}
    642 		if (bus->idleclock == DHD_IDLE_STOP) {
    643 			if (sd1idle) {
    644 				/* Change to SD1 mode and turn off clock */
    645 				iovalue = 1;
    646 				err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
    647 				                      &iovalue, sizeof(iovalue), TRUE);
    648 				if (err) {
    649 					DHD_ERROR(("%s: error changing sd_clock: %d\n",
    650 					           __FUNCTION__, err));
    651 					return BCME_ERROR;
    652 				}
    653 			}
    654 
    655 			iovalue = 0;
    656 			err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
    657 			                      &iovalue, sizeof(iovalue), TRUE);
    658 			if (err) {
    659 				DHD_ERROR(("%s: error disabling sd_clock: %d\n",
    660 				           __FUNCTION__, err));
    661 				return BCME_ERROR;
    662 			}
    663 		} else if (bus->idleclock != DHD_IDLE_ACTIVE) {
    664 			/* Set divisor to idle value */
    665 			iovalue = bus->idleclock;
    666 			err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
    667 			                      &iovalue, sizeof(iovalue), TRUE);
    668 			if (err) {
    669 				DHD_ERROR(("%s: error changing sd_divisor: %d\n",
    670 				           __FUNCTION__, err));
    671 				return BCME_ERROR;
    672 			}
    673 		}
    674 		bus->clkstate = CLK_NONE;
    675 	}
    676 
    677 	return BCME_OK;
    678 }
    679 
    680 /* Transition SD and backplane clock readiness */
    681 static int
    682 dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
    683 {
    684 #ifdef DHD_DEBUG
    685 	uint oldstate = bus->clkstate;
    686 #endif /* DHD_DEBUG */
    687 
    688 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
    689 
    690 	/* Early exit if we're already there */
    691 	if (bus->clkstate == target) {
    692 		if (target == CLK_AVAIL) {
    693 			dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
    694 			bus->activity = TRUE;
    695 		}
    696 		return BCME_OK;
    697 	}
    698 
    699 	switch (target) {
    700 	case CLK_AVAIL:
    701 		/* Make sure SD clock is available */
    702 		if (bus->clkstate == CLK_NONE)
    703 			dhdsdio_sdclk(bus, TRUE);
    704 		/* Now request HT Avail on the backplane */
    705 		dhdsdio_htclk(bus, TRUE, pendok);
    706 		dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
    707 		bus->activity = TRUE;
    708 		break;
    709 
    710 	case CLK_SDONLY:
    711 		/* Remove HT request, or bring up SD clock */
    712 		if (bus->clkstate == CLK_NONE)
    713 			dhdsdio_sdclk(bus, TRUE);
    714 		else if (bus->clkstate == CLK_AVAIL)
    715 			dhdsdio_htclk(bus, FALSE, FALSE);
    716 		else
    717 			DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
    718 			           bus->clkstate, target));
    719 		dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
    720 		break;
    721 
    722 	case CLK_NONE:
    723 		/* Make sure to remove HT request */
    724 		if (bus->clkstate == CLK_AVAIL)
    725 			dhdsdio_htclk(bus, FALSE, FALSE);
    726 		/* Now remove the SD clock */
    727 		dhdsdio_sdclk(bus, FALSE);
    728 		dhd_os_wd_timer(bus->dhd, 0);
    729 		break;
    730 	}
    731 #ifdef DHD_DEBUG
    732 	DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
    733 #endif /* DHD_DEBUG */
    734 
    735 	return BCME_OK;
    736 }
    737 
    738 int
    739 dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
    740 {
    741 	bcmsdh_info_t *sdh = bus->sdh;
    742 	sdpcmd_regs_t *regs = bus->regs;
    743 	uint retries = 0;
    744 
    745 	DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
    746 	          (sleep ? "SLEEP" : "WAKE"),
    747 	          (bus->sleeping ? "SLEEP" : "WAKE")));
    748 
    749 	/* Done if we're already in the requested state */
    750 	if (sleep == bus->sleeping)
    751 		return BCME_OK;
    752 
    753 	/* Going to sleep: set the alarm and turn off the lights... */
    754 	if (sleep) {
    755 		/* Don't sleep if something is pending */
    756 		if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
    757 			return BCME_BUSY;
    758 
    759 
    760 		/* Disable SDIO interrupts (no longer interested) */
    761 		bcmsdh_intr_disable(bus->sdh);
    762 
    763 		/* Make sure the controller has the bus up */
    764 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
    765 
    766 		/* Tell device to start using OOB wakeup */
    767 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
    768 		if (retries > retry_limit)
    769 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
    770 
    771 		/* Turn off our contribution to the HT clock request */
    772 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
    773 
    774 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
    775 		                 SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
    776 
    777 		/* Isolate the bus */
    778 		if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) {
    779 				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
    780 					SBSDIO_DEVCTL_PADS_ISO, NULL);
    781 		}
    782 
    783 		/* Change state */
    784 		bus->sleeping = TRUE;
    785 
    786 	} else {
    787 		/* Waking up: bus power up is ok, set local state */
    788 
    789 		bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
    790 		                 0, NULL);
    791 
    792 		/* Force pad isolation off if possible (in case power never toggled) */
    793 		if ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev >= 10))
    794 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
    795 
    796 
    797 		/* Make sure the controller has the bus up */
    798 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
    799 
    800 		/* Send misc interrupt to indicate OOB not needed */
    801 		W_SDREG(0, &regs->tosbmailboxdata, retries);
    802 		if (retries <= retry_limit)
    803 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
    804 
    805 		if (retries > retry_limit)
    806 			DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
    807 
    808 		/* Make sure we have SD bus access */
    809 		dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
    810 
    811 		/* Change state */
    812 		bus->sleeping = FALSE;
    813 
    814 		/* Enable interrupts again */
    815 		if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
    816 			bus->intdis = FALSE;
    817 			bcmsdh_intr_enable(bus->sdh);
    818 		}
    819 	}
    820 
    821 	return BCME_OK;
    822 }
    823 #if defined(OOB_INTR_ONLY)
    824 void
    825 dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
    826 {
    827 #if defined(HW_OOB)
    828 	bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
    829 #else
    830 	sdpcmd_regs_t *regs = bus->regs;
    831 	uint retries = 0;
    832 
    833 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
    834 	if (enable == TRUE) {
    835 
    836 		/* Tell device to start using OOB wakeup */
    837 		W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
    838 		if (retries > retry_limit)
    839 			DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
    840 
    841 	} else {
    842 		/* Send misc interrupt to indicate OOB not needed */
    843 		W_SDREG(0, &regs->tosbmailboxdata, retries);
    844 		if (retries <= retry_limit)
    845 			W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
    846 	}
    847 
    848 	/* Turn off our contribution to the HT clock request */
    849 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
    850 #endif /* !defined(HW_OOB) */
    851 }
    852 #endif /* defined(OOB_INTR_ONLY) */
    853 
    854 #define BUS_WAKE(bus) \
    855 	do { \
    856 		if ((bus)->sleeping) \
    857 			dhdsdio_bussleep((bus), FALSE); \
    858 	} while (0);
    859 
    860 
    861 /* Writes a HW/SW header into the packet and sends it. */
    862 /* Assumes: (a) header space already there, (b) caller holds lock */
    863 static int
    864 dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
    865 {
    866 	int ret;
    867 	osl_t *osh;
    868 	uint8 *frame;
    869 	uint16 len, pad = 0;
    870 	uint32 swheader;
    871 	uint retries = 0;
    872 	bcmsdh_info_t *sdh;
    873 	void *new;
    874 	int i;
    875 
    876 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
    877 
    878 	sdh = bus->sdh;
    879 	osh = bus->dhd->osh;
    880 
    881 	if (bus->dhd->dongle_reset) {
    882 		ret = BCME_NOTREADY;
    883 		goto done;
    884 	}
    885 
    886 	frame = (uint8*)PKTDATA(osh, pkt);
    887 
    888 	/* Add alignment padding, allocate new packet if needed */
    889 	if ((pad = ((uintptr)frame % DHD_SDALIGN))) {
    890 		if (PKTHEADROOM(osh, pkt) < pad) {
    891 			DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
    892 			          __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad));
    893 			bus->dhd->tx_realloc++;
    894 			new = PKTGET(osh, (PKTLEN(osh, pkt) + DHD_SDALIGN), TRUE);
    895 			if (!new) {
    896 				DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n",
    897 				           __FUNCTION__, PKTLEN(osh, pkt) + DHD_SDALIGN));
    898 				ret = BCME_NOMEM;
    899 				goto done;
    900 			}
    901 
    902 			PKTALIGN(osh, new, PKTLEN(osh, pkt), DHD_SDALIGN);
    903 			bcopy(PKTDATA(osh, pkt), PKTDATA(osh, new), PKTLEN(osh, pkt));
    904 			if (free_pkt)
    905 				PKTFREE(osh, pkt, TRUE);
    906 			/* free the pkt if canned one is not used */
    907 			free_pkt = TRUE;
    908 			pkt = new;
    909 			frame = (uint8*)PKTDATA(osh, pkt);
    910 			ASSERT(((uintptr)frame % DHD_SDALIGN) == 0);
    911 			pad = 0;
    912 		} else {
    913 			PKTPUSH(osh, pkt, pad);
    914 			frame = (uint8*)PKTDATA(osh, pkt);
    915 
    916 			ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt));
    917 			bzero(frame, pad + SDPCM_HDRLEN);
    918 		}
    919 	}
    920 	ASSERT(pad < DHD_SDALIGN);
    921 
    922 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
    923 	len = (uint16)PKTLEN(osh, pkt);
    924 	*(uint16*)frame = htol16(len);
    925 	*(((uint16*)frame) + 1) = htol16(~len);
    926 
    927 	/* Software tag: channel, sequence number, data offset */
    928 	swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
    929 	        (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
    930 	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
    931 	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
    932 	bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
    933 
    934 #ifdef DHD_DEBUG
    935 	tx_packets[PKTPRIO(pkt)]++;
    936 	if (DHD_BYTES_ON() &&
    937 	    (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
    938 	      (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
    939 		prhex("Tx Frame", frame, len);
    940 	} else if (DHD_HDRS_ON()) {
    941 		prhex("TxHdr", frame, MIN(len, 16));
    942 	}
    943 #endif
    944 
    945 	/* Raise len to next SDIO block to eliminate tail command */
    946 	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
    947 		uint16 pad = bus->blocksize - (len % bus->blocksize);
    948 		if ((pad <= bus->roundup) && (pad < bus->blocksize))
    949 #ifdef NOTUSED
    950 			if (pad <= PKTTAILROOM(osh, pkt))
    951 #endif /* NOTUSED */
    952 				len += pad;
    953 	} else if (len % DHD_SDALIGN) {
    954 		len += DHD_SDALIGN - (len % DHD_SDALIGN);
    955 	}
    956 
    957 	/* Some controllers have trouble with odd bytes -- round to even */
    958 	if (forcealign && (len & (ALIGNMENT - 1))) {
    959 #ifdef NOTUSED
    960 		if (PKTTAILROOM(osh, pkt))
    961 #endif
    962 			len = ROUNDUP(len, ALIGNMENT);
    963 #ifdef NOTUSED
    964 		else
    965 			DHD_ERROR(("%s: sending unrounded %d-byte packet\n", __FUNCTION__, len));
    966 #endif
    967 	}
    968 
    969 	do {
    970 		ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
    971 		                      frame, len, pkt, NULL, NULL);
    972 		bus->f2txdata++;
    973 		ASSERT(ret != BCME_PENDING);
    974 
    975 		if (ret < 0) {
    976 			/* On failure, abort the command and terminate the frame */
    977 			DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
    978 			          __FUNCTION__, ret));
    979 			bus->tx_sderrs++;
    980 
    981 			bcmsdh_abort(sdh, SDIO_FUNC_2);
    982 			bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
    983 			                 SFC_WF_TERM, NULL);
    984 			bus->f1regdata++;
    985 
    986 			for (i = 0; i < 3; i++) {
    987 				uint8 hi, lo;
    988 				hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
    989 				                     SBSDIO_FUNC1_WFRAMEBCHI, NULL);
    990 				lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
    991 				                     SBSDIO_FUNC1_WFRAMEBCLO, NULL);
    992 				bus->f1regdata += 2;
    993 				if ((hi == 0) && (lo == 0))
    994 					break;
    995 			}
    996 
    997 		}
    998 	} while ((ret < 0) && retrydata && retries++ < TXRETRIES);
    999 
   1000 done:
   1001 	/* restore pkt buffer pointer before calling tx complete routine */
   1002 	PKTPULL(osh, pkt, SDPCM_HDRLEN + pad);
   1003 	dhd_os_sdunlock(bus->dhd);
   1004 	dhd_txcomplete(bus->dhd, pkt, ret != 0);
   1005 	dhd_os_sdlock(bus->dhd);
   1006 
   1007 	if (free_pkt)
   1008 		PKTFREE(osh, pkt, TRUE);
   1009 
   1010 	return ret;
   1011 }
   1012 
   1013 int
   1014 dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
   1015 {
   1016 	int ret = BCME_ERROR;
   1017 	osl_t *osh;
   1018 	uint datalen, prec;
   1019 
   1020 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   1021 
   1022 	osh = bus->dhd->osh;
   1023 	datalen = PKTLEN(osh, pkt);
   1024 
   1025 #ifdef SDTEST
   1026 	/* Push the test header if doing loopback */
   1027 	if (bus->ext_loop) {
   1028 		uint8* data;
   1029 		PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
   1030 		data = PKTDATA(osh, pkt);
   1031 		*data++ = SDPCM_TEST_ECHOREQ;
   1032 		*data++ = (uint8)bus->loopid++;
   1033 		*data++ = (datalen >> 0);
   1034 		*data++ = (datalen >> 8);
   1035 		datalen += SDPCM_TEST_HDRLEN;
   1036 	}
   1037 #endif /* SDTEST */
   1038 
   1039 	/* Add space for the header */
   1040 	PKTPUSH(osh, pkt, SDPCM_HDRLEN);
   1041 	ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
   1042 
   1043 	prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
   1044 
   1045 
   1046 	/* Check for existing queue, current flow-control, pending event, or pending clock */
   1047 	if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
   1048 	    (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
   1049 	    (bus->clkstate == CLK_PENDING)) {
   1050 		DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__,
   1051 			pktq_len(&bus->txq)));
   1052 		bus->fcqueued++;
   1053 
   1054 		/* Priority based enq */
   1055 		dhd_os_sdlock_txq(bus->dhd);
   1056 		if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == FALSE) {
   1057 			PKTPULL(osh, pkt, SDPCM_HDRLEN);
   1058 			dhd_txcomplete(bus->dhd, pkt, FALSE);
   1059 			PKTFREE(osh, pkt, TRUE);
   1060 			DHD_ERROR(("%s: out of bus->txq !!!\n", __FUNCTION__));
   1061 			ret = BCME_NORESOURCE;
   1062 		} else {
   1063 			ret = BCME_OK;
   1064 		}
   1065 		dhd_os_sdunlock_txq(bus->dhd);
   1066 
   1067 		if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow)
   1068 			dhd_txflowcontrol(bus->dhd, 0, ON);
   1069 
   1070 #ifdef DHD_DEBUG
   1071 		if (pktq_plen(&bus->txq, prec) > qcount[prec])
   1072 			qcount[prec] = pktq_plen(&bus->txq, prec);
   1073 #endif
   1074 		/* Schedule DPC if needed to send queued packet(s) */
   1075 		if (dhd_deferred_tx && !bus->dpc_sched) {
   1076 			bus->dpc_sched = TRUE;
   1077 			dhd_sched_dpc(bus->dhd);
   1078 		}
   1079 	} else {
   1080 		/* Lock: we're about to use shared data/code (and SDIO) */
   1081 		dhd_os_sdlock(bus->dhd);
   1082 
   1083 		/* Otherwise, send it now */
   1084 		BUS_WAKE(bus);
   1085 		dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
   1086 
   1087 #ifndef SDTEST
   1088 		DHD_TRACE(("%s: calling txpkt\n", __FUNCTION__));
   1089 		ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE);
   1090 #else
   1091 		ret = dhdsdio_txpkt(bus, pkt,
   1092 		        (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE);
   1093 #endif
   1094 		if (ret)
   1095 			bus->dhd->tx_errors++;
   1096 		else
   1097 			bus->dhd->dstats.tx_bytes += datalen;
   1098 
   1099 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
   1100 			bus->activity = FALSE;
   1101 			dhdsdio_clkctl(bus, CLK_NONE, TRUE);
   1102 		}
   1103 
   1104 		dhd_os_sdunlock(bus->dhd);
   1105 	}
   1106 
   1107 
   1108 	return ret;
   1109 }
   1110 
   1111 static uint
   1112 dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
   1113 {
   1114 	void *pkt;
   1115 	uint32 intstatus = 0;
   1116 	uint retries = 0;
   1117 	int ret = 0, prec_out;
   1118 	uint cnt = 0;
   1119 	uint datalen;
   1120 	uint8 tx_prec_map;
   1121 
   1122 	dhd_pub_t *dhd = bus->dhd;
   1123 	sdpcmd_regs_t *regs = bus->regs;
   1124 
   1125 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   1126 
   1127 	tx_prec_map = ~bus->flowcontrol;
   1128 
   1129 	/* Send frames until the limit or some other event */
   1130 	for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
   1131 		dhd_os_sdlock_txq(bus->dhd);
   1132 		if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) {
   1133 			dhd_os_sdunlock_txq(bus->dhd);
   1134 			break;
   1135 		}
   1136 		dhd_os_sdunlock_txq(bus->dhd);
   1137 		datalen = PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN;
   1138 
   1139 #ifndef SDTEST
   1140 		ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE);
   1141 #else
   1142 		ret = dhdsdio_txpkt(bus, pkt,
   1143 		        (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE);
   1144 #endif
   1145 		if (ret)
   1146 			bus->dhd->tx_errors++;
   1147 		else
   1148 			bus->dhd->dstats.tx_bytes += datalen;
   1149 
   1150 		/* In poll mode, need to check for other events */
   1151 		if (!bus->intr && cnt)
   1152 		{
   1153 			/* Check device status, signal pending interrupt */
   1154 			R_SDREG(intstatus, &regs->intstatus, retries);
   1155 			bus->f2txdata++;
   1156 			if (bcmsdh_regfail(bus->sdh))
   1157 				break;
   1158 			if (intstatus & bus->hostintmask)
   1159 				bus->ipend = TRUE;
   1160 		}
   1161 	}
   1162 
   1163 	/* Deflow-control stack if needed */
   1164 	if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
   1165 	    dhd->txoff && (pktq_len(&bus->txq) < FCLOW))
   1166 		dhd_txflowcontrol(dhd, 0, OFF);
   1167 
   1168 	return cnt;
   1169 }
   1170 
   1171 int
   1172 dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
   1173 {
   1174 	uint8 *frame;
   1175 	uint16 len;
   1176 	uint32 swheader;
   1177 	uint retries = 0;
   1178 	bcmsdh_info_t *sdh = bus->sdh;
   1179 	uint8 doff = 0;
   1180 	int ret = -1;
   1181 	int i;
   1182 
   1183 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   1184 
   1185 	if (bus->dhd->dongle_reset)
   1186 		return -EIO;
   1187 
   1188 	/* Back the pointer to make a room for bus header */
   1189 	frame = msg - SDPCM_HDRLEN;
   1190 	len = (msglen += SDPCM_HDRLEN);
   1191 
   1192 	/* Add alignment padding (optional for ctl frames) */
   1193 	if (dhd_alignctl) {
   1194 		if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
   1195 			frame -= doff;
   1196 			len += doff;
   1197 			msglen += doff;
   1198 			bzero(frame, doff + SDPCM_HDRLEN);
   1199 		}
   1200 		ASSERT(doff < DHD_SDALIGN);
   1201 	}
   1202 	doff += SDPCM_HDRLEN;
   1203 
   1204 	/* Round send length to next SDIO block */
   1205 	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
   1206 		uint16 pad = bus->blocksize - (len % bus->blocksize);
   1207 		if ((pad <= bus->roundup) && (pad < bus->blocksize))
   1208 			len += pad;
   1209 	} else if (len % DHD_SDALIGN) {
   1210 		len += DHD_SDALIGN - (len % DHD_SDALIGN);
   1211 	}
   1212 
   1213 	/* Satisfy length-alignment requirements */
   1214 	if (forcealign && (len & (ALIGNMENT - 1)))
   1215 		len = ROUNDUP(len, ALIGNMENT);
   1216 
   1217 	ASSERT(ISALIGNED((uintptr)frame, 2));
   1218 
   1219 
   1220 	/* Need to lock here to protect txseq and SDIO tx calls */
   1221 	dhd_os_sdlock(bus->dhd);
   1222 
   1223 	BUS_WAKE(bus);
   1224 
   1225 	/* Make sure backplane clock is on */
   1226 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
   1227 
   1228 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
   1229 	*(uint16*)frame = htol16((uint16)msglen);
   1230 	*(((uint16*)frame) + 1) = htol16(~msglen);
   1231 
   1232 	/* Software tag: channel, sequence number, data offset */
   1233 	swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
   1234 	        | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
   1235 	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
   1236 	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
   1237 
   1238 	if (!DATAOK(bus)) {
   1239 		bus->ctrl_frame_stat = TRUE;
   1240 		/* Send from dpc */
   1241 		bus->ctrl_frame_buf = frame;
   1242 		bus->ctrl_frame_len = len;
   1243 
   1244 		dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
   1245 
   1246 		if (bus->ctrl_frame_stat == FALSE)
   1247 			ret = 0;
   1248 		else
   1249 			ret = -1;
   1250 	}
   1251 
   1252 	if (ret == -1) {
   1253 		bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
   1254 
   1255 #ifdef DHD_DEBUG
   1256 		if (DHD_BYTES_ON() && DHD_CTL_ON()) {
   1257 			prhex("Tx Frame", frame, len);
   1258 		} else if (DHD_HDRS_ON()) {
   1259 			prhex("TxHdr", frame, MIN(len, 16));
   1260 		}
   1261 #endif
   1262 
   1263 		do {
   1264 			ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
   1265 			                          frame, len, NULL, NULL, NULL);
   1266 			ASSERT(ret != BCME_PENDING);
   1267 
   1268 			if (ret < 0) {
   1269 				/* On failure, abort the command and terminate the frame */
   1270 				DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
   1271 				          __FUNCTION__, ret));
   1272 				bus->tx_sderrs++;
   1273 
   1274 				bcmsdh_abort(sdh, SDIO_FUNC_2);
   1275 
   1276 				bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
   1277 				                 SFC_WF_TERM, NULL);
   1278 				bus->f1regdata++;
   1279 
   1280 				for (i = 0; i < 3; i++) {
   1281 					uint8 hi, lo;
   1282 					hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
   1283 					                     SBSDIO_FUNC1_WFRAMEBCHI, NULL);
   1284 					lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
   1285 					                     SBSDIO_FUNC1_WFRAMEBCLO, NULL);
   1286 					bus->f1regdata += 2;
   1287 					if ((hi == 0) && (lo == 0))
   1288 						break;
   1289 				}
   1290 
   1291 			}
   1292 		} while ((ret < 0) && retries++ < TXRETRIES);
   1293 	}
   1294 
   1295 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
   1296 		bus->activity = FALSE;
   1297 		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
   1298 	}
   1299 
   1300 	dhd_os_sdunlock(bus->dhd);
   1301 
   1302 	if (ret)
   1303 		bus->dhd->tx_ctlerrs++;
   1304 	else
   1305 		bus->dhd->tx_ctlpkts++;
   1306 
   1307 	return ret ? -EIO : 0;
   1308 }
   1309 
   1310 int
   1311 dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
   1312 {
   1313 	int timeleft;
   1314 	uint rxlen = 0;
   1315 	bool pending;
   1316 
   1317 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   1318 
   1319 	if (bus->dhd->dongle_reset)
   1320 		return -EIO;
   1321 
   1322 	/* Wait until control frame is available */
   1323 	timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
   1324 
   1325 	dhd_os_sdlock(bus->dhd);
   1326 	rxlen = bus->rxlen;
   1327 	bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
   1328 	bus->rxlen = 0;
   1329 	dhd_os_sdunlock(bus->dhd);
   1330 
   1331 	if (rxlen) {
   1332 		DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
   1333 		         __FUNCTION__, rxlen, msglen));
   1334 	} else if (timeleft == 0) {
   1335 		DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
   1336 	} else if (pending == TRUE) {
   1337 		DHD_CTL(("%s: cancelled\n", __FUNCTION__));
   1338 		return -ERESTARTSYS;
   1339 	} else {
   1340 		DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
   1341 	}
   1342 
   1343 	if (rxlen)
   1344 		bus->dhd->rx_ctlpkts++;
   1345 	else
   1346 		bus->dhd->rx_ctlerrs++;
   1347 
   1348 	return rxlen ? (int)rxlen : -ETIMEDOUT;
   1349 }
   1350 
   1351 /* IOVar table */
   1352 enum {
   1353 	IOV_INTR = 1,
   1354 	IOV_POLLRATE,
   1355 	IOV_SDREG,
   1356 	IOV_SBREG,
   1357 	IOV_SDCIS,
   1358 	IOV_MEMBYTES,
   1359 	IOV_MEMSIZE,
   1360 	IOV_DOWNLOAD,
   1361 	IOV_FORCEEVEN,
   1362 	IOV_SDIOD_DRIVE,
   1363 	IOV_READAHEAD,
   1364 	IOV_SDRXCHAIN,
   1365 	IOV_ALIGNCTL,
   1366 	IOV_SDALIGN,
   1367 	IOV_DEVRESET,
   1368 	IOV_CPU,
   1369 #ifdef SDTEST
   1370 	IOV_PKTGEN,
   1371 	IOV_EXTLOOP,
   1372 #endif /* SDTEST */
   1373 	IOV_SPROM,
   1374 	IOV_TXBOUND,
   1375 	IOV_RXBOUND,
   1376 	IOV_TXMINMAX,
   1377 	IOV_IDLETIME,
   1378 	IOV_IDLECLOCK,
   1379 	IOV_SD1IDLE,
   1380 	IOV_SLEEP,
   1381 	IOV_VARS
   1382 };
   1383 
   1384 const bcm_iovar_t dhdsdio_iovars[] = {
   1385 	{"intr",	IOV_INTR,	0,	IOVT_BOOL,	0 },
   1386 	{"sleep",	IOV_SLEEP,	0,	IOVT_BOOL,	0 },
   1387 	{"pollrate",	IOV_POLLRATE,	0,	IOVT_UINT32,	0 },
   1388 	{"idletime",	IOV_IDLETIME,	0,	IOVT_INT32,	0 },
   1389 	{"idleclock",	IOV_IDLECLOCK,	0,	IOVT_INT32,	0 },
   1390 	{"sd1idle",	IOV_SD1IDLE,	0,	IOVT_BOOL,	0 },
   1391 	{"membytes",	IOV_MEMBYTES,	0,	IOVT_BUFFER,	2 * sizeof(int) },
   1392 	{"memsize",	IOV_MEMSIZE,	0,	IOVT_UINT32,	0 },
   1393 	{"download",	IOV_DOWNLOAD,	0,	IOVT_BOOL,	0 },
   1394 	{"vars",	IOV_VARS,	0,	IOVT_BUFFER,	0 },
   1395 	{"sdiod_drive",	IOV_SDIOD_DRIVE, 0,	IOVT_UINT32,	0 },
   1396 	{"readahead",	IOV_READAHEAD,	0,	IOVT_BOOL,	0 },
   1397 	{"sdrxchain",	IOV_SDRXCHAIN,	0,	IOVT_BOOL,	0 },
   1398 	{"alignctl",	IOV_ALIGNCTL,	0,	IOVT_BOOL,	0 },
   1399 	{"sdalign",	IOV_SDALIGN,	0,	IOVT_BOOL,	0 },
   1400 	{"devreset",	IOV_DEVRESET,	0,	IOVT_BOOL,	0 },
   1401 #ifdef DHD_DEBUG
   1402 	{"sdreg",	IOV_SDREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
   1403 	{"sbreg",	IOV_SBREG,	0,	IOVT_BUFFER,	sizeof(sdreg_t) },
   1404 	{"sd_cis",	IOV_SDCIS,	0,	IOVT_BUFFER,	DHD_IOCTL_MAXLEN },
   1405 	{"forcealign",	IOV_FORCEEVEN,	0,	IOVT_BOOL,	0 },
   1406 	{"txbound",	IOV_TXBOUND,	0,	IOVT_UINT32,	0 },
   1407 	{"rxbound",	IOV_RXBOUND,	0,	IOVT_UINT32,	0 },
   1408 	{"txminmax", IOV_TXMINMAX,	0,	IOVT_UINT32,	0 },
   1409 	{"cpu",		IOV_CPU,	0,	IOVT_BOOL,	0 },
   1410 #endif /* DHD_DEBUG */
   1411 #ifdef SDTEST
   1412 	{"extloop",	IOV_EXTLOOP,	0,	IOVT_BOOL,	0 },
   1413 	{"pktgen",	IOV_PKTGEN,	0,	IOVT_BUFFER,	sizeof(dhd_pktgen_t) },
   1414 #endif /* SDTEST */
   1415 
   1416 	{NULL, 0, 0, 0, 0 }
   1417 };
   1418 
   1419 static void
   1420 dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
   1421 {
   1422 	uint q1, q2;
   1423 
   1424 	if (!div) {
   1425 		bcm_bprintf(strbuf, "%s N/A", desc);
   1426 	} else {
   1427 		q1 = num / div;
   1428 		q2 = (100 * (num - (q1 * div))) / div;
   1429 		bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
   1430 	}
   1431 }
   1432 
   1433 void
   1434 dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
   1435 {
   1436 	dhd_bus_t *bus = dhdp->bus;
   1437 
   1438 	bcm_bprintf(strbuf, "Bus SDIO structure:\n");
   1439 	bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
   1440 	            bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
   1441 	bcm_bprintf(strbuf, "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
   1442 	            bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
   1443 	            bus->rxlen, bus->rx_seq);
   1444 	bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
   1445 	            bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
   1446 	bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
   1447 	            bus->pollrate, bus->pollcnt, bus->regfails);
   1448 
   1449 	bcm_bprintf(strbuf, "\nAdditional counters:\n");
   1450 	bcm_bprintf(strbuf, "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
   1451 	            bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
   1452 	            bus->rxc_errors);
   1453 	bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
   1454 	            bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
   1455 	bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n",
   1456 	            bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
   1457 	bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
   1458 	            bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
   1459 	bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n",
   1460 	            (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
   1461 	            bus->f2txdata, bus->f1regdata);
   1462 	{
   1463 		dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
   1464 		             (bus->f2rxhdrs + bus->f2rxdata));
   1465 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
   1466 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
   1467 		             (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
   1468 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
   1469 		bcm_bprintf(strbuf, "\n");
   1470 
   1471 		dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
   1472 		             bus->dhd->rx_packets);
   1473 		dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
   1474 		bcm_bprintf(strbuf, "\n");
   1475 
   1476 		dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
   1477 		dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
   1478 		dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
   1479 		             (bus->f2txdata + bus->f1regdata));
   1480 		dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
   1481 		bcm_bprintf(strbuf, "\n");
   1482 
   1483 		dhd_dump_pct(strbuf, "Total: pkts/f2rw",
   1484 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
   1485 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
   1486 		dhd_dump_pct(strbuf, ", pkts/f1sd",
   1487 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
   1488 		dhd_dump_pct(strbuf, ", pkts/sd",
   1489 		             (bus->dhd->tx_packets + bus->dhd->rx_packets),
   1490 		             (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
   1491 		dhd_dump_pct(strbuf, ", pkts/int",
   1492 		             (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
   1493 		bcm_bprintf(strbuf, "\n\n");
   1494 	}
   1495 
   1496 #ifdef SDTEST
   1497 	if (bus->pktgen_count) {
   1498 		bcm_bprintf(strbuf, "pktgen config and count:\n");
   1499 		bcm_bprintf(strbuf, "freq %d count %d print %d total %d min %d len %d\n",
   1500 		            bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
   1501 		            bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
   1502 		bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
   1503 		            bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
   1504 	}
   1505 #endif /* SDTEST */
   1506 #ifdef DHD_DEBUG
   1507 	bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
   1508 	            bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
   1509 	bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize, bus->roundup);
   1510 #endif /* DHD_DEBUG */
   1511 	bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
   1512 	            bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
   1513 }
   1514 
   1515 void
   1516 dhd_bus_clearcounts(dhd_pub_t *dhdp)
   1517 {
   1518 	dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
   1519 
   1520 	bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
   1521 	bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
   1522 	bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
   1523 	bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
   1524 	bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
   1525 	bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
   1526 }
   1527 
   1528 #ifdef SDTEST
   1529 static int
   1530 dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
   1531 {
   1532 	dhd_pktgen_t pktgen;
   1533 
   1534 	pktgen.version = DHD_PKTGEN_VERSION;
   1535 	pktgen.freq = bus->pktgen_freq;
   1536 	pktgen.count = bus->pktgen_count;
   1537 	pktgen.print = bus->pktgen_print;
   1538 	pktgen.total = bus->pktgen_total;
   1539 	pktgen.minlen = bus->pktgen_minlen;
   1540 	pktgen.maxlen = bus->pktgen_maxlen;
   1541 	pktgen.numsent = bus->pktgen_sent;
   1542 	pktgen.numrcvd = bus->pktgen_rcvd;
   1543 	pktgen.numfail = bus->pktgen_fail;
   1544 	pktgen.mode = bus->pktgen_mode;
   1545 	pktgen.stop = bus->pktgen_stop;
   1546 
   1547 	bcopy(&pktgen, arg, sizeof(pktgen));
   1548 
   1549 	return 0;
   1550 }
   1551 
   1552 static int
   1553 dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
   1554 {
   1555 	dhd_pktgen_t pktgen;
   1556 	uint oldcnt, oldmode;
   1557 
   1558 	bcopy(arg, &pktgen, sizeof(pktgen));
   1559 	if (pktgen.version != DHD_PKTGEN_VERSION)
   1560 		return BCME_BADARG;
   1561 
   1562 	oldcnt = bus->pktgen_count;
   1563 	oldmode = bus->pktgen_mode;
   1564 
   1565 	bus->pktgen_freq = pktgen.freq;
   1566 	bus->pktgen_count = pktgen.count;
   1567 	bus->pktgen_print = pktgen.print;
   1568 	bus->pktgen_total = pktgen.total;
   1569 	bus->pktgen_minlen = pktgen.minlen;
   1570 	bus->pktgen_maxlen = pktgen.maxlen;
   1571 	bus->pktgen_mode = pktgen.mode;
   1572 	bus->pktgen_stop = pktgen.stop;
   1573 
   1574 	bus->pktgen_tick = bus->pktgen_ptick = 0;
   1575 	bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
   1576 	bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
   1577 
   1578 	/* Clear counts for a new pktgen (mode change, or was stopped) */
   1579 	if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode))
   1580 		bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0;
   1581 
   1582 	return 0;
   1583 }
   1584 #endif /* SDTEST */
   1585 
   1586 static int
   1587 dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
   1588 {
   1589 	int bcmerror = 0;
   1590 	uint32 sdaddr;
   1591 	uint dsize;
   1592 
   1593 	/* Determine initial transfer parameters */
   1594 	sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
   1595 	if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
   1596 		dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
   1597 	else
   1598 		dsize = size;
   1599 
   1600 	/* Set the backplane window to include the start address */
   1601 	if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
   1602 		DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
   1603 		goto xfer_done;
   1604 	}
   1605 
   1606 	/* Do the transfer(s) */
   1607 	while (size) {
   1608 		DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
   1609 		          __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
   1610 		          (address & SBSDIO_SBWINDOW_MASK)));
   1611 		if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) {
   1612 			DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
   1613 			break;
   1614 		}
   1615 
   1616 		/* Adjust for next transfer (if any) */
   1617 		if ((size -= dsize)) {
   1618 			data += dsize;
   1619 			address += dsize;
   1620 			if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
   1621 				DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
   1622 				break;
   1623 			}
   1624 			sdaddr = 0;
   1625 			dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
   1626 		}
   1627 	}
   1628 
   1629 xfer_done:
   1630 	/* Return the window to backplane enumeration space for core access */
   1631 	if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
   1632 		DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
   1633 			bcmsdh_cur_sbwad(bus->sdh)));
   1634 	}
   1635 
   1636 	return bcmerror;
   1637 }
   1638 
   1639 
   1640 int
   1641 dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
   1642 {
   1643 	int bcmerror = BCME_OK;
   1644 
   1645 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   1646 
   1647 	/* Basic sanity checks */
   1648 	if (bus->dhd->up) {
   1649 		bcmerror = BCME_NOTDOWN;
   1650 		goto err;
   1651 	}
   1652 	if (!len) {
   1653 		bcmerror = BCME_BUFTOOSHORT;
   1654 		goto err;
   1655 	}
   1656 
   1657 	/* Free the old ones and replace with passed variables */
   1658 	if (bus->vars)
   1659 		MFREE(bus->dhd->osh, bus->vars, bus->varsz);
   1660 
   1661 	bus->vars = MALLOC(bus->dhd->osh, len);
   1662 	bus->varsz = bus->vars ? len : 0;
   1663 	if (bus->vars == NULL) {
   1664 		bcmerror = BCME_NOMEM;
   1665 		goto err;
   1666 	}
   1667 
   1668 	/* Copy the passed variables, which should include the terminating double-null */
   1669 	bcopy(arg, bus->vars, bus->varsz);
   1670 err:
   1671 	return bcmerror;
   1672 }
   1673 
   1674 static int
   1675 dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
   1676                 void *params, int plen, void *arg, int len, int val_size)
   1677 {
   1678 	int bcmerror = 0;
   1679 	int32 int_val = 0;
   1680 	bool bool_val = 0;
   1681 
   1682 	DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
   1683 	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
   1684 
   1685 	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
   1686 		goto exit;
   1687 
   1688 	if (plen >= (int)sizeof(int_val))
   1689 		bcopy(params, &int_val, sizeof(int_val));
   1690 
   1691 	bool_val = (int_val != 0) ? TRUE : FALSE;
   1692 
   1693 
   1694 	/* Some ioctls use the bus */
   1695 	dhd_os_sdlock(bus->dhd);
   1696 
   1697 	/* Check if dongle is in reset. If so, only allow DEVRESET iovars */
   1698 	if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
   1699 	                                actionid == IOV_GVAL(IOV_DEVRESET))) {
   1700 		bcmerror = BCME_NOTREADY;
   1701 		goto exit;
   1702 	}
   1703 
   1704 	/* Handle sleep stuff before any clock mucking */
   1705 	if (vi->varid == IOV_SLEEP) {
   1706 		if (IOV_ISSET(actionid)) {
   1707 			bcmerror = dhdsdio_bussleep(bus, bool_val);
   1708 		} else {
   1709 			int_val = (int32)bus->sleeping;
   1710 			bcopy(&int_val, arg, val_size);
   1711 		}
   1712 		goto exit;
   1713 	}
   1714 
   1715 	/* Request clock to allow SDIO accesses */
   1716 	if (!bus->dhd->dongle_reset) {
   1717 		BUS_WAKE(bus);
   1718 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
   1719 	}
   1720 
   1721 	switch (actionid) {
   1722 	case IOV_GVAL(IOV_INTR):
   1723 		int_val = (int32)bus->intr;
   1724 		bcopy(&int_val, arg, val_size);
   1725 		break;
   1726 
   1727 	case IOV_SVAL(IOV_INTR):
   1728 		bus->intr = bool_val;
   1729 		bus->intdis = FALSE;
   1730 		if (bus->dhd->up) {
   1731 			if (bus->intr) {
   1732 				DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
   1733 				bcmsdh_intr_enable(bus->sdh);
   1734 			} else {
   1735 				DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
   1736 				bcmsdh_intr_disable(bus->sdh);
   1737 			}
   1738 		}
   1739 		break;
   1740 
   1741 	case IOV_GVAL(IOV_POLLRATE):
   1742 		int_val = (int32)bus->pollrate;
   1743 		bcopy(&int_val, arg, val_size);
   1744 		break;
   1745 
   1746 	case IOV_SVAL(IOV_POLLRATE):
   1747 		bus->pollrate = (uint)int_val;
   1748 		bus->poll = (bus->pollrate != 0);
   1749 		break;
   1750 
   1751 	case IOV_GVAL(IOV_IDLETIME):
   1752 		int_val = bus->idletime;
   1753 		bcopy(&int_val, arg, val_size);
   1754 		break;
   1755 
   1756 	case IOV_SVAL(IOV_IDLETIME):
   1757 		if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
   1758 			bcmerror = BCME_BADARG;
   1759 		} else {
   1760 			bus->idletime = int_val;
   1761 		}
   1762 		break;
   1763 
   1764 	case IOV_GVAL(IOV_IDLECLOCK):
   1765 		int_val = (int32)bus->idleclock;
   1766 		bcopy(&int_val, arg, val_size);
   1767 		break;
   1768 
   1769 	case IOV_SVAL(IOV_IDLECLOCK):
   1770 		bus->idleclock = int_val;
   1771 		break;
   1772 
   1773 	case IOV_GVAL(IOV_SD1IDLE):
   1774 		int_val = (int32)sd1idle;
   1775 		bcopy(&int_val, arg, val_size);
   1776 		break;
   1777 
   1778 	case IOV_SVAL(IOV_SD1IDLE):
   1779 		sd1idle = bool_val;
   1780 		break;
   1781 
   1782 
   1783 	case IOV_SVAL(IOV_MEMBYTES):
   1784 	case IOV_GVAL(IOV_MEMBYTES):
   1785 	{
   1786 		uint32 address;
   1787 		uint size, dsize;
   1788 		uint8 *data;
   1789 
   1790 		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
   1791 
   1792 		ASSERT(plen >= 2*sizeof(int));
   1793 
   1794 		address = (uint32)int_val;
   1795 		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
   1796 		size = (uint)int_val;
   1797 
   1798 		/* Do some validation */
   1799 		dsize = set ? plen - (2 * sizeof(int)) : len;
   1800 		if (dsize < size) {
   1801 			DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
   1802 			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
   1803 			bcmerror = BCME_BADARG;
   1804 			break;
   1805 		}
   1806 
   1807 		DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
   1808 		          (set ? "write" : "read"), size, address));
   1809 
   1810 		/* If we know about SOCRAM, check for a fit */
   1811 		if ((bus->orig_ramsize) &&
   1812 		    ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize))) {
   1813 			DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
   1814 			           __FUNCTION__, bus->orig_ramsize, size, address));
   1815 			bcmerror = BCME_BADARG;
   1816 			break;
   1817 		}
   1818 
   1819 		/* Generate the actual data pointer */
   1820 		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
   1821 
   1822 		/* Call to do the transfer */
   1823 		bcmerror = dhdsdio_membytes(bus, set, address, data, size);
   1824 
   1825 		break;
   1826 	}
   1827 
   1828 	case IOV_GVAL(IOV_MEMSIZE):
   1829 		int_val = (int32)bus->ramsize;
   1830 		bcopy(&int_val, arg, val_size);
   1831 		break;
   1832 
   1833 	case IOV_GVAL(IOV_SDIOD_DRIVE):
   1834 		int_val = (int32)dhd_sdiod_drive_strength;
   1835 		bcopy(&int_val, arg, val_size);
   1836 		break;
   1837 
   1838 	case IOV_SVAL(IOV_SDIOD_DRIVE):
   1839 		dhd_sdiod_drive_strength = int_val;
   1840 		si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
   1841 		break;
   1842 
   1843 	case IOV_SVAL(IOV_DOWNLOAD):
   1844 		bcmerror = dhdsdio_download_state(bus, bool_val);
   1845 		break;
   1846 
   1847 	case IOV_SVAL(IOV_VARS):
   1848 		bcmerror = dhdsdio_downloadvars(bus, arg, len);
   1849 		break;
   1850 
   1851 	case IOV_GVAL(IOV_READAHEAD):
   1852 		int_val = (int32)dhd_readahead;
   1853 		bcopy(&int_val, arg, val_size);
   1854 		break;
   1855 
   1856 	case IOV_SVAL(IOV_READAHEAD):
   1857 		if (bool_val && !dhd_readahead)
   1858 			bus->nextlen = 0;
   1859 		dhd_readahead = bool_val;
   1860 		break;
   1861 
   1862 	case IOV_GVAL(IOV_SDRXCHAIN):
   1863 		int_val = (int32)bus->use_rxchain;
   1864 		bcopy(&int_val, arg, val_size);
   1865 		break;
   1866 
   1867 	case IOV_SVAL(IOV_SDRXCHAIN):
   1868 		if (bool_val && !bus->sd_rxchain)
   1869 			bcmerror = BCME_UNSUPPORTED;
   1870 		else
   1871 			bus->use_rxchain = bool_val;
   1872 		break;
   1873 	case IOV_GVAL(IOV_ALIGNCTL):
   1874 		int_val = (int32)dhd_alignctl;
   1875 		bcopy(&int_val, arg, val_size);
   1876 		break;
   1877 
   1878 	case IOV_SVAL(IOV_ALIGNCTL):
   1879 		dhd_alignctl = bool_val;
   1880 		break;
   1881 
   1882 	case IOV_GVAL(IOV_SDALIGN):
   1883 		int_val = DHD_SDALIGN;
   1884 		bcopy(&int_val, arg, val_size);
   1885 		break;
   1886 
   1887 #ifdef DHD_DEBUG
   1888 	case IOV_GVAL(IOV_VARS):
   1889 		if (bus->varsz < (uint)len)
   1890 			bcopy(bus->vars, arg, bus->varsz);
   1891 		else
   1892 			bcmerror = BCME_BUFTOOSHORT;
   1893 		break;
   1894 #endif /* DHD_DEBUG */
   1895 
   1896 #ifdef DHD_DEBUG
   1897 	case IOV_GVAL(IOV_SDREG):
   1898 	{
   1899 		sdreg_t *sd_ptr;
   1900 		uint32 addr, size;
   1901 
   1902 		sd_ptr = (sdreg_t *)params;
   1903 
   1904 		addr = (uintptr)bus->regs + sd_ptr->offset;
   1905 		size = sd_ptr->func;
   1906 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
   1907 		if (bcmsdh_regfail(bus->sdh))
   1908 			bcmerror = BCME_SDIO_ERROR;
   1909 		bcopy(&int_val, arg, sizeof(int32));
   1910 		break;
   1911 	}
   1912 
   1913 	case IOV_SVAL(IOV_SDREG):
   1914 	{
   1915 		sdreg_t *sd_ptr;
   1916 		uint32 addr, size;
   1917 
   1918 		sd_ptr = (sdreg_t *)params;
   1919 
   1920 		addr = (uintptr)bus->regs + sd_ptr->offset;
   1921 		size = sd_ptr->func;
   1922 		bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
   1923 		if (bcmsdh_regfail(bus->sdh))
   1924 			bcmerror = BCME_SDIO_ERROR;
   1925 		break;
   1926 	}
   1927 
   1928 	/* Same as above, but offset is not backplane (not SDIO core) */
   1929 	case IOV_GVAL(IOV_SBREG):
   1930 	{
   1931 		sdreg_t sdreg;
   1932 		uint32 addr, size;
   1933 
   1934 		bcopy(params, &sdreg, sizeof(sdreg));
   1935 
   1936 		addr = SI_ENUM_BASE + sdreg.offset;
   1937 		size = sdreg.func;
   1938 		int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
   1939 		if (bcmsdh_regfail(bus->sdh))
   1940 			bcmerror = BCME_SDIO_ERROR;
   1941 		bcopy(&int_val, arg, sizeof(int32));
   1942 		break;
   1943 	}
   1944 
   1945 	case IOV_SVAL(IOV_SBREG):
   1946 	{
   1947 		sdreg_t sdreg;
   1948 		uint32 addr, size;
   1949 
   1950 		bcopy(params, &sdreg, sizeof(sdreg));
   1951 
   1952 		addr = SI_ENUM_BASE + sdreg.offset;
   1953 		size = sdreg.func;
   1954 		bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
   1955 		if (bcmsdh_regfail(bus->sdh))
   1956 			bcmerror = BCME_SDIO_ERROR;
   1957 		break;
   1958 	}
   1959 
   1960 	case IOV_GVAL(IOV_SDCIS):
   1961 	{
   1962 		*(char *)arg = 0;
   1963 
   1964 		bcmstrcat(arg, "\nFunc 0\n");
   1965 		bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
   1966 		bcmstrcat(arg, "\nFunc 1\n");
   1967 		bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
   1968 		bcmstrcat(arg, "\nFunc 2\n");
   1969 		bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
   1970 		break;
   1971 	}
   1972 
   1973 	case IOV_GVAL(IOV_FORCEEVEN):
   1974 		int_val = (int32)forcealign;
   1975 		bcopy(&int_val, arg, val_size);
   1976 		break;
   1977 
   1978 	case IOV_SVAL(IOV_FORCEEVEN):
   1979 		forcealign = bool_val;
   1980 		break;
   1981 
   1982 	case IOV_GVAL(IOV_TXBOUND):
   1983 		int_val = (int32)dhd_txbound;
   1984 		bcopy(&int_val, arg, val_size);
   1985 		break;
   1986 
   1987 	case IOV_SVAL(IOV_TXBOUND):
   1988 		dhd_txbound = (uint)int_val;
   1989 		break;
   1990 
   1991 	case IOV_GVAL(IOV_RXBOUND):
   1992 		int_val = (int32)dhd_rxbound;
   1993 		bcopy(&int_val, arg, val_size);
   1994 		break;
   1995 
   1996 	case IOV_SVAL(IOV_RXBOUND):
   1997 		dhd_rxbound = (uint)int_val;
   1998 		break;
   1999 
   2000 	case IOV_GVAL(IOV_TXMINMAX):
   2001 		int_val = (int32)dhd_txminmax;
   2002 		bcopy(&int_val, arg, val_size);
   2003 		break;
   2004 
   2005 	case IOV_SVAL(IOV_TXMINMAX):
   2006 		dhd_txminmax = (uint)int_val;
   2007 		break;
   2008 
   2009 
   2010 
   2011 #endif /* DHD_DEBUG */
   2012 
   2013 
   2014 #ifdef SDTEST
   2015 	case IOV_GVAL(IOV_EXTLOOP):
   2016 		int_val = (int32)bus->ext_loop;
   2017 		bcopy(&int_val, arg, val_size);
   2018 		break;
   2019 
   2020 	case IOV_SVAL(IOV_EXTLOOP):
   2021 		bus->ext_loop = bool_val;
   2022 		break;
   2023 
   2024 	case IOV_GVAL(IOV_PKTGEN):
   2025 		bcmerror = dhdsdio_pktgen_get(bus, arg);
   2026 		break;
   2027 
   2028 	case IOV_SVAL(IOV_PKTGEN):
   2029 		bcmerror = dhdsdio_pktgen_set(bus, arg);
   2030 		break;
   2031 #endif /* SDTEST */
   2032 
   2033 
   2034 	case IOV_SVAL(IOV_DEVRESET):
   2035 		DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
   2036 		           __FUNCTION__, bool_val, bus->dhd->dongle_reset,
   2037 		           bus->dhd->busstate));
   2038 
   2039 		ASSERT(bus->dhd->osh);
   2040 		/* ASSERT(bus->cl_devid); */
   2041 
   2042 		dhd_bus_devreset(bus->dhd, (uint8)bool_val);
   2043 
   2044 		break;
   2045 
   2046 	case IOV_GVAL(IOV_DEVRESET):
   2047 		DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
   2048 
   2049 		/* Get its status */
   2050 		int_val = (bool) bus->dhd->dongle_reset;
   2051 		bcopy(&int_val, arg, val_size);
   2052 
   2053 		break;
   2054 
   2055 	default:
   2056 		bcmerror = BCME_UNSUPPORTED;
   2057 		break;
   2058 	}
   2059 
   2060 exit:
   2061 	if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
   2062 		bus->activity = FALSE;
   2063 		dhdsdio_clkctl(bus, CLK_NONE, TRUE);
   2064 	}
   2065 
   2066 	dhd_os_sdunlock(bus->dhd);
   2067 
   2068 	if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == FALSE)
   2069 		dhd_preinit_ioctls((dhd_pub_t *) bus->dhd);
   2070 
   2071 	return bcmerror;
   2072 }
   2073 
   2074 static int
   2075 dhdsdio_write_vars(dhd_bus_t *bus)
   2076 {
   2077 	int bcmerror = 0;
   2078 	uint32 varsize;
   2079 	uint32 varaddr;
   2080 	uint8 *vbuffer;
   2081 	uint32 varsizew;
   2082 #ifdef DHD_DEBUG
   2083 	char *nvram_ularray;
   2084 #endif /* DHD_DEBUG */
   2085 
   2086 	/* Even if there are no vars are to be written, we still need to set the ramsize. */
   2087 	varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
   2088 	varaddr = (bus->ramsize - 4) - varsize;
   2089 
   2090 	if (bus->vars) {
   2091 		vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
   2092 		if (!vbuffer)
   2093 			return BCME_NOMEM;
   2094 
   2095 		bzero(vbuffer, varsize);
   2096 		bcopy(bus->vars, vbuffer, bus->varsz);
   2097 
   2098 		/* Write the vars list */
   2099 		bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize);
   2100 #ifdef DHD_DEBUG
   2101 		/* Verify NVRAM bytes */
   2102 		DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
   2103 		nvram_ularray = (char*)MALLOC(bus->dhd->osh, varsize);
   2104 		if (!nvram_ularray)
   2105 			return BCME_NOMEM;
   2106 
   2107 		/* Upload image to verify downloaded contents. */
   2108 		memset(nvram_ularray, 0xaa, varsize);
   2109 
   2110 		/* Read the vars list to temp buffer for comparison */
   2111 		bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
   2112 		if (bcmerror) {
   2113 				DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
   2114 					__FUNCTION__, bcmerror, varsize, varaddr));
   2115 		}
   2116 		/* Compare the org NVRAM with the one read from RAM */
   2117 		if (memcmp(vbuffer, nvram_ularray, varsize)) {
   2118 			DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
   2119 		} else
   2120 			DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
   2121 			__FUNCTION__));
   2122 
   2123 		MFREE(bus->dhd->osh, nvram_ularray, varsize);
   2124 #endif /* DHD_DEBUG */
   2125 
   2126 		MFREE(bus->dhd->osh, vbuffer, varsize);
   2127 	}
   2128 
   2129 	/* adjust to the user specified RAM */
   2130 	DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
   2131 		bus->orig_ramsize, bus->ramsize));
   2132 	DHD_INFO(("Vars are at %d, orig varsize is %d\n",
   2133 		varaddr, varsize));
   2134 	varsize = ((bus->orig_ramsize - 4) - varaddr);
   2135 
   2136 	/*
   2137 	 * Determine the length token:
   2138 	 * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
   2139 	 */
   2140 	if (bcmerror) {
   2141 		varsizew = 0;
   2142 	} else {
   2143 		varsizew = varsize / 4;
   2144 		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
   2145 		varsizew = htol32(varsizew);
   2146 	}
   2147 
   2148 	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
   2149 
   2150 	/* Write the length token to the last word */
   2151 	bcmerror = dhdsdio_membytes(bus, TRUE, (bus->orig_ramsize - 4),
   2152 		(uint8*)&varsizew, 4);
   2153 
   2154 	return bcmerror;
   2155 }
   2156 
   2157 static int
   2158 dhdsdio_download_state(dhd_bus_t *bus, bool enter)
   2159 {
   2160 	uint retries;
   2161 	int bcmerror = 0;
   2162 
   2163 	/* To enter download state, disable ARM and reset SOCRAM.
   2164 	 * To exit download state, simply reset ARM (default is RAM boot).
   2165 	 */
   2166 	if (enter) {
   2167 
   2168 		bus->alp_only = TRUE;
   2169 
   2170 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
   2171 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
   2172 			DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
   2173 			bcmerror = BCME_ERROR;
   2174 			goto fail;
   2175 		}
   2176 
   2177 		si_core_disable(bus->sih, 0);
   2178 		if (bcmsdh_regfail(bus->sdh)) {
   2179 			bcmerror = BCME_SDIO_ERROR;
   2180 			goto fail;
   2181 		}
   2182 
   2183 		if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
   2184 			DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
   2185 			bcmerror = BCME_ERROR;
   2186 			goto fail;
   2187 		}
   2188 
   2189 		si_core_reset(bus->sih, 0, 0);
   2190 		if (bcmsdh_regfail(bus->sdh)) {
   2191 			DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__));
   2192 			bcmerror = BCME_SDIO_ERROR;
   2193 			goto fail;
   2194 		}
   2195 
   2196 		/* Clear the top bit of memory */
   2197 		if (bus->ramsize) {
   2198 			uint32 zeros = 0;
   2199 			dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, (uint8*)&zeros, 4);
   2200 		}
   2201 	} else {
   2202 		if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
   2203 			DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
   2204 			bcmerror = BCME_ERROR;
   2205 			goto fail;
   2206 		}
   2207 
   2208 		if (!si_iscoreup(bus->sih)) {
   2209 			DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
   2210 			bcmerror = BCME_ERROR;
   2211 			goto fail;
   2212 		}
   2213 
   2214 		if ((bcmerror = dhdsdio_write_vars(bus))) {
   2215 			DHD_ERROR(("%s: no vars written to RAM\n", __FUNCTION__));
   2216 			bcmerror = 0;
   2217 		}
   2218 
   2219 		if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
   2220 		    !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
   2221 			DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
   2222 			bcmerror = BCME_ERROR;
   2223 			goto fail;
   2224 		}
   2225 		W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
   2226 
   2227 
   2228 		if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
   2229 		    !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
   2230 			DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
   2231 			bcmerror = BCME_ERROR;
   2232 			goto fail;
   2233 		}
   2234 
   2235 		si_core_reset(bus->sih, 0, 0);
   2236 		if (bcmsdh_regfail(bus->sdh)) {
   2237 			DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
   2238 			bcmerror = BCME_SDIO_ERROR;
   2239 			goto fail;
   2240 		}
   2241 
   2242 		/* Allow HT Clock now that the ARM is running. */
   2243 		bus->alp_only = FALSE;
   2244 
   2245 		bus->dhd->busstate = DHD_BUS_LOAD;
   2246 	}
   2247 
   2248 fail:
   2249 	/* Always return to SDIOD core */
   2250 	if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
   2251 		si_setcore(bus->sih, SDIOD_CORE_ID, 0);
   2252 
   2253 	return bcmerror;
   2254 }
   2255 
   2256 int
   2257 dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
   2258                  void *params, int plen, void *arg, int len, bool set)
   2259 {
   2260 	dhd_bus_t *bus = dhdp->bus;
   2261 	const bcm_iovar_t *vi = NULL;
   2262 	int bcmerror = 0;
   2263 	int val_size;
   2264 	uint32 actionid;
   2265 
   2266 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   2267 
   2268 	ASSERT(name);
   2269 	ASSERT(len >= 0);
   2270 
   2271 	/* Get MUST have return space */
   2272 	ASSERT(set || (arg && len));
   2273 
   2274 	/* Set does NOT take qualifiers */
   2275 	ASSERT(!set || (!params && !plen));
   2276 
   2277 	/* Look up var locally; if not found pass to host driver */
   2278 	if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
   2279 		dhd_os_sdlock(bus->dhd);
   2280 
   2281 		BUS_WAKE(bus);
   2282 
   2283 		/* Turn on clock in case SD command needs backplane */
   2284 		dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
   2285 
   2286 		bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
   2287 
   2288 		/* Check for bus configuration changes of interest */
   2289 
   2290 		/* If it was divisor change, read the new one */
   2291 		if (set && strcmp(name, "sd_divisor") == 0) {
   2292 			if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
   2293 			                    &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
   2294 				bus->sd_divisor = -1;
   2295 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
   2296 			} else {
   2297 				DHD_INFO(("%s: noted %s update, value now %d\n",
   2298 				          __FUNCTION__, name, bus->sd_divisor));
   2299 			}
   2300 		}
   2301 		/* If it was a mode change, read the new one */
   2302 		if (set && strcmp(name, "sd_mode") == 0) {
   2303 			if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
   2304 			                    &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
   2305 				bus->sd_mode = -1;
   2306 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
   2307 			} else {
   2308 				DHD_INFO(("%s: noted %s update, value now %d\n",
   2309 				          __FUNCTION__, name, bus->sd_mode));
   2310 			}
   2311 		}
   2312 		/* Similar check for blocksize change */
   2313 		if (set && strcmp(name, "sd_blocksize") == 0) {
   2314 			int32 fnum = 2;
   2315 			if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
   2316 			                    &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
   2317 				bus->blocksize = 0;
   2318 				DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
   2319 			} else {
   2320 				DHD_INFO(("%s: noted %s update, value now %d\n",
   2321 				          __FUNCTION__, "sd_blocksize", bus->blocksize));
   2322 			}
   2323 		}
   2324 		bus->roundup = MIN(max_roundup, bus->blocksize);
   2325 
   2326 		if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
   2327 			bus->activity = FALSE;
   2328 			dhdsdio_clkctl(bus, CLK_NONE, TRUE);
   2329 		}
   2330 
   2331 		dhd_os_sdunlock(bus->dhd);
   2332 		goto exit;
   2333 	}
   2334 
   2335 	DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
   2336 	         name, (set ? "set" : "get"), len, plen));
   2337 
   2338 	/* set up 'params' pointer in case this is a set command so that
   2339 	 * the convenience int and bool code can be common to set and get
   2340 	 */
   2341 	if (params == NULL) {
   2342 		params = arg;
   2343 		plen = len;
   2344 	}
   2345 
   2346 	if (vi->type == IOVT_VOID)
   2347 		val_size = 0;
   2348 	else if (vi->type == IOVT_BUFFER)
   2349 		val_size = len;
   2350 	else
   2351 		/* all other types are integer sized */
   2352 		val_size = sizeof(int);
   2353 
   2354 	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
   2355 	bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
   2356 
   2357 exit:
   2358 	return bcmerror;
   2359 }
   2360 
   2361 void
   2362 dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
   2363 {
   2364 	osl_t *osh = bus->dhd->osh;
   2365 	uint32 local_hostintmask;
   2366 	uint8 saveclk;
   2367 	uint retries;
   2368 	int err;
   2369 
   2370 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   2371 
   2372 	if (enforce_mutex)
   2373 		dhd_os_sdlock(bus->dhd);
   2374 
   2375 	BUS_WAKE(bus);
   2376 
   2377 	/* Enable clock for device interrupts */
   2378 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
   2379 
   2380 	/* Disable and clear interrupts at the chip level also */
   2381 	W_SDREG(0, &bus->regs->hostintmask, retries);
   2382 	local_hostintmask = bus->hostintmask;
   2383 	bus->hostintmask = 0;
   2384 
   2385 	/* Change our idea of bus state */
   2386 	bus->dhd->busstate = DHD_BUS_DOWN;
   2387 
   2388 	/* Force clocks on backplane to be sure F2 interrupt propagates */
   2389 	saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
   2390 	if (!err) {
   2391 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
   2392 		                 (saveclk | SBSDIO_FORCE_HT), &err);
   2393 	}
   2394 	if (err) {
   2395 		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
   2396 	}
   2397 
   2398 	/* Turn off the bus (F2), free any pending packets */
   2399 	DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
   2400 	bcmsdh_intr_disable(bus->sdh);
   2401 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
   2402 
   2403 	/* Clear any pending interrupts now that F2 is disabled */
   2404 	W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
   2405 
   2406 	/* Turn off the backplane clock (only) */
   2407 	dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
   2408 
   2409 	/* Clear the data packet queues */
   2410 	pktq_flush(osh, &bus->txq, TRUE);
   2411 
   2412 	/* Clear any held glomming stuff */
   2413 	if (bus->glomd)
   2414 		PKTFREE(osh, bus->glomd, FALSE);
   2415 
   2416 	if (bus->glom)
   2417 		PKTFREE(osh, bus->glom, FALSE);
   2418 
   2419 	bus->glom = bus->glomd = NULL;
   2420 
   2421 	/* Clear rx control and wake any waiters */
   2422 	bus->rxlen = 0;
   2423 	dhd_os_ioctl_resp_wake(bus->dhd);
   2424 
   2425 	/* Reset some F2 state stuff */
   2426 	bus->rxskip = FALSE;
   2427 	bus->tx_seq = bus->rx_seq = 0;
   2428 
   2429 	if (enforce_mutex)
   2430 		dhd_os_sdunlock(bus->dhd);
   2431 }
   2432 
   2433 int
   2434 dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
   2435 {
   2436 	dhd_bus_t *bus = dhdp->bus;
   2437 	dhd_timeout_t tmo;
   2438 	uint retries = 0;
   2439 	uint8 ready, enable;
   2440 	int err, ret = 0;
   2441 	uint8 saveclk;
   2442 
   2443 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   2444 
   2445 	ASSERT(bus->dhd);
   2446 	if (!bus->dhd)
   2447 		return 0;
   2448 
   2449 	if (enforce_mutex)
   2450 		dhd_os_sdlock(bus->dhd);
   2451 
   2452 	/* Make sure backplane clock is on, needed to generate F2 interrupt */
   2453 	dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
   2454 	if (bus->clkstate != CLK_AVAIL)
   2455 		goto exit;
   2456 
   2457 
   2458 	/* Force clocks on backplane to be sure F2 interrupt propagates */
   2459 	saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
   2460 	if (!err) {
   2461 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
   2462 		                 (saveclk | SBSDIO_FORCE_HT), &err);
   2463 	}
   2464 	if (err) {
   2465 		DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
   2466 		goto exit;
   2467 	}
   2468 
   2469 	/* Enable function 2 (frame transfers) */
   2470 	W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
   2471 	        &bus->regs->tosbmailboxdata, retries);
   2472 	enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
   2473 
   2474 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
   2475 
   2476 	/* Give the dongle some time to do its thing and set IOR2 */
   2477 	dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
   2478 
   2479 	ready = 0;
   2480 	while (ready != enable && !dhd_timeout_expired(&tmo))
   2481 	        ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
   2482 
   2483 
   2484 	DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
   2485 	          __FUNCTION__, enable, ready, tmo.elapsed));
   2486 
   2487 
   2488 	/* If F2 successfully enabled, set core and enable interrupts */
   2489 	if (ready == enable) {
   2490 		/* Make sure we're talking to the core. */
   2491 		if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
   2492 			bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
   2493 
   2494 		/* Set up the interrupt mask and enable interrupts */
   2495 		bus->hostintmask = HOSTINTMASK;
   2496 		W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
   2497 
   2498 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err);
   2499 
   2500 		/* Set bus state according to enable result */
   2501 		dhdp->busstate = DHD_BUS_DATA;
   2502 
   2503 		/* bcmsdh_intr_unmask(bus->sdh); */
   2504 
   2505 		bus->intdis = FALSE;
   2506 		if (bus->intr) {
   2507 			DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
   2508 			bcmsdh_intr_enable(bus->sdh);
   2509 		} else {
   2510 			DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
   2511 			bcmsdh_intr_disable(bus->sdh);
   2512 		}
   2513 
   2514 	}
   2515 
   2516 
   2517 	else {
   2518 		/* Disable F2 again */
   2519 		enable = SDIO_FUNC_ENABLE_1;
   2520 		bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
   2521 	}
   2522 
   2523 	/* Restore previous clock setting */
   2524 	bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
   2525 
   2526 
   2527 	/* If we didn't come up, turn off backplane clock */
   2528 	if (dhdp->busstate != DHD_BUS_DATA)
   2529 		dhdsdio_clkctl(bus, CLK_NONE, FALSE);
   2530 
   2531 exit:
   2532 	if (enforce_mutex)
   2533 		dhd_os_sdunlock(bus->dhd);
   2534 
   2535 	return ret;
   2536 }
   2537 
   2538 static void
   2539 dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
   2540 {
   2541 	bcmsdh_info_t *sdh = bus->sdh;
   2542 	sdpcmd_regs_t *regs = bus->regs;
   2543 	uint retries = 0;
   2544 	uint16 lastrbc;
   2545 	uint8 hi, lo;
   2546 	int err;
   2547 
   2548 	DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
   2549 	           (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
   2550 
   2551 	if (abort) {
   2552 		bcmsdh_abort(sdh, SDIO_FUNC_2);
   2553 	}
   2554 
   2555 	bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
   2556 	bus->f1regdata++;
   2557 
   2558 	/* Wait until the packet has been flushed (device/FIFO stable) */
   2559 	for (lastrbc = retries = 0xffff; retries > 0; retries--) {
   2560 		hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
   2561 		lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL);
   2562 		bus->f1regdata += 2;
   2563 
   2564 		if ((hi == 0) && (lo == 0))
   2565 			break;
   2566 
   2567 		if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
   2568 			DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
   2569 			           __FUNCTION__, lastrbc, ((hi << 8) + lo)));
   2570 		}
   2571 		lastrbc = (hi << 8) + lo;
   2572 	}
   2573 
   2574 	if (!retries) {
   2575 		DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
   2576 	} else {
   2577 		DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
   2578 	}
   2579 
   2580 	if (rtx) {
   2581 		bus->rxrtx++;
   2582 		W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
   2583 		bus->f1regdata++;
   2584 		if (retries <= retry_limit) {
   2585 			bus->rxskip = TRUE;
   2586 		}
   2587 	}
   2588 
   2589 	/* Clear partial in any case */
   2590 	bus->nextlen = 0;
   2591 
   2592 	/* If we can't reach the device, signal failure */
   2593 	if (err || bcmsdh_regfail(sdh))
   2594 		bus->dhd->busstate = DHD_BUS_DOWN;
   2595 }
   2596 
   2597 static void
   2598 dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
   2599 {
   2600 	bcmsdh_info_t *sdh = bus->sdh;
   2601 	uint rdlen, pad;
   2602 
   2603 	int sdret;
   2604 
   2605 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   2606 
   2607 	/* Control data already received in aligned rxctl */
   2608 	if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
   2609 		goto gotpkt;
   2610 
   2611 	ASSERT(bus->rxbuf);
   2612 	/* Set rxctl for frame (w/optional alignment) */
   2613 	bus->rxctl = bus->rxbuf;
   2614 	if (dhd_alignctl) {
   2615 		bus->rxctl += firstread;
   2616 		if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
   2617 			bus->rxctl += (DHD_SDALIGN - pad);
   2618 		bus->rxctl -= firstread;
   2619 	}
   2620 	ASSERT(bus->rxctl >= bus->rxbuf);
   2621 
   2622 	/* Copy the already-read portion over */
   2623 	bcopy(hdr, bus->rxctl, firstread);
   2624 	if (len <= firstread)
   2625 		goto gotpkt;
   2626 
   2627 	/* Copy the full data pkt in gSPI case and process ioctl. */
   2628 	if (bus->bus == SPI_BUS) {
   2629 		bcopy(hdr, bus->rxctl, len);
   2630 		goto gotpkt;
   2631 	}
   2632 
   2633 	/* Raise rdlen to next SDIO block to avoid tail command */
   2634 	rdlen = len - firstread;
   2635 	if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
   2636 		pad = bus->blocksize - (rdlen % bus->blocksize);
   2637 		if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
   2638 		    ((len + pad) < bus->dhd->maxctl))
   2639 			rdlen += pad;
   2640 	} else if (rdlen % DHD_SDALIGN) {
   2641 		rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
   2642 	}
   2643 
   2644 	/* Satisfy length-alignment requirements */
   2645 	if (forcealign && (rdlen & (ALIGNMENT - 1)))
   2646 		rdlen = ROUNDUP(rdlen, ALIGNMENT);
   2647 
   2648 	/* Drop if the read is too big or it exceeds our maximum */
   2649 	if ((rdlen + firstread) > bus->dhd->maxctl) {
   2650 		DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
   2651 		           __FUNCTION__, rdlen, bus->dhd->maxctl));
   2652 		bus->dhd->rx_errors++;
   2653 		dhdsdio_rxfail(bus, FALSE, FALSE);
   2654 		goto done;
   2655 	}
   2656 
   2657 	if ((len - doff) > bus->dhd->maxctl) {
   2658 		DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
   2659 		           __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
   2660 		bus->dhd->rx_errors++; bus->rx_toolong++;
   2661 		dhdsdio_rxfail(bus, FALSE, FALSE);
   2662 		goto done;
   2663 	}
   2664 
   2665 
   2666 	/* Read remainder of frame body into the rxctl buffer */
   2667 	sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
   2668 	                            (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
   2669 	bus->f2rxdata++;
   2670 	ASSERT(sdret != BCME_PENDING);
   2671 
   2672 	/* Control frame failures need retransmission */
   2673 	if (sdret < 0) {
   2674 		DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
   2675 		bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
   2676 		dhdsdio_rxfail(bus, TRUE, TRUE);
   2677 		goto done;
   2678 	}
   2679 
   2680 gotpkt:
   2681 
   2682 #ifdef DHD_DEBUG
   2683 	if (DHD_BYTES_ON() && DHD_CTL_ON()) {
   2684 		prhex("RxCtrl", bus->rxctl, len);
   2685 	}
   2686 #endif
   2687 
   2688 	/* Point to valid data and indicate its length */
   2689 	bus->rxctl += doff;
   2690 	bus->rxlen = len - doff;
   2691 
   2692 done:
   2693 	/* Awake any waiters */
   2694 	dhd_os_ioctl_resp_wake(bus->dhd);
   2695 }
   2696 
   2697 static uint8
   2698 dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
   2699 {
   2700 	uint16 dlen, totlen;
   2701 	uint8 *dptr, num = 0;
   2702 
   2703 	uint16 sublen, check;
   2704 	void *pfirst, *plast, *pnext, *save_pfirst;
   2705 	osl_t *osh = bus->dhd->osh;
   2706 
   2707 	int errcode;
   2708 	uint8 chan, seq, doff, sfdoff;
   2709 	uint8 txmax;
   2710 
   2711 	int ifidx = 0;
   2712 	bool usechain = bus->use_rxchain;
   2713 
   2714 	/* If packets, issue read(s) and send up packet chain */
   2715 	/* Return sequence numbers consumed? */
   2716 
   2717 	DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
   2718 
   2719 	/* If there's a descriptor, generate the packet chain */
   2720 	if (bus->glomd) {
   2721 		dhd_os_sdlock_rxq(bus->dhd);
   2722 
   2723 		pfirst = plast = pnext = NULL;
   2724 		dlen = (uint16)PKTLEN(osh, bus->glomd);
   2725 		dptr = PKTDATA(osh, bus->glomd);
   2726 		if (!dlen || (dlen & 1)) {
   2727 			DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
   2728 			           __FUNCTION__, dlen));
   2729 			dlen = 0;
   2730 		}
   2731 
   2732 		for (totlen = num = 0; dlen; num++) {
   2733 			/* Get (and move past) next length */
   2734 			sublen = ltoh16_ua(dptr);
   2735 			dlen -= sizeof(uint16);
   2736 			dptr += sizeof(uint16);
   2737 			if ((sublen < SDPCM_HDRLEN) ||
   2738 			    ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
   2739 				DHD_ERROR(("%s: descriptor len %d bad: %d\n",
   2740 				           __FUNCTION__, num, sublen));
   2741 				pnext = NULL;
   2742 				break;
   2743 			}
   2744 			if (sublen % DHD_SDALIGN) {
   2745 				DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
   2746 				           __FUNCTION__, sublen, DHD_SDALIGN));
   2747 				usechain = FALSE;
   2748 			}
   2749 			totlen += sublen;
   2750 
   2751 			/* For last frame, adjust read len so total is a block multiple */
   2752 			if (!dlen) {
   2753 				sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
   2754 				totlen = ROUNDUP(totlen, bus->blocksize);
   2755 			}
   2756 
   2757 			/* Allocate/chain packet for next subframe */
   2758 			if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
   2759 				DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
   2760 				           __FUNCTION__, num, sublen));
   2761 				break;
   2762 			}
   2763 			ASSERT(!PKTLINK(pnext));
   2764 			if (!pfirst) {
   2765 				ASSERT(!plast);
   2766 				pfirst = plast = pnext;
   2767 			} else {
   2768 				ASSERT(plast);
   2769 				PKTSETNEXT(osh, plast, pnext);
   2770 				plast = pnext;
   2771 			}
   2772 
   2773 			/* Adhere to start alignment requirements */
   2774 			PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
   2775 		}
   2776 
   2777 		/* If all allocations succeeded, save packet chain in bus structure */
   2778 		if (pnext) {
   2779 			DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
   2780 			          __FUNCTION__, totlen, num));
   2781 			if (DHD_GLOM_ON() && bus->nextlen) {
   2782 				if (totlen != bus->nextlen) {
   2783 					DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
   2784 					          "rxseq %d\n", __FUNCTION__, bus->nextlen,
   2785 					          totlen, rxseq));
   2786 				}
   2787 			}
   2788 			bus->glom = pfirst;
   2789 			pfirst = pnext = NULL;
   2790 		} else {
   2791 			if (pfirst)
   2792 				PKTFREE(osh, pfirst, FALSE);
   2793 			bus->glom = NULL;
   2794 			num = 0;
   2795 		}
   2796 
   2797 		/* Done with descriptor packet */
   2798 		PKTFREE(osh, bus->glomd, FALSE);
   2799 		bus->glomd = NULL;
   2800 		bus->nextlen = 0;
   2801 
   2802 		dhd_os_sdunlock_rxq(bus->dhd);
   2803 	}
   2804 
   2805 	/* Ok -- either we just generated a packet chain, or had one from before */
   2806 	if (bus->glom) {
   2807 		if (DHD_GLOM_ON()) {
   2808 			DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
   2809 			for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
   2810 				DHD_GLOM(("    %p: %p len 0x%04x (%d)\n",
   2811 				          pnext, (uint8*)PKTDATA(osh, pnext),
   2812 				          PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
   2813 			}
   2814 		}
   2815 
   2816 		pfirst = bus->glom;
   2817 		dlen = (uint16)pkttotlen(osh, pfirst);
   2818 
   2819 		/* Do an SDIO read for the superframe.  Configurable iovar to
   2820 		 * read directly into the chained packet, or allocate a large
   2821 		 * packet and and copy into the chain.
   2822 		 */
   2823 		if (usechain) {
   2824 			errcode = dhd_bcmsdh_recv_buf(bus,
   2825 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
   2826 			                              F2SYNC, (uint8*)PKTDATA(osh, pfirst),
   2827 			                              dlen, pfirst, NULL, NULL);
   2828 		} else if (bus->dataptr) {
   2829 			errcode = dhd_bcmsdh_recv_buf(bus,
   2830 			                              bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
   2831 			                              F2SYNC, bus->dataptr,
   2832 			                              dlen, NULL, NULL, NULL);
   2833 			sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
   2834 			if (sublen != dlen) {
   2835 				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
   2836 				           __FUNCTION__, dlen, sublen));
   2837 				errcode = -1;
   2838 			}
   2839 			pnext = NULL;
   2840 		} else {
   2841 			DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
   2842 			errcode = -1;
   2843 		}
   2844 		bus->f2rxdata++;
   2845 		ASSERT(errcode != BCME_PENDING);
   2846 
   2847 		/* On failure, kill the superframe, allow a couple retries */
   2848 		if (errcode < 0) {
   2849 			DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
   2850 			           __FUNCTION__, dlen, errcode));
   2851 			bus->dhd->rx_errors++;
   2852 
   2853 			if (bus->glomerr++ < 3) {
   2854 				dhdsdio_rxfail(bus, TRUE, TRUE);
   2855 			} else {
   2856 				bus->glomerr = 0;
   2857 				dhdsdio_rxfail(bus, TRUE, FALSE);
   2858 				dhd_os_sdlock_rxq(bus->dhd);
   2859 				PKTFREE(osh, bus->glom, FALSE);
   2860 				dhd_os_sdunlock_rxq(bus->dhd);
   2861 				bus->rxglomfail++;
   2862 				bus->glom = NULL;
   2863 			}
   2864 			return 0;
   2865 		}
   2866 
   2867 #ifdef DHD_DEBUG
   2868 		if (DHD_GLOM_ON()) {
   2869 			prhex("SUPERFRAME", PKTDATA(osh, pfirst),
   2870 			      MIN(PKTLEN(osh, pfirst), 48));
   2871 		}
   2872 #endif
   2873 
   2874 
   2875 		/* Validate the superframe header */
   2876 		dptr = (uint8 *)PKTDATA(osh, pfirst);
   2877 		sublen = ltoh16_ua(dptr);
   2878 		check = ltoh16_ua(dptr + sizeof(uint16));
   2879 
   2880 		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
   2881 		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
   2882 		bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
   2883 		if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
   2884 			DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
   2885 			          __FUNCTION__, bus->nextlen, seq));
   2886 			bus->nextlen = 0;
   2887 		}
   2888 		doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
   2889 		txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
   2890 
   2891 		errcode = 0;
   2892 		if ((uint16)~(sublen^check)) {
   2893 			DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
   2894 			           __FUNCTION__, sublen, check));
   2895 			errcode = -1;
   2896 		} else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
   2897 			DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
   2898 			           __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
   2899 			errcode = -1;
   2900 		} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
   2901 			DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
   2902 			           SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
   2903 			errcode = -1;
   2904 		} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
   2905 			DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
   2906 			errcode = -1;
   2907 		} else if ((doff < SDPCM_HDRLEN) ||
   2908 		           (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
   2909 			DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
   2910 			           __FUNCTION__, doff, sublen, PKTLEN(osh, pfirst), SDPCM_HDRLEN));
   2911 			errcode = -1;
   2912 		}
   2913 
   2914 		/* Check sequence number of superframe SW header */
   2915 		if (rxseq != seq) {
   2916 			DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
   2917 			          __FUNCTION__, seq, rxseq));
   2918 			bus->rx_badseq++;
   2919 			rxseq = seq;
   2920 		}
   2921 
   2922 		/* Check window for sanity */
   2923 		if ((uint8)(txmax - bus->tx_seq) > 0x40) {
   2924 			DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
   2925 			           __FUNCTION__, txmax, bus->tx_seq));
   2926 			txmax = bus->tx_seq + 2;
   2927 		}
   2928 		bus->tx_max = txmax;
   2929 
   2930 		/* Remove superframe header, remember offset */
   2931 		PKTPULL(osh, pfirst, doff);
   2932 		sfdoff = doff;
   2933 
   2934 		/* Validate all the subframe headers */
   2935 		for (num = 0, pnext = pfirst; pnext && !errcode;
   2936 		     num++, pnext = PKTNEXT(osh, pnext)) {
   2937 			dptr = (uint8 *)PKTDATA(osh, pnext);
   2938 			dlen = (uint16)PKTLEN(osh, pnext);
   2939 			sublen = ltoh16_ua(dptr);
   2940 			check = ltoh16_ua(dptr + sizeof(uint16));
   2941 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
   2942 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
   2943 #ifdef DHD_DEBUG
   2944 			if (DHD_GLOM_ON()) {
   2945 				prhex("subframe", dptr, 32);
   2946 			}
   2947 #endif
   2948 
   2949 			if ((uint16)~(sublen^check)) {
   2950 				DHD_ERROR(("%s (subframe %d): HW hdr error: "
   2951 				           "len/check 0x%04x/0x%04x\n",
   2952 				           __FUNCTION__, num, sublen, check));
   2953 				errcode = -1;
   2954 			} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
   2955 				DHD_ERROR(("%s (subframe %d): length mismatch: "
   2956 				           "len 0x%04x, expect 0x%04x\n",
   2957 				           __FUNCTION__, num, sublen, dlen));
   2958 				errcode = -1;
   2959 			} else if ((chan != SDPCM_DATA_CHANNEL) &&
   2960 			           (chan != SDPCM_EVENT_CHANNEL)) {
   2961 				DHD_ERROR(("%s (subframe %d): bad channel %d\n",
   2962 				           __FUNCTION__, num, chan));
   2963 				errcode = -1;
   2964 			} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
   2965 				DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
   2966 				           __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
   2967 				errcode = -1;
   2968 			}
   2969 		}
   2970 
   2971 		if (errcode) {
   2972 			/* Terminate frame on error, request a couple retries */
   2973 			if (bus->glomerr++ < 3) {
   2974 				/* Restore superframe header space */
   2975 				PKTPUSH(osh, pfirst, sfdoff);
   2976 				dhdsdio_rxfail(bus, TRUE, TRUE);
   2977 			} else {
   2978 				bus->glomerr = 0;
   2979 				dhdsdio_rxfail(bus, TRUE, FALSE);
   2980 				dhd_os_sdlock_rxq(bus->dhd);
   2981 				PKTFREE(osh, bus->glom, FALSE);
   2982 				dhd_os_sdunlock_rxq(bus->dhd);
   2983 				bus->rxglomfail++;
   2984 				bus->glom = NULL;
   2985 			}
   2986 			bus->nextlen = 0;
   2987 			return 0;
   2988 		}
   2989 
   2990 		/* Basic SD framing looks ok - process each packet (header) */
   2991 		save_pfirst = pfirst;
   2992 		bus->glom = NULL;
   2993 		plast = NULL;
   2994 
   2995 		dhd_os_sdlock_rxq(bus->dhd);
   2996 		for (num = 0; pfirst; rxseq++, pfirst = pnext) {
   2997 			pnext = PKTNEXT(osh, pfirst);
   2998 			PKTSETNEXT(osh, pfirst, NULL);
   2999 
   3000 			dptr = (uint8 *)PKTDATA(osh, pfirst);
   3001 			sublen = ltoh16_ua(dptr);
   3002 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
   3003 			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
   3004 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
   3005 
   3006 			DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
   3007 			          __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
   3008 			          PKTLEN(osh, pfirst), sublen, chan, seq));
   3009 
   3010 			ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
   3011 
   3012 			if (rxseq != seq) {
   3013 				DHD_GLOM(("%s: rx_seq %d, expected %d\n",
   3014 				          __FUNCTION__, seq, rxseq));
   3015 				bus->rx_badseq++;
   3016 				rxseq = seq;
   3017 			}
   3018 
   3019 #ifdef DHD_DEBUG
   3020 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
   3021 				prhex("Rx Subframe Data", dptr, dlen);
   3022 			}
   3023 #endif
   3024 
   3025 			PKTSETLEN(osh, pfirst, sublen);
   3026 			PKTPULL(osh, pfirst, doff);
   3027 
   3028 			if (PKTLEN(osh, pfirst) == 0) {
   3029 				PKTFREE(bus->dhd->osh, pfirst, FALSE);
   3030 				if (plast) {
   3031 					PKTSETNEXT(osh, plast, pnext);
   3032 				} else {
   3033 					ASSERT(save_pfirst == pfirst);
   3034 					save_pfirst = pnext;
   3035 				}
   3036 				continue;
   3037 			} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) != 0) {
   3038 				DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
   3039 				bus->dhd->rx_errors++;
   3040 				PKTFREE(osh, pfirst, FALSE);
   3041 				if (plast) {
   3042 					PKTSETNEXT(osh, plast, pnext);
   3043 				} else {
   3044 					ASSERT(save_pfirst == pfirst);
   3045 					save_pfirst = pnext;
   3046 				}
   3047 				continue;
   3048 			}
   3049 
   3050 			/* this packet will go up, link back into chain and count it */
   3051 			PKTSETNEXT(osh, pfirst, pnext);
   3052 			plast = pfirst;
   3053 			num++;
   3054 
   3055 #ifdef DHD_DEBUG
   3056 			if (DHD_GLOM_ON()) {
   3057 				DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
   3058 				          __FUNCTION__, num, pfirst,
   3059 				          PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
   3060 				          PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
   3061 				prhex("", (uint8 *)PKTDATA(osh, pfirst),
   3062 				      MIN(PKTLEN(osh, pfirst), 32));
   3063 			}
   3064 #endif /* DHD_DEBUG */
   3065 		}
   3066 		dhd_os_sdunlock_rxq(bus->dhd);
   3067 		if (num) {
   3068 			dhd_os_sdunlock(bus->dhd);
   3069 			dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num);
   3070 			dhd_os_sdlock(bus->dhd);
   3071 		}
   3072 
   3073 		bus->rxglomframes++;
   3074 		bus->rxglompkts += num;
   3075 	}
   3076 	return num;
   3077 }
   3078 
   3079 /* Return TRUE if there may be more frames to read */
   3080 static uint
   3081 dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
   3082 {
   3083 	osl_t *osh = bus->dhd->osh;
   3084 	bcmsdh_info_t *sdh = bus->sdh;
   3085 
   3086 	uint16 len, check;	/* Extracted hardware header fields */
   3087 	uint8 chan, seq, doff;	/* Extracted software header fields */
   3088 	uint8 fcbits;		/* Extracted fcbits from software header */
   3089 	uint8 delta;
   3090 
   3091 	void *pkt;	/* Packet for event or data frames */
   3092 	uint16 pad;	/* Number of pad bytes to read */
   3093 	uint16 rdlen;	/* Total number of bytes to read */
   3094 	uint8 rxseq;	/* Next sequence number to expect */
   3095 	uint rxleft = 0;	/* Remaining number of frames allowed */
   3096 	int sdret;	/* Return code from bcmsdh calls */
   3097 	uint8 txmax;	/* Maximum tx sequence offered */
   3098 	bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
   3099 	uint8 *rxbuf;
   3100 	int ifidx = 0;
   3101 	uint rxcount = 0; /* Total frames read */
   3102 
   3103 #if defined(DHD_DEBUG) || defined(SDTEST)
   3104 	bool sdtest = FALSE;	/* To limit message spew from test mode */
   3105 #endif
   3106 
   3107 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
   3108 
   3109 	ASSERT(maxframes);
   3110 
   3111 #ifdef SDTEST
   3112 	/* Allow pktgen to override maxframes */
   3113 	if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
   3114 		maxframes = bus->pktgen_count;
   3115 		sdtest = TRUE;
   3116 	}
   3117 #endif
   3118 
   3119 	/* Not finished unless we encounter no more frames indication */
   3120 	*finished = FALSE;
   3121 
   3122 
   3123 	for (rxseq = bus->rx_seq, rxleft = maxframes;
   3124 	     !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
   3125 	     rxseq++, rxleft--) {
   3126 
   3127 		/* Handle glomming separately */
   3128 		if (bus->glom || bus->glomd) {
   3129 			uint8 cnt;
   3130 			DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
   3131 			          __FUNCTION__, bus->glomd, bus->glom));
   3132 			cnt = dhdsdio_rxglom(bus, rxseq);
   3133 			DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
   3134 			rxseq += cnt - 1;
   3135 			rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
   3136 			continue;
   3137 		}
   3138 
   3139 		/* Try doing single read if we can */
   3140 		if (dhd_readahead && bus->nextlen) {
   3141 			uint16 nextlen = bus->nextlen;
   3142 			bus->nextlen = 0;
   3143 
   3144 			if (bus->bus == SPI_BUS) {
   3145 				rdlen = len = nextlen;
   3146 			}
   3147 			else {
   3148 				rdlen = len = nextlen << 4;
   3149 
   3150 				/* Pad read to blocksize for efficiency */
   3151 				if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
   3152 					pad = bus->blocksize - (rdlen % bus->blocksize);
   3153 					if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
   3154 						((rdlen + pad + firstread) < MAX_RX_DATASZ))
   3155 						rdlen += pad;
   3156 				} else if (rdlen % DHD_SDALIGN) {
   3157 					rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
   3158 				}
   3159 			}
   3160 
   3161 			/* We use bus->rxctl buffer in WinXP for initial control pkt receives.
   3162 			 * Later we use buffer-poll for data as well as control packets.
   3163 			 * This is required becuase dhd receives full frame in gSPI unlike SDIO.
   3164 			 * After the frame is received we have to distinguish whether it is data
   3165 			 * or non-data frame.
   3166 			 */
   3167 			/* Allocate a packet buffer */
   3168 			dhd_os_sdlock_rxq(bus->dhd);
   3169 			if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
   3170 				if (bus->bus == SPI_BUS) {
   3171 					bus->usebufpool = FALSE;
   3172 					bus->rxctl = bus->rxbuf;
   3173 					if (dhd_alignctl) {
   3174 						bus->rxctl += firstread;
   3175 						if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
   3176 							bus->rxctl += (DHD_SDALIGN - pad);
   3177 						bus->rxctl -= firstread;
   3178 					}
   3179 					ASSERT(bus->rxctl >= bus->rxbuf);
   3180 					rxbuf = bus->rxctl;
   3181 					/* Read the entire frame */
   3182 					sdret = dhd_bcmsdh_recv_buf(bus,
   3183 					                            bcmsdh_cur_sbwad(sdh),
   3184 					                            SDIO_FUNC_2,
   3185 					                            F2SYNC, rxbuf, rdlen,
   3186 					                            NULL, NULL, NULL);
   3187 					bus->f2rxdata++;
   3188 					ASSERT(sdret != BCME_PENDING);
   3189 
   3190 
   3191 					/* Control frame failures need retransmission */
   3192 					if (sdret < 0) {
   3193 						DHD_ERROR(("%s: read %d control bytes failed: %d\n",
   3194 						   __FUNCTION__, rdlen, sdret));
   3195 						/* dhd.rx_ctlerrs is higher level */
   3196 						bus->rxc_errors++;
   3197 						dhd_os_sdunlock_rxq(bus->dhd);
   3198 						dhdsdio_rxfail(bus, TRUE,
   3199 						    (bus->bus == SPI_BUS) ? FALSE : TRUE);
   3200 						continue;
   3201 					}
   3202 				} else {
   3203 					/* Give up on data, request rtx of events */
   3204 					DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
   3205 					           "expected rxseq %d\n",
   3206 					           __FUNCTION__, len, rdlen, rxseq));
   3207 					/* Just go try again w/normal header read */
   3208 					dhd_os_sdunlock_rxq(bus->dhd);
   3209 					continue;
   3210 				}
   3211 			} else {
   3212 				if (bus->bus == SPI_BUS)
   3213 					bus->usebufpool = TRUE;
   3214 
   3215 				ASSERT(!PKTLINK(pkt));
   3216 				PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
   3217 				rxbuf = (uint8 *)PKTDATA(osh, pkt);
   3218 				/* Read the entire frame */
   3219 				sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
   3220 				                            SDIO_FUNC_2,
   3221 				                            F2SYNC, rxbuf, rdlen,
   3222 				                            pkt, NULL, NULL);
   3223 				bus->f2rxdata++;
   3224 				ASSERT(sdret != BCME_PENDING);
   3225 
   3226 				if (sdret < 0) {
   3227 					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
   3228 					   __FUNCTION__, rdlen, sdret));
   3229 					PKTFREE(bus->dhd->osh, pkt, FALSE);
   3230 					bus->dhd->rx_errors++;
   3231 					dhd_os_sdunlock_rxq(bus->dhd);
   3232 					/* Force retry w/normal header read.  Don't attemp NAK for
   3233 					 * gSPI
   3234 					 */
   3235 					dhdsdio_rxfail(bus, TRUE,
   3236 					      (bus->bus == SPI_BUS) ? FALSE : TRUE);
   3237 					continue;
   3238 				}
   3239 			}
   3240 			dhd_os_sdunlock_rxq(bus->dhd);
   3241 
   3242 			/* Now check the header */
   3243 			bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
   3244 
   3245 			/* Extract hardware header fields */
   3246 			len = ltoh16_ua(bus->rxhdr);
   3247 			check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
   3248 
   3249 			/* All zeros means readahead info was bad */
   3250 			if (!(len|check)) {
   3251 				DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
   3252 				           __FUNCTION__));
   3253 				dhd_os_sdlock_rxq(bus->dhd);
   3254 				PKTFREE2();
   3255 				dhd_os_sdunlock_rxq(bus->dhd);
   3256 				GSPI_PR55150_BAILOUT;
   3257 				continue;
   3258 			}
   3259 
   3260 			/* Validate check bytes */
   3261 			if ((uint16)~(len^check)) {
   3262 				DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
   3263 				           " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
   3264 				           len, check));
   3265 				dhd_os_sdlock_rxq(bus->dhd);
   3266 				PKTFREE2();
   3267 				dhd_os_sdunlock_rxq(bus->dhd);
   3268 				bus->rx_badhdr++;
   3269 				dhdsdio_rxfail(bus, FALSE, FALSE);
   3270 				GSPI_PR55150_BAILOUT;
   3271 				continue;
   3272 			}
   3273 
   3274 			/* Validate frame length */
   3275 			if (len < SDPCM_HDRLEN) {
   3276 				DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
   3277 				           __FUNCTION__, len));
   3278 				dhd_os_sdlock_rxq(bus->dhd);
   3279 				PKTFREE2();
   3280 				dhd_os_sdunlock_rxq(bus->dhd);
   3281 				GSPI_PR55150_BAILOUT;
   3282 				continue;
   3283 			}
   3284 
   3285 			/* Check for consistency with readahead info */
   3286 				len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
   3287 			if (len_consistent) {
   3288 				/* Mismatch, force retry w/normal header (may be >4K) */
   3289 				DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
   3290 				           "expected rxseq %d\n",
   3291 				           __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
   3292 				dhd_os_sdlock_rxq(bus->dhd);
   3293 				PKTFREE2();
   3294 				dhd_os_sdunlock_rxq(bus->dhd);
   3295 				dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
   3296 				GSPI_PR55150_BAILOUT;
   3297 				continue;
   3298 			}
   3299 
   3300 
   3301 			/* Extract software header fields */
   3302 			chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
   3303 			seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
   3304 			doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
   3305 			txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
   3306 
   3307 				bus->nextlen =
   3308 				         bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
   3309 				if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
   3310 					DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
   3311 					          " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
   3312 					          seq));
   3313 					bus->nextlen = 0;
   3314 				}
   3315 
   3316 				bus->dhd->rx_readahead_cnt ++;
   3317 			/* Handle Flow Control */
   3318 			fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
   3319 
   3320 			delta = 0;
   3321 			if (~bus->flowcontrol & fcbits) {
   3322 				bus->fc_xoff++;
   3323 				delta = 1;
   3324 			}
   3325 			if (bus->flowcontrol & ~fcbits) {
   3326 				bus->fc_xon++;
   3327 				delta = 1;
   3328 			}
   3329 
   3330 			if (delta) {
   3331 				bus->fc_rcvd++;
   3332 				bus->flowcontrol = fcbits;
   3333 			}
   3334 
   3335 			/* Check and update sequence number */
   3336 			if (rxseq != seq) {
   3337 				DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
   3338 				          __FUNCTION__, seq, rxseq));
   3339 				bus->rx_badseq++;
   3340 				rxseq = seq;
   3341 			}
   3342 
   3343 			/* Check window for sanity */
   3344 			if ((uint8)(txmax - bus->tx_seq) > 0x40) {
   3345 					DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
   3346 						__FUNCTION__, txmax, bus->tx_seq));
   3347 					txmax = bus->tx_seq + 2;
   3348 			}
   3349 			bus->tx_max = txmax;
   3350 
   3351 #ifdef DHD_DEBUG
   3352 			if (DHD_BYTES_ON() && DHD_DATA_ON()) {
   3353 				prhex("Rx Data", rxbuf, len);
   3354 			} else if (DHD_HDRS_ON()) {
   3355 				prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
   3356 			}
   3357 #endif
   3358 
   3359 			if (chan == SDPCM_CONTROL_CHANNEL) {
   3360 				if (bus->bus == SPI_BUS) {
   3361 					dhdsdio_read_control(bus, rxbuf, len, doff);
   3362 					if (bus->usebufpool) {
   3363 						dhd_os_sdlock_rxq(bus->dhd);
   3364 						PKTFREE(bus->dhd->osh, pkt, FALSE);
   3365 						dhd_os_sdunlock_rxq(bus->dhd);
   3366 					}
   3367 					continue;
   3368 				} else {
   3369 					DHD_ERROR(("%s (nextlen): readahead on control"
   3370 					           " packet %d?\n", __FUNCTION__, seq));
   3371 					/* Force retry w/normal header read */
   3372 					bus->nextlen = 0;
   3373 					dhdsdio_rxfail(bus, FALSE, TRUE);
   3374 					dhd_os_sdlock_rxq(bus->dhd);
   3375 					PKTFREE2();
   3376 					dhd_os_sdunlock_rxq(bus->dhd);
   3377 					continue;
   3378 				}
   3379 			}
   3380 
   3381 			if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
   3382 				DHD_ERROR(("Received %d bytes on %d channel. Running out of "
   3383 				           "rx pktbuf's or not yet malloced.\n", len, chan));
   3384 				continue;
   3385 			}
   3386 
   3387 			/* Validate data offset */
   3388 			if ((doff < SDPCM_HDRLEN) || (doff > len)) {
   3389 				DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
   3390 				           __FUNCTION__, doff, len, SDPCM_HDRLEN));
   3391 				dhd_os_sdlock_rxq(bus->dhd);
   3392 				PKTFREE2();
   3393 				dhd_os_sdunlock_rxq(bus->dhd);
   3394 				ASSERT(0);
   3395 				dhdsdio_rxfail(bus, FALSE, FALSE);
   3396 				continue;
   3397 			}
   3398 
   3399 			/* All done with this one -- now deliver the packet */
   3400 			goto deliver;
   3401 		}
   3402 		/* gSPI frames should not be handled in fractions */
   3403 		if (bus->bus == SPI_BUS) {
   3404 			break;
   3405 		}
   3406 
   3407 		/* Read frame header (hardware and software) */
   3408 		sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
   3409 		                            bus->rxhdr, firstread, NULL, NULL, NULL);
   3410 		bus->f2rxhdrs++;
   3411 		ASSERT(sdret != BCME_PENDING);
   3412 
   3413 		if (sdret < 0) {
   3414 			DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
   3415 			bus->rx_hdrfail++;
   3416 			dhdsdio_rxfail(bus, TRUE, TRUE);
   3417 			continue;
   3418 		}
   3419 
   3420 #ifdef DHD_DEBUG
   3421 		if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
   3422 			prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
   3423 		}
   3424 #endif
   3425 
   3426 		/* Extract hardware header fields */
   3427 		len = ltoh16_ua(bus->rxhdr);
   3428 		check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
   3429 
   3430 		/* All zeros means no more frames */
   3431 		if (!(len|check)) {
   3432 			*finished = TRUE;
   3433 			break;
   3434 		}
   3435 
   3436 		/* Validate check bytes */
   3437 		if ((uint16)~(len^check)) {
   3438