]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
staging: brcm80211: macro cleanup
[mv-sheeva.git] / drivers / staging / brcm80211 / brcmfmac / dhd_sdio.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/types.h>
18 #include <linux/kernel.h>
19 #include <linux/printk.h>
20 #include <linux/pci_ids.h>
21 #include <linux/netdevice.h>
22 #include <bcmdefs.h>
23 #include <bcmsdh.h>
24
25 #ifdef BCMEMBEDIMAGE
26 #include BCMEMBEDIMAGE
27 #endif                          /* BCMEMBEDIMAGE */
28
29 #include <bcmdefs.h>
30 #include <bcmutils.h>
31 #include <bcmdevs.h>
32
33 #include <bcmsoc.h>
34 #ifdef DHD_DEBUG
35
36 /* ARM trap handling */
37
38 /* Trap types defined by ARM (see arminc.h) */
39
40 /* Trap locations in lo memory */
41 #define TRAP_STRIDE     4
42 #define FIRST_TRAP      TR_RST
43 #define LAST_TRAP       (TR_FIQ * TRAP_STRIDE)
44
45 #if defined(__ARM_ARCH_4T__)
46 #define MAX_TRAP_TYPE   (TR_FIQ + 1)
47 #elif defined(__ARM_ARCH_7M__)
48 #define MAX_TRAP_TYPE   (TR_ISR + ARMCM3_NUMINTS)
49 #endif                          /* __ARM_ARCH_7M__ */
50
51 /* The trap structure is defined here as offsets for assembly */
52 #define TR_TYPE         0x00
53 #define TR_EPC          0x04
54 #define TR_CPSR         0x08
55 #define TR_SPSR         0x0c
56 #define TR_REGS         0x10
57 #define TR_REG(n)       (TR_REGS + (n) * 4)
58 #define TR_SP           TR_REG(13)
59 #define TR_LR           TR_REG(14)
60 #define TR_PC           TR_REG(15)
61
62 #define TRAP_T_SIZE     80
63
64 typedef struct _trap_struct {
65         u32 type;
66         u32 epc;
67         u32 cpsr;
68         u32 spsr;
69         u32 r0;
70         u32 r1;
71         u32 r2;
72         u32 r3;
73         u32 r4;
74         u32 r5;
75         u32 r6;
76         u32 r7;
77         u32 r8;
78         u32 r9;
79         u32 r10;
80         u32 r11;
81         u32 r12;
82         u32 r13;
83         u32 r14;
84         u32 pc;
85 } trap_t;
86
87 #define CBUF_LEN        (128)
88
89 #define LOG_BUF_LEN     1024
90
91 typedef struct {
92         u32 buf;                /* Can't be pointer on (64-bit) hosts */
93         uint buf_size;
94         uint idx;
95         char *_buf_compat;      /* Redundant pointer for backward compat. */
96 } rte_log_t;
97
98 typedef struct {
99         /* Virtual UART
100          * When there is no UART (e.g. Quickturn),
101          * the host should write a complete
102          * input line directly into cbuf and then write
103          * the length into vcons_in.
104          * This may also be used when there is a real UART
105          * (at risk of conflicting with
106          * the real UART).  vcons_out is currently unused.
107          */
108         volatile uint vcons_in;
109         volatile uint vcons_out;
110
111         /* Output (logging) buffer
112          * Console output is written to a ring buffer log_buf at index log_idx.
113          * The host may read the output when it sees log_idx advance.
114          * Output will be lost if the output wraps around faster than the host
115          * polls.
116          */
117         rte_log_t log;
118
119         /* Console input line buffer
120          * Characters are read one at a time into cbuf
121          * until <CR> is received, then
122          * the buffer is processed as a command line.
123          * Also used for virtual UART.
124          */
125         uint cbuf_idx;
126         char cbuf[CBUF_LEN];
127 } rte_cons_t;
128
129 #endif                          /* DHD_DEBUG */
130 #include <chipcommon.h>
131
132 #include <sdio.h>
133 #include <sbsdio.h>
134 #include <sbsdpcmdev.h>
135 #include <bcmsdpcm.h>
136
137 #include <dngl_stats.h>
138 #include <dhd.h>
139 #include <dhd_bus.h>
140 #include <dhd_proto.h>
141 #include <dhd_dbg.h>
142 #include <sdiovar.h>
143 #include <bcmchip.h>
144
145 #ifndef DHDSDIO_MEM_DUMP_FNAME
146 #define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
147 #endif
148
149 #define TXQLEN          2048    /* bulk tx queue length */
150 #define TXHI            (TXQLEN - 256)  /* turn on flow control above TXHI */
151 #define TXLOW           (TXHI - 256)    /* turn off flow control below TXLOW */
152 #define PRIOMASK        7
153
154 #define TXRETRIES       2       /* # of retries for tx frames */
155
156 #if defined(CONFIG_MACH_SANDGATE2G)
157 #define DHD_RXBOUND     250     /* Default for max rx frames in
158                                  one scheduling */
159 #else
160 #define DHD_RXBOUND     50      /* Default for max rx frames in
161                                  one scheduling */
162 #endif                          /* defined(CONFIG_MACH_SANDGATE2G) */
163
164 #define DHD_TXBOUND     20      /* Default for max tx frames in
165                                  one scheduling */
166
167 #define DHD_TXMINMAX    1       /* Max tx frames if rx still pending */
168
169 #define MEMBLOCK        2048    /* Block size used for downloading
170                                  of dongle image */
171 #define MAX_DATA_BUF    (32 * 1024)     /* Must be large enough to hold
172                                  biggest possible glom */
173
174 /* Packet alignment for most efficient SDIO (can change based on platform) */
175 #ifndef DHD_SDALIGN
176 #define DHD_SDALIGN     32
177 #endif
178 #if !ISPOWEROF2(DHD_SDALIGN)
179 #error DHD_SDALIGN is not a power of 2!
180 #endif
181
182 #ifndef DHD_FIRSTREAD
183 #define DHD_FIRSTREAD   32
184 #endif
185 #if !ISPOWEROF2(DHD_FIRSTREAD)
186 #error DHD_FIRSTREAD is not a power of 2!
187 #endif
188
189 /* Total length of frame header for dongle protocol */
190 #define SDPCM_HDRLEN    (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
191 #ifdef SDTEST
192 #define SDPCM_RESERVE   (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
193 #else
194 #define SDPCM_RESERVE   (SDPCM_HDRLEN + DHD_SDALIGN)
195 #endif
196
197 /* Space for header read, limit for data packets */
198 #ifndef MAX_HDR_READ
199 #define MAX_HDR_READ    32
200 #endif
201 #if !ISPOWEROF2(MAX_HDR_READ)
202 #error MAX_HDR_READ is not a power of 2!
203 #endif
204
205 #define MAX_RX_DATASZ   2048
206
207 /* Maximum milliseconds to wait for F2 to come up */
208 #define DHD_WAIT_F2RDY  3000
209
210 /* Bump up limit on waiting for HT to account for first startup;
211  * if the image is doing a CRC calculation before programming the PMU
212  * for HT availability, it could take a couple hundred ms more, so
213  * max out at a 1 second (1000000us).
214  */
215 #if (PMU_MAX_TRANSITION_DLY <= 1000000)
216 #undef PMU_MAX_TRANSITION_DLY
217 #define PMU_MAX_TRANSITION_DLY 1000000
218 #endif
219
220 /* Value for ChipClockCSR during initial setup */
221 #define DHD_INIT_CLKCTL1        (SBSDIO_FORCE_HW_CLKREQ_OFF |   \
222                                         SBSDIO_ALP_AVAIL_REQ)
223 #define DHD_INIT_CLKCTL2        (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
224
225 /* Flags for SDH calls */
226 #define F2SYNC  (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
227
228 /* sbimstate */
229 #define SBIM_IBE                0x20000 /* inbanderror */
230 #define SBIM_TO                 0x40000 /* timeout */
231 #define SBIM_BY                 0x01800000      /* busy (sonics >= 2.3) */
232 #define SBIM_RJ                 0x02000000      /* reject (sonics >= 2.3) */
233
234 /* sbtmstatelow */
235 #define SBTML_RESET             0x0001  /* reset */
236 #define SBTML_REJ_MASK          0x0006  /* reject field */
237 #define SBTML_REJ               0x0002  /* reject */
238 #define SBTML_TMPREJ            0x0004  /* temporary reject, for error recovery */
239
240 #define SBTML_SICF_SHIFT        16      /* Shift to locate the SI control flags in sbtml */
241
242 /* sbtmstatehigh */
243 #define SBTMH_SERR              0x0001  /* serror */
244 #define SBTMH_INT               0x0002  /* interrupt */
245 #define SBTMH_BUSY              0x0004  /* busy */
246 #define SBTMH_TO                0x0020  /* timeout (sonics >= 2.3) */
247
248 #define SBTMH_SISF_SHIFT        16      /* Shift to locate the SI status flags in sbtmh */
249
250 /* sbidlow */
251 #define SBIDL_INIT              0x80    /* initiator */
252
253 /* sbidhigh */
254 #define SBIDH_RC_MASK           0x000f  /* revision code */
255 #define SBIDH_RCE_MASK          0x7000  /* revision code extension field */
256 #define SBIDH_RCE_SHIFT         8
257 #define SBCOREREV(sbidh) \
258         ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK))
259 #define SBIDH_CC_MASK           0x8ff0  /* core code */
260 #define SBIDH_CC_SHIFT          4
261 #define SBIDH_VC_MASK           0xffff0000      /* vendor code */
262 #define SBIDH_VC_SHIFT          16
263
264 /*
265  * Conversion of 802.1D priority to precedence level
266  */
267 #define PRIO2PREC(prio) \
268         (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
269         ((prio^2)) : (prio))
270
271 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
272 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
273                             uint len);
274
275 /* Core reg address translation */
276 #define CORE_CC_REG(base, field)        (base + offsetof(chipcregs_t, field))
277 #define CORE_BUS_REG(base, field)       (base + offsetof(sdpcmd_regs_t, field))
278 #define CORE_SB(base, field) \
279                 (base + SBCONFIGOFF + offsetof(sbconfig_t, field))
280
281 #ifdef DHD_DEBUG
282 /* Device console log buffer state */
283 typedef struct dhd_console {
284         uint count;             /* Poll interval msec counter */
285         uint log_addr;          /* Log struct address (fixed) */
286         rte_log_t log;  /* Log struct (host copy) */
287         uint bufsize;           /* Size of log buffer */
288         u8 *buf;                /* Log buffer (host copy) */
289         uint last;              /* Last buffer read index */
290 } dhd_console_t;
291 #endif                          /* DHD_DEBUG */
292
293 /* misc chip info needed by some of the routines */
294 struct chip_info {
295         u32 chip;
296         u32 chiprev;
297         u32 cccorebase;
298         u32 ccrev;
299         u32 cccaps;
300         u32 buscorebase;
301         u32 buscorerev;
302         u32 buscoretype;
303         u32 ramcorebase;
304         u32 armcorebase;
305         u32 pmurev;
306         u32 ramsize;
307 };
308
309 /* Private data for SDIO bus interaction */
310 typedef struct dhd_bus {
311         dhd_pub_t *dhd;
312
313         bcmsdh_info_t *sdh;     /* Handle for BCMSDH calls */
314         struct chip_info *ci;   /* Chip info struct */
315         char *vars;             /* Variables (from CIS and/or other) */
316         uint varsz;             /* Size of variables buffer */
317         u32 sbaddr;             /* Current SB window pointer (-1, invalid) */
318
319         sdpcmd_regs_t *regs;    /* Registers for SDIO core */
320         uint sdpcmrev;          /* SDIO core revision */
321         uint armrev;            /* CPU core revision */
322         uint ramrev;            /* SOCRAM core revision */
323         u32 ramsize;            /* Size of RAM in SOCRAM (bytes) */
324         u32 orig_ramsize;       /* Size of RAM in SOCRAM (bytes) */
325
326         u32 bus;                /* gSPI or SDIO bus */
327         u32 hostintmask;        /* Copy of Host Interrupt Mask */
328         u32 intstatus;  /* Intstatus bits (events) pending */
329         bool dpc_sched;         /* Indicates DPC schedule (intrpt rcvd) */
330         bool fcstate;           /* State of dongle flow-control */
331
332         u16 cl_devid;   /* cached devid for dhdsdio_probe_attach() */
333         char *fw_path;          /* module_param: path to firmware image */
334         char *nv_path;          /* module_param: path to nvram vars file */
335         const char *nvram_params;       /* user specified nvram params. */
336
337         uint blocksize;         /* Block size of SDIO transfers */
338         uint roundup;           /* Max roundup limit */
339
340         struct pktq txq;        /* Queue length used for flow-control */
341         u8 flowcontrol; /* per prio flow control bitmask */
342         u8 tx_seq;              /* Transmit sequence number (next) */
343         u8 tx_max;              /* Maximum transmit sequence allowed */
344
345         u8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
346         u8 *rxhdr;              /* Header of current rx frame (in hdrbuf) */
347         u16 nextlen;            /* Next Read Len from last header */
348         u8 rx_seq;              /* Receive sequence number (expected) */
349         bool rxskip;            /* Skip receive (awaiting NAK ACK) */
350
351         struct sk_buff *glomd;  /* Packet containing glomming descriptor */
352         struct sk_buff *glom;   /* Packet chain for glommed superframe */
353         uint glomerr;           /* Glom packet read errors */
354
355         u8 *rxbuf;              /* Buffer for receiving control packets */
356         uint rxblen;            /* Allocated length of rxbuf */
357         u8 *rxctl;              /* Aligned pointer into rxbuf */
358         u8 *databuf;            /* Buffer for receiving big glom packet */
359         u8 *dataptr;            /* Aligned pointer into databuf */
360         uint rxlen;             /* Length of valid data in buffer */
361
362         u8 sdpcm_ver;   /* Bus protocol reported by dongle */
363
364         bool intr;              /* Use interrupts */
365         bool poll;              /* Use polling */
366         bool ipend;             /* Device interrupt is pending */
367         bool intdis;            /* Interrupts disabled by isr */
368         uint intrcount;         /* Count of device interrupt callbacks */
369         uint lastintrs;         /* Count as of last watchdog timer */
370         uint spurious;          /* Count of spurious interrupts */
371         uint pollrate;          /* Ticks between device polls */
372         uint polltick;          /* Tick counter */
373         uint pollcnt;           /* Count of active polls */
374
375 #ifdef DHD_DEBUG
376         dhd_console_t console;  /* Console output polling support */
377         uint console_addr;      /* Console address from shared struct */
378 #endif                          /* DHD_DEBUG */
379
380         uint regfails;          /* Count of R_REG/W_REG failures */
381
382         uint clkstate;          /* State of sd and backplane clock(s) */
383         bool activity;          /* Activity flag for clock down */
384         s32 idletime;           /* Control for activity timeout */
385         s32 idlecount;  /* Activity timeout counter */
386         s32 idleclock;  /* How to set bus driver when idle */
387         s32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
388         bool use_rxchain;       /* If dhd should use PKT chains */
389         bool sleeping;          /* Is SDIO bus sleeping? */
390         bool rxflow_mode;       /* Rx flow control mode */
391         bool rxflow;            /* Is rx flow control on */
392         uint prev_rxlim_hit;    /* Is prev rx limit exceeded
393                                          (per dpc schedule) */
394         bool alp_only;          /* Don't use HT clock (ALP only) */
395 /* Field to decide if rx of control frames happen in rxbuf or lb-pool */
396         bool usebufpool;
397
398 #ifdef SDTEST
399         /* external loopback */
400         bool ext_loop;
401         u8 loopid;
402
403         /* pktgen configuration */
404         uint pktgen_freq;       /* Ticks between bursts */
405         uint pktgen_count;      /* Packets to send each burst */
406         uint pktgen_print;      /* Bursts between count displays */
407         uint pktgen_total;      /* Stop after this many */
408         uint pktgen_minlen;     /* Minimum packet data len */
409         uint pktgen_maxlen;     /* Maximum packet data len */
410         uint pktgen_mode;       /* Configured mode: tx, rx, or echo */
411         uint pktgen_stop;       /* Number of tx failures causing stop */
412
413         /* active pktgen fields */
414         uint pktgen_tick;       /* Tick counter for bursts */
415         uint pktgen_ptick;      /* Burst counter for printing */
416         uint pktgen_sent;       /* Number of test packets generated */
417         uint pktgen_rcvd;       /* Number of test packets received */
418         uint pktgen_fail;       /* Number of failed send attempts */
419         u16 pktgen_len; /* Length of next packet to send */
420 #endif                          /* SDTEST */
421
422         /* Some additional counters */
423         uint tx_sderrs;         /* Count of tx attempts with sd errors */
424         uint fcqueued;          /* Tx packets that got queued */
425         uint rxrtx;             /* Count of rtx requests (NAK to dongle) */
426         uint rx_toolong;        /* Receive frames too long to receive */
427         uint rxc_errors;        /* SDIO errors when reading control frames */
428         uint rx_hdrfail;        /* SDIO errors on header reads */
429         uint rx_badhdr;         /* Bad received headers (roosync?) */
430         uint rx_badseq;         /* Mismatched rx sequence number */
431         uint fc_rcvd;           /* Number of flow-control events received */
432         uint fc_xoff;           /* Number which turned on flow-control */
433         uint fc_xon;            /* Number which turned off flow-control */
434         uint rxglomfail;        /* Failed deglom attempts */
435         uint rxglomframes;      /* Number of glom frames (superframes) */
436         uint rxglompkts;        /* Number of packets from glom frames */
437         uint f2rxhdrs;          /* Number of header reads */
438         uint f2rxdata;          /* Number of frame data reads */
439         uint f2txdata;          /* Number of f2 frame writes */
440         uint f1regdata;         /* Number of f1 register accesses */
441
442         u8 *ctrl_frame_buf;
443         u32 ctrl_frame_len;
444         bool ctrl_frame_stat;
445 } dhd_bus_t;
446
447 typedef volatile struct _sbconfig {
448         u32 PAD[2];
449         u32 sbipsflag;  /* initiator port ocp slave flag */
450         u32 PAD[3];
451         u32 sbtpsflag;  /* target port ocp slave flag */
452         u32 PAD[11];
453         u32 sbtmerrloga;        /* (sonics >= 2.3) */
454         u32 PAD;
455         u32 sbtmerrlog; /* (sonics >= 2.3) */
456         u32 PAD[3];
457         u32 sbadmatch3; /* address match3 */
458         u32 PAD;
459         u32 sbadmatch2; /* address match2 */
460         u32 PAD;
461         u32 sbadmatch1; /* address match1 */
462         u32 PAD[7];
463         u32 sbimstate;  /* initiator agent state */
464         u32 sbintvec;   /* interrupt mask */
465         u32 sbtmstatelow;       /* target state */
466         u32 sbtmstatehigh;      /* target state */
467         u32 sbbwa0;             /* bandwidth allocation table0 */
468         u32 PAD;
469         u32 sbimconfiglow;      /* initiator configuration */
470         u32 sbimconfighigh;     /* initiator configuration */
471         u32 sbadmatch0; /* address match0 */
472         u32 PAD;
473         u32 sbtmconfiglow;      /* target configuration */
474         u32 sbtmconfighigh;     /* target configuration */
475         u32 sbbconfig;  /* broadcast configuration */
476         u32 PAD;
477         u32 sbbstate;   /* broadcast state */
478         u32 PAD[3];
479         u32 sbactcnfg;  /* activate configuration */
480         u32 PAD[3];
481         u32 sbflagst;   /* current sbflags */
482         u32 PAD[3];
483         u32 sbidlow;            /* identification */
484         u32 sbidhigh;   /* identification */
485 } sbconfig_t;
486
487 /* clkstate */
488 #define CLK_NONE        0
489 #define CLK_SDONLY      1
490 #define CLK_PENDING     2       /* Not used yet */
491 #define CLK_AVAIL       3
492
493 #define DHD_NOPMU(dhd)  (false)
494
495 #ifdef DHD_DEBUG
496 static int qcount[NUMPRIO];
497 static int tx_packets[NUMPRIO];
498 #endif                          /* DHD_DEBUG */
499
500 /* Deferred transmit */
501 const uint dhd_deferred_tx = 1;
502
503 extern uint dhd_watchdog_ms;
504 extern void dhd_os_wd_timer(void *bus, uint wdtick);
505
506 /* Tx/Rx bounds */
507 uint dhd_txbound;
508 uint dhd_rxbound;
509 uint dhd_txminmax;
510
511 /* override the RAM size if possible */
512 #define DONGLE_MIN_MEMSIZE (128 * 1024)
513 int dhd_dongle_memsize;
514
515 static bool dhd_alignctl;
516
517 static bool sd1idle;
518
519 static bool retrydata;
520 #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
521
522 static const uint watermark = 8;
523 static const uint firstread = DHD_FIRSTREAD;
524
525 #define HDATLEN (firstread - (SDPCM_HDRLEN))
526
527 /* Retry count for register access failures */
528 static const uint retry_limit = 2;
529
530 /* Force even SD lengths (some host controllers mess up on odd bytes) */
531 static bool forcealign;
532
533 #define ALIGNMENT  4
534
535 #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
536 extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
537 #endif
538
539 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
540 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
541 #endif  /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
542 #define PKTALIGN(_p, _len, _align)                              \
543         do {                                                            \
544                 uint datalign;                                          \
545                 datalign = (unsigned long)((_p)->data);                 \
546                 datalign = roundup(datalign, (_align)) - datalign;      \
547                 ASSERT(datalign < (_align));                            \
548                 ASSERT((_p)->len >= ((_len) + datalign));               \
549                 if (datalign)                                           \
550                         skb_pull((_p), datalign);                       \
551                 __skb_trim((_p), (_len));                               \
552         } while (0)
553
554 /* Limit on rounding up frames */
555 static const uint max_roundup = 512;
556
557 /* Try doing readahead */
558 static bool dhd_readahead;
559
560 /* To check if there's window offered */
561 #define DATAOK(bus) \
562         (((u8)(bus->tx_max - bus->tx_seq) != 0) && \
563         (((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
564
565 /* Macros to get register read/write status */
566 /* NOTE: these assume a local dhdsdio_bus_t *bus! */
567 #define R_SDREG(regvar, regaddr, retryvar) \
568 do { \
569         retryvar = 0; \
570         do { \
571                 regvar = R_REG(regaddr); \
572         } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
573         if (retryvar) { \
574                 bus->regfails += (retryvar-1); \
575                 if (retryvar > retry_limit) { \
576                         DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
577                         __func__, __LINE__)); \
578                         regvar = 0; \
579                 } \
580         } \
581 } while (0)
582
583 #define W_SDREG(regval, regaddr, retryvar) \
584 do { \
585         retryvar = 0; \
586         do { \
587                 W_REG(regaddr, regval); \
588         } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
589         if (retryvar) { \
590                 bus->regfails += (retryvar-1); \
591                 if (retryvar > retry_limit) \
592                         DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
593                         __func__, __LINE__)); \
594         } \
595 } while (0)
596
597 #define DHD_BUS                 SDIO_BUS
598
599 #define PKT_AVAILABLE()         (intstatus & I_HMB_FRAME_IND)
600
601 #define HOSTINTMASK             (I_HMB_SW_MASK | I_CHIPACTIVE)
602
603 #ifdef SDTEST
604 static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
605 static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
606 #endif
607
608 #ifdef DHD_DEBUG
609 static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size);
610 static int dhdsdio_mem_dump(dhd_bus_t *bus);
611 #endif                          /* DHD_DEBUG  */
612 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
613
614 static void dhdsdio_release(dhd_bus_t *bus);
615 static void dhdsdio_release_malloc(dhd_bus_t *bus);
616 static void dhdsdio_disconnect(void *ptr);
617 static bool dhdsdio_chipmatch(u16 chipid);
618 static bool dhdsdio_probe_attach(dhd_bus_t *bus, void *sdh,
619                                  void *regsva, u16 devid);
620 static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh);
621 static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh);
622 static void dhdsdio_release_dongle(dhd_bus_t *bus);
623
624 static uint process_nvram_vars(char *varbuf, uint len);
625
626 static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size);
627 static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn,
628                                uint flags, u8 *buf, uint nbytes,
629                                struct sk_buff *pkt, bcmsdh_cmplt_fn_t complete,
630                                void *handle);
631
632 static bool dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh);
633 static int _dhdsdio_download_firmware(struct dhd_bus *bus);
634
635 static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
636 static int dhdsdio_download_nvram(struct dhd_bus *bus);
637 #ifdef BCMEMBEDIMAGE
638 static int dhdsdio_download_code_array(struct dhd_bus *bus);
639 #endif
640 static void dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase);
641 static int dhdsdio_chip_attach(struct dhd_bus *bus, void *regs);
642 static void dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase);
643 static void dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus,
644                                         u32 drivestrength);
645 static void dhdsdio_chip_detach(struct dhd_bus *bus);
646
647 /* Packet free applicable unconditionally for sdio and sdspi.
648  * Conditional if bufpool was present for gspi bus.
649  */
650 static void dhdsdio_pktfree2(dhd_bus_t *bus, struct sk_buff *pkt)
651 {
652         dhd_os_sdlock_rxq(bus->dhd);
653         if ((bus->bus != SPI_BUS) || bus->usebufpool)
654                 bcm_pkt_buf_free_skb(pkt);
655         dhd_os_sdunlock_rxq(bus->dhd);
656 }
657
658 static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
659 {
660         s32 min_size = DONGLE_MIN_MEMSIZE;
661         /* Restrict the memsize to user specified limit */
662         DHD_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
663                 dhd_dongle_memsize, min_size));
664         if ((dhd_dongle_memsize > min_size) &&
665             (dhd_dongle_memsize < (s32) bus->orig_ramsize))
666                 bus->ramsize = dhd_dongle_memsize;
667 }
668
669 static int dhdsdio_set_siaddr_window(dhd_bus_t *bus, u32 address)
670 {
671         int err = 0;
672         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
673                          (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
674         if (!err)
675                 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
676                                  (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
677         if (!err)
678                 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
679                                  (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
680                                  &err);
681         return err;
682 }
683
684 /* Turn backplane clock on or off */
685 static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
686 {
687         int err;
688         u8 clkctl, clkreq, devctl;
689         bcmsdh_info_t *sdh;
690
691         DHD_TRACE(("%s: Enter\n", __func__));
692
693 #if defined(OOB_INTR_ONLY)
694         pendok = false;
695 #endif
696         clkctl = 0;
697         sdh = bus->sdh;
698
699         if (on) {
700                 /* Request HT Avail */
701                 clkreq =
702                     bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
703
704                 if ((bus->ci->chip == BCM4329_CHIP_ID)
705                     && (bus->ci->chiprev == 0))
706                         clkreq |= SBSDIO_FORCE_ALP;
707
708                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
709                                  clkreq, &err);
710                 if (err) {
711                         DHD_ERROR(("%s: HT Avail request error: %d\n",
712                                    __func__, err));
713                         return -EBADE;
714                 }
715
716                 if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
717                                && (bus->ci->buscorerev == 9))) {
718                         u32 dummy, retries;
719                         R_SDREG(dummy, &bus->regs->clockctlstatus, retries);
720                 }
721
722                 /* Check current status */
723                 clkctl =
724                     bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
725                                     &err);
726                 if (err) {
727                         DHD_ERROR(("%s: HT Avail read error: %d\n",
728                                    __func__, err));
729                         return -EBADE;
730                 }
731
732                 /* Go to pending and await interrupt if appropriate */
733                 if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
734                         /* Allow only clock-available interrupt */
735                         devctl =
736                             bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
737                                             &err);
738                         if (err) {
739                                 DHD_ERROR(("%s: Devctl error setting CA: %d\n",
740                                         __func__, err));
741                                 return -EBADE;
742                         }
743
744                         devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
745                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
746                                          devctl, &err);
747                         DHD_INFO(("CLKCTL: set PENDING\n"));
748                         bus->clkstate = CLK_PENDING;
749
750                         return 0;
751                 } else if (bus->clkstate == CLK_PENDING) {
752                         /* Cancel CA-only interrupt filter */
753                         devctl =
754                             bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
755                                             &err);
756                         devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
757                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
758                                          devctl, &err);
759                 }
760
761                 /* Otherwise, wait here (polling) for HT Avail */
762                 if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
763                         SPINWAIT_SLEEP(sdioh_spinwait_sleep,
764                                        ((clkctl =
765                                          bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
766                                                  SBSDIO_FUNC1_CHIPCLKCSR,
767                                                          &err)),
768                                         !SBSDIO_CLKAV(clkctl, bus->alp_only)),
769                                        PMU_MAX_TRANSITION_DLY);
770                 }
771                 if (err) {
772                         DHD_ERROR(("%s: HT Avail request error: %d\n",
773                                    __func__, err));
774                         return -EBADE;
775                 }
776                 if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
777                         DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
778                                    __func__, PMU_MAX_TRANSITION_DLY, clkctl));
779                         return -EBADE;
780                 }
781
782                 /* Mark clock available */
783                 bus->clkstate = CLK_AVAIL;
784                 DHD_INFO(("CLKCTL: turned ON\n"));
785
786 #if defined(DHD_DEBUG)
787                 if (bus->alp_only == true) {
788 #if !defined(BCMLXSDMMC)
789                         if (!SBSDIO_ALPONLY(clkctl)) {
790                                 DHD_ERROR(("%s: HT Clock, when ALP Only\n",
791                                            __func__));
792                         }
793 #endif                          /* !defined(BCMLXSDMMC) */
794                 } else {
795                         if (SBSDIO_ALPONLY(clkctl)) {
796                                 DHD_ERROR(("%s: HT Clock should be on.\n",
797                                            __func__));
798                         }
799                 }
800 #endif                          /* defined (DHD_DEBUG) */
801
802                 bus->activity = true;
803         } else {
804                 clkreq = 0;
805
806                 if (bus->clkstate == CLK_PENDING) {
807                         /* Cancel CA-only interrupt filter */
808                         devctl =
809                             bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
810                                             &err);
811                         devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
812                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
813                                          devctl, &err);
814                 }
815
816                 bus->clkstate = CLK_SDONLY;
817                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
818                                  clkreq, &err);
819                 DHD_INFO(("CLKCTL: turned OFF\n"));
820                 if (err) {
821                         DHD_ERROR(("%s: Failed access turning clock off: %d\n",
822                                    __func__, err));
823                         return -EBADE;
824                 }
825         }
826         return 0;
827 }
828
829 /* Change idle/active SD state */
830 static int dhdsdio_sdclk(dhd_bus_t *bus, bool on)
831 {
832         DHD_TRACE(("%s: Enter\n", __func__));
833
834         if (on)
835                 bus->clkstate = CLK_SDONLY;
836         else
837                 bus->clkstate = CLK_NONE;
838
839         return 0;
840 }
841
842 /* Transition SD and backplane clock readiness */
843 static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
844 {
845 #ifdef DHD_DEBUG
846         uint oldstate = bus->clkstate;
847 #endif                          /* DHD_DEBUG */
848
849         DHD_TRACE(("%s: Enter\n", __func__));
850
851         /* Early exit if we're already there */
852         if (bus->clkstate == target) {
853                 if (target == CLK_AVAIL) {
854                         dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
855                         bus->activity = true;
856                 }
857                 return 0;
858         }
859
860         switch (target) {
861         case CLK_AVAIL:
862                 /* Make sure SD clock is available */
863                 if (bus->clkstate == CLK_NONE)
864                         dhdsdio_sdclk(bus, true);
865                 /* Now request HT Avail on the backplane */
866                 dhdsdio_htclk(bus, true, pendok);
867                 dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
868                 bus->activity = true;
869                 break;
870
871         case CLK_SDONLY:
872                 /* Remove HT request, or bring up SD clock */
873                 if (bus->clkstate == CLK_NONE)
874                         dhdsdio_sdclk(bus, true);
875                 else if (bus->clkstate == CLK_AVAIL)
876                         dhdsdio_htclk(bus, false, false);
877                 else
878                         DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
879                                    bus->clkstate, target));
880                 dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
881                 break;
882
883         case CLK_NONE:
884                 /* Make sure to remove HT request */
885                 if (bus->clkstate == CLK_AVAIL)
886                         dhdsdio_htclk(bus, false, false);
887                 /* Now remove the SD clock */
888                 dhdsdio_sdclk(bus, false);
889                 dhd_os_wd_timer(bus->dhd, 0);
890                 break;
891         }
892 #ifdef DHD_DEBUG
893         DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
894 #endif                          /* DHD_DEBUG */
895
896         return 0;
897 }
898
899 int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
900 {
901         bcmsdh_info_t *sdh = bus->sdh;
902         sdpcmd_regs_t *regs = bus->regs;
903         uint retries = 0;
904
905         DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
906                   (sleep ? "SLEEP" : "WAKE"),
907                   (bus->sleeping ? "SLEEP" : "WAKE")));
908
909         /* Done if we're already in the requested state */
910         if (sleep == bus->sleeping)
911                 return 0;
912
913         /* Going to sleep: set the alarm and turn off the lights... */
914         if (sleep) {
915                 /* Don't sleep if something is pending */
916                 if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
917                         return -EBUSY;
918
919                 /* Disable SDIO interrupts (no longer interested) */
920                 bcmsdh_intr_disable(bus->sdh);
921
922                 /* Make sure the controller has the bus up */
923                 dhdsdio_clkctl(bus, CLK_AVAIL, false);
924
925                 /* Tell device to start using OOB wakeup */
926                 W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
927                 if (retries > retry_limit)
928                         DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
929
930                 /* Turn off our contribution to the HT clock request */
931                 dhdsdio_clkctl(bus, CLK_SDONLY, false);
932
933                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
934                                  SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
935
936                 /* Isolate the bus */
937                 if (bus->ci->chip != BCM4329_CHIP_ID
938                     && bus->ci->chip != BCM4319_CHIP_ID) {
939                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
940                                          SBSDIO_DEVCTL_PADS_ISO, NULL);
941                 }
942
943                 /* Change state */
944                 bus->sleeping = true;
945
946         } else {
947                 /* Waking up: bus power up is ok, set local state */
948
949                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
950                                  0, NULL);
951
952                 /* Force pad isolation off if possible
953                          (in case power never toggled) */
954                 if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
955                     && (bus->ci->buscorerev >= 10))
956                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0,
957                                          NULL);
958
959                 /* Make sure the controller has the bus up */
960                 dhdsdio_clkctl(bus, CLK_AVAIL, false);
961
962                 /* Send misc interrupt to indicate OOB not needed */
963                 W_SDREG(0, &regs->tosbmailboxdata, retries);
964                 if (retries <= retry_limit)
965                         W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
966
967                 if (retries > retry_limit)
968                         DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
969
970                 /* Make sure we have SD bus access */
971                 dhdsdio_clkctl(bus, CLK_SDONLY, false);
972
973                 /* Change state */
974                 bus->sleeping = false;
975
976                 /* Enable interrupts again */
977                 if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
978                         bus->intdis = false;
979                         bcmsdh_intr_enable(bus->sdh);
980                 }
981         }
982
983         return 0;
984 }
985
986 #if defined(OOB_INTR_ONLY)
987 void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
988 {
989 #if defined(HW_OOB)
990         bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
991 #else
992         sdpcmd_regs_t *regs = bus->regs;
993         uint retries = 0;
994
995         dhdsdio_clkctl(bus, CLK_AVAIL, false);
996         if (enable == true) {
997
998                 /* Tell device to start using OOB wakeup */
999                 W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
1000                 if (retries > retry_limit)
1001                         DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
1002
1003         } else {
1004                 /* Send misc interrupt to indicate OOB not needed */
1005                 W_SDREG(0, &regs->tosbmailboxdata, retries);
1006                 if (retries <= retry_limit)
1007                         W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
1008         }
1009
1010         /* Turn off our contribution to the HT clock request */
1011         dhdsdio_clkctl(bus, CLK_SDONLY, false);
1012 #endif                          /* !defined(HW_OOB) */
1013 }
1014 #endif                          /* defined(OOB_INTR_ONLY) */
1015
1016 #define BUS_WAKE(bus) \
1017         do { \
1018                 if ((bus)->sleeping) \
1019                         dhdsdio_bussleep((bus), false); \
1020         } while (0);
1021
1022 /* Writes a HW/SW header into the packet and sends it. */
1023 /* Assumes: (a) header space already there, (b) caller holds lock */
1024 static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
1025                          bool free_pkt)
1026 {
1027         int ret;
1028         u8 *frame;
1029         u16 len, pad = 0;
1030         u32 swheader;
1031         uint retries = 0;
1032         bcmsdh_info_t *sdh;
1033         struct sk_buff *new;
1034         int i;
1035
1036         DHD_TRACE(("%s: Enter\n", __func__));
1037
1038         sdh = bus->sdh;
1039
1040         if (bus->dhd->dongle_reset) {
1041                 ret = -EPERM;
1042                 goto done;
1043         }
1044
1045         frame = (u8 *) (pkt->data);
1046
1047         /* Add alignment padding, allocate new packet if needed */
1048         pad = ((unsigned long)frame % DHD_SDALIGN);
1049         if (pad) {
1050                 if (skb_headroom(pkt) < pad) {
1051                         DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
1052                                   __func__, skb_headroom(pkt), pad));
1053                         bus->dhd->tx_realloc++;
1054                         new = bcm_pkt_buf_get_skb(pkt->len + DHD_SDALIGN);
1055                         if (!new) {
1056                                 DHD_ERROR(("%s: couldn't allocate new %d-byte "
1057                                         "packet\n",
1058                                         __func__, pkt->len + DHD_SDALIGN));
1059                                 ret = -ENOMEM;
1060                                 goto done;
1061                         }
1062
1063                         PKTALIGN(new, pkt->len, DHD_SDALIGN);
1064                         memcpy(new->data, pkt->data, pkt->len);
1065                         if (free_pkt)
1066                                 bcm_pkt_buf_free_skb(pkt);
1067                         /* free the pkt if canned one is not used */
1068                         free_pkt = true;
1069                         pkt = new;
1070                         frame = (u8 *) (pkt->data);
1071                         ASSERT(((unsigned long)frame % DHD_SDALIGN) == 0);
1072                         pad = 0;
1073                 } else {
1074                         skb_push(pkt, pad);
1075                         frame = (u8 *) (pkt->data);
1076
1077                         ASSERT((pad + SDPCM_HDRLEN) <= (int)(pkt->len));
1078                         memset(frame, 0, pad + SDPCM_HDRLEN);
1079                 }
1080         }
1081         ASSERT(pad < DHD_SDALIGN);
1082
1083         /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
1084         len = (u16) (pkt->len);
1085         *(u16 *) frame = cpu_to_le16(len);
1086         *(((u16 *) frame) + 1) = cpu_to_le16(~len);
1087
1088         /* Software tag: channel, sequence number, data offset */
1089         swheader =
1090             ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
1091             (((pad +
1092                SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
1093
1094         put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
1095         put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
1096
1097 #ifdef DHD_DEBUG
1098         tx_packets[pkt->priority]++;
1099         if (DHD_BYTES_ON() &&
1100             (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
1101               (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
1102                 printk(KERN_DEBUG "Tx Frame:\n");
1103                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
1104         } else if (DHD_HDRS_ON()) {
1105                 printk(KERN_DEBUG "TxHdr:\n");
1106                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
1107                                      frame, min_t(u16, len, 16));
1108         }
1109 #endif
1110
1111         /* Raise len to next SDIO block to eliminate tail command */
1112         if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
1113                 u16 pad = bus->blocksize - (len % bus->blocksize);
1114                 if ((pad <= bus->roundup) && (pad < bus->blocksize))
1115 #ifdef NOTUSED
1116                         if (pad <= skb_tailroom(pkt))
1117 #endif                          /* NOTUSED */
1118                                 len += pad;
1119         } else if (len % DHD_SDALIGN) {
1120                 len += DHD_SDALIGN - (len % DHD_SDALIGN);
1121         }
1122
1123         /* Some controllers have trouble with odd bytes -- round to even */
1124         if (forcealign && (len & (ALIGNMENT - 1))) {
1125 #ifdef NOTUSED
1126                 if (skb_tailroom(pkt))
1127 #endif
1128                         len = roundup(len, ALIGNMENT);
1129 #ifdef NOTUSED
1130                 else
1131                         DHD_ERROR(("%s: sending unrounded %d-byte packet\n",
1132                                    __func__, len));
1133 #endif
1134         }
1135
1136         do {
1137                 ret =
1138                     dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
1139                                         F2SYNC, frame, len, pkt, NULL, NULL);
1140                 bus->f2txdata++;
1141                 ASSERT(ret != -BCME_PENDING);
1142
1143                 if (ret < 0) {
1144                         /* On failure, abort the command
1145                          and terminate the frame */
1146                         DHD_INFO(("%s: sdio error %d, abort command and "
1147                                 "terminate frame.\n", __func__, ret));
1148                         bus->tx_sderrs++;
1149
1150                         bcmsdh_abort(sdh, SDIO_FUNC_2);
1151                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
1152                                          SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
1153                                          NULL);
1154                         bus->f1regdata++;
1155
1156                         for (i = 0; i < 3; i++) {
1157                                 u8 hi, lo;
1158                                 hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
1159                                                      SBSDIO_FUNC1_WFRAMEBCHI,
1160                                                      NULL);
1161                                 lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
1162                                                      SBSDIO_FUNC1_WFRAMEBCLO,
1163                                                      NULL);
1164                                 bus->f1regdata += 2;
1165                                 if ((hi == 0) && (lo == 0))
1166                                         break;
1167                         }
1168
1169                 }
1170                 if (ret == 0)
1171                         bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
1172
1173         } while ((ret < 0) && retrydata && retries++ < TXRETRIES);
1174
1175 done:
1176         /* restore pkt buffer pointer before calling tx complete routine */
1177         skb_pull(pkt, SDPCM_HDRLEN + pad);
1178         dhd_os_sdunlock(bus->dhd);
1179         dhd_txcomplete(bus->dhd, pkt, ret != 0);
1180         dhd_os_sdlock(bus->dhd);
1181
1182         if (free_pkt)
1183                 bcm_pkt_buf_free_skb(pkt);
1184
1185         return ret;
1186 }
1187
1188 int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
1189 {
1190         int ret = -EBADE;
1191         uint datalen, prec;
1192
1193         DHD_TRACE(("%s: Enter\n", __func__));
1194
1195         datalen = pkt->len;
1196
1197 #ifdef SDTEST
1198         /* Push the test header if doing loopback */
1199         if (bus->ext_loop) {
1200                 u8 *data;
1201                 skb_push(pkt, SDPCM_TEST_HDRLEN);
1202                 data = pkt->data;
1203                 *data++ = SDPCM_TEST_ECHOREQ;
1204                 *data++ = (u8) bus->loopid++;
1205                 *data++ = (datalen >> 0);
1206                 *data++ = (datalen >> 8);
1207                 datalen += SDPCM_TEST_HDRLEN;
1208         }
1209 #endif                          /* SDTEST */
1210
1211         /* Add space for the header */
1212         skb_push(pkt, SDPCM_HDRLEN);
1213         ASSERT(IS_ALIGNED((unsigned long)(pkt->data), 2));
1214
1215         prec = PRIO2PREC((pkt->priority & PRIOMASK));
1216
1217         /* Check for existing queue, current flow-control,
1218                          pending event, or pending clock */
1219         if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
1220             || bus->dpc_sched || (!DATAOK(bus))
1221             || (bus->flowcontrol & NBITVAL(prec))
1222             || (bus->clkstate != CLK_AVAIL)) {
1223                 DHD_TRACE(("%s: deferring pktq len %d\n", __func__,
1224                            pktq_len(&bus->txq)));
1225                 bus->fcqueued++;
1226
1227                 /* Priority based enq */
1228                 dhd_os_sdlock_txq(bus->dhd);
1229                 if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == false) {
1230                         skb_pull(pkt, SDPCM_HDRLEN);
1231                         dhd_txcomplete(bus->dhd, pkt, false);
1232                         bcm_pkt_buf_free_skb(pkt);
1233                         DHD_ERROR(("%s: out of bus->txq !!!\n", __func__));
1234                         ret = -ENOSR;
1235                 } else {
1236                         ret = 0;
1237                 }
1238                 dhd_os_sdunlock_txq(bus->dhd);
1239
1240                 if (pktq_len(&bus->txq) >= TXHI)
1241                         dhd_txflowcontrol(bus->dhd, 0, ON);
1242
1243 #ifdef DHD_DEBUG
1244                 if (pktq_plen(&bus->txq, prec) > qcount[prec])
1245                         qcount[prec] = pktq_plen(&bus->txq, prec);
1246 #endif
1247                 /* Schedule DPC if needed to send queued packet(s) */
1248                 if (dhd_deferred_tx && !bus->dpc_sched) {
1249                         bus->dpc_sched = true;
1250                         dhd_sched_dpc(bus->dhd);
1251                 }
1252         } else {
1253                 /* Lock: we're about to use shared data/code (and SDIO) */
1254                 dhd_os_sdlock(bus->dhd);
1255
1256                 /* Otherwise, send it now */
1257                 BUS_WAKE(bus);
1258                 /* Make sure back plane ht clk is on, no pending allowed */
1259                 dhdsdio_clkctl(bus, CLK_AVAIL, true);
1260
1261 #ifndef SDTEST
1262                 DHD_TRACE(("%s: calling txpkt\n", __func__));
1263                 ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
1264 #else
1265                 ret = dhdsdio_txpkt(bus, pkt,
1266                                     (bus->ext_loop ? SDPCM_TEST_CHANNEL :
1267                                      SDPCM_DATA_CHANNEL), true);
1268 #endif
1269                 if (ret)
1270                         bus->dhd->tx_errors++;
1271                 else
1272                         bus->dhd->dstats.tx_bytes += datalen;
1273
1274                 if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
1275                         bus->activity = false;
1276                         dhdsdio_clkctl(bus, CLK_NONE, true);
1277                 }
1278
1279                 dhd_os_sdunlock(bus->dhd);
1280         }
1281
1282         return ret;
1283 }
1284
1285 static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
1286 {
1287         struct sk_buff *pkt;
1288         u32 intstatus = 0;
1289         uint retries = 0;
1290         int ret = 0, prec_out;
1291         uint cnt = 0;
1292         uint datalen;
1293         u8 tx_prec_map;
1294
1295         dhd_pub_t *dhd = bus->dhd;
1296         sdpcmd_regs_t *regs = bus->regs;
1297
1298         DHD_TRACE(("%s: Enter\n", __func__));
1299
1300         tx_prec_map = ~bus->flowcontrol;
1301
1302         /* Send frames until the limit or some other event */
1303         for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
1304                 dhd_os_sdlock_txq(bus->dhd);
1305                 pkt = bcm_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
1306                 if (pkt == NULL) {
1307                         dhd_os_sdunlock_txq(bus->dhd);
1308                         break;
1309                 }
1310                 dhd_os_sdunlock_txq(bus->dhd);
1311                 datalen = pkt->len - SDPCM_HDRLEN;
1312
1313 #ifndef SDTEST
1314                 ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
1315 #else
1316                 ret = dhdsdio_txpkt(bus, pkt,
1317                                     (bus->ext_loop ? SDPCM_TEST_CHANNEL :
1318                                      SDPCM_DATA_CHANNEL), true);
1319 #endif
1320                 if (ret)
1321                         bus->dhd->tx_errors++;
1322                 else
1323                         bus->dhd->dstats.tx_bytes += datalen;
1324
1325                 /* In poll mode, need to check for other events */
1326                 if (!bus->intr && cnt) {
1327                         /* Check device status, signal pending interrupt */
1328                         R_SDREG(intstatus, &regs->intstatus, retries);
1329                         bus->f2txdata++;
1330                         if (bcmsdh_regfail(bus->sdh))
1331                                 break;
1332                         if (intstatus & bus->hostintmask)
1333                                 bus->ipend = true;
1334                 }
1335         }
1336
1337         /* Deflow-control stack if needed */
1338         if (dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
1339             dhd->txoff && (pktq_len(&bus->txq) < TXLOW))
1340                 dhd_txflowcontrol(dhd, 0, OFF);
1341
1342         return cnt;
1343 }
1344
1345 int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
1346 {
1347         u8 *frame;
1348         u16 len;
1349         u32 swheader;
1350         uint retries = 0;
1351         bcmsdh_info_t *sdh = bus->sdh;
1352         u8 doff = 0;
1353         int ret = -1;
1354         int i;
1355
1356         DHD_TRACE(("%s: Enter\n", __func__));
1357
1358         if (bus->dhd->dongle_reset)
1359                 return -EIO;
1360
1361         /* Back the pointer to make a room for bus header */
1362         frame = msg - SDPCM_HDRLEN;
1363         len = (msglen += SDPCM_HDRLEN);
1364
1365         /* Add alignment padding (optional for ctl frames) */
1366         if (dhd_alignctl) {
1367                 doff = ((unsigned long)frame % DHD_SDALIGN);
1368                 if (doff) {
1369                         frame -= doff;
1370                         len += doff;
1371                         msglen += doff;
1372                         memset(frame, 0, doff + SDPCM_HDRLEN);
1373                 }
1374                 ASSERT(doff < DHD_SDALIGN);
1375         }
1376         doff += SDPCM_HDRLEN;
1377
1378         /* Round send length to next SDIO block */
1379         if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
1380                 u16 pad = bus->blocksize - (len % bus->blocksize);
1381                 if ((pad <= bus->roundup) && (pad < bus->blocksize))
1382                         len += pad;
1383         } else if (len % DHD_SDALIGN) {
1384                 len += DHD_SDALIGN - (len % DHD_SDALIGN);
1385         }
1386
1387         /* Satisfy length-alignment requirements */
1388         if (forcealign && (len & (ALIGNMENT - 1)))
1389                 len = roundup(len, ALIGNMENT);
1390
1391         ASSERT(IS_ALIGNED((unsigned long)frame, 2));
1392
1393         /* Need to lock here to protect txseq and SDIO tx calls */
1394         dhd_os_sdlock(bus->dhd);
1395
1396         BUS_WAKE(bus);
1397
1398         /* Make sure backplane clock is on */
1399         dhdsdio_clkctl(bus, CLK_AVAIL, false);
1400
1401         /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
1402         *(u16 *) frame = cpu_to_le16((u16) msglen);
1403         *(((u16 *) frame) + 1) = cpu_to_le16(~msglen);
1404
1405         /* Software tag: channel, sequence number, data offset */
1406         swheader =
1407             ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
1408              SDPCM_CHANNEL_MASK)
1409             | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
1410                              SDPCM_DOFFSET_MASK);
1411         put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
1412         put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
1413
1414         if (!DATAOK(bus)) {
1415                 DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
1416                           __func__, bus->tx_max, bus->tx_seq));
1417                 bus->ctrl_frame_stat = true;
1418                 /* Send from dpc */
1419                 bus->ctrl_frame_buf = frame;
1420                 bus->ctrl_frame_len = len;
1421
1422                 dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
1423
1424                 if (bus->ctrl_frame_stat == false) {
1425                         DHD_INFO(("%s: ctrl_frame_stat == false\n", __func__));
1426                         ret = 0;
1427                 } else {
1428                         DHD_INFO(("%s: ctrl_frame_stat == true\n", __func__));
1429                         ret = -1;
1430                 }
1431         }
1432
1433         if (ret == -1) {
1434 #ifdef DHD_DEBUG
1435                 if (DHD_BYTES_ON() && DHD_CTL_ON()) {
1436                         printk(KERN_DEBUG "Tx Frame:\n");
1437                         print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
1438                                              frame, len);
1439                 } else if (DHD_HDRS_ON()) {
1440                         printk(KERN_DEBUG "TxHdr:\n");
1441                         print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
1442                                              frame, min_t(u16, len, 16));
1443                 }
1444 #endif
1445
1446                 do {
1447                         bus->ctrl_frame_stat = false;
1448                         ret =
1449                             dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh),
1450                                                 SDIO_FUNC_2, F2SYNC, frame, len,
1451                                                 NULL, NULL, NULL);
1452
1453                         ASSERT(ret != -BCME_PENDING);
1454
1455                         if (ret < 0) {
1456                                 /* On failure, abort the command and
1457                                  terminate the frame */
1458                                 DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
1459                                         __func__, ret));
1460                                 bus->tx_sderrs++;
1461
1462                                 bcmsdh_abort(sdh, SDIO_FUNC_2);
1463
1464                                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
1465                                                  SBSDIO_FUNC1_FRAMECTRL,
1466                                                  SFC_WF_TERM, NULL);
1467                                 bus->f1regdata++;
1468
1469                                 for (i = 0; i < 3; i++) {
1470                                         u8 hi, lo;
1471                                         hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
1472                                              SBSDIO_FUNC1_WFRAMEBCHI,
1473                                              NULL);
1474                                         lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
1475                                              SBSDIO_FUNC1_WFRAMEBCLO,
1476                                                              NULL);
1477                                         bus->f1regdata += 2;
1478                                         if ((hi == 0) && (lo == 0))
1479                                                 break;
1480                                 }
1481
1482                         }
1483                         if (ret == 0) {
1484                                 bus->tx_seq =
1485                                     (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
1486                         }
1487                 } while ((ret < 0) && retries++ < TXRETRIES);
1488         }
1489
1490         if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
1491                 bus->activity = false;
1492                 dhdsdio_clkctl(bus, CLK_NONE, true);
1493         }
1494
1495         dhd_os_sdunlock(bus->dhd);
1496
1497         if (ret)
1498                 bus->dhd->tx_ctlerrs++;
1499         else
1500                 bus->dhd->tx_ctlpkts++;
1501
1502         return ret ? -EIO : 0;
1503 }
1504
1505 int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
1506 {
1507         int timeleft;
1508         uint rxlen = 0;
1509         bool pending;
1510
1511         DHD_TRACE(("%s: Enter\n", __func__));
1512
1513         if (bus->dhd->dongle_reset)
1514                 return -EIO;
1515
1516         /* Wait until control frame is available */
1517         timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
1518
1519         dhd_os_sdlock(bus->dhd);
1520         rxlen = bus->rxlen;
1521         memcpy(msg, bus->rxctl, min(msglen, rxlen));
1522         bus->rxlen = 0;
1523         dhd_os_sdunlock(bus->dhd);
1524
1525         if (rxlen) {
1526                 DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
1527                          __func__, rxlen, msglen));
1528         } else if (timeleft == 0) {
1529                 DHD_ERROR(("%s: resumed on timeout\n", __func__));
1530 #ifdef DHD_DEBUG
1531                 dhd_os_sdlock(bus->dhd);
1532                 dhdsdio_checkdied(bus, NULL, 0);
1533                 dhd_os_sdunlock(bus->dhd);
1534 #endif                          /* DHD_DEBUG */
1535         } else if (pending == true) {
1536                 DHD_CTL(("%s: cancelled\n", __func__));
1537                 return -ERESTARTSYS;
1538         } else {
1539                 DHD_CTL(("%s: resumed for unknown reason?\n", __func__));
1540 #ifdef DHD_DEBUG
1541                 dhd_os_sdlock(bus->dhd);
1542                 dhdsdio_checkdied(bus, NULL, 0);
1543                 dhd_os_sdunlock(bus->dhd);
1544 #endif                          /* DHD_DEBUG */
1545         }
1546
1547         if (rxlen)
1548                 bus->dhd->rx_ctlpkts++;
1549         else
1550                 bus->dhd->rx_ctlerrs++;
1551
1552         return rxlen ? (int)rxlen : -ETIMEDOUT;
1553 }
1554
1555 /* IOVar table */
1556 enum {
1557         IOV_INTR = 1,
1558         IOV_POLLRATE,
1559         IOV_SDREG,
1560         IOV_SBREG,
1561         IOV_SDCIS,
1562         IOV_MEMBYTES,
1563         IOV_MEMSIZE,
1564 #ifdef DHD_DEBUG
1565         IOV_CHECKDIED,
1566 #endif
1567         IOV_DOWNLOAD,
1568         IOV_FORCEEVEN,
1569         IOV_SDIOD_DRIVE,
1570         IOV_READAHEAD,
1571         IOV_SDRXCHAIN,
1572         IOV_ALIGNCTL,
1573         IOV_SDALIGN,
1574         IOV_DEVRESET,
1575         IOV_CPU,
1576 #ifdef SDTEST
1577         IOV_PKTGEN,
1578         IOV_EXTLOOP,
1579 #endif                          /* SDTEST */
1580         IOV_SPROM,
1581         IOV_TXBOUND,
1582         IOV_RXBOUND,
1583         IOV_TXMINMAX,
1584         IOV_IDLETIME,
1585         IOV_IDLECLOCK,
1586         IOV_SD1IDLE,
1587         IOV_SLEEP,
1588         IOV_VARS
1589 };
1590
1591 const bcm_iovar_t dhdsdio_iovars[] = {
1592         {"intr", IOV_INTR, 0, IOVT_BOOL, 0},
1593         {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0},
1594         {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0},
1595         {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0},
1596         {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0},
1597         {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0},
1598         {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int)},
1599         {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0},
1600         {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0},
1601         {"vars", IOV_VARS, 0, IOVT_BUFFER, 0},
1602         {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0},
1603         {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0},
1604         {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0},
1605         {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0},
1606         {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0},
1607         {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0},
1608 #ifdef DHD_DEBUG
1609         {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
1610         ,
1611         {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
1612         ,
1613         {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}
1614         ,
1615         {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0}
1616         ,
1617         {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0}
1618         ,
1619         {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0}
1620         ,
1621         {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0}
1622         ,
1623         {"cpu", IOV_CPU, 0, IOVT_BOOL, 0}
1624         ,
1625 #ifdef DHD_DEBUG
1626         {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0}
1627         ,
1628 #endif                          /* DHD_DEBUG  */
1629 #endif                          /* DHD_DEBUG */
1630 #ifdef SDTEST
1631         {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0}
1632         ,
1633         {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t)}
1634         ,
1635 #endif                          /* SDTEST */
1636
1637         {NULL, 0, 0, 0, 0}
1638 };
1639
1640 static void
1641 dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
1642 {
1643         uint q1, q2;
1644
1645         if (!div) {
1646                 bcm_bprintf(strbuf, "%s N/A", desc);
1647         } else {
1648                 q1 = num / div;
1649                 q2 = (100 * (num - (q1 * div))) / div;
1650                 bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
1651         }
1652 }
1653
1654 void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
1655 {
1656         dhd_bus_t *bus = dhdp->bus;
1657
1658         bcm_bprintf(strbuf, "Bus SDIO structure:\n");
1659         bcm_bprintf(strbuf,
1660                     "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
1661                     bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
1662         bcm_bprintf(strbuf,
1663                     "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
1664                     bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max,
1665                     bus->rxskip, bus->rxlen, bus->rx_seq);
1666         bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
1667                     bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
1668         bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
1669                     bus->pollrate, bus->pollcnt, bus->regfails);
1670
1671         bcm_bprintf(strbuf, "\nAdditional counters:\n");
1672         bcm_bprintf(strbuf,
1673                     "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
1674                     bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
1675                     bus->rxc_errors);
1676         bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
1677                     bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
1678         bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", bus->fc_rcvd,
1679                     bus->fc_xoff, bus->fc_xon);
1680         bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
1681                     bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
1682         bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n",
1683                     (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs,
1684                     bus->f2rxdata, bus->f2txdata, bus->f1regdata);
1685         {
1686                 dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
1687                              (bus->f2rxhdrs + bus->f2rxdata));
1688                 dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets,
1689                              bus->f1regdata);
1690                 dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
1691                              (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
1692                 dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets,
1693                              bus->intrcount);
1694                 bcm_bprintf(strbuf, "\n");
1695
1696                 dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
1697                              bus->dhd->rx_packets);
1698                 dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
1699                              bus->rxglomframes);
1700                 bcm_bprintf(strbuf, "\n");
1701
1702                 dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets,
1703                              bus->f2txdata);
1704                 dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets,
1705                              bus->f1regdata);
1706                 dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
1707                              (bus->f2txdata + bus->f1regdata));
1708                 dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets,
1709                              bus->intrcount);
1710                 bcm_bprintf(strbuf, "\n");
1711
1712                 dhd_dump_pct(strbuf, "Total: pkts/f2rw",
1713                              (bus->dhd->tx_packets + bus->dhd->rx_packets),
1714                              (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
1715                 dhd_dump_pct(strbuf, ", pkts/f1sd",
1716                              (bus->dhd->tx_packets + bus->dhd->rx_packets),
1717                              bus->f1regdata);
1718                 dhd_dump_pct(strbuf, ", pkts/sd",
1719                              (bus->dhd->tx_packets + bus->dhd->rx_packets),
1720                              (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata +
1721                               bus->f1regdata));
1722                 dhd_dump_pct(strbuf, ", pkts/int",
1723                              (bus->dhd->tx_packets + bus->dhd->rx_packets),
1724                              bus->intrcount);
1725                 bcm_bprintf(strbuf, "\n\n");
1726         }
1727
1728 #ifdef SDTEST
1729         if (bus->pktgen_count) {
1730                 bcm_bprintf(strbuf, "pktgen config and count:\n");
1731                 bcm_bprintf(strbuf,
1732                             "freq %d count %d print %d total %d min %d len %d\n",
1733                             bus->pktgen_freq, bus->pktgen_count,
1734                             bus->pktgen_print, bus->pktgen_total,
1735                             bus->pktgen_minlen, bus->pktgen_maxlen);
1736                 bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
1737                             bus->pktgen_sent, bus->pktgen_rcvd,
1738                             bus->pktgen_fail);
1739         }
1740 #endif                          /* SDTEST */
1741 #ifdef DHD_DEBUG
1742         bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
1743                     bus->dpc_sched,
1744                     (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
1745         bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
1746                     bus->roundup);
1747 #endif                          /* DHD_DEBUG */
1748         bcm_bprintf(strbuf,
1749                     "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
1750                     bus->clkstate, bus->activity, bus->idletime, bus->idlecount,
1751                     bus->sleeping);
1752 }
1753
1754 void dhd_bus_clearcounts(dhd_pub_t *dhdp)
1755 {
1756         dhd_bus_t *bus = (dhd_bus_t *) dhdp->bus;
1757
1758         bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
1759         bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
1760         bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
1761         bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
1762         bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
1763         bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
1764 }
1765
1766 #ifdef SDTEST
1767 static int dhdsdio_pktgen_get(dhd_bus_t *bus, u8 *arg)
1768 {
1769         dhd_pktgen_t pktgen;
1770
1771         pktgen.version = DHD_PKTGEN_VERSION;
1772         pktgen.freq = bus->pktgen_freq;
1773         pktgen.count = bus->pktgen_count;
1774         pktgen.print = bus->pktgen_print;
1775         pktgen.total = bus->pktgen_total;
1776         pktgen.minlen = bus->pktgen_minlen;
1777         pktgen.maxlen = bus->pktgen_maxlen;
1778         pktgen.numsent = bus->pktgen_sent;
1779         pktgen.numrcvd = bus->pktgen_rcvd;
1780         pktgen.numfail = bus->pktgen_fail;
1781         pktgen.mode = bus->pktgen_mode;
1782         pktgen.stop = bus->pktgen_stop;
1783
1784         memcpy(arg, &pktgen, sizeof(pktgen));
1785
1786         return 0;
1787 }
1788
1789 static int dhdsdio_pktgen_set(dhd_bus_t *bus, u8 *arg)
1790 {
1791         dhd_pktgen_t pktgen;
1792         uint oldcnt, oldmode;
1793
1794         memcpy(&pktgen, arg, sizeof(pktgen));
1795         if (pktgen.version != DHD_PKTGEN_VERSION)
1796                 return -EINVAL;
1797
1798         oldcnt = bus->pktgen_count;
1799         oldmode = bus->pktgen_mode;
1800
1801         bus->pktgen_freq = pktgen.freq;
1802         bus->pktgen_count = pktgen.count;
1803         bus->pktgen_print = pktgen.print;
1804         bus->pktgen_total = pktgen.total;
1805         bus->pktgen_minlen = pktgen.minlen;
1806         bus->pktgen_maxlen = pktgen.maxlen;
1807         bus->pktgen_mode = pktgen.mode;
1808         bus->pktgen_stop = pktgen.stop;
1809
1810         bus->pktgen_tick = bus->pktgen_ptick = 0;
1811         bus->pktgen_len = max(bus->pktgen_len, bus->pktgen_minlen);
1812         bus->pktgen_len = min(bus->pktgen_len, bus->pktgen_maxlen);
1813
1814         /* Clear counts for a new pktgen (mode change, or was stopped) */
1815         if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode))
1816                 bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0;
1817
1818         return 0;
1819 }
1820 #endif                          /* SDTEST */
1821
1822 static int
1823 dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
1824                  uint size)
1825 {
1826         int bcmerror = 0;
1827         u32 sdaddr;
1828         uint dsize;
1829
1830         /* Determine initial transfer parameters */
1831         sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
1832         if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
1833                 dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
1834         else
1835                 dsize = size;
1836
1837         /* Set the backplane window to include the start address */
1838         bcmerror = dhdsdio_set_siaddr_window(bus, address);
1839         if (bcmerror) {
1840                 DHD_ERROR(("%s: window change failed\n", __func__));
1841                 goto xfer_done;
1842         }
1843
1844         /* Do the transfer(s) */
1845         while (size) {
1846                 DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
1847                           __func__, (write ? "write" : "read"), dsize,
1848                           sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
1849                 bcmerror =
1850                      bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize);
1851                 if (bcmerror) {
1852                         DHD_ERROR(("%s: membytes transfer failed\n", __func__));
1853                         break;
1854                 }
1855
1856                 /* Adjust for next transfer (if any) */
1857                 size -= dsize;
1858                 if (size) {
1859                         data += dsize;
1860                         address += dsize;
1861                         bcmerror = dhdsdio_set_siaddr_window(bus, address);
1862                         if (bcmerror) {
1863                                 DHD_ERROR(("%s: window change failed\n",
1864                                            __func__));
1865                                 break;
1866                         }
1867                         sdaddr = 0;
1868                         dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
1869                 }
1870         }
1871
1872 xfer_done:
1873         /* Return the window to backplane enumeration space for core access */
1874         if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
1875                 DHD_ERROR(("%s: FAILED to set window back to 0x%x\n",
1876                            __func__, bcmsdh_cur_sbwad(bus->sdh)));
1877         }
1878
1879         return bcmerror;
1880 }
1881
1882 #ifdef DHD_DEBUG
1883 static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
1884 {
1885         u32 addr;
1886         int rv;
1887
1888         /* Read last word in memory to determine address of
1889                          sdpcm_shared structure */
1890         rv = dhdsdio_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr, 4);
1891         if (rv < 0)
1892                 return rv;
1893
1894         addr = le32_to_cpu(addr);
1895
1896         DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
1897
1898         /*
1899          * Check if addr is valid.
1900          * NVRAM length at the end of memory should have been overwritten.
1901          */
1902         if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
1903                 DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
1904                            __func__, addr));
1905                 return -EBADE;
1906         }
1907
1908         /* Read rte_shared structure */
1909         rv = dhdsdio_membytes(bus, false, addr, (u8 *) sh,
1910                               sizeof(sdpcm_shared_t));
1911         if (rv < 0)
1912                 return rv;
1913
1914         /* Endianness */
1915         sh->flags = le32_to_cpu(sh->flags);
1916         sh->trap_addr = le32_to_cpu(sh->trap_addr);
1917         sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr);
1918         sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr);
1919         sh->assert_line = le32_to_cpu(sh->assert_line);
1920         sh->console_addr = le32_to_cpu(sh->console_addr);
1921         sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
1922
1923         if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
1924                 DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
1925                            "is different than sdpcm_shared version %d in dongle\n",
1926                            __func__, SDPCM_SHARED_VERSION,
1927                            sh->flags & SDPCM_SHARED_VERSION_MASK));
1928                 return -EBADE;
1929         }
1930
1931         return 0;
1932 }
1933
1934 static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
1935 {
1936         int bcmerror = 0;
1937         uint msize = 512;
1938         char *mbuffer = NULL;
1939         uint maxstrlen = 256;
1940         char *str = NULL;
1941         trap_t tr;
1942         sdpcm_shared_t sdpcm_shared;
1943         struct bcmstrbuf strbuf;
1944
1945         DHD_TRACE(("%s: Enter\n", __func__));
1946
1947         if (data == NULL) {
1948                 /*
1949                  * Called after a rx ctrl timeout. "data" is NULL.
1950                  * allocate memory to trace the trap or assert.
1951                  */
1952                 size = msize;
1953                 mbuffer = data = kmalloc(msize, GFP_ATOMIC);
1954                 if (mbuffer == NULL) {
1955                         DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__,
1956                                    msize));
1957                         bcmerror = -ENOMEM;
1958                         goto done;
1959                 }
1960         }
1961
1962         str = kmalloc(maxstrlen, GFP_ATOMIC);
1963         if (str == NULL) {
1964                 DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
1965                 bcmerror = -ENOMEM;
1966                 goto done;
1967         }
1968
1969         bcmerror = dhdsdio_readshared(bus, &sdpcm_shared);
1970         if (bcmerror < 0)
1971                 goto done;
1972
1973         bcm_binit(&strbuf, data, size);
1974
1975         bcm_bprintf(&strbuf,
1976                     "msgtrace address : 0x%08X\nconsole address  : 0x%08X\n",
1977                     sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
1978
1979         if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
1980                 /* NOTE: Misspelled assert is intentional - DO NOT FIX.
1981                  * (Avoids conflict with real asserts for programmatic
1982                  * parsing of output.)
1983                  */
1984                 bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
1985         }
1986
1987         if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) ==
1988             0) {
1989                 /* NOTE: Misspelled assert is intentional - DO NOT FIX.
1990                  * (Avoids conflict with real asserts for programmatic
1991                  * parsing of output.)
1992                  */
1993                 bcm_bprintf(&strbuf, "No trap%s in dongle",
1994                             (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
1995                             ? "/assrt" : "");
1996         } else {
1997                 if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
1998                         /* Download assert */
1999                         bcm_bprintf(&strbuf, "Dongle assert");
2000                         if (sdpcm_shared.assert_exp_addr != 0) {
2001                                 str[0] = '\0';
2002                                 bcmerror = dhdsdio_membytes(bus, false,
2003                                                 sdpcm_shared.assert_exp_addr,
2004                                                 (u8 *) str, maxstrlen);
2005                                 if (bcmerror < 0)
2006                                         goto done;
2007
2008                                 str[maxstrlen - 1] = '\0';
2009                                 bcm_bprintf(&strbuf, " expr \"%s\"", str);
2010                         }
2011
2012                         if (sdpcm_shared.assert_file_addr != 0) {
2013                                 str[0] = '\0';
2014                                 bcmerror = dhdsdio_membytes(bus, false,
2015                                                 sdpcm_shared.assert_file_addr,
2016                                                 (u8 *) str, maxstrlen);
2017                                 if (bcmerror < 0)
2018                                         goto done;
2019
2020                                 str[maxstrlen - 1] = '\0';
2021                                 bcm_bprintf(&strbuf, " file \"%s\"", str);
2022                         }
2023
2024                         bcm_bprintf(&strbuf, " line %d ",
2025                                     sdpcm_shared.assert_line);
2026                 }
2027
2028                 if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
2029                         bcmerror = dhdsdio_membytes(bus, false,
2030                                         sdpcm_shared.trap_addr, (u8 *)&tr,
2031                                         sizeof(trap_t));
2032                         if (bcmerror < 0)
2033                                 goto done;
2034
2035                         bcm_bprintf(&strbuf,
2036                                     "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
2037                                     "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
2038                                     "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
2039                                     tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13,
2040                                     tr.r14, tr.pc, sdpcm_shared.trap_addr,
2041                                     tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5,
2042                                     tr.r6, tr.r7);
2043                 }
2044         }
2045
2046         if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP))
2047                 DHD_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
2048
2049 #ifdef DHD_DEBUG
2050         if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
2051                 /* Mem dump to a file on device */
2052                 dhdsdio_mem_dump(bus);
2053         }
2054 #endif                          /* DHD_DEBUG */
2055
2056 done:
2057         kfree(mbuffer);
2058         kfree(str);
2059
2060         return bcmerror;
2061 }
2062
2063 static int dhdsdio_mem_dump(dhd_bus_t *bus)
2064 {
2065         int ret = 0;
2066         int size;               /* Full mem size */
2067         int start = 0;          /* Start address */
2068         int read_size = 0;      /* Read size of each iteration */
2069         u8 *buf = NULL, *databuf = NULL;
2070
2071         /* Get full mem size */
2072         size = bus->ramsize;
2073         buf = kmalloc(size, GFP_ATOMIC);
2074         if (!buf) {
2075                 DHD_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
2076                 return -1;
2077         }
2078
2079         /* Read mem content */
2080         printk(KERN_DEBUG "Dump dongle memory");
2081         databuf = buf;
2082         while (size) {
2083                 read_size = min(MEMBLOCK, size);
2084                 ret = dhdsdio_membytes(bus, false, start, databuf, read_size);
2085                 if (ret) {
2086                         DHD_ERROR(("%s: Error membytes %d\n", __func__, ret));
2087                         kfree(buf);
2088                         return -1;
2089                 }
2090                 printk(".");
2091
2092                 /* Decrement size and increment start address */
2093                 size -= read_size;
2094                 start += read_size;
2095                 databuf += read_size;
2096         }
2097         printk(KERN_DEBUG "Done\n");
2098
2099         /* free buf before return !!! */
2100         if (write_to_file(bus->dhd, buf, bus->ramsize)) {
2101                 DHD_ERROR(("%s: Error writing to files\n", __func__));
2102                 return -1;
2103         }
2104
2105         /* buf free handled in write_to_file, not here */
2106         return 0;
2107 }
2108
2109 #define CONSOLE_LINE_MAX        192
2110
2111 static int dhdsdio_readconsole(dhd_bus_t *bus)
2112 {
2113         dhd_console_t *c = &bus->console;
2114         u8 line[CONSOLE_LINE_MAX], ch;
2115         u32 n, idx, addr;
2116         int rv;
2117
2118         /* Don't do anything until FWREADY updates console address */
2119         if (bus->console_addr == 0)
2120                 return 0;
2121
2122         /* Read console log struct */
2123         addr = bus->console_addr + offsetof(rte_cons_t, log);
2124         rv = dhdsdio_membytes(bus, false, addr, (u8 *)&c->log,
2125                                 sizeof(c->log));
2126         if (rv < 0)
2127                 return rv;
2128
2129         /* Allocate console buffer (one time only) */
2130         if (c->buf == NULL) {
2131                 c->bufsize = le32_to_cpu(c->log.buf_size);
2132                 c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
2133                 if (c->buf == NULL)
2134                         return -ENOMEM;
2135         }
2136
2137         idx = le32_to_cpu(c->log.idx);
2138
2139         /* Protect against corrupt value */
2140         if (idx > c->bufsize)
2141                 return -EBADE;
2142
2143         /* Skip reading the console buffer if the index pointer
2144          has not moved */
2145         if (idx == c->last)
2146                 return 0;
2147
2148         /* Read the console buffer */
2149         addr = le32_to_cpu(c->log.buf);
2150         rv = dhdsdio_membytes(bus, false, addr, c->buf, c->bufsize);
2151         if (rv < 0)
2152                 return rv;
2153
2154         while (c->last != idx) {
2155                 for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
2156                         if (c->last == idx) {
2157                                 /* This would output a partial line.
2158                                  * Instead, back up
2159                                  * the buffer pointer and output this
2160                                  * line next time around.
2161                                  */
2162                                 if (c->last >= n)
2163                                         c->last -= n;
2164                                 else
2165                                         c->last = c->bufsize - n;
2166                                 goto break2;
2167                         }
2168                         ch = c->buf[c->last];
2169                         c->last = (c->last + 1) % c->bufsize;
2170                         if (ch == '\n')
2171                                 break;
2172                         line[n] = ch;
2173                 }
2174
2175                 if (n > 0) {
2176                         if (line[n - 1] == '\r')
2177                                 n--;
2178                         line[n] = 0;
2179                         printk(KERN_DEBUG "CONSOLE: %s\n", line);
2180                 }
2181         }
2182 break2:
2183
2184         return 0;
2185 }
2186 #endif                          /* DHD_DEBUG */
2187
2188 int dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
2189 {
2190         int bcmerror = 0;
2191
2192         DHD_TRACE(("%s: Enter\n", __func__));
2193
2194         /* Basic sanity checks */
2195         if (bus->dhd->up) {
2196                 bcmerror = -EISCONN;
2197                 goto err;
2198         }
2199         if (!len) {
2200                 bcmerror = -EOVERFLOW;
2201                 goto err;
2202         }
2203
2204         /* Free the old ones and replace with passed variables */
2205         kfree(bus->vars);
2206
2207         bus->vars = kmalloc(len, GFP_ATOMIC);
2208         bus->varsz = bus->vars ? len : 0;
2209         if (bus->vars == NULL) {
2210                 bcmerror = -ENOMEM;
2211                 goto err;
2212         }
2213
2214         /* Copy the passed variables, which should include the
2215                  terminating double-null */
2216         memcpy(bus->vars, arg, bus->varsz);
2217 err:
2218         return bcmerror;
2219 }
2220
2221 static int
2222 dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
2223                 const char *name, void *params, int plen, void *arg, int len,
2224                 int val_size)
2225 {
2226         int bcmerror = 0;
2227         s32 int_val = 0;
2228         bool bool_val = 0;
2229
2230         DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p "
2231                 "len %d val_size %d\n",
2232                 __func__, actionid, name, params, plen, arg, len, val_size));
2233
2234         bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
2235         if (bcmerror != 0)
2236                 goto exit;
2237
2238         if (plen >= (int)sizeof(int_val))
2239                 memcpy(&int_val, params, sizeof(int_val));
2240
2241         bool_val = (int_val != 0) ? true : false;
2242
2243         /* Some ioctls use the bus */
2244         dhd_os_sdlock(bus->dhd);
2245
2246         /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
2247         if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
2248                                         actionid == IOV_GVAL(IOV_DEVRESET))) {
2249                 bcmerror = -EPERM;
2250                 goto exit;
2251         }
2252
2253         /* Handle sleep stuff before any clock mucking */
2254         if (vi->varid == IOV_SLEEP) {
2255                 if (IOV_ISSET(actionid)) {
2256                         bcmerror = dhdsdio_bussleep(bus, bool_val);
2257                 } else {
2258                         int_val = (s32) bus->sleeping;
2259                         memcpy(arg, &int_val, val_size);
2260                 }
2261                 goto exit;
2262         }
2263
2264         /* Request clock to allow SDIO accesses */
2265         if (!bus->dhd->dongle_reset) {
2266                 BUS_WAKE(bus);
2267                 dhdsdio_clkctl(bus, CLK_AVAIL, false);
2268         }
2269
2270         switch (actionid) {
2271         case IOV_GVAL(IOV_INTR):
2272                 int_val = (s32) bus->intr;
2273                 memcpy(arg, &int_val, val_size);
2274                 break;
2275
2276         case IOV_SVAL(IOV_INTR):
2277                 bus->intr = bool_val;
2278                 bus->intdis = false;
2279                 if (bus->dhd->up) {
2280                         if (bus->intr) {
2281                                 DHD_INTR(("%s: enable SDIO device interrupts\n",
2282                                           __func__));
2283                                 bcmsdh_intr_enable(bus->sdh);
2284                         } else {
2285                                 DHD_INTR(("%s: disable SDIO interrupts\n",
2286                                           __func__));
2287                                 bcmsdh_intr_disable(bus->sdh);
2288                         }
2289                 }
2290                 break;
2291
2292         case IOV_GVAL(IOV_POLLRATE):
2293                 int_val = (s32) bus->pollrate;
2294                 memcpy(arg, &int_val, val_size);
2295                 break;
2296
2297         case IOV_SVAL(IOV_POLLRATE):
2298                 bus->pollrate = (uint) int_val;
2299                 bus->poll = (bus->pollrate != 0);
2300                 break;
2301
2302         case IOV_GVAL(IOV_IDLETIME):
2303                 int_val = bus->idletime;
2304                 memcpy(arg, &int_val, val_size);
2305                 break;
2306
2307         case IOV_SVAL(IOV_IDLETIME):
2308                 if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE))
2309                         bcmerror = -EINVAL;
2310                 else
2311                         bus->idletime = int_val;
2312                 break;
2313
2314         case IOV_GVAL(IOV_IDLECLOCK):
2315                 int_val = (s32) bus->idleclock;
2316                 memcpy(arg, &int_val, val_size);
2317                 break;
2318
2319         case IOV_SVAL(IOV_IDLECLOCK):
2320                 bus->idleclock = int_val;
2321                 break;
2322
2323         case IOV_GVAL(IOV_SD1IDLE):
2324                 int_val = (s32) sd1idle;
2325                 memcpy(arg, &int_val, val_size);
2326                 break;
2327
2328         case IOV_SVAL(IOV_SD1IDLE):
2329                 sd1idle = bool_val;
2330                 break;
2331
2332         case IOV_SVAL(IOV_MEMBYTES):
2333         case IOV_GVAL(IOV_MEMBYTES):
2334                 {
2335                         u32 address;
2336                         uint size, dsize;
2337                         u8 *data;
2338
2339                         bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
2340
2341                         ASSERT(plen >= 2 * sizeof(int));
2342
2343                         address = (u32) int_val;
2344                         memcpy(&int_val, (char *)params + sizeof(int_val),
2345                                sizeof(int_val));
2346                         size = (uint) int_val;
2347
2348                         /* Do some validation */
2349                         dsize = set ? plen - (2 * sizeof(int)) : len;
2350                         if (dsize < size) {
2351                                 DHD_ERROR(("%s: error on %s membytes, addr "
2352                                 "0x%08x size %d dsize %d\n",
2353                                 __func__, (set ? "set" : "get"),
2354                                 address, size, dsize));
2355                                 bcmerror = -EINVAL;
2356                                 break;
2357                         }
2358
2359                         DHD_INFO(("%s: Request to %s %d bytes at address "
2360                         "0x%08x\n",
2361                         __func__, (set ? "write" : "read"), size, address));
2362
2363                         /* If we know about SOCRAM, check for a fit */
2364                         if ((bus->orig_ramsize) &&
2365                             ((address > bus->orig_ramsize)
2366                              || (address + size > bus->orig_ramsize))) {
2367                                 DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d "
2368                                 "bytes at 0x%08x\n",
2369                                 __func__, bus->orig_ramsize, size, address));
2370                                 bcmerror = -EINVAL;
2371                                 break;
2372                         }
2373
2374                         /* Generate the actual data pointer */
2375                         data =
2376                             set ? (u8 *) params +
2377                             2 * sizeof(int) : (u8 *) arg;
2378
2379                         /* Call to do the transfer */
2380                         bcmerror =
2381                             dhdsdio_membytes(bus, set, address, data, size);
2382
2383                         break;
2384                 }
2385
2386         case IOV_GVAL(IOV_MEMSIZE):
2387                 int_val = (s32) bus->ramsize;
2388                 memcpy(arg, &int_val, val_size);
2389                 break;
2390
2391         case IOV_GVAL(IOV_SDIOD_DRIVE):
2392                 int_val = (s32) dhd_sdiod_drive_strength;
2393                 memcpy(arg, &int_val, val_size);
2394                 break;
2395
2396         case IOV_SVAL(IOV_SDIOD_DRIVE):
2397                 dhd_sdiod_drive_strength = int_val;
2398                 dhdsdio_sdiod_drive_strength_init(bus,
2399                                              dhd_sdiod_drive_strength);
2400                 break;
2401
2402         case IOV_SVAL(IOV_DOWNLOAD):
2403                 bcmerror = dhdsdio_download_state(bus, bool_val);
2404                 break;
2405
2406         case IOV_SVAL(IOV_VARS):
2407                 bcmerror = dhdsdio_downloadvars(bus, arg, len);
2408                 break;
2409
2410         case IOV_GVAL(IOV_READAHEAD):
2411                 int_val = (s32) dhd_readahead;
2412                 memcpy(arg, &int_val, val_size);
2413                 break;
2414
2415         case IOV_SVAL(IOV_READAHEAD):
2416                 if (bool_val && !dhd_readahead)
2417                         bus->nextlen = 0;
2418                 dhd_readahead = bool_val;
2419                 break;
2420
2421         case IOV_GVAL(IOV_SDRXCHAIN):
2422                 int_val = (s32) bus->use_rxchain;
2423                 memcpy(arg, &int_val, val_size);
2424                 break;
2425
2426         case IOV_SVAL(IOV_SDRXCHAIN):
2427                 if (bool_val && !bus->sd_rxchain)
2428                         bcmerror = -ENOTSUPP;
2429                 else
2430                         bus->use_rxchain = bool_val;
2431                 break;
2432         case IOV_GVAL(IOV_ALIGNCTL):
2433                 int_val = (s32) dhd_alignctl;
2434                 memcpy(arg, &int_val, val_size);
2435                 break;
2436
2437         case IOV_SVAL(IOV_ALIGNCTL):
2438                 dhd_alignctl = bool_val;
2439                 break;
2440
2441         case IOV_GVAL(IOV_SDALIGN):
2442                 int_val = DHD_SDALIGN;
2443                 memcpy(arg, &int_val, val_size);
2444                 break;
2445
2446 #ifdef DHD_DEBUG
2447         case IOV_GVAL(IOV_VARS):
2448                 if (bus->varsz < (uint) len)
2449                         memcpy(arg, bus->vars, bus->varsz);
2450                 else
2451                         bcmerror = -EOVERFLOW;
2452                 break;
2453 #endif                          /* DHD_DEBUG */
2454
2455 #ifdef DHD_DEBUG
2456         case IOV_GVAL(IOV_SDREG):
2457                 {
2458                         sdreg_t *sd_ptr;
2459                         u32 addr, size;
2460
2461                         sd_ptr = (sdreg_t *) params;
2462
2463                         addr = (unsigned long)bus->regs + sd_ptr->offset;
2464                         size = sd_ptr->func;
2465                         int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
2466                         if (bcmsdh_regfail(bus->sdh))
2467                                 bcmerror = -EIO;
2468                         memcpy(arg, &int_val, sizeof(s32));
2469                         break;
2470                 }
2471
2472         case IOV_SVAL(IOV_SDREG):
2473                 {
2474                         sdreg_t *sd_ptr;
2475                         u32 addr, size;
2476
2477                         sd_ptr = (sdreg_t *) params;
2478
2479                         addr = (unsigned long)bus->regs + sd_ptr->offset;
2480                         size = sd_ptr->func;
2481                         bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
2482                         if (bcmsdh_regfail(bus->sdh))
2483                                 bcmerror = -EIO;
2484                         break;
2485                 }
2486
2487                 /* Same as above, but offset is not backplane
2488                  (not SDIO core) */
2489         case IOV_GVAL(IOV_SBREG):
2490                 {
2491                         sdreg_t sdreg;
2492                         u32 addr, size;
2493
2494                         memcpy(&sdreg, params, sizeof(sdreg));
2495
2496                         addr = SI_ENUM_BASE + sdreg.offset;
2497                         size = sdreg.func;
2498                         int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
2499                         if (bcmsdh_regfail(bus->sdh))
2500                                 bcmerror = -EIO;
2501                         memcpy(arg, &int_val, sizeof(s32));
2502                         break;
2503                 }
2504
2505         case IOV_SVAL(IOV_SBREG):
2506                 {
2507                         sdreg_t sdreg;
2508                         u32 addr, size;
2509
2510                         memcpy(&sdreg, params, sizeof(sdreg));
2511
2512                         addr = SI_ENUM_BASE + sdreg.offset;
2513                         size = sdreg.func;
2514                         bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
2515                         if (bcmsdh_regfail(bus->sdh))
2516                                 bcmerror = -EIO;
2517                         break;
2518                 }
2519
2520         case IOV_GVAL(IOV_SDCIS):
2521                 {
2522                         *(char *)arg = 0;
2523
2524                         strcat(arg, "\nFunc 0\n");
2525                         bcmsdh_cis_read(bus->sdh, 0x10,
2526                                         (u8 *) arg + strlen(arg),
2527                                         SBSDIO_CIS_SIZE_LIMIT);
2528                         strcat(arg, "\nFunc 1\n");
2529                         bcmsdh_cis_read(bus->sdh, 0x11,
2530                                         (u8 *) arg + strlen(arg),
2531                                         SBSDIO_CIS_SIZE_LIMIT);
2532                         strcat(arg, "\nFunc 2\n");
2533                         bcmsdh_cis_read(bus->sdh, 0x12,
2534                                         (u8 *) arg + strlen(arg),
2535                                         SBSDIO_CIS_SIZE_LIMIT);
2536                         break;
2537                 }
2538
2539         case IOV_GVAL(IOV_FORCEEVEN):
2540                 int_val = (s32) forcealign;
2541                 memcpy(arg, &int_val, val_size);
2542                 break;
2543
2544         case IOV_SVAL(IOV_FORCEEVEN):
2545                 forcealign = bool_val;
2546                 break;
2547
2548         case IOV_GVAL(IOV_TXBOUND):
2549                 int_val = (s32) dhd_txbound;
2550                 memcpy(arg, &int_val, val_size);
2551                 break;
2552
2553         case IOV_SVAL(IOV_TXBOUND):
2554                 dhd_txbound = (uint) int_val;
2555                 break;
2556
2557         case IOV_GVAL(IOV_RXBOUND):
2558                 int_val = (s32) dhd_rxbound;
2559                 memcpy(arg, &int_val, val_size);
2560                 break;
2561
2562         case IOV_SVAL(IOV_RXBOUND):
2563                 dhd_rxbound = (uint) int_val;
2564                 break;
2565
2566         case IOV_GVAL(IOV_TXMINMAX):
2567                 int_val = (s32) dhd_txminmax;
2568                 memcpy(arg, &int_val, val_size);
2569                 break;
2570
2571         case IOV_SVAL(IOV_TXMINMAX):
2572                 dhd_txminmax = (uint) int_val;
2573                 break;
2574 #endif                          /* DHD_DEBUG */
2575
2576 #ifdef SDTEST
2577         case IOV_GVAL(IOV_EXTLOOP):
2578                 int_val = (s32) bus->ext_loop;
2579                 memcpy(arg, &int_val, val_size);
2580                 break;
2581
2582         case IOV_SVAL(IOV_EXTLOOP):
2583                 bus->ext_loop = bool_val;
2584                 break;
2585
2586         case IOV_GVAL(IOV_PKTGEN):
2587                 bcmerror = dhdsdio_pktgen_get(bus, arg);
2588                 break;
2589
2590         case IOV_SVAL(IOV_PKTGEN):
2591                 bcmerror = dhdsdio_pktgen_set(bus, arg);
2592                 break;
2593 #endif                          /* SDTEST */
2594
2595         case IOV_SVAL(IOV_DEVRESET):
2596                 DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
2597                         "busstate=%d\n",
2598                         __func__, bool_val, bus->dhd->dongle_reset,
2599                         bus->dhd->busstate));
2600
2601                 dhd_bus_devreset(bus->dhd, (u8) bool_val);
2602
2603                 break;
2604
2605         case IOV_GVAL(IOV_DEVRESET):
2606                 DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
2607
2608                 /* Get its status */
2609                 int_val = (bool) bus->dhd->dongle_reset;
2610                 memcpy(arg, &int_val, val_size);
2611
2612                 break;
2613
2614         default:
2615                 bcmerror = -ENOTSUPP;
2616                 break;
2617         }
2618
2619 exit:
2620         if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
2621                 bus->activity = false;
2622                 dhdsdio_clkctl(bus, CLK_NONE, true);
2623         }
2624
2625         dhd_os_sdunlock(bus->dhd);
2626
2627         if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
2628                 dhd_preinit_ioctls((dhd_pub_t *) bus->dhd);
2629
2630         return bcmerror;
2631 }
2632
2633 static int dhdsdio_write_vars(dhd_bus_t *bus)
2634 {
2635         int bcmerror = 0;
2636         u32 varsize;
2637         u32 varaddr;
2638         u8 *vbuffer;
2639         u32 varsizew;
2640 #ifdef DHD_DEBUG
2641         char *nvram_ularray;
2642 #endif                          /* DHD_DEBUG */
2643
2644         /* Even if there are no vars are to be written, we still
2645                  need to set the ramsize. */
2646         varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
2647         varaddr = (bus->ramsize - 4) - varsize;
2648
2649         if (bus->vars) {
2650                 vbuffer = kzalloc(varsize, GFP_ATOMIC);
2651                 if (!vbuffer)
2652                         return -ENOMEM;
2653
2654                 memcpy(vbuffer, bus->vars, bus->varsz);
2655
2656                 /* Write the vars list */
2657                 bcmerror =
2658                     dhdsdio_membytes(bus, true, varaddr, vbuffer, varsize);
2659 #ifdef DHD_DEBUG
2660                 /* Verify NVRAM bytes */
2661                 DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
2662                 nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
2663                 if (!nvram_ularray)
2664                         return -ENOMEM;
2665
2666                 /* Upload image to verify downloaded contents. */
2667                 memset(nvram_ularray, 0xaa, varsize);
2668
2669                 /* Read the vars list to temp buffer for comparison */
2670                 bcmerror =
2671                     dhdsdio_membytes(bus, false, varaddr, nvram_ularray,
2672                                      varsize);
2673                 if (bcmerror) {
2674                         DHD_ERROR(("%s: error %d on reading %d nvram bytes at "
2675                         "0x%08x\n", __func__, bcmerror, varsize, varaddr));
2676                 }
2677                 /* Compare the org NVRAM with the one read from RAM */
2678                 if (memcmp(vbuffer, nvram_ularray, varsize)) {
2679                         DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n",
2680                                    __func__));
2681                 } else
2682                         DHD_ERROR(("%s: Download/Upload/Compare of NVRAM ok.\n",
2683                                 __func__));
2684
2685                 kfree(nvram_ularray);
2686 #endif                          /* DHD_DEBUG */
2687
2688                 kfree(vbuffer);
2689         }
2690
2691         /* adjust to the user specified RAM */
2692         DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
2693                   bus->orig_ramsize, bus->ramsize));
2694         DHD_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
2695         varsize = ((bus->orig_ramsize - 4) - varaddr);
2696
2697         /*
2698          * Determine the length token:
2699          * Varsize, converted to words, in lower 16-bits, checksum
2700          * in upper 16-bits.
2701          */
2702         if (bcmerror) {
2703                 varsizew = 0;
2704         } else {
2705                 varsizew = varsize / 4;
2706                 varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
2707                 varsizew = cpu_to_le32(varsizew);
2708         }
2709
2710         DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
2711                   varsizew));
2712
2713         /* Write the length token to the last word */
2714         bcmerror = dhdsdio_membytes(bus, true, (bus->orig_ramsize - 4),
2715                                     (u8 *)&varsizew, 4);
2716
2717         return bcmerror;
2718 }
2719
2720 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter)
2721 {
2722         uint retries;
2723         u32 regdata;
2724         int bcmerror = 0;
2725
2726         /* To enter download state, disable ARM and reset SOCRAM.
2727          * To exit download state, simply reset ARM (default is RAM boot).
2728          */
2729         if (enter) {
2730                 bus->alp_only = true;
2731
2732                 dhdsdio_chip_disablecore(bus->sdh, bus->ci->armcorebase);
2733
2734                 dhdsdio_chip_resetcore(bus->sdh, bus->ci->ramcorebase);
2735
2736                 /* Clear the top bit of memory */
2737                 if (bus->ramsize) {
2738                         u32 zeros = 0;
2739                         dhdsdio_membytes(bus, true, bus->ramsize - 4,
2740                                          (u8 *)&zeros, 4);
2741                 }
2742         } else {
2743                 regdata = bcmsdh_reg_read(bus->sdh,
2744                         CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
2745                 regdata &= (SBTML_RESET | SBTML_REJ_MASK |
2746                         (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
2747                 if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
2748                         DHD_ERROR(("%s: SOCRAM core is down after reset?\n",
2749                                    __func__));
2750                         bcmerror = -EBADE;
2751                         goto fail;
2752                 }
2753
2754                 bcmerror = dhdsdio_write_vars(bus);
2755                 if (bcmerror) {
2756                         DHD_ERROR(("%s: no vars written to RAM\n", __func__));
2757                         bcmerror = 0;
2758                 }
2759
2760                 W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
2761
2762                 dhdsdio_chip_resetcore(bus->sdh, bus->ci->armcorebase);
2763
2764                 /* Allow HT Clock now that the ARM is running. */
2765                 bus->alp_only = false;
2766
2767                 bus->dhd->busstate = DHD_BUS_LOAD;
2768         }
2769 fail:
2770         return bcmerror;
2771 }
2772
2773 int
2774 dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
2775                  void *params, int plen, void *arg, int len, bool set)
2776 {
2777         dhd_bus_t *bus = dhdp->bus;
2778         const bcm_iovar_t *vi = NULL;
2779         int bcmerror = 0;
2780         int val_size;
2781         u32 actionid;
2782
2783         DHD_TRACE(("%s: Enter\n", __func__));
2784
2785         ASSERT(name);
2786         ASSERT(len >= 0);
2787
2788         /* Get MUST have return space */
2789         ASSERT(set || (arg && len));
2790
2791         /* Set does NOT take qualifiers */
2792         ASSERT(!set || (!params && !plen));
2793
2794         /* Look up var locally; if not found pass to host driver */
2795         vi = bcm_iovar_lookup(dhdsdio_iovars, name);
2796         if (vi == NULL) {
2797                 dhd_os_sdlock(bus->dhd);
2798
2799                 BUS_WAKE(bus);
2800
2801                 /* Turn on clock in case SD command needs backplane */
2802                 dhdsdio_clkctl(bus, CLK_AVAIL, false);
2803
2804                 bcmerror =
2805                     bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len,
2806                                     set);
2807
2808                 /* Similar check for blocksize change */
2809                 if (set && strcmp(name, "sd_blocksize") == 0) {
2810                         s32 fnum = 2;
2811                         if (bcmsdh_iovar_op
2812                             (bus->sdh, "sd_blocksize", &fnum, sizeof(s32),
2813                              &bus->blocksize, sizeof(s32),
2814                              false) != 0) {
2815                                 bus->blocksize = 0;
2816                                 DHD_ERROR(("%s: fail on %s get\n", __func__,
2817                                            "sd_blocksize"));
2818                         } else {
2819                                 DHD_INFO(("%s: noted %s update, value now %d\n",
2820                                           __func__, "sd_blocksize",
2821                                           bus->blocksize));
2822                         }
2823                 }
2824                 bus->roundup = min(max_roundup, bus->blocksize);
2825
2826                 if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
2827                         bus->activity = false;
2828                         dhdsdio_clkctl(bus, CLK_NONE, true);
2829                 }
2830
2831                 dhd_os_sdunlock(bus->dhd);
2832                 goto exit;
2833         }
2834
2835         DHD_CTL(("%s: %s %s, len %d plen %d\n", __func__,
2836                  name, (set ? "set" : "get"), len, plen));
2837
2838         /* set up 'params' pointer in case this is a set command so that
2839          * the convenience int and bool code can be common to set and get
2840          */
2841         if (params == NULL) {
2842                 params = arg;
2843                 plen = len;
2844         }
2845
2846         if (vi->type == IOVT_VOID)
2847                 val_size = 0;
2848         else if (vi->type == IOVT_BUFFER)
2849                 val_size = len;
2850         else
2851                 /* all other types are integer sized */
2852                 val_size = sizeof(int);
2853
2854         actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
2855         bcmerror =
2856             dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len,
2857                             val_size);
2858
2859 exit:
2860         return bcmerror;
2861 }
2862
2863 void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
2864 {
2865         u32 local_hostintmask;
2866         u8 saveclk;
2867         uint retries;
2868         int err;
2869
2870         DHD_TRACE(("%s: Enter\n", __func__));
2871
2872         if (enforce_mutex)
2873                 dhd_os_sdlock(bus->dhd);
2874
2875         BUS_WAKE(bus);
2876
2877         /* Enable clock for device interrupts */
2878         dhdsdio_clkctl(bus, CLK_AVAIL, false);
2879
2880         /* Disable and clear interrupts at the chip level also */
2881         W_SDREG(0, &bus->regs->hostintmask, retries);
2882         local_hostintmask = bus->hostintmask;
2883         bus->hostintmask = 0;
2884
2885         /* Change our idea of bus state */
2886         bus->dhd->busstate = DHD_BUS_DOWN;
2887
2888         /* Force clocks on backplane to be sure F2 interrupt propagates */
2889         saveclk =
2890             bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
2891                             &err);
2892         if (!err) {
2893                 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
2894                                  (saveclk | SBSDIO_FORCE_HT), &err);
2895         }
2896         if (err) {
2897                 DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
2898                            __func__, err));
2899         }
2900
2901         /* Turn off the bus (F2), free any pending packets */
2902         DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
2903         bcmsdh_intr_disable(bus->sdh);
2904         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
2905                          SDIO_FUNC_ENABLE_1, NULL);
2906
2907         /* Clear any pending interrupts now that F2 is disabled */
2908         W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
2909
2910         /* Turn off the backplane clock (only) */
2911         dhdsdio_clkctl(bus, CLK_SDONLY, false);
2912
2913         /* Clear the data packet queues */
2914         bcm_pktq_flush(&bus->txq, true, NULL, NULL);
2915
2916         /* Clear any held glomming stuff */
2917         if (bus->glomd)
2918                 bcm_pkt_buf_free_skb(bus->glomd);
2919
2920         if (bus->glom)
2921                 bcm_pkt_buf_free_skb(bus->glom);
2922
2923         bus->glom = bus->glomd = NULL;
2924
2925         /* Clear rx control and wake any waiters */
2926         bus->rxlen = 0;
2927         dhd_os_ioctl_resp_wake(bus->dhd);
2928
2929         /* Reset some F2 state stuff */
2930         bus->rxskip = false;
2931         bus->tx_seq = bus->rx_seq = 0;
2932
2933         if (enforce_mutex)
2934                 dhd_os_sdunlock(bus->dhd);
2935 }
2936
2937 int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
2938 {
2939         dhd_bus_t *bus = dhdp->bus;
2940         dhd_timeout_t tmo;
2941         uint retries = 0;
2942         u8 ready, enable;
2943         int err, ret = 0;
2944         u8 saveclk;
2945
2946         DHD_TRACE(("%s: Enter\n", __func__));
2947
2948         ASSERT(bus->dhd);
2949         if (!bus->dhd)
2950                 return 0;
2951
2952         if (enforce_mutex)
2953                 dhd_os_sdlock(bus->dhd);
2954
2955         /* Make sure backplane clock is on, needed to generate F2 interrupt */
2956         dhdsdio_clkctl(bus, CLK_AVAIL, false);
2957         if (bus->clkstate != CLK_AVAIL)
2958                 goto exit;
2959
2960         /* Force clocks on backplane to be sure F2 interrupt propagates */
2961         saveclk =
2962             bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
2963                             &err);
2964         if (!err) {
2965                 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
2966                                  (saveclk | SBSDIO_FORCE_HT), &err);
2967         }
2968         if (err) {
2969                 DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
2970                            __func__, err));
2971                 goto exit;
2972         }
2973
2974         /* Enable function 2 (frame transfers) */
2975         W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
2976                 &bus->regs->tosbmailboxdata, retries);
2977         enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
2978
2979         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
2980
2981         /* Give the dongle some time to do its thing and set IOR2 */
2982         dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
2983
2984         ready = 0;
2985         while (ready != enable && !dhd_timeout_expired(&tmo))
2986                 ready =
2987                     bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY,
2988                                     NULL);
2989
2990         DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
2991                   __func__, enable, ready, tmo.elapsed));
2992
2993         /* If F2 successfully enabled, set core and enable interrupts */
2994         if (ready == enable) {
2995                 /* Set up the interrupt mask and enable interrupts */
2996                 bus->hostintmask = HOSTINTMASK;
2997                 W_SDREG(bus->hostintmask,
2998                         (unsigned int *)CORE_BUS_REG(bus->ci->buscorebase,
2999                         hostintmask), retries);
3000
3001                 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
3002                                  (u8) watermark, &err);
3003
3004                 /* Set bus state according to enable result */
3005                 dhdp->busstate = DHD_BUS_DATA;
3006
3007                 /* bcmsdh_intr_unmask(bus->sdh); */
3008
3009                 bus->intdis = false;
3010                 if (bus->intr) {
3011                         DHD_INTR(("%s: enable SDIO device interrupts\n",
3012                                   __func__));
3013                         bcmsdh_intr_enable(bus->sdh);
3014                 } else {
3015                         DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
3016                         bcmsdh_intr_disable(bus->sdh);
3017                 }
3018
3019         }
3020
3021         else {
3022                 /* Disable F2 again */
3023                 enable = SDIO_FUNC_ENABLE_1;
3024                 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable,
3025                                  NULL);
3026         }
3027
3028         /* Restore previous clock setting */
3029         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
3030                          saveclk, &err);
3031
3032         /* If we didn't come up, turn off backplane clock */
3033         if (dhdp->busstate != DHD_BUS_DATA)
3034                 dhdsdio_clkctl(bus, CLK_NONE, false);
3035
3036 exit:
3037         if (enforce_mutex)
3038                 dhd_os_sdunlock(bus->dhd);
3039
3040         return ret;
3041 }
3042
3043 static void dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
3044 {
3045         bcmsdh_info_t *sdh = bus->sdh;
3046         sdpcmd_regs_t *regs = bus->regs;
3047         uint retries = 0;
3048         u16 lastrbc;
3049         u8 hi, lo;
3050         int err;
3051
3052         DHD_ERROR(("%s: %sterminate frame%s\n", __func__,
3053                    (abort ? "abort command, " : ""),
3054                    (rtx ? ", send NAK" : "")));
3055
3056         if (abort)
3057                 bcmsdh_abort(sdh, SDIO_FUNC_2);
3058
3059         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
3060                          &err);
3061         bus->f1regdata++;
3062
3063         /* Wait until the packet has been flushed (device/FIFO stable) */
3064         for (lastrbc = retries = 0xffff; retries > 0; retries--) {
3065                 hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI,
3066                                      NULL);
3067                 lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO,
3068                                      NULL);
3069                 bus->f1regdata += 2;
3070
3071                 if ((hi == 0) && (lo == 0))
3072                         break;
3073
3074                 if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
3075                         DHD_ERROR(("%s: count growing: last 0x%04x now "
3076                                 "0x%04x\n",
3077                                 __func__, lastrbc, ((hi << 8) + lo)));
3078                 }
3079                 lastrbc = (hi << 8) + lo;
3080         }
3081
3082         if (!retries) {
3083                 DHD_ERROR(("%s: count never zeroed: last 0x%04x\n",
3084                            __func__, lastrbc));
3085         } else {
3086                 DHD_INFO(("%s: flush took %d iterations\n", __func__,
3087                           (0xffff - retries)));
3088         }
3089
3090         if (rtx) {
3091                 bus->rxrtx++;
3092                 W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
3093                 bus->f1regdata++;
3094                 if (retries <= retry_limit)
3095                         bus->rxskip = true;
3096         }
3097
3098         /* Clear partial in any case */
3099         bus->nextlen = 0;
3100
3101         /* If we can't reach the device, signal failure */
3102         if (err || bcmsdh_regfail(sdh))
3103                 bus->dhd->busstate = DHD_BUS_DOWN;
3104 }
3105
3106 static void
3107 dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
3108 {
3109         bcmsdh_info_t *sdh = bus->sdh;
3110         uint rdlen, pad;
3111
3112         int sdret;
3113
3114         DHD_TRACE(("%s: Enter\n", __func__));
3115
3116         /* Control data already received in aligned rxctl */
3117         if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
3118                 goto gotpkt;
3119
3120         ASSERT(bus->rxbuf);
3121         /* Set rxctl for frame (w/optional alignment) */
3122         bus->rxctl = bus->rxbuf;
3123         if (dhd_alignctl) {
3124                 bus->rxctl += firstread;
3125                 pad = ((unsigned long)bus->rxctl % DHD_SDALIGN);
3126                 if (pad)
3127                         bus->rxctl += (DHD_SDALIGN - pad);
3128                 bus->rxctl -= firstread;
3129         }
3130         ASSERT(bus->rxctl >= bus->rxbuf);
3131
3132         /* Copy the already-read portion over */
3133         memcpy(bus->rxctl, hdr, firstread);
3134         if (len <= firstread)
3135                 goto gotpkt;
3136
3137         /* Copy the full data pkt in gSPI case and process ioctl. */
3138         if (bus->bus == SPI_BUS) {
3139                 memcpy(bus->rxctl, hdr, len);
3140                 goto gotpkt;
3141         }
3142
3143         /* Raise rdlen to next SDIO block to avoid tail command */
3144         rdlen = len - firstread;
3145         if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
3146                 pad = bus->blocksize - (rdlen % bus->blocksize);
3147                 if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
3148                     ((len + pad) < bus->dhd->maxctl))
3149                         rdlen += pad;
3150         } else if (rdlen % DHD_SDALIGN) {
3151                 rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
3152         }
3153
3154         /* Satisfy length-alignment requirements */
3155         if (forcealign && (rdlen & (ALIGNMENT - 1)))
3156                 rdlen = roundup(rdlen, ALIGNMENT);
3157
3158         /* Drop if the read is too big or it exceeds our maximum */
3159         if ((rdlen + firstread) > bus->dhd->maxctl) {
3160                 DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
3161                            __func__, rdlen, bus->dhd->maxctl));
3162                 bus->dhd->rx_errors++;
3163                 dhdsdio_rxfail(bus, false, false);
3164                 goto done;
3165         }
3166
3167         if ((len - doff) > bus->dhd->maxctl) {
3168                 DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
3169                         "%d-byte limit\n",
3170                         __func__, len, (len - doff), bus->dhd->maxctl));
3171                 bus->dhd->rx_errors++;
3172                 bus->rx_toolong++;
3173                 dhdsdio_rxfail(bus, false, false);
3174                 goto done;
3175         }
3176
3177         /* Read remainder of frame body into the rxctl buffer */
3178         sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
3179                                 F2SYNC, (bus->rxctl + firstread), rdlen,
3180                                 NULL, NULL, NULL);
3181         bus->f2rxdata++;
3182         ASSERT(sdret != -BCME_PENDING);
3183
3184         /* Control frame failures need retransmission */
3185         if (sdret < 0) {
3186                 DHD_ERROR(("%s: read %d control bytes failed: %d\n",
3187                            __func__, rdlen, sdret));
3188                 bus->rxc_errors++;      /* dhd.rx_ctlerrs is higher level */
3189                 dhdsdio_rxfail(bus, true, true);
3190                 goto done;
3191         }
3192
3193 gotpkt:
3194
3195 #ifdef DHD_DEBUG
3196         if (DHD_BYTES_ON() && DHD_CTL_ON()) {
3197                 printk(KERN_DEBUG "RxCtrl:\n");
3198                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
3199         }
3200 #endif
3201
3202         /* Point to valid data and indicate its length */
3203         bus->rxctl += doff;
3204         bus->rxlen = len - doff;
3205
3206 done:
3207         /* Awake any waiters */
3208         dhd_os_ioctl_resp_wake(bus->dhd);
3209 }
3210
3211 static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
3212 {
3213         u16 dlen, totlen;
3214         u8 *dptr, num = 0;
3215
3216         u16 sublen, check;
3217         struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
3218
3219         int errcode;
3220         u8 chan, seq, doff, sfdoff;
3221         u8 txmax;
3222
3223         int ifidx = 0;
3224         bool usechain = bus->use_rxchain;
3225
3226         /* If packets, issue read(s) and send up packet chain */
3227         /* Return sequence numbers consumed? */
3228
3229         DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd,
3230                    bus->glom));
3231
3232         /* If there's a descriptor, generate the packet chain */
3233         if (bus->glomd) {
3234                 dhd_os_sdlock_rxq(bus->dhd);
3235
3236                 pfirst = plast = pnext = NULL;
3237                 dlen = (u16) (bus->glomd->len);
3238                 dptr = bus->glomd->data;
3239                 if (!dlen || (dlen & 1)) {
3240                         DHD_ERROR(("%s: bad glomd len(%d), ignore descriptor\n",
3241                         __func__, dlen));
3242                         dlen = 0;
3243                 }
3244
3245                 for (totlen = num = 0; dlen; num++) {
3246                         /* Get (and move past) next length */
3247                         sublen = get_unaligned_le16(dptr);
3248                         dlen -= sizeof(u16);
3249                         dptr += sizeof(u16);
3250                         if ((sublen < SDPCM_HDRLEN) ||
3251                             ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
3252                                 DHD_ERROR(("%s: descriptor len %d bad: %d\n",
3253                                            __func__, num, sublen));
3254                                 pnext = NULL;
3255                                 break;
3256                         }
3257                         if (sublen % DHD_SDALIGN) {
3258                                 DHD_ERROR(("%s: sublen %d not multiple of %d\n",
3259                                 __func__, sublen, DHD_SDALIGN));
3260                                 usechain = false;
3261                         }
3262                         totlen += sublen;
3263
3264                         /* For last frame, adjust read len so total
3265                                  is a block multiple */
3266                         if (!dlen) {
3267                                 sublen +=
3268                                     (roundup(totlen, bus->blocksize) - totlen);
3269                                 totlen = roundup(totlen, bus->blocksize);
3270                         }
3271
3272                         /* Allocate/chain packet for next subframe */
3273                         pnext = bcm_pkt_buf_get_skb(sublen + DHD_SDALIGN);
3274                         if (pnext == NULL) {
3275                                 DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
3276                                         "num %d len %d\n", __func__,
3277                                         num, sublen));
3278                                 break;
3279                         }
3280                         ASSERT(!(pnext->prev));
3281                         if (!pfirst) {
3282                                 ASSERT(!plast);
3283                                 pfirst = plast = pnext;
3284                         } else {
3285                                 ASSERT(plast);
3286                                 plast->next = pnext;
3287                                 plast = pnext;
3288                         }
3289
3290                         /* Adhere to start alignment requirements */
3291                         PKTALIGN(pnext, sublen, DHD_SDALIGN);
3292                 }
3293
3294                 /* If all allocations succeeded, save packet chain
3295                          in bus structure */
3296                 if (pnext) {
3297                         DHD_GLOM(("%s: allocated %d-byte packet chain for %d "
3298                                 "subframes\n", __func__, totlen, num));
3299                         if (DHD_GLOM_ON() && bus->nextlen) {
3300                                 if (totlen != bus->nextlen) {
3301                                         DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d " "rxseq %d\n",
3302                                                 __func__, bus->nextlen,
3303                                                 totlen, rxseq));
3304                                 }
3305                         }
3306                         bus->glom = pfirst;
3307                         pfirst = pnext = NULL;
3308                 } else {
3309                         if (pfirst)
3310                                 bcm_pkt_buf_free_skb(pfirst);
3311                         bus->glom = NULL;
3312                         num = 0;
3313                 }
3314
3315                 /* Done with descriptor packet */
3316                 bcm_pkt_buf_free_skb(bus->glomd);
3317                 bus->glomd = NULL;
3318                 bus->nextlen = 0;
3319
3320                 dhd_os_sdunlock_rxq(bus->dhd);
3321         }
3322
3323         /* Ok -- either we just generated a packet chain,
3324                  or had one from before */
3325         if (bus->glom) {
3326                 if (DHD_GLOM_ON()) {
3327                         DHD_GLOM(("%s: try superframe read, packet chain:\n",
3328                                 __func__));
3329                         for (pnext = bus->glom; pnext; pnext = pnext->next) {
3330                                 DHD_GLOM(("    %p: %p len 0x%04x (%d)\n",
3331                                           pnext, (u8 *) (pnext->data),
3332                                           pnext->len, pnext->len));
3333                         }
3334                 }
3335
3336                 pfirst = bus->glom;
3337                 dlen = (u16) bcm_pkttotlen(pfirst);
3338
3339                 /* Do an SDIO read for the superframe.  Configurable iovar to
3340                  * read directly into the chained packet, or allocate a large
3341                  * packet and and copy into the chain.
3342                  */
3343                 if (usechain) {
3344                         errcode = bcmsdh_recv_buf(bus,
3345                                         bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
3346                                         F2SYNC, (u8 *) pfirst->data, dlen,
3347                                         pfirst, NULL, NULL);
3348                 } else if (bus->dataptr) {
3349                         errcode = bcmsdh_recv_buf(bus,
3350                                         bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
3351                                         F2SYNC, bus->dataptr, dlen,
3352                                         NULL, NULL, NULL);
3353                         sublen = (u16) bcm_pktfrombuf(pfirst, 0, dlen,
3354                                                 bus->dataptr);
3355                         if (sublen != dlen) {
3356                                 DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
3357                                         __func__, dlen, sublen));
3358                                 errcode = -1;
3359                         }
3360                         pnext = NULL;
3361                 } else {
3362                         DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
3363                                 dlen));
3364                         errcode = -1;
3365                 }
3366                 bus->f2rxdata++;
3367                 ASSERT(errcode != -BCME_PENDING);
3368
3369                 /* On failure, kill the superframe, allow a couple retries */
3370                 if (errcode < 0) {
3371                         DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
3372                                    __func__, dlen, errcode));
3373                         bus->dhd->rx_errors++;
3374
3375                         if (bus->glomerr++ < 3) {
3376                                 dhdsdio_rxfail(bus, true, true);
3377                         } else {
3378                                 bus->glomerr = 0;
3379                                 dhdsdio_rxfail(bus, true, false);
3380                                 dhd_os_sdlock_rxq(bus->dhd);
3381                                 bcm_pkt_buf_free_skb(bus->glom);
3382                                 dhd_os_sdunlock_rxq(bus->dhd);
3383                                 bus->rxglomfail++;
3384                                 bus->glom = NULL;
3385                         }
3386                         return 0;
3387                 }
3388 #ifdef DHD_DEBUG
3389                 if (DHD_GLOM_ON()) {
3390                         printk(KERN_DEBUG "SUPERFRAME:\n");
3391                         print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3392                                 pfirst->data, min_t(int, pfirst->len, 48));
3393                 }
3394 #endif
3395
3396                 /* Validate the superframe header */
3397                 dptr = (u8 *) (pfirst->data);
3398                 sublen = get_unaligned_le16(dptr);
3399                 check = get_unaligned_le16(dptr + sizeof(u16));
3400
3401                 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
3402                 seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
3403                 bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
3404                 if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
3405                         DHD_INFO(("%s: nextlen too large (%d) seq %d\n",
3406                                 __func__, bus->nextlen, seq));
3407                         bus->nextlen = 0;
3408                 }
3409                 doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3410                 txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3411
3412                 errcode = 0;
3413                 if ((u16)~(sublen ^ check)) {
3414                         DHD_ERROR(("%s (superframe): HW hdr error: len/check "
3415                                 "0x%04x/0x%04x\n", __func__, sublen, check));
3416                         errcode = -1;
3417                 } else if (roundup(sublen, bus->blocksize) != dlen) {
3418                         DHD_ERROR(("%s (superframe): len 0x%04x, rounded "
3419                                 "0x%04x, expect 0x%04x\n",
3420                                 __func__, sublen,
3421                                 roundup(sublen, bus->blocksize), dlen));
3422                         errcode = -1;
3423                 } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
3424                            SDPCM_GLOM_CHANNEL) {
3425                         DHD_ERROR(("%s (superframe): bad channel %d\n",
3426                                    __func__,
3427                                    SDPCM_PACKET_CHANNEL(&dptr
3428                                                         [SDPCM_FRAMETAG_LEN])));
3429                         errcode = -1;
3430                 } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
3431                         DHD_ERROR(("%s (superframe): got second descriptor?\n",
3432                                    __func__));
3433                         errcode = -1;
3434                 } else if ((doff < SDPCM_HDRLEN) ||
3435                            (doff > (pfirst->len - SDPCM_HDRLEN))) {
3436                         DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d "
3437                                 "pkt %d min %d\n",
3438                                 __func__, doff, sublen,
3439                                 pfirst->len, SDPCM_HDRLEN));
3440                         errcode = -1;
3441                 }
3442
3443                 /* Check sequence number of superframe SW header */
3444                 if (rxseq != seq) {
3445                         DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
3446                                   __func__, seq, rxseq));
3447                         bus->rx_badseq++;
3448                         rxseq = seq;
3449                 }
3450
3451                 /* Check window for sanity */
3452                 if ((u8) (txmax - bus->tx_seq) > 0x40) {
3453                         DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
3454                                 __func__, txmax, bus->tx_seq));
3455                         txmax = bus->tx_seq + 2;
3456                 }
3457                 bus->tx_max = txmax;
3458
3459                 /* Remove superframe header, remember offset */
3460                 skb_pull(pfirst, doff);
3461                 sfdoff = doff;
3462
3463                 /* Validate all the subframe headers */
3464                 for (num = 0, pnext = pfirst; pnext && !errcode;
3465                      num++, pnext = pnext->next) {
3466                         dptr = (u8 *) (pnext->data);
3467                         dlen = (u16) (pnext->len);
3468                         sublen = get_unaligned_le16(dptr);
3469                         check = get_unaligned_le16(dptr + sizeof(u16));
3470                         chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
3471                         doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3472 #ifdef DHD_DEBUG
3473                         if (DHD_GLOM_ON()) {
3474                                 printk(KERN_DEBUG "subframe:\n");
3475                                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3476                                                      dptr, 32);
3477                         }
3478 #endif
3479
3480                         if ((u16)~(sublen ^ check)) {
3481                                 DHD_ERROR(("%s (subframe %d): HW hdr error: "
3482                                            "len/check 0x%04x/0x%04x\n",
3483                                            __func__, num, sublen, check));
3484                                 errcode = -1;
3485                         } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
3486                                 DHD_ERROR(("%s (subframe %d): length mismatch: "
3487                                            "len 0x%04x, expect 0x%04x\n",
3488                                            __func__, num, sublen, dlen));
3489                                 errcode = -1;
3490                         } else if ((chan != SDPCM_DATA_CHANNEL) &&
3491                                    (chan != SDPCM_EVENT_CHANNEL)) {
3492                                 DHD_ERROR(("%s (subframe %d): bad channel %d\n",
3493                                            __func__, num, chan));
3494                                 errcode = -1;
3495                         } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
3496                                 DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
3497                                         __func__, num, doff, sublen,
3498                                         SDPCM_HDRLEN));
3499                                 errcode = -1;
3500                         }
3501                 }
3502
3503                 if (errcode) {
3504                         /* Terminate frame on error, request
3505                                  a couple retries */
3506                         if (bus->glomerr++ < 3) {
3507                                 /* Restore superframe header space */
3508                                 skb_push(pfirst, sfdoff);
3509                                 dhdsdio_rxfail(bus, true, true);
3510                         } else {
3511                                 bus->glomerr = 0;
3512                                 dhdsdio_rxfail(bus, true, false);
3513                                 dhd_os_sdlock_rxq(bus->dhd);
3514                                 bcm_pkt_buf_free_skb(bus->glom);
3515                                 dhd_os_sdunlock_rxq(bus->dhd);
3516                                 bus->rxglomfail++;
3517                                 bus->glom = NULL;
3518                         }
3519                         bus->nextlen = 0;
3520                         return 0;
3521                 }
3522
3523                 /* Basic SD framing looks ok - process each packet (header) */
3524                 save_pfirst = pfirst;
3525                 bus->glom = NULL;
3526                 plast = NULL;
3527
3528                 dhd_os_sdlock_rxq(bus->dhd);
3529                 for (num = 0; pfirst; rxseq++, pfirst = pnext) {
3530                         pnext = pfirst->next;
3531                         pfirst->next = NULL;
3532
3533                         dptr = (u8 *) (pfirst->data);
3534                         sublen = get_unaligned_le16(dptr);
3535                         chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
3536                         seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
3537                         doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
3538
3539                         DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d "
3540                                 "chan %d seq %d\n",
3541                                 __func__, num, pfirst, pfirst->data,
3542                                 pfirst->len, sublen, chan, seq));
3543
3544                         ASSERT((chan == SDPCM_DATA_CHANNEL)
3545                                || (chan == SDPCM_EVENT_CHANNEL));
3546
3547                         if (rxseq != seq) {
3548                                 DHD_GLOM(("%s: rx_seq %d, expected %d\n",
3549                                           __func__, seq, rxseq));
3550                                 bus->rx_badseq++;
3551                                 rxseq = seq;
3552                         }
3553 #ifdef DHD_DEBUG
3554                         if (DHD_BYTES_ON() && DHD_DATA_ON()) {
3555                                 printk(KERN_DEBUG "Rx Subframe Data:\n");
3556                                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3557                                                      dptr, dlen);
3558                         }
3559 #endif
3560
3561                         __skb_trim(pfirst, sublen);
3562                         skb_pull(pfirst, doff);
3563
3564                         if (pfirst->len == 0) {
3565                                 bcm_pkt_buf_free_skb(pfirst);
3566                                 if (plast) {
3567                                         plast->next = pnext;
3568                                 } else {
3569                                         ASSERT(save_pfirst == pfirst);
3570                                         save_pfirst = pnext;
3571                                 }
3572                                 continue;
3573                         } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) !=
3574                                    0) {
3575                                 DHD_ERROR(("%s: rx protocol error\n",
3576                                            __func__));
3577                                 bus->dhd->rx_errors++;
3578                                 bcm_pkt_buf_free_skb(pfirst);
3579                                 if (plast) {
3580                                         plast->next = pnext;
3581                                 } else {
3582                                         ASSERT(save_pfirst == pfirst);
3583                                         save_pfirst = pnext;
3584                                 }
3585                                 continue;
3586                         }
3587
3588                         /* this packet will go up, link back into
3589                                  chain and count it */
3590                         pfirst->next = pnext;
3591                         plast = pfirst;
3592                         num++;
3593
3594 #ifdef DHD_DEBUG
3595                         if (DHD_GLOM_ON()) {
3596                                 DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) "
3597                                 "nxt/lnk %p/%p\n",
3598                                 __func__, num, pfirst, pfirst->data,
3599                                 pfirst->len, pfirst->next,
3600                                 pfirst->prev));
3601                                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3602                                                 pfirst->data,
3603                                                 min_t(int, pfirst->len, 32));
3604                         }
3605 #endif                          /* DHD_DEBUG */
3606                 }
3607                 dhd_os_sdunlock_rxq(bus->dhd);
3608                 if (num) {
3609                         dhd_os_sdunlock(bus->dhd);
3610                         dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num);
3611                         dhd_os_sdlock(bus->dhd);
3612                 }
3613
3614                 bus->rxglomframes++;
3615                 bus->rxglompkts += num;
3616         }
3617         return num;
3618 }
3619
3620 /* Return true if there may be more frames to read */
3621 static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
3622 {
3623         bcmsdh_info_t *sdh = bus->sdh;
3624
3625         u16 len, check; /* Extracted hardware header fields */
3626         u8 chan, seq, doff;     /* Extracted software header fields */
3627         u8 fcbits;              /* Extracted fcbits from software header */
3628
3629         struct sk_buff *pkt;            /* Packet for event or data frames */
3630         u16 pad;                /* Number of pad bytes to read */
3631         u16 rdlen;              /* Total number of bytes to read */
3632         u8 rxseq;               /* Next sequence number to expect */
3633         uint rxleft = 0;        /* Remaining number of frames allowed */
3634         int sdret;              /* Return code from bcmsdh calls */
3635         u8 txmax;               /* Maximum tx sequence offered */
3636         bool len_consistent;    /* Result of comparing readahead len and
3637                                          len from hw-hdr */
3638         u8 *rxbuf;
3639         int ifidx = 0;
3640         uint rxcount = 0;       /* Total frames read */
3641
3642 #if defined(DHD_DEBUG) || defined(SDTEST)
3643         bool sdtest = false;    /* To limit message spew from test mode */
3644 #endif
3645
3646         DHD_TRACE(("%s: Enter\n", __func__));
3647
3648         ASSERT(maxframes);
3649
3650 #ifdef SDTEST
3651         /* Allow pktgen to override maxframes */
3652         if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
3653                 maxframes = bus->pktgen_count;
3654                 sdtest = true;
3655         }
3656 #endif
3657
3658         /* Not finished unless we encounter no more frames indication */
3659         *finished = false;
3660
3661         for (rxseq = bus->rx_seq, rxleft = maxframes;
3662              !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
3663              rxseq++, rxleft--) {
3664
3665                 /* Handle glomming separately */
3666                 if (bus->glom || bus->glomd) {
3667                         u8 cnt;
3668                         DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
3669                                   __func__, bus->glomd, bus->glom));
3670                         cnt = dhdsdio_rxglom(bus, rxseq);
3671                         DHD_GLOM(("%s: rxglom returned %d\n", __func__, cnt));
3672                         rxseq += cnt - 1;
3673                         rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
3674                         continue;
3675                 }
3676
3677                 /* Try doing single read if we can */
3678                 if (dhd_readahead && bus->nextlen) {
3679                         u16 nextlen = bus->nextlen;
3680                         bus->nextlen = 0;
3681
3682                         if (bus->bus == SPI_BUS) {
3683                                 rdlen = len = nextlen;
3684                         } else {
3685                                 rdlen = len = nextlen << 4;
3686
3687                                 /* Pad read to blocksize for efficiency */
3688                                 if (bus->roundup && bus->blocksize
3689                                     && (rdlen > bus->blocksize)) {
3690                                         pad =
3691                                             bus->blocksize -
3692                                             (rdlen % bus->blocksize);
3693                                         if ((pad <= bus->roundup)
3694                                             && (pad < bus->blocksize)
3695                                             && ((rdlen + pad + firstread) <
3696                                                 MAX_RX_DATASZ))
3697                                                 rdlen += pad;
3698                                 } else if (rdlen % DHD_SDALIGN) {
3699                                         rdlen +=
3700                                             DHD_SDALIGN - (rdlen % DHD_SDALIGN);
3701                                 }
3702                         }
3703
3704                         /* We use bus->rxctl buffer in WinXP for initial
3705                          * control pkt receives.
3706                          * Later we use buffer-poll for data as well
3707                          * as control packets.
3708                          * This is required because dhd receives full
3709                          * frame in gSPI unlike SDIO.
3710                          * After the frame is received we have to
3711                          * distinguish whether it is data
3712                          * or non-data frame.
3713                          */
3714                         /* Allocate a packet buffer */
3715                         dhd_os_sdlock_rxq(bus->dhd);
3716                         pkt = bcm_pkt_buf_get_skb(rdlen + DHD_SDALIGN);
3717                         if (!pkt) {
3718                                 if (bus->bus == SPI_BUS) {
3719                                         bus->usebufpool = false;
3720                                         bus->rxctl = bus->rxbuf;
3721                                         if (dhd_alignctl) {
3722                                                 bus->rxctl += firstread;
3723                                                 pad = ((unsigned long)bus->rxctl %
3724                                                       DHD_SDALIGN);
3725                                                 if (pad)
3726                                                         bus->rxctl +=
3727                                                             (DHD_SDALIGN - pad);
3728                                                 bus->rxctl -= firstread;
3729                                         }
3730                                         ASSERT(bus->rxctl >= bus->rxbuf);
3731                                         rxbuf = bus->rxctl;
3732                                         /* Read the entire frame */
3733                                         sdret = bcmsdh_recv_buf(bus,
3734                                                     bcmsdh_cur_sbwad(sdh),
3735                                                     SDIO_FUNC_2, F2SYNC,
3736                                                     rxbuf, rdlen,
3737                                                     NULL, NULL, NULL);
3738                                         bus->f2rxdata++;
3739                                         ASSERT(sdret != -BCME_PENDING);
3740
3741                                         /* Control frame failures need
3742                                          retransmission */
3743                                         if (sdret < 0) {
3744                                                 DHD_ERROR(("%s: read %d control bytes failed: %d\n",
3745                                                         __func__,
3746                                                         rdlen, sdret));
3747                                                 /* dhd.rx_ctlerrs is higher */
3748                                                 bus->rxc_errors++;
3749                                                 dhd_os_sdunlock_rxq(bus->dhd);
3750                                                 dhdsdio_rxfail(bus, true,
3751                                                        (bus->bus ==
3752                                                         SPI_BUS) ? false
3753                                                        : true);
3754                                                 continue;
3755                                         }
3756                                 } else {
3757                                         /* Give up on data,
3758                                         request rtx of events */
3759                                         DHD_ERROR(("%s (nextlen): "
3760                                                    "bcm_pkt_buf_get_skb failed:"
3761                                                    " len %d rdlen %d expected"
3762                                                    " rxseq %d\n", __func__,
3763                                                    len, rdlen, rxseq));
3764                                         /* Just go try again w/normal
3765                                         header read */
3766                                         dhd_os_sdunlock_rxq(bus->dhd);
3767                                         continue;
3768                                 }
3769                         } else {
3770                                 if (bus->bus == SPI_BUS)
3771                                         bus->usebufpool = true;
3772
3773                                 ASSERT(!(pkt->prev));
3774                                 PKTALIGN(pkt, rdlen, DHD_SDALIGN);
3775                                 rxbuf = (u8 *) (pkt->data);
3776                                 /* Read the entire frame */
3777                                 sdret = bcmsdh_recv_buf(bus,
3778                                                 bcmsdh_cur_sbwad(sdh),
3779                                                 SDIO_FUNC_2, F2SYNC,
3780                                                 rxbuf, rdlen,
3781                                                 pkt, NULL, NULL);
3782                                 bus->f2rxdata++;
3783                                 ASSERT(sdret != -BCME_PENDING);
3784
3785                                 if (sdret < 0) {
3786                                         DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
3787                                                 __func__, rdlen, sdret));
3788                                         bcm_pkt_buf_free_skb(pkt);
3789                                         bus->dhd->rx_errors++;
3790                                         dhd_os_sdunlock_rxq(bus->dhd);
3791                                         /* Force retry w/normal header read.
3792                                          * Don't attempt NAK for
3793                                          * gSPI
3794                                          */
3795                                         dhdsdio_rxfail(bus, true,
3796                                                        (bus->bus ==
3797                                                         SPI_BUS) ? false :
3798                                                        true);
3799                                         continue;
3800                                 }
3801                         }
3802                         dhd_os_sdunlock_rxq(bus->dhd);
3803
3804                         /* Now check the header */
3805                         memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
3806
3807                         /* Extract hardware header fields */
3808                         len = get_unaligned_le16(bus->rxhdr);
3809                         check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
3810
3811                         /* All zeros means readahead info was bad */
3812                         if (!(len | check)) {
3813                                 DHD_INFO(("%s (nextlen): read zeros in HW "
3814                                         "header???\n", __func__));
3815                                 dhdsdio_pktfree2(bus, pkt);
3816                                 continue;
3817                         }
3818
3819                         /* Validate check bytes */
3820                         if ((u16)~(len ^ check)) {
3821                                 DHD_ERROR(("%s (nextlen): HW hdr error:"
3822                                         " nextlen/len/check"
3823                                         " 0x%04x/0x%04x/0x%04x\n",
3824                                         __func__, nextlen, len, check));
3825                                 bus->rx_badhdr++;
3826                                 dhdsdio_rxfail(bus, false, false);
3827                                 dhdsdio_pktfree2(bus, pkt);
3828                                 continue;
3829                         }
3830
3831                         /* Validate frame length */
3832                         if (len < SDPCM_HDRLEN) {
3833                                 DHD_ERROR(("%s (nextlen): HW hdr length "
3834                                         "invalid: %d\n", __func__, len));
3835                                 dhdsdio_pktfree2(bus, pkt);
3836                                 continue;
3837                         }
3838
3839                         /* Check for consistency withreadahead info */
3840                         len_consistent = (nextlen != (roundup(len, 16) >> 4));
3841                         if (len_consistent) {
3842                                 /* Mismatch, force retry w/normal
3843                                         header (may be >4K) */
3844                                 DHD_ERROR(("%s (nextlen): mismatch, "
3845                                         "nextlen %d len %d rnd %d; "
3846                                         "expected rxseq %d\n",
3847                                         __func__, nextlen,
3848                                         len, roundup(len, 16), rxseq));
3849                                 dhdsdio_rxfail(bus, true, (bus->bus != SPI_BUS));
3850                                 dhdsdio_pktfree2(bus, pkt);
3851                                 continue;
3852                         }
3853
3854                         /* Extract software header fields */
3855                         chan = SDPCM_PACKET_CHANNEL(
3856                                         &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
3857                         seq = SDPCM_PACKET_SEQUENCE(
3858                                         &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
3859                         doff = SDPCM_DOFFSET_VALUE(
3860                                         &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
3861                         txmax = SDPCM_WINDOW_VALUE(
3862                                         &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
3863
3864                         bus->nextlen =
3865                             bus->rxhdr[SDPCM_FRAMETAG_LEN +
3866                                        SDPCM_NEXTLEN_OFFSET];
3867                         if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
3868                                 DHD_INFO(("%s (nextlen): got frame w/nextlen too large" " (%d), seq %d\n",
3869                                         __func__, bus->nextlen, seq));
3870                                 bus->nextlen = 0;
3871                         }
3872
3873                         bus->dhd->rx_readahead_cnt++;
3874
3875                         /* Handle Flow Control */
3876                         fcbits = SDPCM_FCMASK_VALUE(
3877                                         &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
3878
3879                         if (bus->flowcontrol != fcbits) {
3880                                 if (~bus->flowcontrol & fcbits)
3881                                         bus->fc_xoff++;
3882
3883                                 if (bus->flowcontrol & ~fcbits)
3884                                         bus->fc_xon++;
3885
3886                                 bus->fc_rcvd++;
3887                                 bus->flowcontrol = fcbits;
3888                         }
3889
3890                         /* Check and update sequence number */
3891                         if (rxseq != seq) {
3892                                 DHD_INFO(("%s (nextlen): rx_seq %d, expected "
3893                                         "%d\n", __func__, seq, rxseq));
3894                                 bus->rx_badseq++;
3895                                 rxseq = seq;
3896                         }
3897
3898                         /* Check window for sanity */
3899                         if ((u8) (txmax - bus->tx_seq) > 0x40) {
3900                                 DHD_ERROR(("%s: got unlikely tx max %d with "
3901                                         "tx_seq %d\n",
3902                                         __func__, txmax, bus->tx_seq));
3903                                 txmax = bus->tx_seq + 2;
3904                         }
3905                         bus->tx_max = txmax;
3906
3907 #ifdef DHD_DEBUG
3908                         if (DHD_BYTES_ON() && DHD_DATA_ON()) {
3909                                 printk(KERN_DEBUG "Rx Data:\n");
3910                                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3911                                                      rxbuf, len);
3912                         } else if (DHD_HDRS_ON()) {
3913                                 printk(KERN_DEBUG "RxHdr:\n");
3914                                 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3915                                                      bus->rxhdr, SDPCM_HDRLEN);
3916                         }
3917 #endif
3918
3919                         if (chan == SDPCM_CONTROL_CHANNEL) {
3920                                 if (bus->bus == SPI_BUS) {
3921                                         dhdsdio_read_control(bus, rxbuf, len,
3922                                                              doff);
3923                                 } else {
3924                                         DHD_ERROR(("%s (nextlen): readahead on control" " packet %d?\n",
3925                                                 __func__, seq));
3926                                         /* Force retry w/normal header read */
3927                                         bus->nextlen = 0;
3928                                         dhdsdio_rxfail(bus, false, true);
3929                                 }
3930                                 dhdsdio_pktfree2(bus, pkt);
3931                                 continue;
3932                         }
3933
3934                         if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
3935                                 DHD_ERROR(("Received %d bytes on %d channel. Running out of " "rx pktbuf's or not yet malloced.\n",
3936                                         len, chan));
3937                                 continue;
3938                         }
3939
3940                         /* Validate data offset */
3941                         if ((doff < SDPCM_HDRLEN) || (doff > len)) {
3942                                 DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
3943                                         __func__, doff, len, SDPCM_HDRLEN));
3944                                 dhdsdio_rxfail(bus, false, false);
3945                                 dhdsdio_pktfree2(bus, pkt);
3946                                 continue;
3947                         }
3948
3949                         /* All done with this one -- now deliver the packet */
3950                         goto deliver;
3951                 }
3952                 /* gSPI frames should not be handled in fractions */
3953                 if (bus->bus == SPI_BUS)
3954                         break;
3955
3956                 /* Read frame header (hardware and software) */
3957                 sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
3958                                 SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread,
3959                                 NULL, NULL, NULL);
3960                 bus->f2rxhdrs++;
3961                 ASSERT(sdret != -BCME_PENDING);
3962
3963                 if (sdret < 0) {
3964                         DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
3965                                    sdret));
3966                         bus->rx_hdrfail++;
3967                         dhdsdio_rxfail(bus, true, true);
3968                         continue;
3969                 }
3970 #ifdef DHD_DEBUG
3971                 if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
3972                         printk(KERN_DEBUG "RxHdr:\n");
3973                         print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
3974                                              bus->rxhdr, SDPCM_HDRLEN);
3975                 }
3976 #endif
3977
3978                 /* Extract hardware header fields */
3979                 len = get_unaligned_le16(bus->rxhdr);
3980                 check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
3981
3982                 /* All zeros means no more frames */
3983                 if (!(len | check)) {
3984                         *finished = true;
3985                         break;
3986                 }
3987
3988                 /* Validate check bytes */
3989                 if ((u16) ~(len ^ check)) {
3990                         DHD_ERROR(("%s: HW hdr err: len/check 0x%04x/0x%04x\n",
3991                                 __func__, len, check));
3992                         bus->rx_badhdr++;
3993                         dhdsdio_rxfail(bus, false, false);
3994                         continue;
3995                 }
3996
3997                 /* Validate frame length */
3998                 if (len < SDPCM_HDRLEN) {
3999                         DHD_ERROR(("%s: HW hdr length invalid: %d\n",
4000                                    __func__, len));
4001                         continue;
4002                 }
4003
4004                 /* Extract software header fields */
4005                 chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4006                 seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4007                 doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4008                 txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4009
4010                 /* Validate data offset */
4011                 if ((doff < SDPCM_HDRLEN) || (doff > len)) {
4012                         DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d "
4013                                 "seq %d\n",
4014                                 __func__, doff, len, SDPCM_HDRLEN, seq));
4015                         bus->rx_badhdr++;
4016                         ASSERT(0);
4017                         dhdsdio_rxfail(bus, false, false);
4018                         continue;
4019                 }
4020
4021                 /* Save the readahead length if there is one */
4022                 bus->nextlen =
4023                     bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
4024                 if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
4025                         DHD_INFO(("%s (nextlen): got frame w/nextlen too large "
4026                                 "(%d), seq %d\n",
4027                                 __func__, bus->nextlen, seq));
4028                         bus->nextlen = 0;
4029                 }
4030
4031                 /* Handle Flow Control */
4032                 fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
4033
4034                 if (bus->flowcontrol != fcbits) {
4035                         if (~bus->flowcontrol & fcbits)
4036                                 bus->fc_xoff++;
4037
4038                         if (bus->flowcontrol & ~fcbits)
4039                                 bus->fc_xon++;
4040
4041                         bus->fc_rcvd++;
4042                         bus->flowcontrol = fcbits;
4043                 }
4044
4045                 /* Check and update sequence number */
4046                 if (rxseq != seq) {
4047                         DHD_INFO(("%s: rx_seq %d, expected %d\n", __func__,
4048                                   seq, rxseq));
4049                         bus->rx_badseq++;
4050                         rxseq = seq;
4051                 }
4052
4053                 /* Check window for sanity */
4054                 if ((u8) (txmax - bus->tx_seq) > 0x40) {
4055                         DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
4056                                 __func__, txmax, bus->tx_seq));
4057                         txmax = bus->tx_seq + 2;
4058                 }
4059                 bus->tx_max = txmax;
4060
4061                 /* Call a separate function for control frames */
4062                 if (chan == SDPCM_CONTROL_CHANNEL) {
4063                         dhdsdio_read_control(bus, bus->rxhdr, len, doff);
4064                         continue;
4065                 }
4066
4067                 ASSERT((chan == SDPCM_DATA_CHANNEL)
4068                        || (chan == SDPCM_EVENT_CHANNEL)
4069                        || (chan == SDPCM_TEST_CHANNEL)
4070                        || (chan == SDPCM_GLOM_CHANNEL));
4071
4072                 /* Length to read */
4073                 rdlen = (len > firstread) ? (len - firstread) : 0;
4074
4075                 /* May pad read to blocksize for efficiency */
4076                 if (bus->roundup && bus->blocksize &&
4077                         (rdlen > bus->blocksize)) {
4078                         pad = bus->blocksize - (rdlen % bus->blocksize);
4079                         if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
4080                             ((rdlen + pad + firstread) < MAX_RX_DATASZ))
4081                                 rdlen += pad;
4082                 } else if (rdlen % DHD_SDALIGN) {
4083                         rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
4084                 }
4085
4086                 /* Satisfy length-alignment requirements */
4087                 if (forcealign && (rdlen & (ALIGNMENT - 1)))
4088                         rdlen = roundup(rdlen, ALIGNMENT);
4089
4090                 if ((rdlen + firstread) > MAX_RX_DATASZ) {
4091                         /* Too long -- skip this frame */
4092                         DHD_ERROR(("%s: too long: len %d rdlen %d\n",
4093                                    __func__, len, rdlen));
4094                         bus->dhd->rx_errors++;
4095                         bus->rx_toolong++;
4096                         dhdsdio_rxfail(bus, false, false);
4097                         continue;
4098                 }
4099
4100                 dhd_os_sdlock_rxq(bus->dhd);
4101                 pkt = bcm_pkt_buf_get_skb(rdlen + firstread + DHD_SDALIGN);
4102                 if (!pkt) {
4103                         /* Give up on data, request rtx of events */
4104                         DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed: rdlen %d "
4105                                 "chan %d\n", __func__, rdlen, chan));
4106                         bus->dhd->rx_dropped++;
4107                         dhd_os_sdunlock_rxq(bus->dhd);
4108                         dhdsdio_rxfail(bus, false, RETRYCHAN(chan));
4109                         continue;
4110                 }
4111                 dhd_os_sdunlock_rxq(bus->dhd);
4112
4113                 ASSERT(!(pkt->prev));
4114
4115                 /* Leave room for what we already read, and align remainder */
4116                 ASSERT(firstread < pkt->len);
4117                 skb_pull(pkt, firstread);
4118                 PKTALIGN(pkt, rdlen, DHD_SDALIGN);
4119
4120                 /* Read the remaining frame data */
4121                 sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
4122                                         F2SYNC, ((u8 *) (pkt->data)), rdlen,
4123                                         pkt, NULL, NULL);
4124                 bus->f2rxdata++;
4125                 ASSERT(sdret != -BCME_PENDING);
4126
4127                 if (sdret < 0) {
4128                         DHD_ERROR(("%s: read %d %s bytes failed: %d\n",
4129                                    __func__, rdlen,
4130                                    ((chan ==
4131                                      SDPCM_EVENT_CHANNEL) ? "event" : ((chan ==
4132                                         SDPCM_DATA_CHANNEL)
4133                                        ? "data" : "test")),
4134                                    sdret));
4135                         dhd_os_sdlock_rxq(bus->dhd);
4136                         bcm_pkt_buf_free_skb(pkt);
4137                         dhd_os_sdunlock_rxq(bus->dhd);
4138                         bus->dhd->rx_errors++;
4139                         dhdsdio_rxfail(bus, true, RETRYCHAN(chan));
4140                         continue;
4141                 }
4142
4143                 /* Copy the already-read portion */
4144                 skb_push(pkt, firstread);
4145                 memcpy(pkt->data, bus->rxhdr, firstread);
4146
4147 #ifdef DHD_DEBUG
4148                 if (DHD_BYTES_ON() && DHD_DATA_ON()) {
4149                         printk(KERN_DEBUG "Rx Data:\n");
4150                         print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
4151                                              pkt->data, len);
4152                 }
4153 #endif
4154
4155 deliver:
4156                 /* Save superframe descriptor and allocate packet frame */
4157                 if (chan == SDPCM_GLOM_CHANNEL) {
4158                         if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
4159                                 DHD_GLOM(("%s: glom descriptor, %d bytes:\n",
4160                                         __func__, len));
4161 #ifdef DHD_DEBUG
4162                                 if (DHD_GLOM_ON()) {
4163                                         printk(KERN_DEBUG "Glom Data:\n");
4164                                         print_hex_dump_bytes("",
4165                                                              DUMP_PREFIX_OFFSET,
4166                                                              pkt->data, len);
4167                                 }
4168 #endif
4169                                 __skb_trim(pkt, len);
4170                                 ASSERT(doff == SDPCM_HDRLEN);
4171                                 skb_pull(pkt, SDPCM_HDRLEN);
4172                                 bus->glomd = pkt;
4173                         } else {
4174                                 DHD_ERROR(("%s: glom superframe w/o "
4175                                         "descriptor!\n", __func__));
4176                                 dhdsdio_rxfail(bus, false, false);
4177                         }
4178                         continue;
4179                 }
4180
4181                 /* Fill in packet len and prio, deliver upward */
4182                 __skb_trim(pkt, len);
4183                 skb_pull(pkt, doff);
4184
4185 #ifdef SDTEST
4186                 /* Test channel packets are processed separately */
4187                 if (chan == SDPCM_TEST_CHANNEL) {
4188                         dhdsdio_testrcv(bus, pkt, seq);
4189                         continue;
4190                 }
4191 #endif                          /* SDTEST */
4192
4193                 if (pkt->len == 0) {
4194                         dhd_os_sdlock_rxq(bus->dhd);
4195                         bcm_pkt_buf_free_skb(pkt);
4196                         dhd_os_sdunlock_rxq(bus->dhd);
4197                         continue;
4198                 } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) {
4199                         DHD_ERROR(("%s: rx protocol error\n", __func__));
4200                         dhd_os_sdlock_rxq(bus->dhd);
4201                         bcm_pkt_buf_free_skb(pkt);
4202                         dhd_os_sdunlock_rxq(bus->dhd);
4203                         bus->dhd->rx_errors++;
4204                         continue;
4205                 }
4206
4207                 /* Unlock during rx call */
4208                 dhd_os_sdunlock(bus->dhd);
4209                 dhd_rx_frame(bus->dhd, ifidx, pkt, 1);
4210                 dhd_os_sdlock(bus->dhd);
4211         }
4212         rxcount = maxframes - rxleft;
4213 #ifdef DHD_DEBUG
4214         /* Message if we hit the limit */
4215         if (!rxleft && !sdtest)
4216                 DHD_DATA(("%s: hit rx limit of %d frames\n", __func__,
4217                           maxframes));
4218         else
4219 #endif                          /* DHD_DEBUG */
4220                 DHD_DATA(("%s: processed %d frames\n", __func__, rxcount));
4221         /* Back off rxseq if awaiting rtx, update rx_seq */
4222         if (bus->rxskip)
4223                 rxseq--;
4224         bus->rx_seq = rxseq;
4225
4226         return rxcount;
4227 }
4228
4229 static u32 dhdsdio_hostmail(dhd_bus_t *bus)
4230 {
4231         sdpcmd_regs_t *regs = bus->regs;
4232         u32 intstatus = 0;
4233         u32 hmb_data;
4234         u8 fcbits;
4235         uint retries = 0;
4236
4237         DHD_TRACE(("%s: Enter\n", __func__));
4238
4239         /* Read mailbox data and ack that we did so */
4240         R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
4241         if (retries <= retry_limit)
4242                 W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
4243         bus->f1regdata += 2;
4244
4245         /* Dongle recomposed rx frames, accept them again */
4246         if (hmb_data & HMB_DATA_NAKHANDLED) {
4247                 DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
4248                           bus->rx_seq));
4249                 if (!bus->rxskip)
4250                         DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
4251
4252                 bus->rxskip = false;
4253                 intstatus |= I_HMB_FRAME_IND;
4254         }
4255
4256         /*
4257          * DEVREADY does not occur with gSPI.
4258          */
4259         if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
4260                 bus->sdpcm_ver =
4261                     (hmb_data & HMB_DATA_VERSION_MASK) >>
4262                     HMB_DATA_VERSION_SHIFT;
4263                 if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
4264                         DHD_ERROR(("Version mismatch, dongle reports %d, "
4265                                 "expecting %d\n",
4266                                 bus->sdpcm_ver, SDPCM_PROT_VERSION));
4267                 else
4268                         DHD_INFO(("Dongle ready, protocol version %d\n",
4269                                   bus->sdpcm_ver));
4270         }
4271
4272         /*
4273          * Flow Control has been moved into the RX headers and this out of band
4274          * method isn't used any more.
4275          * remaining backward compatible with older dongles.
4276          */
4277         if (hmb_data & HMB_DATA_FC) {
4278                 fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
4279                                                         HMB_DATA_FCDATA_SHIFT;
4280
4281                 if (fcbits & ~bus->flowcontrol)
4282                         bus->fc_xoff++;
4283
4284                 if (bus->flowcontrol & ~fcbits)
4285                         bus->fc_xon++;
4286
4287                 bus->fc_rcvd++;
4288                 bus->flowcontrol = fcbits;
4289         }
4290
4291         /* Shouldn't be any others */
4292         if (hmb_data & ~(HMB_DATA_DEVREADY |
4293                          HMB_DATA_NAKHANDLED |
4294                          HMB_DATA_FC |
4295                          HMB_DATA_FWREADY |
4296                          HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) {
4297                 DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
4298         }
4299
4300         return intstatus;
4301 }
4302
4303 bool dhdsdio_dpc(dhd_bus_t *bus)
4304 {
4305         bcmsdh_info_t *sdh = bus->sdh;
4306         sdpcmd_regs_t *regs = bus->regs;
4307         u32 intstatus, newstatus = 0;
4308         uint retries = 0;
4309         uint rxlimit = dhd_rxbound;     /* Rx frames to read before resched */
4310         uint txlimit = dhd_txbound;     /* Tx frames to send before resched */
4311         uint framecnt = 0;      /* Temporary counter of tx/rx frames */
4312         bool rxdone = true;     /* Flag for no more read data */
4313         bool resched = false;   /* Flag indicating resched wanted */
4314
4315         DHD_TRACE(("%s: Enter\n", __func__));
4316
4317         /* Start with leftover status bits */
4318         intstatus = bus->intstatus;
4319
4320         dhd_os_sdlock(bus->dhd);
4321
4322         /* If waiting for HTAVAIL, check status */
4323         if (bus->clkstate == CLK_PENDING) {
4324                 int err;
4325                 u8 clkctl, devctl = 0;
4326
4327 #ifdef DHD_DEBUG
4328                 /* Check for inconsistent device control */
4329                 devctl =
4330                     bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
4331                 if (err) {
4332                         DHD_ERROR(("%s: error reading DEVCTL: %d\n",
4333                                    __func__, err));
4334                         bus->dhd->busstate = DHD_BUS_DOWN;
4335                 } else {
4336                         ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
4337                 }
4338 #endif                          /* DHD_DEBUG */
4339
4340                 /* Read CSR, if clock on switch to AVAIL, else ignore */
4341                 clkctl =
4342                     bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
4343                                     &err);
4344                 if (err) {
4345                         DHD_ERROR(("%s: error reading CSR: %d\n", __func__,
4346                                    err));
4347                         bus->dhd->busstate = DHD_BUS_DOWN;
4348                 }
4349
4350                 DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl,
4351                           clkctl));
4352
4353                 if (SBSDIO_HTAV(clkctl)) {
4354                         devctl =
4355                             bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
4356                                             &err);
4357                         if (err) {
4358                                 DHD_ERROR(("%s: error reading DEVCTL: %d\n",
4359                                            __func__, err));
4360                                 bus->dhd->busstate = DHD_BUS_DOWN;
4361                         }
4362                         devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
4363                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
4364                                          devctl, &err);
4365                         if (err) {
4366                                 DHD_ERROR(("%s: error writing DEVCTL: %d\n",
4367                                            __func__, err));
4368                                 bus->dhd->busstate = DHD_BUS_DOWN;
4369                         }
4370                         bus->clkstate = CLK_AVAIL;
4371                 } else {
4372                         goto clkwait;
4373                 }
4374         }
4375
4376         BUS_WAKE(bus);
4377
4378         /* Make sure backplane clock is on */
4379         dhdsdio_clkctl(bus, CLK_AVAIL, true);
4380         if (bus->clkstate == CLK_PENDING)
4381                 goto clkwait;
4382
4383         /* Pending interrupt indicates new device status */
4384         if (bus->ipend) {
4385                 bus->ipend = false;
4386                 R_SDREG(newstatus, &regs->intstatus, retries);
4387                 bus->f1regdata++;
4388                 if (bcmsdh_regfail(bus->sdh))
4389                         newstatus = 0;
4390                 newstatus &= bus->hostintmask;
4391                 bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
4392                 if (newstatus) {
4393                         W_SDREG(newstatus, &regs->intstatus, retries);
4394                         bus->f1regdata++;
4395                 }
4396         }
4397
4398         /* Merge new bits with previous */
4399         intstatus |= newstatus;
4400         bus->intstatus = 0;
4401
4402         /* Handle flow-control change: read new state in case our ack
4403          * crossed another change interrupt.  If change still set, assume
4404          * FC ON for safety, let next loop through do the debounce.
4405          */
4406         if (intstatus & I_HMB_FC_CHANGE) {
4407                 intstatus &= ~I_HMB_FC_CHANGE;
4408                 W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
4409                 R_SDREG(newstatus, &regs->intstatus, retries);
4410                 bus->f1regdata += 2;
4411                 bus->fcstate =
4412                     !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
4413                 intstatus |= (newstatus & bus->hostintmask);
4414         }
4415
4416         /* Handle host mailbox indication */
4417         if (intstatus & I_HMB_HOST_INT) {
4418                 intstatus &= ~I_HMB_HOST_INT;
4419                 intstatus |= dhdsdio_hostmail(bus);
4420         }
4421
4422         /* Generally don't ask for these, can get CRC errors... */
4423         if (intstatus & I_WR_OOSYNC) {
4424                 DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
4425                 intstatus &= ~I_WR_OOSYNC;
4426         }
4427
4428         if (intstatus & I_RD_OOSYNC) {
4429                 DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
4430                 intstatus &= ~I_RD_OOSYNC;
4431         }
4432
4433         if (intstatus & I_SBINT) {
4434                 DHD_ERROR(("Dongle reports SBINT\n"));
4435                 intstatus &= ~I_SBINT;
4436         }
4437
4438         /* Would be active due to wake-wlan in gSPI */
4439         if (intstatus & I_CHIPACTIVE) {
4440                 DHD_INFO(("Dongle reports CHIPACTIVE\n"));
4441                 intstatus &= ~I_CHIPACTIVE;
4442         }
4443
4444         /* Ignore frame indications if rxskip is set */
4445         if (bus->rxskip)
4446                 intstatus &= ~I_HMB_FRAME_IND;
4447
4448         /* On frame indication, read available frames */
4449         if (PKT_AVAILABLE()) {
4450                 framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
4451                 if (rxdone || bus->rxskip)
4452                         intstatus &= ~I_HMB_FRAME_IND;
4453                 rxlimit -= min(framecnt, rxlimit);
4454         }
4455
4456         /* Keep still-pending events for next scheduling */
4457         bus->intstatus = intstatus;
4458
4459 clkwait:
4460 #if defined(OOB_INTR_ONLY)
4461         bcmsdh_oob_intr_set(1);
4462 #endif                          /* (OOB_INTR_ONLY) */
4463         /* Re-enable interrupts to detect new device events (mailbox, rx frame)
4464          * or clock availability.  (Allows tx loop to check ipend if desired.)
4465          * (Unless register access seems hosed, as we may not be able to ACK...)
4466          */
4467         if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
4468                 DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
4469                           __func__, rxdone, framecnt));
4470                 bus->intdis = false;
4471                 bcmsdh_intr_enable(sdh);
4472         }
4473
4474         if (DATAOK(bus) && bus->ctrl_frame_stat &&
4475                 (bus->clkstate == CLK_AVAIL)) {
4476                 int ret, i;
4477
4478                 ret =
4479                     dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
4480                                         F2SYNC, (u8 *) bus->ctrl_frame_buf,
4481                                         (u32) bus->ctrl_frame_len, NULL,
4482                                         NULL, NULL);
4483                 ASSERT(ret != -BCME_PENDING);
4484
4485                 if (ret < 0) {
4486                         /* On failure, abort the command and
4487                                 terminate the frame */
4488                         DHD_INFO(("%s: sdio error %d, abort command and "
4489                                 "terminate frame.\n", __func__, ret));
4490                         bus->tx_sderrs++;
4491
4492                         bcmsdh_abort(sdh, SDIO_FUNC_2);
4493
4494                         bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
4495                                          SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
4496                                          NULL);
4497                         bus->f1regdata++;
4498
4499                         for (i = 0; i < 3; i++) {
4500                                 u8 hi, lo;
4501                                 hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
4502                                                      SBSDIO_FUNC1_WFRAMEBCHI,
4503                                                      NULL);
4504                                 lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
4505                                                      SBSDIO_FUNC1_WFRAMEBCLO,
4506                                                      NULL);
4507                                 bus->f1regdata += 2;
4508                                 if ((hi == 0) && (lo == 0))
4509                                         break;
4510                         }
4511
4512                 }
4513                 if (ret == 0)
4514                         bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
4515
4516                 DHD_INFO(("Return_dpc value is : %d\n", ret));
4517                 bus->ctrl_frame_stat = false;
4518                 dhd_wait_event_wakeup(bus->dhd);
4519         }
4520         /* Send queued frames (limit 1 if rx may still be pending) */
4521         else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
4522                  bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
4523                  && DATAOK(bus)) {
4524                 framecnt = rxdone ? txlimit : min(txlimit, dhd_txminmax);
4525                 framecnt = dhdsdio_sendfromq(bus, framecnt);
4526                 txlimit -= framecnt;
4527         }
4528
4529         /* Resched if events or tx frames are pending,
4530                  else await next interrupt */
4531         /* On failed register access, all bets are off:
4532                  no resched or interrupts */
4533         if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
4534                 DHD_ERROR(("%s: failed backplane access over SDIO, halting "
4535                         "operation %d\n", __func__, bcmsdh_regfail(sdh)));
4536                 bus->dhd->busstate = DHD_BUS_DOWN;
4537                 bus->intstatus = 0;
4538         } else if (bus->clkstate == CLK_PENDING) {
4539                 DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
4540                         "I_CHIPACTIVE interrupt\n", __func__));
4541                 resched = true;
4542         } else if (bus->intstatus || bus->ipend ||
4543                 (!bus->fcstate && bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
4544                         DATAOK(bus)) || PKT_AVAILABLE()) {
4545                 resched = true;
4546         }
4547
4548         bus->dpc_sched = resched;
4549
4550         /* If we're done for now, turn off clock request. */
4551         if ((bus->clkstate != CLK_PENDING)
4552             && bus->idletime == DHD_IDLE_IMMEDIATE) {
4553                 bus->activity = false;
4554                 dhdsdio_clkctl(bus, CLK_NONE, false);
4555         }
4556
4557         dhd_os_sdunlock(bus->dhd);
4558
4559         return resched;
4560 }
4561
4562 bool dhd_bus_dpc(struct dhd_bus *bus)
4563 {
4564         bool resched;
4565
4566         /* Call the DPC directly. */
4567         DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
4568         resched = dhdsdio_dpc(bus);
4569
4570         return resched;
4571 }
4572
4573 void dhdsdio_isr(void *arg)
4574 {
4575         dhd_bus_t *bus = (dhd_bus_t *) arg;
4576         bcmsdh_info_t *sdh;
4577
4578         DHD_TRACE(("%s: Enter\n", __func__));
4579
4580         if (!bus) {
4581                 DHD_ERROR(("%s : bus is null pointer , exit\n", __func__));
4582                 return;
4583         }
4584         sdh = bus->sdh;
4585
4586         if (bus->dhd->busstate == DHD_BUS_DOWN) {
4587                 DHD_ERROR(("%s : bus is down. we have nothing to do\n",
4588                            __func__));
4589                 return;
4590         }
4591         /* Count the interrupt call */
4592         bus->intrcount++;
4593         bus->ipend = true;
4594
4595         /* Shouldn't get this interrupt if we're sleeping? */
4596         if (bus->sleeping) {
4597                 DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
4598                 return;
4599         }
4600
4601         /* Disable additional interrupts (is this needed now)? */
4602         if (bus->intr)
4603                 DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
4604         else
4605                 DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
4606
4607         bcmsdh_intr_disable(sdh);
4608         bus->intdis = true;
4609
4610 #if defined(SDIO_ISR_THREAD)
4611         DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
4612         while (dhdsdio_dpc(bus))
4613                 ;
4614 #else
4615         bus->dpc_sched = true;
4616         dhd_sched_dpc(bus->dhd);
4617 #endif
4618
4619 }
4620
4621 #ifdef SDTEST
4622 static void dhdsdio_pktgen_init(dhd_bus_t *bus)
4623 {
4624         /* Default to specified length, or full range */
4625         if (dhd_pktgen_len) {
4626                 bus->pktgen_maxlen = min(dhd_pktgen_len, MAX_PKTGEN_LEN);
4627                 bus->pktgen_minlen = bus->pktgen_maxlen;
4628         } else {
4629                 bus->pktgen_maxlen = MAX_PKTGEN_LEN;
4630                 bus->pktgen_minlen = 0;
4631         }
4632         bus->pktgen_len = (u16) bus->pktgen_minlen;
4633
4634         /* Default to per-watchdog burst with 10s print time */
4635         bus->pktgen_freq = 1;
4636         bus->pktgen_print = 10000 / dhd_watchdog_ms;
4637         bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
4638
4639         /* Default to echo mode */
4640         bus->pktgen_mode = DHD_PKTGEN_ECHO;
4641         bus->pktgen_stop = 1;
4642 }
4643
4644 static void dhdsdio_pktgen(dhd_bus_t *bus)
4645 {
4646         struct sk_buff *pkt;
4647         u8 *data;
4648         uint pktcount;
4649         uint fillbyte;
4650         u16 len;
4651
4652         /* Display current count if appropriate */
4653         if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
4654                 bus->pktgen_ptick = 0;
4655                 printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n",
4656                        __func__, bus->pktgen_sent, bus->pktgen_rcvd);
4657         }
4658
4659         /* For recv mode, just make sure dongle has started sending */
4660         if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
4661                 if (!bus->pktgen_rcvd)
4662                         dhdsdio_sdtest_set(bus, true);
4663                 return;
4664         }
4665
4666         /* Otherwise, generate or request the specified number of packets */
4667         for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
4668                 /* Stop if total has been reached */
4669                 if (bus->pktgen_total
4670                     && (bus->pktgen_sent >= bus->pktgen_total)) {
4671                         bus->pktgen_count = 0;
4672                         break;
4673                 }
4674
4675                 /* Allocate an appropriate-sized packet */
4676                 len = bus->pktgen_len;
4677                 pkt = bcm_pkt_buf_get_skb(
4678                         (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
4679                         true);
4680                 if (!pkt) {
4681                         DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n",
4682                                 __func__));
4683                         break;
4684                 }
4685                 PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
4686                          DHD_SDALIGN);
4687                 data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
4688
4689                 /* Write test header cmd and extra based on mode */
4690                 switch (bus->pktgen_mode) {
4691                 case DHD_PKTGEN_ECHO:
4692                         *data++ = SDPCM_TEST_ECHOREQ;
4693                         *data++ = (u8) bus->pktgen_sent;
4694                         break;
4695
4696                 case DHD_PKTGEN_SEND:
4697                         *data++ = SDPCM_TEST_DISCARD;
4698                         *data++ = (u8) bus->pktgen_sent;
4699                         break;
4700
4701                 case DHD_PKTGEN_RXBURST:
4702                         *data++ = SDPCM_TEST_BURST;
4703                         *data++ = (u8) bus->pktgen_count;
4704                         break;
4705
4706                 default:
4707                         DHD_ERROR(("Unrecognized pktgen mode %d\n",
4708                                    bus->pktgen_mode));
4709                         bcm_pkt_buf_free_skb(pkt, true);
4710                         bus->pktgen_count = 0;
4711                         return;
4712                 }
4713
4714                 /* Write test header length field */
4715                 *data++ = (len >> 0);
4716                 *data++ = (len >> 8);
4717
4718                 /* Then fill in the remainder -- N/A for burst,
4719                          but who cares... */
4720                 for (fillbyte = 0; fillbyte < len; fillbyte++)
4721                         *data++ =
4722                             SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent);
4723
4724 #ifdef DHD_DEBUG
4725                 if (DHD_BYTES_ON() && DHD_DATA_ON()) {
4726                         data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
4727                         printk(KERN_DEBUG "dhdsdio_pktgen: Tx Data:\n");
4728                         print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data,
4729                                              pkt->len - SDPCM_HDRLEN);
4730                 }
4731 #endif
4732
4733                 /* Send it */
4734                 if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
4735                         bus->pktgen_fail++;
4736                         if (bus->pktgen_stop
4737                             && bus->pktgen_stop == bus->pktgen_fail)
4738                                 bus->pktgen_count = 0;
4739                 }
4740                 bus->pktgen_sent++;
4741
4742                 /* Bump length if not fixed, wrap at max */
4743                 if (++bus->pktgen_len > bus->pktgen_maxlen)
4744                         bus->pktgen_len = (u16) bus->pktgen_minlen;
4745
4746                 /* Special case for burst mode: just send one request! */
4747                 if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
4748                         break;
4749         }
4750 }
4751
4752 static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
4753 {
4754         struct sk_buff *pkt;
4755         u8 *data;
4756
4757         /* Allocate the packet */
4758         pkt = bcm_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
4759                 DHD_SDALIGN, true);
4760         if (!pkt) {
4761                 DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n", __func__));
4762                 return;
4763         }
4764         PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
4765         data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
4766
4767         /* Fill in the test header */
4768         *data++ = SDPCM_TEST_SEND;
4769         *data++ = start;
4770         *data++ = (bus->pktgen_maxlen >> 0);
4771         *data++ = (bus->pktgen_maxlen >> 8);
4772
4773         /* Send it */
4774         if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
4775                 bus->pktgen_fail++;
4776 }
4777
4778 static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
4779 {
4780         u8 *data;
4781         uint pktlen;
4782
4783         u8 cmd;
4784         u8 extra;
4785         u16 len;
4786         u16 offset;
4787
4788         /* Check for min length */
4789         pktlen = pkt->len;
4790         if (pktlen < SDPCM_TEST_HDRLEN) {
4791                 DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n",
4792                            pktlen));
4793                 bcm_pkt_buf_free_skb(pkt, false);
4794                 return;
4795         }
4796
4797         /* Extract header fields */
4798         data = pkt->data;
4799         cmd = *data++;
4800         extra = *data++;
4801         len = *data++;
4802         len += *data++ << 8;
4803
4804         /* Check length for relevant commands */
4805         if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ
4806             || cmd == SDPCM_TEST_ECHORSP) {
4807                 if (pktlen != len + SDPCM_TEST_HDRLEN) {
4808                         DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, "
4809                                 "pktlen %d seq %d" " cmd %d extra %d len %d\n",
4810                                 pktlen, seq, cmd, extra, len));
4811                         bcm_pkt_buf_free_skb(pkt, false);
4812                         return;
4813                 }
4814         }
4815
4816         /* Process as per command */
4817         switch (cmd) {
4818         case SDPCM_TEST_ECHOREQ:
4819                 /* Rx->Tx turnaround ok (even on NDIS w/current
4820                          implementation) */
4821                 *(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP;
4822                 if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0) {
4823                         bus->pktgen_sent++;
4824                 } else {
4825                         bus->pktgen_fail++;
4826                         bcm_pkt_buf_free_skb(pkt, false);
4827                 }
4828                 bus->pktgen_rcvd++;
4829                 break;
4830
4831         case SDPCM_TEST_ECHORSP:
4832                 if (bus->ext_loop) {
4833                         bcm_pkt_buf_free_skb(pkt, false);
4834                         bus->pktgen_rcvd++;
4835                         break;
4836                 }
4837
4838                 for (offset = 0; offset < len; offset++, data++) {
4839                         if (*data != SDPCM_TEST_FILL(offset, extra)) {
4840                                 DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: " "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
4841                                         offset, len,
4842                                         SDPCM_TEST_FILL(offset, extra), *data));
4843                                 break;
4844                         }
4845                 }
4846                 bcm_pkt_buf_free_skb(pkt, false);
4847                 bus->pktgen_rcvd++;
4848                 break;
4849
4850         case SDPCM_TEST_DISCARD:
4851                 bcm_pkt_buf_free_skb(pkt, false);
4852                 bus->pktgen_rcvd++;
4853                 break;
4854
4855         case SDPCM_TEST_BURST:
4856         case SDPCM_TEST_SEND:
4857         default:
4858                 DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, "
4859                         "pktlen %d seq %d" " cmd %d extra %d len %d\n",
4860                         pktlen, seq, cmd, extra, len));
4861                 bcm_pkt_buf_free_skb(pkt, false);
4862                 break;
4863         }
4864
4865         /* For recv mode, stop at limie (and tell dongle to stop sending) */
4866         if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
4867                 if (bus->pktgen_total
4868                     && (bus->pktgen_rcvd >= bus->pktgen_total)) {
4869                         bus->pktgen_count = 0;
4870                         dhdsdio_sdtest_set(bus, false);
4871                 }
4872         }
4873 }
4874 #endif                          /* SDTEST */
4875
4876 extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
4877 {
4878         dhd_bus_t *bus;
4879
4880         DHD_TIMER(("%s: Enter\n", __func__));
4881
4882         bus = dhdp->bus;
4883
4884         if (bus->dhd->dongle_reset)
4885                 return false;
4886
4887         /* Ignore the timer if simulating bus down */
4888         if (bus->sleeping)
4889                 return false;
4890
4891         dhd_os_sdlock(bus->dhd);
4892
4893         /* Poll period: check device if appropriate. */
4894         if (bus->poll && (++bus->polltick >= bus->pollrate)) {
4895                 u32 intstatus = 0;
4896
4897                 /* Reset poll tick */
4898                 bus->polltick = 0;
4899
4900                 /* Check device if no interrupts */
4901                 if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
4902
4903                         if (!bus->dpc_sched) {
4904                                 u8 devpend;
4905                                 devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
4906                                                           SDIOD_CCCR_INTPEND,
4907                                                           NULL);
4908                                 intstatus =
4909                                     devpend & (INTR_STATUS_FUNC1 |
4910                                                INTR_STATUS_FUNC2);
4911                         }
4912
4913                         /* If there is something, make like the ISR and
4914                                  schedule the DPC */
4915                         if (intstatus) {
4916                                 bus->pollcnt++;
4917                                 bus->ipend = true;
4918                                 if (bus->intr)
4919                                         bcmsdh_intr_disable(bus->sdh);
4920
4921                                 bus->dpc_sched = true;
4922                                 dhd_sched_dpc(bus->dhd);
4923
4924                         }
4925                 }
4926
4927                 /* Update interrupt tracking */
4928                 bus->lastintrs = bus->intrcount;
4929         }
4930 #ifdef DHD_DEBUG
4931         /* Poll for console output periodically */
4932         if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
4933                 bus->console.count += dhd_watchdog_ms;
4934                 if (bus->console.count >= dhd_console_ms) {
4935                         bus->console.count -= dhd_console_ms;
4936                         /* Make sure backplane clock is on */
4937                         dhdsdio_clkctl(bus, CLK_AVAIL, false);
4938                         if (dhdsdio_readconsole(bus) < 0)
4939                                 dhd_console_ms = 0;     /* On error,
4940                                                          stop trying */
4941                 }
4942         }
4943 #endif                          /* DHD_DEBUG */
4944
4945 #ifdef SDTEST
4946         /* Generate packets if configured */
4947         if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
4948                 /* Make sure backplane clock is on */
4949                 dhdsdio_clkctl(bus, CLK_AVAIL, false);
4950                 bus->pktgen_tick = 0;
4951                 dhdsdio_pktgen(bus);
4952         }
4953 #endif
4954
4955         /* On idle timeout clear activity flag and/or turn off clock */
4956         if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
4957                 if (++bus->idlecount >= bus->idletime) {
4958                         bus->idlecount = 0;
4959                         if (bus->activity) {
4960                                 bus->activity = false;
4961                                 dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
4962                         } else {
4963                                 dhdsdio_clkctl(bus, CLK_NONE, false);
4964                         }
4965                 }
4966         }
4967
4968         dhd_os_sdunlock(bus->dhd);
4969
4970         return bus->ipend;
4971 }
4972
4973 #ifdef DHD_DEBUG
4974 extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
4975 {
4976         dhd_bus_t *bus = dhdp->bus;
4977         u32 addr, val;
4978         int rv;
4979         struct sk_buff *pkt;
4980
4981         /* Address could be zero if CONSOLE := 0 in dongle Makefile */
4982         if (bus->console_addr == 0)
4983                 return -ENOTSUPP;
4984
4985         /* Exclusive bus access */
4986         dhd_os_sdlock(bus->dhd);
4987
4988         /* Don't allow input if dongle is in reset */
4989         if (bus->dhd->dongle_reset) {
4990                 dhd_os_sdunlock(bus->dhd);
4991                 return -EPERM;
4992         }
4993
4994         /* Request clock to allow SDIO accesses */
4995         BUS_WAKE(bus);
4996         /* No pend allowed since txpkt is called later, ht clk has to be on */
4997         dhdsdio_clkctl(bus, CLK_AVAIL, false);
4998
4999         /* Zero cbuf_index */
5000         addr = bus->console_addr + offsetof(rte_cons_t, cbuf_idx);
5001         val = cpu_to_le32(0);
5002         rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
5003         if (rv < 0)
5004                 goto done;
5005
5006         /* Write message into cbuf */
5007         addr = bus->console_addr + offsetof(rte_cons_t, cbuf);
5008         rv = dhdsdio_membytes(bus, true, addr, (u8 *)msg, msglen);
5009         if (rv < 0)
5010                 goto done;
5011
5012         /* Write length into vcons_in */
5013         addr = bus->console_addr + offsetof(rte_cons_t, vcons_in);
5014         val = cpu_to_le32(msglen);
5015         rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
5016         if (rv < 0)
5017                 goto done;
5018
5019         /* Bump dongle by sending an empty event pkt.
5020          * sdpcm_sendup (RX) checks for virtual console input.
5021          */
5022         pkt = bcm_pkt_buf_get_skb(4 + SDPCM_RESERVE);
5023         if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
5024                 dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
5025
5026 done:
5027         if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
5028                 bus->activity = false;
5029                 dhdsdio_clkctl(bus, CLK_NONE, true);
5030         }
5031
5032         dhd_os_sdunlock(bus->dhd);
5033
5034         return rv;
5035 }
5036 #endif                          /* DHD_DEBUG */
5037
5038 #ifdef DHD_DEBUG
5039 static void dhd_dump_cis(uint fn, u8 *cis)
5040 {
5041         uint byte, tag, tdata;
5042         DHD_INFO(("Function %d CIS:\n", fn));
5043
5044         for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
5045                 if ((byte % 16) == 0)
5046                         DHD_INFO(("    "));
5047                 DHD_INFO(("%02x ", cis[byte]));
5048                 if ((byte % 16) == 15)
5049                         DHD_INFO(("\n"));
5050                 if (!tdata--) {
5051                         tag = cis[byte];
5052                         if (tag == 0xff)
5053                                 break;
5054                         else if (!tag)
5055                                 tdata = 0;
5056                         else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
5057                                 tdata = cis[byte + 1] + 1;
5058                         else
5059                                 DHD_INFO(("]"));
5060                 }
5061         }
5062         if ((byte % 16) != 15)
5063                 DHD_INFO(("\n"));
5064 }
5065 #endif                          /* DHD_DEBUG */
5066
5067 static bool dhdsdio_chipmatch(u16 chipid)
5068 {
5069         if (chipid == BCM4325_CHIP_ID)
5070                 return true;
5071         if (chipid == BCM4329_CHIP_ID)
5072                 return true;
5073         if (chipid == BCM4319_CHIP_ID)
5074                 return true;
5075         return false;
5076 }
5077
5078 static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
5079                            u16 slot, u16 func, uint bustype, void *regsva,
5080                            void *sdh)
5081 {
5082         int ret;
5083         dhd_bus_t *bus;
5084
5085         /* Init global variables at run-time, not as part of the declaration.
5086          * This is required to support init/de-init of the driver.
5087          * Initialization
5088          * of globals as part of the declaration results in non-deterministic
5089          * behavior since the value of the globals may be different on the
5090          * first time that the driver is initialized vs subsequent
5091          * initializations.
5092          */
5093         dhd_txbound = DHD_TXBOUND;
5094         dhd_rxbound = DHD_RXBOUND;
5095         dhd_alignctl = true;
5096         sd1idle = true;
5097         dhd_readahead = true;
5098         retrydata = false;
5099         dhd_dongle_memsize = 0;
5100         dhd_txminmax = DHD_TXMINMAX;
5101
5102         forcealign = true;
5103
5104         dhd_common_init();
5105
5106         DHD_TRACE(("%s: Enter\n", __func__));
5107         DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
5108
5109         /* We make assumptions about address window mappings */
5110         ASSERT((unsigned long)regsva == SI_ENUM_BASE);
5111
5112         /* BCMSDH passes venid and devid based on CIS parsing -- but
5113          * low-power start
5114          * means early parse could fail, so here we should get either an ID
5115          * we recognize OR (-1) indicating we must request power first.
5116          */
5117         /* Check the Vendor ID */
5118         switch (venid) {
5119         case 0x0000:
5120         case PCI_VENDOR_ID_BROADCOM:
5121                 break;
5122         default:
5123                 DHD_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
5124                 return NULL;
5125         }
5126
5127         /* Check the Device ID and make sure it's one that we support */
5128         switch (devid) {
5129         case BCM4325_D11DUAL_ID:        /* 4325 802.11a/g id */
5130         case BCM4325_D11G_ID:   /* 4325 802.11g 2.4Ghz band id */
5131         case BCM4325_D11A_ID:   /* 4325 802.11a 5Ghz band id */
5132                 DHD_INFO(("%s: found 4325 Dongle\n", __func__));
5133                 break;
5134         case BCM4329_D11NDUAL_ID:       /* 4329 802.11n dualband device */
5135         case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
5136         case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
5137         case 0x4329:
5138                 DHD_INFO(("%s: found 4329 Dongle\n", __func__));
5139                 break;
5140         case BCM4319_D11N_ID:   /* 4319 802.11n id */
5141         case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
5142         case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
5143                 DHD_INFO(("%s: found 4319 Dongle\n", __func__));
5144                 break;
5145         case 0:
5146                 DHD_INFO(("%s: allow device id 0, will check chip internals\n",
5147                           __func__));
5148                 break;
5149
5150         default:
5151                 DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
5152                            __func__, venid, devid));
5153                 return NULL;
5154         }
5155
5156         /* Allocate private bus interface state */
5157         bus = kzalloc(sizeof(dhd_bus_t), GFP_ATOMIC);
5158         if (!bus) {
5159                 DHD_ERROR(("%s: kmalloc of dhd_bus_t failed\n", __func__));
5160                 goto fail;
5161         }
5162         bus->sdh = sdh;
5163         bus->cl_devid = (u16) devid;
5164         bus->bus = DHD_BUS;
5165         bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
5166         bus->usebufpool = false;        /* Use bufpool if allocated,
5167                                          else use locally malloced rxbuf */
5168
5169         /* attempt to attach to the dongle */
5170         if (!(dhdsdio_probe_attach(bus, sdh, regsva, devid))) {
5171                 DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __func__));
5172                 goto fail;
5173         }
5174
5175         /* Attach to the dhd/OS/network interface */
5176         bus->dhd = dhd_attach(bus, SDPCM_RESERVE);
5177         if (!bus->dhd) {
5178                 DHD_ERROR(("%s: dhd_attach failed\n", __func__));
5179                 goto fail;
5180         }
5181
5182         /* Allocate buffers */
5183         if (!(dhdsdio_probe_malloc(bus, sdh))) {
5184                 DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __func__));
5185                 goto fail;
5186         }
5187
5188         if (!(dhdsdio_probe_init(bus, sdh))) {
5189                 DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __func__));
5190                 goto fail;
5191         }
5192
5193         /* Register interrupt callback, but mask it (not operational yet). */
5194         DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
5195                   __func__));
5196         bcmsdh_intr_disable(sdh);
5197         ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus);
5198         if (ret != 0) {
5199                 DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
5200                            __func__, ret));
5201                 goto fail;
5202         }
5203         DHD_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
5204
5205         DHD_INFO(("%s: completed!!\n", __func__));
5206
5207         /* if firmware path present try to download and bring up bus */
5208         ret = dhd_bus_start(bus->dhd);
5209         if (ret != 0) {
5210                 if (ret == -ENOLINK) {
5211                         DHD_ERROR(("%s: dongle is not responding\n", __func__));
5212                         goto fail;
5213                 }
5214         }
5215         /* Ok, have the per-port tell the stack we're open for business */
5216         if (dhd_net_attach(bus->dhd, 0) != 0) {
5217                 DHD_ERROR(("%s: Net attach failed!!\n", __func__));
5218                 goto fail;
5219         }
5220
5221         return bus;
5222
5223 fail:
5224         dhdsdio_release(bus);
5225         return NULL;
5226 }
5227
5228 static bool
5229 dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
5230 {
5231         u8 clkctl = 0;
5232         int err = 0;
5233
5234         bus->alp_only = true;
5235
5236         /* Return the window to backplane enumeration space for core access */
5237         if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE))
5238                 DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __func__));
5239
5240 #ifdef DHD_DEBUG
5241         printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
5242                bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
5243
5244 #endif                          /* DHD_DEBUG */
5245
5246         /*
5247          * Force PLL off until dhdsdio_chip_attach()
5248          * programs PLL control regs
5249          */
5250
5251         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5252                          DHD_INIT_CLKCTL1, &err);
5253         if (!err)
5254                 clkctl =
5255                     bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5256                                     &err);
5257
5258         if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
5259                 DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote "
5260                         "0x%02x read 0x%02x\n",
5261                         err, DHD_INIT_CLKCTL1, clkctl));
5262                 goto fail;
5263         }
5264 #ifdef DHD_DEBUG
5265         if (DHD_INFO_ON()) {
5266                 uint fn, numfn;
5267                 u8 *cis[SDIOD_MAX_IOFUNCS];
5268                 int err = 0;
5269
5270                 numfn = bcmsdh_query_iofnum(sdh);
5271                 ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
5272
5273                 /* Make sure ALP is available before trying to read CIS */
5274                 SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
5275                                                     SBSDIO_FUNC1_CHIPCLKCSR,
5276                                                     NULL)),
5277                           !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
5278
5279                 /* Now request ALP be put on the bus */
5280                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
5281                                  DHD_INIT_CLKCTL2, &err);
5282                 udelay(65);
5283
5284                 for (fn = 0; fn <= numfn; fn++) {
5285                         cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
5286                         if (!cis[fn]) {
5287                                 DHD_INFO(("dhdsdio_probe: fn %d cis malloc "
5288                                         "failed\n", fn));
5289                                 break;
5290                         }
5291
5292                         err = bcmsdh_cis_read(sdh, fn, cis[fn],
5293                                                 SBSDIO_CIS_SIZE_LIMIT);
5294                         if (err) {
5295                                 DHD_INFO(("dhdsdio_probe: fn %d cis read "
5296                                         "err %d\n", fn, err));
5297                                 kfree(cis[fn]);
5298                                 break;
5299                         }
5300                         dhd_dump_cis(fn, cis[fn]);
5301                 }
5302
5303                 while (fn-- > 0) {
5304                         ASSERT(cis[fn]);
5305                         kfree(cis[fn]);
5306                 }
5307
5308                 if (err) {
5309                         DHD_ERROR(("dhdsdio_probe: error read/parsing CIS\n"));
5310                         goto fail;
5311                 }
5312         }
5313 #endif                          /* DHD_DEBUG */
5314
5315         if (dhdsdio_chip_attach(bus, regsva)) {
5316                 DHD_ERROR(("%s: dhdsdio_chip_attach failed!\n", __func__));
5317                 goto fail;
5318         }
5319
5320         bcmsdh_chipinfo(sdh, bus->ci->chip, bus->ci->chiprev);
5321
5322         if (!dhdsdio_chipmatch((u16) bus->ci->chip)) {
5323                 DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
5324                            __func__, bus->ci->chip));
5325                 goto fail;
5326         }
5327
5328         dhdsdio_sdiod_drive_strength_init(bus, dhd_sdiod_drive_strength);
5329
5330         /* Get info on the ARM and SOCRAM cores... */
5331         if (!DHD_NOPMU(bus)) {
5332                 bus->armrev = SBCOREREV(bcmsdh_reg_read(bus->sdh,
5333                         CORE_SB(bus->ci->armcorebase, sbidhigh), 4));
5334                 bus->orig_ramsize = bus->ci->ramsize;
5335                 if (!(bus->orig_ramsize)) {
5336                         DHD_ERROR(("%s: failed to find SOCRAM memory!\n",
5337                                    __func__));
5338                         goto fail;
5339                 }
5340                 bus->ramsize = bus->orig_ramsize;
5341                 if (dhd_dongle_memsize)
5342                         dhd_dongle_setmemsize(bus, dhd_dongle_memsize);
5343
5344                 DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
5345                            bus->ramsize, bus->orig_ramsize));
5346         }
5347
5348         bus->regs = (void *)bus->ci->buscorebase;
5349
5350         /* Set core control so an SDIO reset does a backplane reset */
5351         OR_REG(&bus->regs->corecontrol, CC_BPRESEN);
5352
5353         bcm_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
5354
5355         /* Locate an appropriately-aligned portion of hdrbuf */
5356         bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], DHD_SDALIGN);
5357
5358         /* Set the poll and/or interrupt flags */
5359         bus->intr = (bool) dhd_intr;
5360         bus->poll = (bool) dhd_poll;
5361         if (bus->poll)
5362                 bus->pollrate = 1;
5363
5364         return true;
5365
5366 fail:
5367         return false;
5368 }
5369
5370 static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
5371 {
5372         DHD_TRACE(("%s: Enter\n", __func__));
5373
5374         if (bus->dhd->maxctl) {
5375                 bus->rxblen =
5376                     roundup((bus->dhd->maxctl + SDPCM_HDRLEN),
5377                             ALIGNMENT) + DHD_SDALIGN;
5378                 bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
5379                 if (!(bus->rxbuf)) {
5380                         DHD_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
5381                                    __func__, bus->rxblen));
5382                         goto fail;
5383                 }
5384         }
5385
5386         /* Allocate buffer to receive glomed packet */
5387         bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
5388         if (!(bus->databuf)) {
5389                 DHD_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
5390                            __func__, MAX_DATA_BUF));
5391                 /* release rxbuf which was already located as above */
5392                 if (!bus->rxblen)
5393                         kfree(bus->rxbuf);
5394                 goto fail;
5395         }
5396
5397         /* Align the buffer */
5398         if ((unsigned long)bus->databuf % DHD_SDALIGN)
5399                 bus->dataptr =
5400                     bus->databuf + (DHD_SDALIGN -
5401                                     ((unsigned long)bus->databuf % DHD_SDALIGN));
5402         else
5403                 bus->dataptr = bus->databuf;
5404
5405         return true;
5406
5407 fail:
5408         return false;
5409 }
5410
5411 static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh)
5412 {
5413         s32 fnum;
5414
5415         DHD_TRACE(("%s: Enter\n", __func__));
5416
5417 #ifdef SDTEST
5418         dhdsdio_pktgen_init(bus);
5419 #endif                          /* SDTEST */
5420
5421         /* Disable F2 to clear any intermediate frame state on the dongle */
5422         bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1,
5423                          NULL);
5424
5425         bus->dhd->busstate = DHD_BUS_DOWN;
5426         bus->sleeping = false;
5427         bus->rxflow = false;
5428         bus->prev_rxlim_hit = 0;
5429
5430         /* Done with backplane-dependent accesses, can drop clock... */
5431         bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
5432
5433         /* ...and initialize clock/power states */
5434         bus->clkstate = CLK_SDONLY;
5435         bus->idletime = (s32) dhd_idletime;
5436         bus->idleclock = DHD_IDLE_ACTIVE;
5437
5438         /* Query the F2 block size, set roundup accordingly */
5439         fnum = 2;
5440         if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(s32),
5441                             &bus->blocksize, sizeof(s32), false) != 0) {
5442                 bus->blocksize = 0;
5443                 DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
5444         } else {
5445                 DHD_INFO(("%s: Initial value for %s is %d\n",
5446                           __func__, "sd_blocksize", bus->blocksize));
5447         }
5448         bus->roundup = min(max_roundup, bus->blocksize);
5449
5450         /* Query if bus module supports packet chaining,
5451                  default to use if supported */
5452         if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
5453                             &bus->sd_rxchain, sizeof(s32),
5454                             false) != 0) {
5455                 bus->sd_rxchain = false;
5456         } else {
5457                 DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
5458                           __func__,
5459                           (bus->sd_rxchain ? "supports" : "does not support")));
5460         }
5461         bus->use_rxchain = (bool) bus->sd_rxchain;
5462
5463         return true;
5464 }
5465
5466 bool
5467 dhd_bus_download_firmware(struct dhd_bus *bus, char *fw_path, char *nv_path)
5468 {
5469         bool ret;
5470         bus->fw_path = fw_path;
5471         bus->nv_path = nv_path;
5472
5473         ret = dhdsdio_download_firmware(bus, bus->sdh);
5474
5475         return ret;
5476 }
5477
5478 static bool
5479 dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh)
5480 {
5481         bool ret;
5482
5483         /* Download the firmware */
5484         dhdsdio_clkctl(bus, CLK_AVAIL, false);
5485
5486         ret = _dhdsdio_download_firmware(bus) == 0;
5487
5488         dhdsdio_clkctl(bus, CLK_SDONLY, false);
5489
5490         return ret;
5491 }
5492
5493 /* Detach and free everything */
5494 static void dhdsdio_release(dhd_bus_t *bus)
5495 {
5496         DHD_TRACE(("%s: Enter\n", __func__));
5497
5498         if (bus) {
5499                 /* De-register interrupt handler */
5500                 bcmsdh_intr_disable(bus->sdh);
5501                 bcmsdh_intr_dereg(bus->sdh);
5502
5503                 if (bus->dhd) {
5504                         dhd_detach(bus->dhd);
5505                         dhdsdio_release_dongle(bus);
5506                         bus->dhd = NULL;
5507                 }
5508
5509                 dhdsdio_release_malloc(bus);
5510
5511                 kfree(bus);
5512         }
5513
5514         DHD_TRACE(("%s: Disconnected\n", __func__));
5515 }
5516
5517 static void dhdsdio_release_malloc(dhd_bus_t *bus)
5518 {
5519         DHD_TRACE(("%s: Enter\n", __func__));
5520
5521         if (bus->dhd && bus->dhd->dongle_reset)
5522                 return;
5523
5524         if (bus->rxbuf) {
5525                 kfree(bus->rxbuf);
5526                 bus->rxctl = bus->rxbuf = NULL;
5527                 bus->rxlen = 0;
5528         }
5529
5530         kfree(bus->databuf);
5531         bus->databuf = NULL;
5532 }
5533
5534 static void dhdsdio_release_dongle(dhd_bus_t *bus)
5535 {
5536         DHD_TRACE(("%s: Enter\n", __func__));
5537
5538         if (bus->dhd && bus->dhd->dongle_reset)
5539                 return;
5540
5541         if (bus->ci) {
5542                 dhdsdio_clkctl(bus, CLK_AVAIL, false);
5543                 dhdsdio_clkctl(bus, CLK_NONE, false);
5544                 dhdsdio_chip_detach(bus);
5545                 if (bus->vars && bus->varsz)
5546                         kfree(bus->vars);
5547                 bus->vars = NULL;
5548         }
5549
5550         DHD_TRACE(("%s: Disconnected\n", __func__));
5551 }
5552
5553 static void dhdsdio_disconnect(void *ptr)
5554 {
5555         dhd_bus_t *bus = (dhd_bus_t *)ptr;
5556
5557         DHD_TRACE(("%s: Enter\n", __func__));
5558
5559         if (bus) {
5560                 ASSERT(bus->dhd);
5561                 dhdsdio_release(bus);
5562         }
5563
5564         DHD_TRACE(("%s: Disconnected\n", __func__));
5565 }
5566
5567 /* Register/Unregister functions are called by the main DHD entry
5568  * point (e.g. module insertion) to link with the bus driver, in
5569  * order to look for or await the device.
5570  */
5571
5572 static bcmsdh_driver_t dhd_sdio = {
5573         dhdsdio_probe,
5574         dhdsdio_disconnect
5575 };
5576
5577 int dhd_bus_register(void)
5578 {
5579         DHD_TRACE(("%s: Enter\n", __func__));
5580
5581         return bcmsdh_register(&dhd_sdio);
5582 }
5583
5584 void dhd_bus_unregister(void)
5585 {
5586         DHD_TRACE(("%s: Enter\n", __func__));
5587
5588         bcmsdh_unregister();
5589 }
5590
5591 #ifdef BCMEMBEDIMAGE
5592 static int dhdsdio_download_code_array(struct dhd_bus *bus)
5593 {
5594         int bcmerror = -1;
5595         int offset = 0;
5596
5597         DHD_INFO(("%s: download embedded firmware...\n", __func__));
5598
5599         /* Download image */
5600         while ((offset + MEMBLOCK) < sizeof(dlarray)) {
5601                 bcmerror =
5602                     dhdsdio_membytes(bus, true, offset, dlarray + offset,
5603                                      MEMBLOCK);
5604                 if (bcmerror) {
5605                         DHD_ERROR(("%s: error %d on writing %d membytes at "
5606                                 "0x%08x\n",
5607                                 __func__, bcmerror, MEMBLOCK, offset));
5608                         goto err;
5609                 }
5610
5611                 offset += MEMBLOCK;
5612         }
5613
5614         if (offset < sizeof(dlarray)) {
5615                 bcmerror = dhdsdio_membytes(bus, true, offset,
5616                                             dlarray + offset,
5617                                             sizeof(dlarray) - offset);
5618                 if (bcmerror) {
5619                         DHD_ERROR(("%s: error %d on writing %d membytes at "
5620                                 "0x%08x\n", __func__, bcmerror,
5621                                 sizeof(dlarray) - offset, offset));
5622                         goto err;
5623                 }
5624         }
5625 #ifdef DHD_DEBUG
5626         /* Upload and compare the downloaded code */
5627         {
5628                 unsigned char *ularray;
5629
5630                 ularray = kmalloc(bus->ramsize, GFP_ATOMIC);
5631                 if (!ularray) {
5632                         bcmerror = -ENOMEM;
5633                         goto err;
5634                 }
5635                 /* Upload image to verify downloaded contents. */
5636                 offset = 0;
5637                 memset(ularray, 0xaa, bus->ramsize);
5638                 while ((offset + MEMBLOCK) < sizeof(dlarray)) {
5639                         bcmerror =
5640                             dhdsdio_membytes(bus, false, offset,
5641                                              ularray + offset, MEMBLOCK);
5642                         if (bcmerror) {
5643                                 DHD_ERROR(("%s: error %d on reading %d membytes"
5644                                         " at 0x%08x\n",
5645                                         __func__, bcmerror, MEMBLOCK, offset));
5646                                 goto free;
5647                         }
5648
5649                         offset += MEMBLOCK;
5650                 }
5651
5652                 if (offset < sizeof(dlarray)) {
5653                         bcmerror = dhdsdio_membytes(bus, false, offset,
5654                                                     ularray + offset,
5655                                                     sizeof(dlarray) - offset);
5656                         if (bcmerror) {
5657                                 DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
5658                                 __func__, bcmerror,
5659                                 sizeof(dlarray) - offset, offset));
5660                                 goto free;
5661                         }
5662                 }
5663
5664                 if (memcmp(dlarray, ularray, sizeof(dlarray))) {
5665                         DHD_ERROR(("%s: Downloaded image is corrupted.\n",
5666                                    __func__));
5667                         ASSERT(0);
5668                         goto free;
5669                 } else
5670                         DHD_ERROR(("%s: Download/Upload/Compare succeeded.\n",
5671                                 __func__));
5672 free:
5673                 kfree(ularray);
5674         }
5675 #endif                          /* DHD_DEBUG */
5676
5677 err:
5678         return bcmerror;
5679 }
5680 #endif                          /* BCMEMBEDIMAGE */
5681
5682 static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
5683 {
5684         int bcmerror = -1;
5685         int offset = 0;
5686         uint len;
5687         void *image = NULL;
5688         u8 *memblock = NULL, *memptr;
5689
5690         DHD_INFO(("%s: download firmware %s\n", __func__, fw_path));
5691
5692         image = dhd_os_open_image(fw_path);
5693         if (image == NULL)
5694                 goto err;
5695
5696         memptr = memblock = kmalloc(MEMBLOCK + DHD_SDALIGN, GFP_ATOMIC);
5697         if (memblock == NULL) {
5698                 DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
5699                            __func__, MEMBLOCK));
5700                 goto err;
5701         }
5702         if ((u32)(unsigned long)memblock % DHD_SDALIGN)
5703                 memptr +=
5704                     (DHD_SDALIGN - ((u32)(unsigned long)memblock % DHD_SDALIGN));
5705
5706         /* Download image */
5707         while ((len =
5708                 dhd_os_get_image_block((char *)memptr, MEMBLOCK, image))) {
5709                 bcmerror = dhdsdio_membytes(bus, true, offset, memptr, len);
5710                 if (bcmerror) {
5711                         DHD_ERROR(("%s: error %d on writing %d membytes at "
5712                         "0x%08x\n", __func__, bcmerror, MEMBLOCK, offset));
5713                         goto err;
5714                 }
5715
5716                 offset += MEMBLOCK;
5717         }
5718
5719 err:
5720         kfree(memblock);
5721
5722         if (image)
5723                 dhd_os_close_image(image);
5724
5725         return bcmerror;
5726 }
5727
5728 /*
5729  * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file
5730  * and ending in a NUL.
5731  * Removes carriage returns, empty lines, comment lines, and converts
5732  * newlines to NULs.
5733  * Shortens buffer as needed and pads with NULs.  End of buffer is marked
5734  * by two NULs.
5735 */
5736
5737 static uint process_nvram_vars(char *varbuf, uint len)
5738 {
5739         char *dp;
5740         bool findNewline;
5741         int column;
5742         uint buf_len, n;
5743
5744         dp = varbuf;
5745
5746         findNewline = false;
5747         column = 0;
5748
5749         for (n = 0; n < len; n++) {
5750                 if (varbuf[n] == 0)
5751                         break;
5752                 if (varbuf[n] == '\r')
5753                         continue;
5754                 if (findNewline && varbuf[n] != '\n')
5755                         continue;
5756                 findNewline = false;
5757                 if (varbuf[n] == '#') {
5758                         findNewline = true;
5759                         continue;
5760                 }
5761                 if (varbuf[n] == '\n') {
5762                         if (column == 0)
5763                                 continue;
5764                         *dp++ = 0;
5765                         column = 0;
5766                         continue;
5767                 }
5768                 *dp++ = varbuf[n];
5769                 column++;
5770         }
5771         buf_len = dp - varbuf;
5772
5773         while (dp < varbuf + n)
5774                 *dp++ = 0;
5775
5776         return buf_len;
5777 }
5778
5779 /*
5780         EXAMPLE: nvram_array
5781         nvram_arry format:
5782         name=value
5783         Use carriage return at the end of each assignment,
5784          and an empty string with
5785         carriage return at the end of array.
5786
5787         For example:
5788         unsigned char  nvram_array[] = {"name1=value1\n",
5789         "name2=value2\n", "\n"};
5790         Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
5791
5792         Search "EXAMPLE: nvram_array" to see how the array is activated.
5793 */
5794
5795 void dhd_bus_set_nvram_params(struct dhd_bus *bus, const char *nvram_params)
5796 {
5797         bus->nvram_params = nvram_params;
5798 }
5799
5800 static int dhdsdio_download_nvram(struct dhd_bus *bus)
5801 {
5802         int bcmerror = -1;
5803         uint len;
5804         void *image = NULL;
5805         char *memblock = NULL;
5806         char *bufp;
5807         char *nv_path;
5808         bool nvram_file_exists;
5809
5810         nv_path = bus->nv_path;
5811
5812         nvram_file_exists = ((nv_path != NULL) && (nv_path[0] != '\0'));
5813         if (!nvram_file_exists && (bus->nvram_params == NULL))
5814                 return 0;
5815
5816         if (nvram_file_exists) {
5817                 image = dhd_os_open_image(nv_path);
5818                 if (image == NULL)
5819                         goto err;
5820         }
5821
5822         memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
5823         if (memblock == NULL) {
5824                 DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
5825                            __func__, MEMBLOCK));
5826                 goto err;
5827         }
5828
5829         /* Download variables */
5830         if (nvram_file_exists) {
5831                 len = dhd_os_get_image_block(memblock, MEMBLOCK, image);
5832         } else {
5833                 len = strlen(bus->nvram_params);
5834                 ASSERT(len <= MEMBLOCK);
5835                 if (len > MEMBLOCK)
5836                         len = MEMBLOCK;
5837                 memcpy(memblock, bus->nvram_params, len);
5838         }
5839
5840         if (len > 0 && len < MEMBLOCK) {
5841                 bufp = (char *)memblock;
5842                 bufp[len] = 0;
5843                 len = process_nvram_vars(bufp, len);
5844                 bufp += len;
5845                 *bufp++ = 0;
5846                 if (len)
5847                         bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
5848                 if (bcmerror) {
5849                         DHD_ERROR(("%s: error downloading vars: %d\n",
5850                                    __func__, bcmerror));
5851                 }
5852         } else {
5853                 DHD_ERROR(("%s: error reading nvram file: %d\n",
5854                            __func__, len));
5855                 bcmerror = -EIO;
5856         }
5857
5858 err:
5859         kfree(memblock);
5860
5861         if (image)
5862                 dhd_os_close_image(image);
5863
5864         return bcmerror;
5865 }
5866
5867 static int _dhdsdio_download_firmware(struct dhd_bus *bus)
5868 {
5869         int bcmerror = -1;
5870
5871         bool embed = false;     /* download embedded firmware */
5872         bool dlok = false;      /* download firmware succeeded */
5873
5874         /* Out immediately if no image to download */
5875         if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
5876 #ifdef BCMEMBEDIMAGE
5877                 embed = true;
5878 #else
5879                 return bcmerror;
5880 #endif
5881         }
5882
5883         /* Keep arm in reset */
5884         if (dhdsdio_download_state(bus, true)) {
5885                 DHD_ERROR(("%s: error placing ARM core in reset\n", __func__));
5886                 goto err;
5887         }
5888
5889         /* External image takes precedence if specified */
5890         if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
5891                 if (dhdsdio_download_code_file(bus, bus->fw_path)) {
5892                         DHD_ERROR(("%s: dongle image file download failed\n",
5893                                    __func__));
5894 #ifdef BCMEMBEDIMAGE
5895                         embed = true;
5896 #else
5897                         goto err;
5898 #endif
5899                 } else {
5900                         embed = false;
5901                         dlok = true;
5902                 }
5903         }
5904 #ifdef BCMEMBEDIMAGE
5905         if (embed) {
5906                 if (dhdsdio_download_code_array(bus)) {
5907                         DHD_ERROR(("%s: dongle image array download failed\n",
5908                                    __func__));
5909                         goto err;
5910                 } else {
5911                         dlok = true;
5912                 }
5913         }
5914 #endif
5915         if (!dlok) {
5916                 DHD_ERROR(("%s: dongle image download failed\n", __func__));
5917                 goto err;
5918         }
5919
5920         /* EXAMPLE: nvram_array */
5921         /* If a valid nvram_arry is specified as above, it can be passed
5922                  down to dongle */
5923         /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
5924
5925         /* External nvram takes precedence if specified */
5926         if (dhdsdio_download_nvram(bus)) {
5927                 DHD_ERROR(("%s: dongle nvram file download failed\n",
5928                            __func__));
5929         }
5930
5931         /* Take arm out of reset */
5932         if (dhdsdio_download_state(bus, false)) {
5933                 DHD_ERROR(("%s: error getting out of ARM core reset\n",
5934                            __func__));
5935                 goto err;
5936         }
5937
5938         bcmerror = 0;
5939
5940 err:
5941         return bcmerror;
5942 }
5943
5944
5945 static int
5946 dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn, uint flags,
5947                     u8 *buf, uint nbytes, struct sk_buff *pkt,
5948                     bcmsdh_cmplt_fn_t complete, void *handle)
5949 {
5950         return bcmsdh_send_buf
5951                 (bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete,
5952                  handle);
5953 }
5954
5955 uint dhd_bus_chip(struct dhd_bus *bus)
5956 {
5957         ASSERT(bus->ci != NULL);
5958         return bus->ci->chip;
5959 }
5960
5961 void *dhd_bus_pub(struct dhd_bus *bus)
5962 {
5963         return bus->dhd;
5964 }
5965
5966 void *dhd_bus_txq(struct dhd_bus *bus)
5967 {
5968         return &bus->txq;
5969 }
5970
5971 uint dhd_bus_hdrlen(struct dhd_bus *bus)
5972 {
5973         return SDPCM_HDRLEN;
5974 }
5975
5976 int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag)
5977 {
5978         int bcmerror = 0;
5979         dhd_bus_t *bus;
5980
5981         bus = dhdp->bus;
5982
5983         if (flag == true) {
5984                 if (!bus->dhd->dongle_reset) {
5985                         /* Expect app to have torn down any
5986                          connection before calling */
5987                         /* Stop the bus, disable F2 */
5988                         dhd_bus_stop(bus, false);
5989
5990                         /* Clean tx/rx buffer pointers,
5991                          detach from the dongle */
5992                         dhdsdio_release_dongle(bus);
5993
5994                         bus->dhd->dongle_reset = true;
5995                         bus->dhd->up = false;
5996
5997                         DHD_TRACE(("%s:  WLAN OFF DONE\n", __func__));
5998                         /* App can now remove power from device */
5999                 } else
6000                         bcmerror = -EIO;
6001         } else {
6002                 /* App must have restored power to device before calling */
6003
6004                 DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
6005
6006                 if (bus->dhd->dongle_reset) {
6007                         /* Turn on WLAN */
6008                         /* Reset SD client */
6009                         bcmsdh_reset(bus->sdh);
6010
6011                         /* Attempt to re-attach & download */
6012                         if (dhdsdio_probe_attach(bus, bus->sdh,
6013                                                  (u32 *) SI_ENUM_BASE,
6014                                                  bus->cl_devid)) {
6015                                 /* Attempt to download binary to the dongle */
6016                                 if (dhdsdio_probe_init
6017                                     (bus, bus->sdh)
6018                                     && dhdsdio_download_firmware(bus,
6019                                                                  bus->sdh)) {
6020
6021                                         /* Re-init bus, enable F2 transfer */
6022                                         dhd_bus_init((dhd_pub_t *) bus->dhd,
6023                                                      false);
6024
6025 #if defined(OOB_INTR_ONLY)
6026                                         dhd_enable_oob_intr(bus, true);
6027 #endif                          /* defined(OOB_INTR_ONLY) */
6028
6029                                         bus->dhd->dongle_reset = false;
6030                                         bus->dhd->up = true;
6031
6032                                         DHD_TRACE(("%s: WLAN ON DONE\n",
6033                                                    __func__));
6034                                 } else
6035                                         bcmerror = -EIO;
6036                         } else
6037                                 bcmerror = -EIO;
6038                 } else {
6039                         bcmerror = -EISCONN;
6040                         DHD_ERROR(("%s: Set DEVRESET=false invoked when device "
6041                                 "is on\n", __func__));
6042                         bcmerror = -EIO;
6043                 }
6044         }
6045         return bcmerror;
6046 }
6047
6048 static int
6049 dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
6050 {
6051         u32 regdata;
6052
6053         /*
6054          * Get CC core rev
6055          * Chipid is assume to be at offset 0 from regs arg
6056          * For different chiptypes or old sdio hosts w/o chipcommon,
6057          * other ways of recognition should be added here.
6058          */
6059         ci->cccorebase = (u32)regs;
6060         regdata = bcmsdh_reg_read(sdh, CORE_CC_REG(ci->cccorebase, chipid), 4);
6061         ci->chip = regdata & CID_ID_MASK;
6062         ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
6063
6064         DHD_INFO(("%s: chipid=0x%x chiprev=%d\n",
6065                 __func__, ci->chip, ci->chiprev));
6066
6067         /* Address of cores for new chips should be added here */
6068         switch (ci->chip) {
6069         case BCM4329_CHIP_ID:
6070                 ci->buscorebase = BCM4329_CORE_BUS_BASE;
6071                 ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
6072                 ci->armcorebase = BCM4329_CORE_ARM_BASE;
6073                 ci->ramsize = BCM4329_RAMSIZE;
6074                 break;
6075         default:
6076                 DHD_ERROR(("%s: chipid 0x%x is not supported\n",
6077                         __func__, ci->chip));
6078                 return -ENODEV;
6079         }
6080
6081         regdata = bcmsdh_reg_read(sdh,
6082                 CORE_SB(ci->cccorebase, sbidhigh), 4);
6083         ci->ccrev = SBCOREREV(regdata);
6084
6085         regdata = bcmsdh_reg_read(sdh,
6086                 CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
6087         ci->pmurev = regdata & PCAP_REV_MASK;
6088
6089         regdata = bcmsdh_reg_read(sdh, CORE_SB(ci->buscorebase, sbidhigh), 4);
6090         ci->buscorerev = SBCOREREV(regdata);
6091         ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
6092
6093         DHD_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
6094                 __func__, ci->ccrev, ci->pmurev,
6095                 ci->buscorerev, ci->buscoretype));
6096
6097         /* get chipcommon capabilites */
6098         ci->cccaps = bcmsdh_reg_read(sdh,
6099                 CORE_CC_REG(ci->cccorebase, capabilities), 4);
6100
6101         return 0;
6102 }
6103
6104 static void
6105 dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase)
6106 {
6107         u32 regdata;
6108
6109         regdata = bcmsdh_reg_read(sdh,
6110                 CORE_SB(corebase, sbtmstatelow), 4);
6111         if (regdata & SBTML_RESET)
6112                 return;
6113
6114         regdata = bcmsdh_reg_read(sdh,
6115                 CORE_SB(corebase, sbtmstatelow), 4);
6116         if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
6117                 /*
6118                  * set target reject and spin until busy is clear
6119                  * (preserve core-specific bits)
6120                  */
6121                 regdata = bcmsdh_reg_read(sdh,
6122                         CORE_SB(corebase, sbtmstatelow), 4);
6123                 bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6124                         regdata | SBTML_REJ);
6125
6126                 regdata = bcmsdh_reg_read(sdh,
6127                         CORE_SB(corebase, sbtmstatelow), 4);
6128                 udelay(1);
6129                 SPINWAIT((bcmsdh_reg_read(sdh,
6130                         CORE_SB(corebase, sbtmstatehigh), 4) &
6131                         SBTMH_BUSY), 100000);
6132
6133                 regdata = bcmsdh_reg_read(sdh,
6134                         CORE_SB(corebase, sbtmstatehigh), 4);
6135                 if (regdata & SBTMH_BUSY)
6136                         DHD_ERROR(("%s: ARM core still busy\n", __func__));
6137
6138                 regdata = bcmsdh_reg_read(sdh,
6139                         CORE_SB(corebase, sbidlow), 4);
6140                 if (regdata & SBIDL_INIT) {
6141                         regdata = bcmsdh_reg_read(sdh,
6142                                 CORE_SB(corebase, sbimstate), 4) |
6143                                 SBIM_RJ;
6144                         bcmsdh_reg_write(sdh,
6145                                 CORE_SB(corebase, sbimstate), 4,
6146                                 regdata);
6147                         regdata = bcmsdh_reg_read(sdh,
6148                                 CORE_SB(corebase, sbimstate), 4);
6149                         udelay(1);
6150                         SPINWAIT((bcmsdh_reg_read(sdh,
6151                                 CORE_SB(corebase, sbimstate), 4) &
6152                                 SBIM_BY), 100000);
6153                 }
6154
6155                 /* set reset and reject while enabling the clocks */
6156                 bcmsdh_reg_write(sdh,
6157                         CORE_SB(corebase, sbtmstatelow), 4,
6158                         (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
6159                         SBTML_REJ | SBTML_RESET));
6160                 regdata = bcmsdh_reg_read(sdh,
6161                         CORE_SB(corebase, sbtmstatelow), 4);
6162                 udelay(10);
6163
6164                 /* clear the initiator reject bit */
6165                 regdata = bcmsdh_reg_read(sdh,
6166                         CORE_SB(corebase, sbidlow), 4);
6167                 if (regdata & SBIDL_INIT) {
6168                         regdata = bcmsdh_reg_read(sdh,
6169                                 CORE_SB(corebase, sbimstate), 4) &
6170                                 ~SBIM_RJ;
6171                         bcmsdh_reg_write(sdh,
6172                                 CORE_SB(corebase, sbimstate), 4,
6173                                 regdata);
6174                 }
6175         }
6176
6177         /* leave reset and reject asserted */
6178         bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6179                 (SBTML_REJ | SBTML_RESET));
6180         udelay(1);
6181 }
6182
6183 static int
6184 dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
6185 {
6186         struct chip_info *ci;
6187         int err;
6188         u8 clkval, clkset;
6189
6190         DHD_TRACE(("%s: Enter\n", __func__));
6191
6192         /* alloc chip_info_t */
6193         ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
6194         if (NULL == ci) {
6195                 DHD_ERROR(("%s: malloc failed!\n", __func__));
6196                 return -ENOMEM;
6197         }
6198
6199         memset((unsigned char *)ci, 0, sizeof(struct chip_info));
6200
6201         /* bus/core/clk setup for register access */
6202         /* Try forcing SDIO core to do ALPAvail request only */
6203         clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
6204         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
6205                         clkset, &err);
6206         if (err) {
6207                 DHD_ERROR(("%s: error writing for HT off\n", __func__));
6208                 goto fail;
6209         }
6210
6211         /* If register supported, wait for ALPAvail and then force ALP */
6212         /* This may take up to 15 milliseconds */
6213         clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
6214                         SBSDIO_FUNC1_CHIPCLKCSR, NULL);
6215         if ((clkval & ~SBSDIO_AVBITS) == clkset) {
6216                 SPINWAIT(((clkval =
6217                                 bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
6218                                                 SBSDIO_FUNC1_CHIPCLKCSR,
6219                                                 NULL)),
6220                                 !SBSDIO_ALPAV(clkval)),
6221                                 PMU_MAX_TRANSITION_DLY);
6222                 if (!SBSDIO_ALPAV(clkval)) {
6223                         DHD_ERROR(("%s: timeout on ALPAV wait, clkval 0x%02x\n",
6224                                 __func__, clkval));
6225                         err = -EBUSY;
6226                         goto fail;
6227                 }
6228                 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
6229                                 SBSDIO_FORCE_ALP;
6230                 bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
6231                                 SBSDIO_FUNC1_CHIPCLKCSR,
6232                                 clkset, &err);
6233                 udelay(65);
6234         } else {
6235                 DHD_ERROR(("%s: ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
6236                         __func__, clkset, clkval));
6237                 err = -EACCES;
6238                 goto fail;
6239         }
6240
6241         /* Also, disable the extra SDIO pull-ups */
6242         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
6243                          NULL);
6244
6245         err = dhdsdio_chip_recognition(bus->sdh, ci, regs);
6246         if (err)
6247                 goto fail;
6248
6249         /*
6250          * Make sure any on-chip ARM is off (in case strapping is wrong),
6251          * or downloaded code was already running.
6252          */
6253         dhdsdio_chip_disablecore(bus->sdh, ci->armcorebase);
6254
6255         bcmsdh_reg_write(bus->sdh,
6256                 CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
6257         bcmsdh_reg_write(bus->sdh,
6258                 CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
6259
6260         /* Disable F2 to clear any intermediate frame state on the dongle */
6261         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
6262                 SDIO_FUNC_ENABLE_1, NULL);
6263
6264         /* WAR: cmd52 backplane read so core HW will drop ALPReq */
6265         clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
6266                         0, NULL);
6267
6268         /* Done with backplane-dependent accesses, can drop clock... */
6269         bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
6270                          NULL);
6271
6272         bus->ci = ci;
6273         return 0;
6274 fail:
6275         bus->ci = NULL;
6276         kfree(ci);
6277         return err;
6278 }
6279
6280 static void
6281 dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase)
6282 {
6283         u32 regdata;
6284
6285         /*
6286          * Must do the disable sequence first to work for
6287          * arbitrary current core state.
6288          */
6289         dhdsdio_chip_disablecore(sdh, corebase);
6290
6291         /*
6292          * Now do the initialization sequence.
6293          * set reset while enabling the clock and
6294          * forcing them on throughout the core
6295          */
6296         bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6297                 ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
6298                 SBTML_RESET);
6299         udelay(1);
6300
6301         regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbtmstatehigh), 4);
6302         if (regdata & SBTMH_SERR)
6303                 bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatehigh), 4, 0);
6304
6305         regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbimstate), 4);
6306         if (regdata & (SBIM_IBE | SBIM_TO))
6307                 bcmsdh_reg_write(sdh, CORE_SB(corebase, sbimstate), 4,
6308                         regdata & ~(SBIM_IBE | SBIM_TO));
6309
6310         /* clear reset and allow it to propagate throughout the core */
6311         bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6312                 (SICF_FGC << SBTML_SICF_SHIFT) |
6313                 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
6314         udelay(1);
6315
6316         /* leave clock enabled */
6317         bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
6318                 (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
6319         udelay(1);
6320 }
6321
6322 /* SDIO Pad drive strength to select value mappings */
6323 struct sdiod_drive_str {
6324         u8 strength;    /* Pad Drive Strength in mA */
6325         u8 sel;         /* Chip-specific select value */
6326 };
6327
6328 /* SDIO Drive Strength to sel value table for PMU Rev 1 */
6329 static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
6330         {
6331         4, 0x2}, {
6332         2, 0x3}, {
6333         1, 0x0}, {
6334         0, 0x0}
6335         };
6336
6337 /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
6338 static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
6339         {
6340         12, 0x7}, {
6341         10, 0x6}, {
6342         8, 0x5}, {
6343         6, 0x4}, {
6344         4, 0x2}, {
6345         2, 0x1}, {
6346         0, 0x0}
6347         };
6348
6349 /* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
6350 static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
6351         {
6352         32, 0x7}, {
6353         26, 0x6}, {
6354         22, 0x5}, {
6355         16, 0x4}, {
6356         12, 0x3}, {
6357         8, 0x2}, {
6358         4, 0x1}, {
6359         0, 0x0}
6360         };
6361
6362 #define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
6363
6364 static void
6365 dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
6366         struct sdiod_drive_str *str_tab = NULL;
6367         u32 str_mask = 0;
6368         u32 str_shift = 0;
6369         char chn[8];
6370
6371         if (!(bus->ci->cccaps & CC_CAP_PMU))
6372                 return;
6373
6374         switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->ci->pmurev)) {
6375         case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
6376                 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
6377                 str_mask = 0x30000000;
6378                 str_shift = 28;
6379                 break;
6380         case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
6381         case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
6382                 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
6383                 str_mask = 0x00003800;
6384                 str_shift = 11;
6385                 break;
6386         case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
6387                 str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
6388                 str_mask = 0x00003800;
6389                 str_shift = 11;
6390                 break;
6391         default:
6392                 DHD_ERROR(("No SDIO Drive strength init"
6393                         "done for chip %s rev %d pmurev %d\n",
6394                         bcm_chipname(bus->ci->chip, chn, 8),
6395                         bus->ci->chiprev, bus->ci->pmurev));
6396                 break;
6397         }
6398
6399         if (str_tab != NULL) {
6400                 u32 drivestrength_sel = 0;
6401                 u32 cc_data_temp;
6402                 int i;
6403
6404                 for (i = 0; str_tab[i].strength != 0; i++) {
6405                         if (drivestrength >= str_tab[i].strength) {
6406                                 drivestrength_sel = str_tab[i].sel;
6407                                 break;
6408                         }
6409                 }
6410
6411                 bcmsdh_reg_write(bus->sdh,
6412                         CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
6413                         4, 1);
6414                 cc_data_temp = bcmsdh_reg_read(bus->sdh,
6415                         CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
6416                 cc_data_temp &= ~str_mask;
6417                 drivestrength_sel <<= str_shift;
6418                 cc_data_temp |= drivestrength_sel;
6419                 bcmsdh_reg_write(bus->sdh,
6420                         CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
6421                         4, cc_data_temp);
6422
6423                 DHD_INFO(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
6424                         drivestrength, cc_data_temp));
6425         }
6426 }
6427
6428 static void
6429 dhdsdio_chip_detach(struct dhd_bus *bus)
6430 {
6431         DHD_TRACE(("%s: Enter\n", __func__));
6432
6433         kfree(bus->ci);
6434         bus->ci = NULL;
6435 }