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, ®s->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, ®s->tosbmailboxdata, retries); 802 if (retries <= retry_limit) 803 W_SDREG(SMB_DEV_INT, ®s->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, ®s->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, ®s->tosbmailboxdata, retries); 844 if (retries <= retry_limit) 845 W_SDREG(SMB_DEV_INT, ®s->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, ®s->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, ®s->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