~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/util/hnddma.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
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/kernel.h>
18
 
#include <linux/string.h>
19
 
#include <linux/netdevice.h>
20
 
#include <linux/pci.h>
21
 
#include <bcmdefs.h>
22
 
#include <bcmdevs.h>
23
 
#include <hndsoc.h>
24
 
#include <bcmutils.h>
25
 
#include <siutils.h>
26
 
 
27
 
#include <sbhnddma.h>
28
 
#include <hnddma.h>
29
 
 
30
 
#if defined(__mips__)
31
 
#include <asm/addrspace.h>
32
 
#endif
33
 
 
34
 
#ifdef BRCM_FULLMAC
35
 
#error "hnddma.c shouldn't be needed for FULLMAC"
36
 
#endif
37
 
 
38
 
/* debug/trace */
39
 
#ifdef BCMDBG
40
 
#define DMA_ERROR(args) \
41
 
        do { \
42
 
                if (!(*di->msg_level & 1)) \
43
 
                        ; \
44
 
                else \
45
 
                        printk args; \
46
 
        } while (0)
47
 
#define DMA_TRACE(args) \
48
 
        do { \
49
 
                if (!(*di->msg_level & 2)) \
50
 
                        ; \
51
 
                else \
52
 
                        printk args; \
53
 
        } while (0)
54
 
#else
55
 
#define DMA_ERROR(args)
56
 
#define DMA_TRACE(args)
57
 
#endif                          /* BCMDBG */
58
 
 
59
 
#define DMA_NONE(args)
60
 
 
61
 
#define d64txregs       dregs.d64_u.txregs_64
62
 
#define d64rxregs       dregs.d64_u.rxregs_64
63
 
#define txd64           dregs.d64_u.txd_64
64
 
#define rxd64           dregs.d64_u.rxd_64
65
 
 
66
 
/* default dma message level (if input msg_level pointer is null in dma_attach()) */
67
 
static uint dma_msg_level;
68
 
 
69
 
#define MAXNAMEL        8       /* 8 char names */
70
 
 
71
 
#define DI_INFO(dmah)   ((dma_info_t *)dmah)
72
 
 
73
 
#define R_SM(r)         (*(r))
74
 
#define W_SM(r, v)      (*(r) = (v))
75
 
 
76
 
/* dma engine software state */
77
 
typedef struct dma_info {
78
 
        struct hnddma_pub hnddma; /* exported structure */
79
 
        uint *msg_level;        /* message level pointer */
80
 
        char name[MAXNAMEL];    /* callers name for diag msgs */
81
 
 
82
 
        void *pbus;             /* bus handle */
83
 
 
84
 
        bool dma64;             /* this dma engine is operating in 64-bit mode */
85
 
        bool addrext;           /* this dma engine supports DmaExtendedAddrChanges */
86
 
 
87
 
        union {
88
 
                struct {
89
 
                        dma64regs_t *txregs_64; /* 64-bit dma tx engine registers */
90
 
                        dma64regs_t *rxregs_64; /* 64-bit dma rx engine registers */
91
 
                        dma64dd_t *txd_64;      /* pointer to dma64 tx descriptor ring */
92
 
                        dma64dd_t *rxd_64;      /* pointer to dma64 rx descriptor ring */
93
 
                } d64_u;
94
 
        } dregs;
95
 
 
96
 
        u16 dmadesc_align;      /* alignment requirement for dma descriptors */
97
 
 
98
 
        u16 ntxd;               /* # tx descriptors tunable */
99
 
        u16 txin;               /* index of next descriptor to reclaim */
100
 
        u16 txout;              /* index of next descriptor to post */
101
 
        void **txp;             /* pointer to parallel array of pointers to packets */
102
 
        hnddma_seg_map_t *txp_dmah;     /* DMA MAP meta-data handle */
103
 
        dmaaddr_t txdpa;        /* Aligned physical address of descriptor ring */
104
 
        dmaaddr_t txdpaorig;    /* Original physical address of descriptor ring */
105
 
        u16 txdalign;   /* #bytes added to alloc'd mem to align txd */
106
 
        u32 txdalloc;   /* #bytes allocated for the ring */
107
 
        u32 xmtptrbase; /* When using unaligned descriptors, the ptr register
108
 
                                 * is not just an index, it needs all 13 bits to be
109
 
                                 * an offset from the addr register.
110
 
                                 */
111
 
 
112
 
        u16 nrxd;               /* # rx descriptors tunable */
113
 
        u16 rxin;               /* index of next descriptor to reclaim */
114
 
        u16 rxout;              /* index of next descriptor to post */
115
 
        void **rxp;             /* pointer to parallel array of pointers to packets */
116
 
        hnddma_seg_map_t *rxp_dmah;     /* DMA MAP meta-data handle */
117
 
        dmaaddr_t rxdpa;        /* Aligned physical address of descriptor ring */
118
 
        dmaaddr_t rxdpaorig;    /* Original physical address of descriptor ring */
119
 
        u16 rxdalign;   /* #bytes added to alloc'd mem to align rxd */
120
 
        u32 rxdalloc;   /* #bytes allocated for the ring */
121
 
        u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */
122
 
 
123
 
        /* tunables */
124
 
        unsigned int rxbufsize; /* rx buffer size in bytes,
125
 
                                 * not including the extra headroom
126
 
                                 */
127
 
        uint rxextrahdrroom;    /* extra rx headroom, reverseved to assist upper stack
128
 
                                 *  e.g. some rx pkt buffers will be bridged to tx side
129
 
                                 *  without byte copying. The extra headroom needs to be
130
 
                                 *  large enough to fit txheader needs.
131
 
                                 *  Some dongle driver may not need it.
132
 
                                 */
133
 
        uint nrxpost;           /* # rx buffers to keep posted */
134
 
        unsigned int rxoffset;  /* rxcontrol offset */
135
 
        uint ddoffsetlow;       /* add to get dma address of descriptor ring, low 32 bits */
136
 
        uint ddoffsethigh;      /*   high 32 bits */
137
 
        uint dataoffsetlow;     /* add to get dma address of data buffer, low 32 bits */
138
 
        uint dataoffsethigh;    /*   high 32 bits */
139
 
        bool aligndesc_4k;      /* descriptor base need to be aligned or not */
140
 
} dma_info_t;
141
 
 
142
 
/* DMA Scatter-gather list is supported. Note this is limited to TX direction only */
143
 
#ifdef BCMDMASGLISTOSL
144
 
#define DMASGLIST_ENAB true
145
 
#else
146
 
#define DMASGLIST_ENAB false
147
 
#endif                          /* BCMDMASGLISTOSL */
148
 
 
149
 
/* descriptor bumping macros */
150
 
#define XXD(x, n)       ((x) & ((n) - 1))       /* faster than %, but n must be power of 2 */
151
 
#define TXD(x)          XXD((x), di->ntxd)
152
 
#define RXD(x)          XXD((x), di->nrxd)
153
 
#define NEXTTXD(i)      TXD((i) + 1)
154
 
#define PREVTXD(i)      TXD((i) - 1)
155
 
#define NEXTRXD(i)      RXD((i) + 1)
156
 
#define PREVRXD(i)      RXD((i) - 1)
157
 
 
158
 
#define NTXDACTIVE(h, t)        TXD((t) - (h))
159
 
#define NRXDACTIVE(h, t)        RXD((t) - (h))
160
 
 
161
 
/* macros to convert between byte offsets and indexes */
162
 
#define B2I(bytes, type)        ((bytes) / sizeof(type))
163
 
#define I2B(index, type)        ((index) * sizeof(type))
164
 
 
165
 
#define PCI32ADDR_HIGH          0xc0000000      /* address[31:30] */
166
 
#define PCI32ADDR_HIGH_SHIFT    30      /* address[31:30] */
167
 
 
168
 
#define PCI64ADDR_HIGH          0x80000000      /* address[63] */
169
 
#define PCI64ADDR_HIGH_SHIFT    31      /* address[63] */
170
 
 
171
 
/* Common prototypes */
172
 
static bool _dma_isaddrext(dma_info_t *di);
173
 
static bool _dma_descriptor_align(dma_info_t *di);
174
 
static bool _dma_alloc(dma_info_t *di, uint direction);
175
 
static void _dma_detach(dma_info_t *di);
176
 
static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa);
177
 
static void _dma_rxinit(dma_info_t *di);
178
 
static void *_dma_rx(dma_info_t *di);
179
 
static bool _dma_rxfill(dma_info_t *di);
180
 
static void _dma_rxreclaim(dma_info_t *di);
181
 
static void _dma_rxenable(dma_info_t *di);
182
 
static void *_dma_getnextrxp(dma_info_t *di, bool forceall);
183
 
static void _dma_rx_param_get(dma_info_t *di, u16 *rxoffset,
184
 
                              u16 *rxbufsize);
185
 
 
186
 
static void _dma_txblock(dma_info_t *di);
187
 
static void _dma_txunblock(dma_info_t *di);
188
 
static uint _dma_txactive(dma_info_t *di);
189
 
static uint _dma_rxactive(dma_info_t *di);
190
 
static uint _dma_txpending(dma_info_t *di);
191
 
static uint _dma_txcommitted(dma_info_t *di);
192
 
 
193
 
static void *_dma_peeknexttxp(dma_info_t *di);
194
 
static void *_dma_peeknextrxp(dma_info_t *di);
195
 
static unsigned long _dma_getvar(dma_info_t *di, const char *name);
196
 
static void _dma_counterreset(dma_info_t *di);
197
 
static void _dma_fifoloopbackenable(dma_info_t *di);
198
 
static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags);
199
 
static u8 dma_align_sizetobits(uint size);
200
 
static void *dma_ringalloc(dma_info_t *di, u32 boundary, uint size,
201
 
                           u16 *alignbits, uint *alloced,
202
 
                           dmaaddr_t *descpa);
203
 
 
204
 
/* Prototypes for 64-bit routines */
205
 
static bool dma64_alloc(dma_info_t *di, uint direction);
206
 
static bool dma64_txreset(dma_info_t *di);
207
 
static bool dma64_rxreset(dma_info_t *di);
208
 
static bool dma64_txsuspendedidle(dma_info_t *di);
209
 
static int dma64_txfast(dma_info_t *di, struct sk_buff *p0, bool commit);
210
 
static int dma64_txunframed(dma_info_t *di, void *p0, uint len, bool commit);
211
 
static void *dma64_getpos(dma_info_t *di, bool direction);
212
 
static void *dma64_getnexttxp(dma_info_t *di, txd_range_t range);
213
 
static void *dma64_getnextrxp(dma_info_t *di, bool forceall);
214
 
static void dma64_txrotate(dma_info_t *di);
215
 
 
216
 
static bool dma64_rxidle(dma_info_t *di);
217
 
static void dma64_txinit(dma_info_t *di);
218
 
static bool dma64_txenabled(dma_info_t *di);
219
 
static void dma64_txsuspend(dma_info_t *di);
220
 
static void dma64_txresume(dma_info_t *di);
221
 
static bool dma64_txsuspended(dma_info_t *di);
222
 
static void dma64_txreclaim(dma_info_t *di, txd_range_t range);
223
 
static bool dma64_txstopped(dma_info_t *di);
224
 
static bool dma64_rxstopped(dma_info_t *di);
225
 
static bool dma64_rxenabled(dma_info_t *di);
226
 
static bool _dma64_addrext(dma64regs_t *dma64regs);
227
 
 
228
 
static inline u32 parity32(u32 data);
229
 
 
230
 
const di_fcn_t dma64proc = {
231
 
        (di_detach_t) _dma_detach,
232
 
        (di_txinit_t) dma64_txinit,
233
 
        (di_txreset_t) dma64_txreset,
234
 
        (di_txenabled_t) dma64_txenabled,
235
 
        (di_txsuspend_t) dma64_txsuspend,
236
 
        (di_txresume_t) dma64_txresume,
237
 
        (di_txsuspended_t) dma64_txsuspended,
238
 
        (di_txsuspendedidle_t) dma64_txsuspendedidle,
239
 
        (di_txfast_t) dma64_txfast,
240
 
        (di_txunframed_t) dma64_txunframed,
241
 
        (di_getpos_t) dma64_getpos,
242
 
        (di_txstopped_t) dma64_txstopped,
243
 
        (di_txreclaim_t) dma64_txreclaim,
244
 
        (di_getnexttxp_t) dma64_getnexttxp,
245
 
        (di_peeknexttxp_t) _dma_peeknexttxp,
246
 
        (di_txblock_t) _dma_txblock,
247
 
        (di_txunblock_t) _dma_txunblock,
248
 
        (di_txactive_t) _dma_txactive,
249
 
        (di_txrotate_t) dma64_txrotate,
250
 
 
251
 
        (di_rxinit_t) _dma_rxinit,
252
 
        (di_rxreset_t) dma64_rxreset,
253
 
        (di_rxidle_t) dma64_rxidle,
254
 
        (di_rxstopped_t) dma64_rxstopped,
255
 
        (di_rxenable_t) _dma_rxenable,
256
 
        (di_rxenabled_t) dma64_rxenabled,
257
 
        (di_rx_t) _dma_rx,
258
 
        (di_rxfill_t) _dma_rxfill,
259
 
        (di_rxreclaim_t) _dma_rxreclaim,
260
 
        (di_getnextrxp_t) _dma_getnextrxp,
261
 
        (di_peeknextrxp_t) _dma_peeknextrxp,
262
 
        (di_rxparam_get_t) _dma_rx_param_get,
263
 
 
264
 
        (di_fifoloopbackenable_t) _dma_fifoloopbackenable,
265
 
        (di_getvar_t) _dma_getvar,
266
 
        (di_counterreset_t) _dma_counterreset,
267
 
        (di_ctrlflags_t) _dma_ctrlflags,
268
 
        NULL,
269
 
        NULL,
270
 
        NULL,
271
 
        (di_rxactive_t) _dma_rxactive,
272
 
        (di_txpending_t) _dma_txpending,
273
 
        (di_txcommitted_t) _dma_txcommitted,
274
 
        39
275
 
};
276
 
 
277
 
struct hnddma_pub *dma_attach(char *name, si_t *sih,
278
 
                     void *dmaregstx, void *dmaregsrx, uint ntxd,
279
 
                     uint nrxd, uint rxbufsize, int rxextheadroom,
280
 
                     uint nrxpost, uint rxoffset, uint *msg_level)
281
 
{
282
 
        dma_info_t *di;
283
 
        uint size;
284
 
 
285
 
        /* allocate private info structure */
286
 
        di = kzalloc(sizeof(dma_info_t), GFP_ATOMIC);
287
 
        if (di == NULL) {
288
 
#ifdef BCMDBG
289
 
                printk(KERN_ERR "dma_attach: out of memory\n");
290
 
#endif
291
 
                return NULL;
292
 
        }
293
 
 
294
 
        di->msg_level = msg_level ? msg_level : &dma_msg_level;
295
 
 
296
 
        /* old chips w/o sb is no longer supported */
297
 
        ASSERT(sih != NULL);
298
 
 
299
 
        di->dma64 = ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
300
 
 
301
 
        /* check arguments */
302
 
        ASSERT(ISPOWEROF2(ntxd));
303
 
        ASSERT(ISPOWEROF2(nrxd));
304
 
 
305
 
        if (nrxd == 0)
306
 
                ASSERT(dmaregsrx == NULL);
307
 
        if (ntxd == 0)
308
 
                ASSERT(dmaregstx == NULL);
309
 
 
310
 
        /* init dma reg pointer */
311
 
        ASSERT(ntxd <= D64MAXDD);
312
 
        ASSERT(nrxd <= D64MAXDD);
313
 
        di->d64txregs = (dma64regs_t *) dmaregstx;
314
 
        di->d64rxregs = (dma64regs_t *) dmaregsrx;
315
 
        di->hnddma.di_fn = (const di_fcn_t *)&dma64proc;
316
 
 
317
 
        /* Default flags (which can be changed by the driver calling dma_ctrlflags
318
 
         * before enable): For backwards compatibility both Rx Overflow Continue
319
 
         * and Parity are DISABLED.
320
 
         * supports it.
321
 
         */
322
 
        di->hnddma.di_fn->ctrlflags(&di->hnddma, DMA_CTRL_ROC | DMA_CTRL_PEN,
323
 
                                    0);
324
 
 
325
 
        DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
326
 
                   "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
327
 
                   "dmaregstx %p dmaregsrx %p\n", name, "DMA64",
328
 
                   di->hnddma.dmactrlflags, ntxd, nrxd, rxbufsize,
329
 
                   rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
330
 
 
331
 
        /* make a private copy of our callers name */
332
 
        strncpy(di->name, name, MAXNAMEL);
333
 
        di->name[MAXNAMEL - 1] = '\0';
334
 
 
335
 
        di->pbus = ((struct si_info *)sih)->pbus;
336
 
 
337
 
        /* save tunables */
338
 
        di->ntxd = (u16) ntxd;
339
 
        di->nrxd = (u16) nrxd;
340
 
 
341
 
        /* the actual dma size doesn't include the extra headroom */
342
 
        di->rxextrahdrroom =
343
 
            (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom;
344
 
        if (rxbufsize > BCMEXTRAHDROOM)
345
 
                di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom);
346
 
        else
347
 
                di->rxbufsize = (u16) rxbufsize;
348
 
 
349
 
        di->nrxpost = (u16) nrxpost;
350
 
        di->rxoffset = (u8) rxoffset;
351
 
 
352
 
        /*
353
 
         * figure out the DMA physical address offset for dd and data
354
 
         *     PCI/PCIE: they map silicon backplace address to zero based memory, need offset
355
 
         *     Other bus: use zero
356
 
         *     SI_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor
357
 
         */
358
 
        di->ddoffsetlow = 0;
359
 
        di->dataoffsetlow = 0;
360
 
        /* for pci bus, add offset */
361
 
        if (sih->bustype == PCI_BUS) {
362
 
                /* pcie with DMA64 */
363
 
                di->ddoffsetlow = 0;
364
 
                di->ddoffsethigh = SI_PCIE_DMA_H32;
365
 
                di->dataoffsetlow = di->ddoffsetlow;
366
 
                di->dataoffsethigh = di->ddoffsethigh;
367
 
        }
368
 
#if defined(__mips__) && defined(IL_BIGENDIAN)
369
 
        di->dataoffsetlow = di->dataoffsetlow + SI_SDRAM_SWAPPED;
370
 
#endif                          /* defined(__mips__) && defined(IL_BIGENDIAN) */
371
 
        /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
372
 
        if ((si_coreid(sih) == SDIOD_CORE_ID)
373
 
            && ((si_corerev(sih) > 0) && (si_corerev(sih) <= 2)))
374
 
                di->addrext = 0;
375
 
        else if ((si_coreid(sih) == I2S_CORE_ID) &&
376
 
                 ((si_corerev(sih) == 0) || (si_corerev(sih) == 1)))
377
 
                di->addrext = 0;
378
 
        else
379
 
                di->addrext = _dma_isaddrext(di);
380
 
 
381
 
        /* does the descriptors need to be aligned and if yes, on 4K/8K or not */
382
 
        di->aligndesc_4k = _dma_descriptor_align(di);
383
 
        if (di->aligndesc_4k) {
384
 
                di->dmadesc_align = D64RINGALIGN_BITS;
385
 
                if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) {
386
 
                        /* for smaller dd table, HW relax alignment reqmnt */
387
 
                        di->dmadesc_align = D64RINGALIGN_BITS - 1;
388
 
                }
389
 
        } else
390
 
                di->dmadesc_align = 4;  /* 16 byte alignment */
391
 
 
392
 
        DMA_NONE(("DMA descriptor align_needed %d, align %d\n",
393
 
                  di->aligndesc_4k, di->dmadesc_align));
394
 
 
395
 
        /* allocate tx packet pointer vector */
396
 
        if (ntxd) {
397
 
                size = ntxd * sizeof(void *);
398
 
                di->txp = kzalloc(size, GFP_ATOMIC);
399
 
                if (di->txp == NULL) {
400
 
                        DMA_ERROR(("%s: dma_attach: out of tx memory\n", di->name));
401
 
                        goto fail;
402
 
                }
403
 
        }
404
 
 
405
 
        /* allocate rx packet pointer vector */
406
 
        if (nrxd) {
407
 
                size = nrxd * sizeof(void *);
408
 
                di->rxp = kzalloc(size, GFP_ATOMIC);
409
 
                if (di->rxp == NULL) {
410
 
                        DMA_ERROR(("%s: dma_attach: out of rx memory\n", di->name));
411
 
                        goto fail;
412
 
                }
413
 
        }
414
 
 
415
 
        /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */
416
 
        if (ntxd) {
417
 
                if (!_dma_alloc(di, DMA_TX))
418
 
                        goto fail;
419
 
        }
420
 
 
421
 
        /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */
422
 
        if (nrxd) {
423
 
                if (!_dma_alloc(di, DMA_RX))
424
 
                        goto fail;
425
 
        }
426
 
 
427
 
        if ((di->ddoffsetlow != 0) && !di->addrext) {
428
 
                if (PHYSADDRLO(di->txdpa) > SI_PCI_DMA_SZ) {
429
 
                        DMA_ERROR(("%s: dma_attach: txdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->txdpa)));
430
 
                        goto fail;
431
 
                }
432
 
                if (PHYSADDRLO(di->rxdpa) > SI_PCI_DMA_SZ) {
433
 
                        DMA_ERROR(("%s: dma_attach: rxdpa 0x%x: addrext not supported\n", di->name, (u32) PHYSADDRLO(di->rxdpa)));
434
 
                        goto fail;
435
 
                }
436
 
        }
437
 
 
438
 
        DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, di->dataoffsethigh, di->addrext));
439
 
 
440
 
        /* allocate DMA mapping vectors */
441
 
        if (DMASGLIST_ENAB) {
442
 
                if (ntxd) {
443
 
                        size = ntxd * sizeof(hnddma_seg_map_t);
444
 
                        di->txp_dmah = kzalloc(size, GFP_ATOMIC);
445
 
                        if (di->txp_dmah == NULL)
446
 
                                goto fail;
447
 
                }
448
 
 
449
 
                if (nrxd) {
450
 
                        size = nrxd * sizeof(hnddma_seg_map_t);
451
 
                        di->rxp_dmah = kzalloc(size, GFP_ATOMIC);
452
 
                        if (di->rxp_dmah == NULL)
453
 
                                goto fail;
454
 
                }
455
 
        }
456
 
 
457
 
        return (struct hnddma_pub *) di;
458
 
 
459
 
 fail:
460
 
        _dma_detach(di);
461
 
        return NULL;
462
 
}
463
 
 
464
 
/* Check for odd number of 1's */
465
 
static inline u32 parity32(u32 data)
466
 
{
467
 
        data ^= data >> 16;
468
 
        data ^= data >> 8;
469
 
        data ^= data >> 4;
470
 
        data ^= data >> 2;
471
 
        data ^= data >> 1;
472
 
 
473
 
        return data & 1;
474
 
}
475
 
 
476
 
#define DMA64_DD_PARITY(dd)  parity32((dd)->addrlow ^ (dd)->addrhigh ^ (dd)->ctrl1 ^ (dd)->ctrl2)
477
 
 
478
 
static inline void
479
 
dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, dmaaddr_t pa, uint outidx,
480
 
             u32 *flags, u32 bufcount)
481
 
{
482
 
        u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;
483
 
 
484
 
        /* PCI bus with big(>1G) physical address, use address extension */
485
 
#if defined(__mips__) && defined(IL_BIGENDIAN)
486
 
        if ((di->dataoffsetlow == SI_SDRAM_SWAPPED)
487
 
            || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
488
 
#else
489
 
        if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
490
 
#endif                          /* defined(__mips__) && defined(IL_BIGENDIAN) */
491
 
                ASSERT((PHYSADDRHI(pa) & PCI64ADDR_HIGH) == 0);
492
 
 
493
 
                W_SM(&ddring[outidx].addrlow,
494
 
                     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
495
 
                W_SM(&ddring[outidx].addrhigh,
496
 
                     BUS_SWAP32(PHYSADDRHI(pa) + di->dataoffsethigh));
497
 
                W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
498
 
                W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
499
 
        } else {
500
 
                /* address extension for 32-bit PCI */
501
 
                u32 ae;
502
 
                ASSERT(di->addrext);
503
 
 
504
 
                ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
505
 
                PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
506
 
                ASSERT(PHYSADDRHI(pa) == 0);
507
 
 
508
 
                ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;
509
 
                W_SM(&ddring[outidx].addrlow,
510
 
                     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
511
 
                W_SM(&ddring[outidx].addrhigh,
512
 
                     BUS_SWAP32(0 + di->dataoffsethigh));
513
 
                W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags));
514
 
                W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2));
515
 
        }
516
 
        if (di->hnddma.dmactrlflags & DMA_CTRL_PEN) {
517
 
                if (DMA64_DD_PARITY(&ddring[outidx])) {
518
 
                        W_SM(&ddring[outidx].ctrl2,
519
 
                             BUS_SWAP32(ctrl2 | D64_CTRL2_PARITY));
520
 
                }
521
 
        }
522
 
}
523
 
 
524
 
static bool _dma_alloc(dma_info_t *di, uint direction)
525
 
{
526
 
        return dma64_alloc(di, direction);
527
 
}
528
 
 
529
 
void *dma_alloc_consistent(struct pci_dev *pdev, uint size, u16 align_bits,
530
 
                               uint *alloced, unsigned long *pap)
531
 
{
532
 
        if (align_bits) {
533
 
                u16 align = (1 << align_bits);
534
 
                if (!IS_ALIGNED(PAGE_SIZE, align))
535
 
                        size += align;
536
 
                *alloced = size;
537
 
        }
538
 
        return pci_alloc_consistent(pdev, size, (dma_addr_t *) pap);
539
 
}
540
 
 
541
 
/* !! may be called with core in reset */
542
 
static void _dma_detach(dma_info_t *di)
543
 
{
544
 
 
545
 
        DMA_TRACE(("%s: dma_detach\n", di->name));
546
 
 
547
 
        /* shouldn't be here if descriptors are unreclaimed */
548
 
        ASSERT(di->txin == di->txout);
549
 
        ASSERT(di->rxin == di->rxout);
550
 
 
551
 
        /* free dma descriptor rings */
552
 
        if (di->txd64)
553
 
                pci_free_consistent(di->pbus, di->txdalloc,
554
 
                                    ((s8 *)di->txd64 - di->txdalign),
555
 
                                    (di->txdpaorig));
556
 
        if (di->rxd64)
557
 
                pci_free_consistent(di->pbus, di->rxdalloc,
558
 
                                    ((s8 *)di->rxd64 - di->rxdalign),
559
 
                                    (di->rxdpaorig));
560
 
 
561
 
        /* free packet pointer vectors */
562
 
        kfree(di->txp);
563
 
        kfree(di->rxp);
564
 
 
565
 
        /* free tx packet DMA handles */
566
 
        kfree(di->txp_dmah);
567
 
 
568
 
        /* free rx packet DMA handles */
569
 
        kfree(di->rxp_dmah);
570
 
 
571
 
        /* free our private info structure */
572
 
        kfree(di);
573
 
 
574
 
}
575
 
 
576
 
static bool _dma_descriptor_align(dma_info_t *di)
577
 
{
578
 
        u32 addrl;
579
 
 
580
 
        /* Check to see if the descriptors need to be aligned on 4K/8K or not */
581
 
        if (di->d64txregs != NULL) {
582
 
                W_REG(&di->d64txregs->addrlow, 0xff0);
583
 
                addrl = R_REG(&di->d64txregs->addrlow);
584
 
                if (addrl != 0)
585
 
                        return false;
586
 
        } else if (di->d64rxregs != NULL) {
587
 
                W_REG(&di->d64rxregs->addrlow, 0xff0);
588
 
                addrl = R_REG(&di->d64rxregs->addrlow);
589
 
                if (addrl != 0)
590
 
                        return false;
591
 
        }
592
 
        return true;
593
 
}
594
 
 
595
 
/* return true if this dma engine supports DmaExtendedAddrChanges, otherwise false */
596
 
static bool _dma_isaddrext(dma_info_t *di)
597
 
{
598
 
        /* DMA64 supports full 32- or 64-bit operation. AE is always valid */
599
 
 
600
 
        /* not all tx or rx channel are available */
601
 
        if (di->d64txregs != NULL) {
602
 
                if (!_dma64_addrext(di->d64txregs)) {
603
 
                        DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
604
 
                                   "AE set\n", di->name));
605
 
                        ASSERT(0);
606
 
                }
607
 
                return true;
608
 
        } else if (di->d64rxregs != NULL) {
609
 
                if (!_dma64_addrext(di->d64rxregs)) {
610
 
                        DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
611
 
                                   "AE set\n", di->name));
612
 
                        ASSERT(0);
613
 
                }
614
 
                return true;
615
 
        }
616
 
        return false;
617
 
}
618
 
 
619
 
/* initialize descriptor table base address */
620
 
static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa)
621
 
{
622
 
        if (!di->aligndesc_4k) {
623
 
                if (direction == DMA_TX)
624
 
                        di->xmtptrbase = PHYSADDRLO(pa);
625
 
                else
626
 
                        di->rcvptrbase = PHYSADDRLO(pa);
627
 
        }
628
 
 
629
 
        if ((di->ddoffsetlow == 0)
630
 
            || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
631
 
                if (direction == DMA_TX) {
632
 
                        W_REG(&di->d64txregs->addrlow,
633
 
                              (PHYSADDRLO(pa) + di->ddoffsetlow));
634
 
                        W_REG(&di->d64txregs->addrhigh,
635
 
                              (PHYSADDRHI(pa) + di->ddoffsethigh));
636
 
                } else {
637
 
                        W_REG(&di->d64rxregs->addrlow,
638
 
                              (PHYSADDRLO(pa) + di->ddoffsetlow));
639
 
                        W_REG(&di->d64rxregs->addrhigh,
640
 
                                (PHYSADDRHI(pa) + di->ddoffsethigh));
641
 
                }
642
 
        } else {
643
 
                /* DMA64 32bits address extension */
644
 
                u32 ae;
645
 
                ASSERT(di->addrext);
646
 
                ASSERT(PHYSADDRHI(pa) == 0);
647
 
 
648
 
                /* shift the high bit(s) from pa to ae */
649
 
                ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
650
 
                    PCI32ADDR_HIGH_SHIFT;
651
 
                PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
652
 
 
653
 
                if (direction == DMA_TX) {
654
 
                        W_REG(&di->d64txregs->addrlow,
655
 
                              (PHYSADDRLO(pa) + di->ddoffsetlow));
656
 
                        W_REG(&di->d64txregs->addrhigh,
657
 
                              di->ddoffsethigh);
658
 
                        SET_REG(&di->d64txregs->control,
659
 
                                D64_XC_AE, (ae << D64_XC_AE_SHIFT));
660
 
                } else {
661
 
                        W_REG(&di->d64rxregs->addrlow,
662
 
                              (PHYSADDRLO(pa) + di->ddoffsetlow));
663
 
                        W_REG(&di->d64rxregs->addrhigh,
664
 
                              di->ddoffsethigh);
665
 
                        SET_REG(&di->d64rxregs->control,
666
 
                                D64_RC_AE, (ae << D64_RC_AE_SHIFT));
667
 
                }
668
 
        }
669
 
}
670
 
 
671
 
static void _dma_fifoloopbackenable(dma_info_t *di)
672
 
{
673
 
        DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
674
 
 
675
 
        OR_REG(&di->d64txregs->control, D64_XC_LE);
676
 
}
677
 
 
678
 
static void _dma_rxinit(dma_info_t *di)
679
 
{
680
 
        DMA_TRACE(("%s: dma_rxinit\n", di->name));
681
 
 
682
 
        if (di->nrxd == 0)
683
 
                return;
684
 
 
685
 
        di->rxin = di->rxout = 0;
686
 
 
687
 
        /* clear rx descriptor ring */
688
 
        memset((void *)di->rxd64, '\0',
689
 
                (di->nrxd * sizeof(dma64dd_t)));
690
 
 
691
 
        /* DMA engine with out alignment requirement requires table to be inited
692
 
         * before enabling the engine
693
 
         */
694
 
        if (!di->aligndesc_4k)
695
 
                _dma_ddtable_init(di, DMA_RX, di->rxdpa);
696
 
 
697
 
        _dma_rxenable(di);
698
 
 
699
 
        if (di->aligndesc_4k)
700
 
                _dma_ddtable_init(di, DMA_RX, di->rxdpa);
701
 
}
702
 
 
703
 
static void _dma_rxenable(dma_info_t *di)
704
 
{
705
 
        uint dmactrlflags = di->hnddma.dmactrlflags;
706
 
        u32 control;
707
 
 
708
 
        DMA_TRACE(("%s: dma_rxenable\n", di->name));
709
 
 
710
 
        control =
711
 
            (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
712
 
            D64_RC_RE;
713
 
 
714
 
        if ((dmactrlflags & DMA_CTRL_PEN) == 0)
715
 
                control |= D64_RC_PD;
716
 
 
717
 
        if (dmactrlflags & DMA_CTRL_ROC)
718
 
                control |= D64_RC_OC;
719
 
 
720
 
        W_REG(&di->d64rxregs->control,
721
 
                ((di->rxoffset << D64_RC_RO_SHIFT) | control));
722
 
}
723
 
 
724
 
static void
725
 
_dma_rx_param_get(dma_info_t *di, u16 *rxoffset, u16 *rxbufsize)
726
 
{
727
 
        /* the normal values fit into 16 bits */
728
 
        *rxoffset = (u16) di->rxoffset;
729
 
        *rxbufsize = (u16) di->rxbufsize;
730
 
}
731
 
 
732
 
/* !! rx entry routine
733
 
 * returns a pointer to the next frame received, or NULL if there are no more
734
 
 *   if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is supported
735
 
 *      with pkts chain
736
 
 *   otherwise, it's treated as giant pkt and will be tossed.
737
 
 *   The DMA scattering starts with normal DMA header, followed by first buffer data.
738
 
 *   After it reaches the max size of buffer, the data continues in next DMA descriptor
739
 
 *   buffer WITHOUT DMA header
740
 
 */
741
 
static void *BCMFASTPATH _dma_rx(dma_info_t *di)
742
 
{
743
 
        struct sk_buff *p, *head, *tail;
744
 
        uint len;
745
 
        uint pkt_len;
746
 
        int resid = 0;
747
 
 
748
 
 next_frame:
749
 
        head = _dma_getnextrxp(di, false);
750
 
        if (head == NULL)
751
 
                return NULL;
752
 
 
753
 
        len = le16_to_cpu(*(u16 *) (head->data));
754
 
        DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
755
 
 
756
 
#if defined(__mips__)
757
 
#define OSL_UNCACHED(va)        ((void *)KSEG1ADDR((va)))
758
 
        if (!len) {
759
 
                while (!(len = *(u16 *) OSL_UNCACHED(head->data)))
760
 
                        udelay(1);
761
 
 
762
 
                *(u16 *) (head->data) = cpu_to_le16((u16) len);
763
 
        }
764
 
#endif                          /* defined(__mips__) */
765
 
 
766
 
        /* set actual length */
767
 
        pkt_len = min((di->rxoffset + len), di->rxbufsize);
768
 
        __skb_trim(head, pkt_len);
769
 
        resid = len - (di->rxbufsize - di->rxoffset);
770
 
 
771
 
        /* check for single or multi-buffer rx */
772
 
        if (resid > 0) {
773
 
                tail = head;
774
 
                while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
775
 
                        tail->next = p;
776
 
                        pkt_len = min(resid, (int)di->rxbufsize);
777
 
                        __skb_trim(p, pkt_len);
778
 
 
779
 
                        tail = p;
780
 
                        resid -= di->rxbufsize;
781
 
                }
782
 
 
783
 
#ifdef BCMDBG
784
 
                if (resid > 0) {
785
 
                        uint cur;
786
 
                        ASSERT(p == NULL);
787
 
                        cur =
788
 
                            B2I(((R_REG(&di->d64rxregs->status0) &
789
 
                                  D64_RS0_CD_MASK) -
790
 
                                 di->rcvptrbase) & D64_RS0_CD_MASK,
791
 
                                dma64dd_t);
792
 
                        DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n",
793
 
                                   di->rxin, di->rxout, cur));
794
 
                }
795
 
#endif                          /* BCMDBG */
796
 
 
797
 
                if ((di->hnddma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
798
 
                        DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
799
 
                                   di->name, len));
800
 
                        pkt_buf_free_skb(head);
801
 
                        di->hnddma.rxgiants++;
802
 
                        goto next_frame;
803
 
                }
804
 
        }
805
 
 
806
 
        return head;
807
 
}
808
 
 
809
 
/* post receive buffers
810
 
 *  return false is refill failed completely and ring is empty
811
 
 *  this will stall the rx dma and user might want to call rxfill again asap
812
 
 *  This unlikely happens on memory-rich NIC, but often on memory-constrained dongle
813
 
 */
814
 
static bool BCMFASTPATH _dma_rxfill(dma_info_t *di)
815
 
{
816
 
        struct sk_buff *p;
817
 
        u16 rxin, rxout;
818
 
        u32 flags = 0;
819
 
        uint n;
820
 
        uint i;
821
 
        dmaaddr_t pa;
822
 
        uint extra_offset = 0;
823
 
        bool ring_empty;
824
 
 
825
 
        ring_empty = false;
826
 
 
827
 
        /*
828
 
         * Determine how many receive buffers we're lacking
829
 
         * from the full complement, allocate, initialize,
830
 
         * and post them, then update the chip rx lastdscr.
831
 
         */
832
 
 
833
 
        rxin = di->rxin;
834
 
        rxout = di->rxout;
835
 
 
836
 
        n = di->nrxpost - NRXDACTIVE(rxin, rxout);
837
 
 
838
 
        DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));
839
 
 
840
 
        if (di->rxbufsize > BCMEXTRAHDROOM)
841
 
                extra_offset = di->rxextrahdrroom;
842
 
 
843
 
        for (i = 0; i < n; i++) {
844
 
                /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the
845
 
                   size to be allocated
846
 
                 */
847
 
 
848
 
                p = pkt_buf_get_skb(di->rxbufsize + extra_offset);
849
 
 
850
 
                if (p == NULL) {
851
 
                        DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n",
852
 
                                   di->name));
853
 
                        if (i == 0 && dma64_rxidle(di)) {
854
 
                                DMA_ERROR(("%s: rxfill64: ring is empty !\n",
855
 
                                           di->name));
856
 
                                ring_empty = true;
857
 
                        }
858
 
                        di->hnddma.rxnobuf++;
859
 
                        break;
860
 
                }
861
 
                /* reserve an extra headroom, if applicable */
862
 
                if (extra_offset)
863
 
                        skb_pull(p, extra_offset);
864
 
 
865
 
                /* Do a cached write instead of uncached write since DMA_MAP
866
 
                 * will flush the cache.
867
 
                 */
868
 
                *(u32 *) (p->data) = 0;
869
 
 
870
 
                if (DMASGLIST_ENAB)
871
 
                        memset(&di->rxp_dmah[rxout], 0,
872
 
                                sizeof(hnddma_seg_map_t));
873
 
 
874
 
                pa = pci_map_single(di->pbus, p->data,
875
 
                        di->rxbufsize, PCI_DMA_FROMDEVICE);
876
 
 
877
 
                ASSERT(IS_ALIGNED(PHYSADDRLO(pa), 4));
878
 
 
879
 
                /* save the free packet pointer */
880
 
                ASSERT(di->rxp[rxout] == NULL);
881
 
                di->rxp[rxout] = p;
882
 
 
883
 
                /* reset flags for each descriptor */
884
 
                flags = 0;
885
 
                if (rxout == (di->nrxd - 1))
886
 
                        flags = D64_CTRL1_EOT;
887
 
 
888
 
                dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
889
 
                             di->rxbufsize);
890
 
                rxout = NEXTRXD(rxout);
891
 
        }
892
 
 
893
 
        di->rxout = rxout;
894
 
 
895
 
        /* update the chip lastdscr pointer */
896
 
        W_REG(&di->d64rxregs->ptr,
897
 
              di->rcvptrbase + I2B(rxout, dma64dd_t));
898
 
 
899
 
        return ring_empty;
900
 
}
901
 
 
902
 
/* like getnexttxp but no reclaim */
903
 
static void *_dma_peeknexttxp(dma_info_t *di)
904
 
{
905
 
        uint end, i;
906
 
 
907
 
        if (di->ntxd == 0)
908
 
                return NULL;
909
 
 
910
 
        end =
911
 
            B2I(((R_REG(&di->d64txregs->status0) &
912
 
                  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
913
 
                  dma64dd_t);
914
 
 
915
 
        for (i = di->txin; i != end; i = NEXTTXD(i))
916
 
                if (di->txp[i])
917
 
                        return di->txp[i];
918
 
 
919
 
        return NULL;
920
 
}
921
 
 
922
 
/* like getnextrxp but not take off the ring */
923
 
static void *_dma_peeknextrxp(dma_info_t *di)
924
 
{
925
 
        uint end, i;
926
 
 
927
 
        if (di->nrxd == 0)
928
 
                return NULL;
929
 
 
930
 
        end =
931
 
            B2I(((R_REG(&di->d64rxregs->status0) &
932
 
                  D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK,
933
 
                  dma64dd_t);
934
 
 
935
 
        for (i = di->rxin; i != end; i = NEXTRXD(i))
936
 
                if (di->rxp[i])
937
 
                        return di->rxp[i];
938
 
 
939
 
        return NULL;
940
 
}
941
 
 
942
 
static void _dma_rxreclaim(dma_info_t *di)
943
 
{
944
 
        void *p;
945
 
 
946
 
        DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
947
 
 
948
 
        while ((p = _dma_getnextrxp(di, true)))
949
 
                pkt_buf_free_skb(p);
950
 
}
951
 
 
952
 
static void *BCMFASTPATH _dma_getnextrxp(dma_info_t *di, bool forceall)
953
 
{
954
 
        if (di->nrxd == 0)
955
 
                return NULL;
956
 
 
957
 
        return dma64_getnextrxp(di, forceall);
958
 
}
959
 
 
960
 
static void _dma_txblock(dma_info_t *di)
961
 
{
962
 
        di->hnddma.txavail = 0;
963
 
}
964
 
 
965
 
static void _dma_txunblock(dma_info_t *di)
966
 
{
967
 
        di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
968
 
}
969
 
 
970
 
static uint _dma_txactive(dma_info_t *di)
971
 
{
972
 
        return NTXDACTIVE(di->txin, di->txout);
973
 
}
974
 
 
975
 
static uint _dma_txpending(dma_info_t *di)
976
 
{
977
 
        uint curr;
978
 
 
979
 
        curr =
980
 
            B2I(((R_REG(&di->d64txregs->status0) &
981
 
                  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
982
 
                  dma64dd_t);
983
 
 
984
 
        return NTXDACTIVE(curr, di->txout);
985
 
}
986
 
 
987
 
static uint _dma_txcommitted(dma_info_t *di)
988
 
{
989
 
        uint ptr;
990
 
        uint txin = di->txin;
991
 
 
992
 
        if (txin == di->txout)
993
 
                return 0;
994
 
 
995
 
        ptr = B2I(R_REG(&di->d64txregs->ptr), dma64dd_t);
996
 
 
997
 
        return NTXDACTIVE(di->txin, ptr);
998
 
}
999
 
 
1000
 
static uint _dma_rxactive(dma_info_t *di)
1001
 
{
1002
 
        return NRXDACTIVE(di->rxin, di->rxout);
1003
 
}
1004
 
 
1005
 
static void _dma_counterreset(dma_info_t *di)
1006
 
{
1007
 
        /* reset all software counter */
1008
 
        di->hnddma.rxgiants = 0;
1009
 
        di->hnddma.rxnobuf = 0;
1010
 
        di->hnddma.txnobuf = 0;
1011
 
}
1012
 
 
1013
 
static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags)
1014
 
{
1015
 
        uint dmactrlflags = di->hnddma.dmactrlflags;
1016
 
 
1017
 
        if (di == NULL) {
1018
 
                DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
1019
 
                return 0;
1020
 
        }
1021
 
 
1022
 
        ASSERT((flags & ~mask) == 0);
1023
 
 
1024
 
        dmactrlflags &= ~mask;
1025
 
        dmactrlflags |= flags;
1026
 
 
1027
 
        /* If trying to enable parity, check if parity is actually supported */
1028
 
        if (dmactrlflags & DMA_CTRL_PEN) {
1029
 
                u32 control;
1030
 
 
1031
 
                control = R_REG(&di->d64txregs->control);
1032
 
                W_REG(&di->d64txregs->control,
1033
 
                      control | D64_XC_PD);
1034
 
                if (R_REG(&di->d64txregs->control) & D64_XC_PD) {
1035
 
                        /* We *can* disable it so it is supported,
1036
 
                         * restore control register
1037
 
                         */
1038
 
                        W_REG(&di->d64txregs->control,
1039
 
                        control);
1040
 
                } else {
1041
 
                        /* Not supported, don't allow it to be enabled */
1042
 
                        dmactrlflags &= ~DMA_CTRL_PEN;
1043
 
                }
1044
 
        }
1045
 
 
1046
 
        di->hnddma.dmactrlflags = dmactrlflags;
1047
 
 
1048
 
        return dmactrlflags;
1049
 
}
1050
 
 
1051
 
/* get the address of the var in order to change later */
1052
 
static unsigned long _dma_getvar(dma_info_t *di, const char *name)
1053
 
{
1054
 
        if (!strcmp(name, "&txavail"))
1055
 
                return (unsigned long)&(di->hnddma.txavail);
1056
 
        else {
1057
 
                ASSERT(0);
1058
 
        }
1059
 
        return 0;
1060
 
}
1061
 
 
1062
 
static
1063
 
u8 dma_align_sizetobits(uint size)
1064
 
{
1065
 
        u8 bitpos = 0;
1066
 
        ASSERT(size);
1067
 
        ASSERT(!(size & (size - 1)));
1068
 
        while (size >>= 1) {
1069
 
                bitpos++;
1070
 
        }
1071
 
        return bitpos;
1072
 
}
1073
 
 
1074
 
/* This function ensures that the DMA descriptor ring will not get allocated
1075
 
 * across Page boundary. If the allocation is done across the page boundary
1076
 
 * at the first time, then it is freed and the allocation is done at
1077
 
 * descriptor ring size aligned location. This will ensure that the ring will
1078
 
 * not cross page boundary
1079
 
 */
1080
 
static void *dma_ringalloc(dma_info_t *di, u32 boundary, uint size,
1081
 
                           u16 *alignbits, uint *alloced,
1082
 
                           dmaaddr_t *descpa)
1083
 
{
1084
 
        void *va;
1085
 
        u32 desc_strtaddr;
1086
 
        u32 alignbytes = 1 << *alignbits;
1087
 
 
1088
 
        va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
1089
 
 
1090
 
        if (NULL == va)
1091
 
                return NULL;
1092
 
 
1093
 
        desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
1094
 
        if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
1095
 
                                                        & boundary)) {
1096
 
                *alignbits = dma_align_sizetobits(size);
1097
 
                pci_free_consistent(di->pbus, size, va, *descpa);
1098
 
                va = dma_alloc_consistent(di->pbus, size, *alignbits,
1099
 
                        alloced, descpa);
1100
 
        }
1101
 
        return va;
1102
 
}
1103
 
 
1104
 
/* 64-bit DMA functions */
1105
 
 
1106
 
static void dma64_txinit(dma_info_t *di)
1107
 
{
1108
 
        u32 control = D64_XC_XE;
1109
 
 
1110
 
        DMA_TRACE(("%s: dma_txinit\n", di->name));
1111
 
 
1112
 
        if (di->ntxd == 0)
1113
 
                return;
1114
 
 
1115
 
        di->txin = di->txout = 0;
1116
 
        di->hnddma.txavail = di->ntxd - 1;
1117
 
 
1118
 
        /* clear tx descriptor ring */
1119
 
        memset((void *)di->txd64, '\0', (di->ntxd * sizeof(dma64dd_t)));
1120
 
 
1121
 
        /* DMA engine with out alignment requirement requires table to be inited
1122
 
         * before enabling the engine
1123
 
         */
1124
 
        if (!di->aligndesc_4k)
1125
 
                _dma_ddtable_init(di, DMA_TX, di->txdpa);
1126
 
 
1127
 
        if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0)
1128
 
                control |= D64_XC_PD;
1129
 
        OR_REG(&di->d64txregs->control, control);
1130
 
 
1131
 
        /* DMA engine with alignment requirement requires table to be inited
1132
 
         * before enabling the engine
1133
 
         */
1134
 
        if (di->aligndesc_4k)
1135
 
                _dma_ddtable_init(di, DMA_TX, di->txdpa);
1136
 
}
1137
 
 
1138
 
static bool dma64_txenabled(dma_info_t *di)
1139
 
{
1140
 
        u32 xc;
1141
 
 
1142
 
        /* If the chip is dead, it is not enabled :-) */
1143
 
        xc = R_REG(&di->d64txregs->control);
1144
 
        return (xc != 0xffffffff) && (xc & D64_XC_XE);
1145
 
}
1146
 
 
1147
 
static void dma64_txsuspend(dma_info_t *di)
1148
 
{
1149
 
        DMA_TRACE(("%s: dma_txsuspend\n", di->name));
1150
 
 
1151
 
        if (di->ntxd == 0)
1152
 
                return;
1153
 
 
1154
 
        OR_REG(&di->d64txregs->control, D64_XC_SE);
1155
 
}
1156
 
 
1157
 
static void dma64_txresume(dma_info_t *di)
1158
 
{
1159
 
        DMA_TRACE(("%s: dma_txresume\n", di->name));
1160
 
 
1161
 
        if (di->ntxd == 0)
1162
 
                return;
1163
 
 
1164
 
        AND_REG(&di->d64txregs->control, ~D64_XC_SE);
1165
 
}
1166
 
 
1167
 
static bool dma64_txsuspended(dma_info_t *di)
1168
 
{
1169
 
        return (di->ntxd == 0) ||
1170
 
            ((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
1171
 
             D64_XC_SE);
1172
 
}
1173
 
 
1174
 
static void BCMFASTPATH dma64_txreclaim(dma_info_t *di, txd_range_t range)
1175
 
{
1176
 
        void *p;
1177
 
 
1178
 
        DMA_TRACE(("%s: dma_txreclaim %s\n", di->name,
1179
 
                   (range == HNDDMA_RANGE_ALL) ? "all" :
1180
 
                   ((range ==
1181
 
                     HNDDMA_RANGE_TRANSMITTED) ? "transmitted" :
1182
 
                    "transferred")));
1183
 
 
1184
 
        if (di->txin == di->txout)
1185
 
                return;
1186
 
 
1187
 
        while ((p = dma64_getnexttxp(di, range))) {
1188
 
                /* For unframed data, we don't have any packets to free */
1189
 
                if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED))
1190
 
                        pkt_buf_free_skb(p);
1191
 
        }
1192
 
}
1193
 
 
1194
 
static bool dma64_txstopped(dma_info_t *di)
1195
 
{
1196
 
        return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
1197
 
                D64_XS0_XS_STOPPED);
1198
 
}
1199
 
 
1200
 
static bool dma64_rxstopped(dma_info_t *di)
1201
 
{
1202
 
        return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) ==
1203
 
                D64_RS0_RS_STOPPED);
1204
 
}
1205
 
 
1206
 
static bool dma64_alloc(dma_info_t *di, uint direction)
1207
 
{
1208
 
        u16 size;
1209
 
        uint ddlen;
1210
 
        void *va;
1211
 
        uint alloced = 0;
1212
 
        u16 align;
1213
 
        u16 align_bits;
1214
 
 
1215
 
        ddlen = sizeof(dma64dd_t);
1216
 
 
1217
 
        size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
1218
 
        align_bits = di->dmadesc_align;
1219
 
        align = (1 << align_bits);
1220
 
 
1221
 
        if (direction == DMA_TX) {
1222
 
                va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
1223
 
                        &alloced, &di->txdpaorig);
1224
 
                if (va == NULL) {
1225
 
                        DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
1226
 
                        return false;
1227
 
                }
1228
 
                align = (1 << align_bits);
1229
 
                di->txd64 = (dma64dd_t *) roundup((unsigned long)va, align);
1230
 
                di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
1231
 
                PHYSADDRLOSET(di->txdpa,
1232
 
                              PHYSADDRLO(di->txdpaorig) + di->txdalign);
1233
 
                /* Make sure that alignment didn't overflow */
1234
 
                ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig));
1235
 
 
1236
 
                PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig));
1237
 
                di->txdalloc = alloced;
1238
 
                ASSERT(IS_ALIGNED((unsigned long)di->txd64, align));
1239
 
        } else {
1240
 
                va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
1241
 
                        &alloced, &di->rxdpaorig);
1242
 
                if (va == NULL) {
1243
 
                        DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
1244
 
                        return false;
1245
 
                }
1246
 
                align = (1 << align_bits);
1247
 
                di->rxd64 = (dma64dd_t *) roundup((unsigned long)va, align);
1248
 
                di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
1249
 
                PHYSADDRLOSET(di->rxdpa,
1250
 
                              PHYSADDRLO(di->rxdpaorig) + di->rxdalign);
1251
 
                /* Make sure that alignment didn't overflow */
1252
 
                ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig));
1253
 
 
1254
 
                PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig));
1255
 
                di->rxdalloc = alloced;
1256
 
                ASSERT(IS_ALIGNED((unsigned long)di->rxd64, align));
1257
 
        }
1258
 
 
1259
 
        return true;
1260
 
}
1261
 
 
1262
 
static bool dma64_txreset(dma_info_t *di)
1263
 
{
1264
 
        u32 status;
1265
 
 
1266
 
        if (di->ntxd == 0)
1267
 
                return true;
1268
 
 
1269
 
        /* suspend tx DMA first */
1270
 
        W_REG(&di->d64txregs->control, D64_XC_SE);
1271
 
        SPINWAIT(((status =
1272
 
                   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
1273
 
                  != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
1274
 
                 && (status != D64_XS0_XS_STOPPED), 10000);
1275
 
 
1276
 
        W_REG(&di->d64txregs->control, 0);
1277
 
        SPINWAIT(((status =
1278
 
                   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
1279
 
                  != D64_XS0_XS_DISABLED), 10000);
1280
 
 
1281
 
        /* wait for the last transaction to complete */
1282
 
        udelay(300);
1283
 
 
1284
 
        return status == D64_XS0_XS_DISABLED;
1285
 
}
1286
 
 
1287
 
static bool dma64_rxidle(dma_info_t *di)
1288
 
{
1289
 
        DMA_TRACE(("%s: dma_rxidle\n", di->name));
1290
 
 
1291
 
        if (di->nrxd == 0)
1292
 
                return true;
1293
 
 
1294
 
        return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
1295
 
                (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
1296
 
}
1297
 
 
1298
 
static bool dma64_rxreset(dma_info_t *di)
1299
 
{
1300
 
        u32 status;
1301
 
 
1302
 
        if (di->nrxd == 0)
1303
 
                return true;
1304
 
 
1305
 
        W_REG(&di->d64rxregs->control, 0);
1306
 
        SPINWAIT(((status =
1307
 
                   (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
1308
 
                  != D64_RS0_RS_DISABLED), 10000);
1309
 
 
1310
 
        return status == D64_RS0_RS_DISABLED;
1311
 
}
1312
 
 
1313
 
static bool dma64_rxenabled(dma_info_t *di)
1314
 
{
1315
 
        u32 rc;
1316
 
 
1317
 
        rc = R_REG(&di->d64rxregs->control);
1318
 
        return (rc != 0xffffffff) && (rc & D64_RC_RE);
1319
 
}
1320
 
 
1321
 
static bool dma64_txsuspendedidle(dma_info_t *di)
1322
 
{
1323
 
 
1324
 
        if (di->ntxd == 0)
1325
 
                return true;
1326
 
 
1327
 
        if (!(R_REG(&di->d64txregs->control) & D64_XC_SE))
1328
 
                return 0;
1329
 
 
1330
 
        if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
1331
 
            D64_XS0_XS_IDLE)
1332
 
                return 1;
1333
 
 
1334
 
        return 0;
1335
 
}
1336
 
 
1337
 
/* Useful when sending unframed data.  This allows us to get a progress report from the DMA.
1338
 
 * We return a pointer to the beginning of the DATA buffer of the current descriptor.
1339
 
 * If DMA is idle, we return NULL.
1340
 
 */
1341
 
static void *dma64_getpos(dma_info_t *di, bool direction)
1342
 
{
1343
 
        void *va;
1344
 
        bool idle;
1345
 
        u32 cd_offset;
1346
 
 
1347
 
        if (direction == DMA_TX) {
1348
 
                cd_offset =
1349
 
                    R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK;
1350
 
                idle = !NTXDACTIVE(di->txin, di->txout);
1351
 
                va = di->txp[B2I(cd_offset, dma64dd_t)];
1352
 
        } else {
1353
 
                cd_offset =
1354
 
                    R_REG(&di->d64rxregs->status0) & D64_XS0_CD_MASK;
1355
 
                idle = !NRXDACTIVE(di->rxin, di->rxout);
1356
 
                va = di->rxp[B2I(cd_offset, dma64dd_t)];
1357
 
        }
1358
 
 
1359
 
        /* If DMA is IDLE, return NULL */
1360
 
        if (idle) {
1361
 
                DMA_TRACE(("%s: DMA idle, return NULL\n", __func__));
1362
 
                va = NULL;
1363
 
        }
1364
 
 
1365
 
        return va;
1366
 
}
1367
 
 
1368
 
/* TX of unframed data
1369
 
 *
1370
 
 * Adds a DMA ring descriptor for the data pointed to by "buf".
1371
 
 * This is for DMA of a buffer of data and is unlike other hnddma TX functions
1372
 
 * that take a pointer to a "packet"
1373
 
 * Each call to this is results in a single descriptor being added for "len" bytes of
1374
 
 * data starting at "buf", it doesn't handle chained buffers.
1375
 
 */
1376
 
static int dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit)
1377
 
{
1378
 
        u16 txout;
1379
 
        u32 flags = 0;
1380
 
        dmaaddr_t pa;           /* phys addr */
1381
 
 
1382
 
        txout = di->txout;
1383
 
 
1384
 
        /* return nonzero if out of tx descriptors */
1385
 
        if (NEXTTXD(txout) == di->txin)
1386
 
                goto outoftxd;
1387
 
 
1388
 
        if (len == 0)
1389
 
                return 0;
1390
 
 
1391
 
        pa = pci_map_single(di->pbus, buf, len, PCI_DMA_TODEVICE);
1392
 
 
1393
 
        flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF);
1394
 
 
1395
 
        if (txout == (di->ntxd - 1))
1396
 
                flags |= D64_CTRL1_EOT;
1397
 
 
1398
 
        dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
1399
 
        ASSERT(di->txp[txout] == NULL);
1400
 
 
1401
 
        /* save the buffer pointer - used by dma_getpos */
1402
 
        di->txp[txout] = buf;
1403
 
 
1404
 
        txout = NEXTTXD(txout);
1405
 
        /* bump the tx descriptor index */
1406
 
        di->txout = txout;
1407
 
 
1408
 
        /* kick the chip */
1409
 
        if (commit) {
1410
 
                W_REG(&di->d64txregs->ptr,
1411
 
                      di->xmtptrbase + I2B(txout, dma64dd_t));
1412
 
        }
1413
 
 
1414
 
        /* tx flow control */
1415
 
        di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
1416
 
 
1417
 
        return 0;
1418
 
 
1419
 
 outoftxd:
1420
 
        DMA_ERROR(("%s: %s: out of txds !!!\n", di->name, __func__));
1421
 
        di->hnddma.txavail = 0;
1422
 
        di->hnddma.txnobuf++;
1423
 
        return -1;
1424
 
}
1425
 
 
1426
 
/* !! tx entry routine
1427
 
 * WARNING: call must check the return value for error.
1428
 
 *   the error(toss frames) could be fatal and cause many subsequent hard to debug problems
1429
 
 */
1430
 
static int BCMFASTPATH dma64_txfast(dma_info_t *di, struct sk_buff *p0,
1431
 
                                    bool commit)
1432
 
{
1433
 
        struct sk_buff *p, *next;
1434
 
        unsigned char *data;
1435
 
        uint len;
1436
 
        u16 txout;
1437
 
        u32 flags = 0;
1438
 
        dmaaddr_t pa;
1439
 
 
1440
 
        DMA_TRACE(("%s: dma_txfast\n", di->name));
1441
 
 
1442
 
        txout = di->txout;
1443
 
 
1444
 
        /*
1445
 
         * Walk the chain of packet buffers
1446
 
         * allocating and initializing transmit descriptor entries.
1447
 
         */
1448
 
        for (p = p0; p; p = next) {
1449
 
                uint nsegs, j;
1450
 
                hnddma_seg_map_t *map;
1451
 
 
1452
 
                data = p->data;
1453
 
                len = p->len;
1454
 
#ifdef BCM_DMAPAD
1455
 
                len += PKTDMAPAD(di->osh, p);
1456
 
#endif                          /* BCM_DMAPAD */
1457
 
                next = p->next;
1458
 
 
1459
 
                /* return nonzero if out of tx descriptors */
1460
 
                if (NEXTTXD(txout) == di->txin)
1461
 
                        goto outoftxd;
1462
 
 
1463
 
                if (len == 0)
1464
 
                        continue;
1465
 
 
1466
 
                /* get physical address of buffer start */
1467
 
                if (DMASGLIST_ENAB)
1468
 
                        memset(&di->txp_dmah[txout], 0,
1469
 
                                sizeof(hnddma_seg_map_t));
1470
 
 
1471
 
                pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
1472
 
 
1473
 
                if (DMASGLIST_ENAB) {
1474
 
                        map = &di->txp_dmah[txout];
1475
 
 
1476
 
                        /* See if all the segments can be accounted for */
1477
 
                        if (map->nsegs >
1478
 
                            (uint) (di->ntxd - NTXDACTIVE(di->txin, di->txout) -
1479
 
                                    1))
1480
 
                                goto outoftxd;
1481
 
 
1482
 
                        nsegs = map->nsegs;
1483
 
                } else
1484
 
                        nsegs = 1;
1485
 
 
1486
 
                for (j = 1; j <= nsegs; j++) {
1487
 
                        flags = 0;
1488
 
                        if (p == p0 && j == 1)
1489
 
                                flags |= D64_CTRL1_SOF;
1490
 
 
1491
 
                        /* With a DMA segment list, Descriptor table is filled
1492
 
                         * using the segment list instead of looping over
1493
 
                         * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when
1494
 
                         * end of segment list is reached.
1495
 
                         */
1496
 
                        if ((!DMASGLIST_ENAB && next == NULL) ||
1497
 
                            (DMASGLIST_ENAB && j == nsegs))
1498
 
                                flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF);
1499
 
                        if (txout == (di->ntxd - 1))
1500
 
                                flags |= D64_CTRL1_EOT;
1501
 
 
1502
 
                        if (DMASGLIST_ENAB) {
1503
 
                                len = map->segs[j - 1].length;
1504
 
                                pa = map->segs[j - 1].addr;
1505
 
                        }
1506
 
                        dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
1507
 
                        ASSERT(di->txp[txout] == NULL);
1508
 
 
1509
 
                        txout = NEXTTXD(txout);
1510
 
                }
1511
 
 
1512
 
                /* See above. No need to loop over individual buffers */
1513
 
                if (DMASGLIST_ENAB)
1514
 
                        break;
1515
 
        }
1516
 
 
1517
 
        /* if last txd eof not set, fix it */
1518
 
        if (!(flags & D64_CTRL1_EOF))
1519
 
                W_SM(&di->txd64[PREVTXD(txout)].ctrl1,
1520
 
                     BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF));
1521
 
 
1522
 
        /* save the packet */
1523
 
        di->txp[PREVTXD(txout)] = p0;
1524
 
 
1525
 
        /* bump the tx descriptor index */
1526
 
        di->txout = txout;
1527
 
 
1528
 
        /* kick the chip */
1529
 
        if (commit)
1530
 
                W_REG(&di->d64txregs->ptr,
1531
 
                      di->xmtptrbase + I2B(txout, dma64dd_t));
1532
 
 
1533
 
        /* tx flow control */
1534
 
        di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
1535
 
 
1536
 
        return 0;
1537
 
 
1538
 
 outoftxd:
1539
 
        DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name));
1540
 
        pkt_buf_free_skb(p0);
1541
 
        di->hnddma.txavail = 0;
1542
 
        di->hnddma.txnobuf++;
1543
 
        return -1;
1544
 
}
1545
 
 
1546
 
/*
1547
 
 * Reclaim next completed txd (txds if using chained buffers) in the range
1548
 
 * specified and return associated packet.
1549
 
 * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be
1550
 
 * transmitted as noted by the hardware "CurrDescr" pointer.
1551
 
 * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be
1552
 
 * transferred by the DMA as noted by the hardware "ActiveDescr" pointer.
1553
 
 * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
1554
 
 * return associated packet regardless of the value of hardware pointers.
1555
 
 */
1556
 
static void *BCMFASTPATH dma64_getnexttxp(dma_info_t *di, txd_range_t range)
1557
 
{
1558
 
        u16 start, end, i;
1559
 
        u16 active_desc;
1560
 
        void *txp;
1561
 
 
1562
 
        DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
1563
 
                   (range == HNDDMA_RANGE_ALL) ? "all" :
1564
 
                   ((range ==
1565
 
                     HNDDMA_RANGE_TRANSMITTED) ? "transmitted" :
1566
 
                    "transferred")));
1567
 
 
1568
 
        if (di->ntxd == 0)
1569
 
                return NULL;
1570
 
 
1571
 
        txp = NULL;
1572
 
 
1573
 
        start = di->txin;
1574
 
        if (range == HNDDMA_RANGE_ALL)
1575
 
                end = di->txout;
1576
 
        else {
1577
 
                dma64regs_t *dregs = di->d64txregs;
1578
 
 
1579
 
                end =
1580
 
                    (u16) (B2I
1581
 
                              (((R_REG(&dregs->status0) &
1582
 
                                 D64_XS0_CD_MASK) -
1583
 
                                di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t));
1584
 
 
1585
 
                if (range == HNDDMA_RANGE_TRANSFERED) {
1586
 
                        active_desc =
1587
 
                            (u16) (R_REG(&dregs->status1) &
1588
 
                                      D64_XS1_AD_MASK);
1589
 
                        active_desc =
1590
 
                            (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
1591
 
                        active_desc = B2I(active_desc, dma64dd_t);
1592
 
                        if (end != active_desc)
1593
 
                                end = PREVTXD(active_desc);
1594
 
                }
1595
 
        }
1596
 
 
1597
 
        if ((start == 0) && (end > di->txout))
1598
 
                goto bogus;
1599
 
 
1600
 
        for (i = start; i != end && !txp; i = NEXTTXD(i)) {
1601
 
                dmaaddr_t pa;
1602
 
                hnddma_seg_map_t *map = NULL;
1603
 
                uint size, j, nsegs;
1604
 
 
1605
 
                PHYSADDRLOSET(pa,
1606
 
                              (BUS_SWAP32(R_SM(&di->txd64[i].addrlow)) -
1607
 
                               di->dataoffsetlow));
1608
 
                PHYSADDRHISET(pa,
1609
 
                              (BUS_SWAP32(R_SM(&di->txd64[i].addrhigh)) -
1610
 
                               di->dataoffsethigh));
1611
 
 
1612
 
                if (DMASGLIST_ENAB) {
1613
 
                        map = &di->txp_dmah[i];
1614
 
                        size = map->origsize;
1615
 
                        nsegs = map->nsegs;
1616
 
                } else {
1617
 
                        size =
1618
 
                            (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) &
1619
 
                             D64_CTRL2_BC_MASK);
1620
 
                        nsegs = 1;
1621
 
                }
1622
 
 
1623
 
                for (j = nsegs; j > 0; j--) {
1624
 
                        W_SM(&di->txd64[i].addrlow, 0xdeadbeef);
1625
 
                        W_SM(&di->txd64[i].addrhigh, 0xdeadbeef);
1626
 
 
1627
 
                        txp = di->txp[i];
1628
 
                        di->txp[i] = NULL;
1629
 
                        if (j > 1)
1630
 
                                i = NEXTTXD(i);
1631
 
                }
1632
 
 
1633
 
                pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
1634
 
        }
1635
 
 
1636
 
        di->txin = i;
1637
 
 
1638
 
        /* tx flow control */
1639
 
        di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
1640
 
 
1641
 
        return txp;
1642
 
 
1643
 
 bogus:
1644
 
        DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", start, end, di->txout, forceall));
1645
 
        return NULL;
1646
 
}
1647
 
 
1648
 
static void *BCMFASTPATH dma64_getnextrxp(dma_info_t *di, bool forceall)
1649
 
{
1650
 
        uint i, curr;
1651
 
        void *rxp;
1652
 
        dmaaddr_t pa;
1653
 
 
1654
 
        /* if forcing, dma engine must be disabled */
1655
 
        ASSERT(!forceall || !dma64_rxenabled(di));
1656
 
 
1657
 
        i = di->rxin;
1658
 
 
1659
 
        /* return if no packets posted */
1660
 
        if (i == di->rxout)
1661
 
                return NULL;
1662
 
 
1663
 
        curr =
1664
 
            B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
1665
 
                 di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t);
1666
 
 
1667
 
        /* ignore curr if forceall */
1668
 
        if (!forceall && (i == curr))
1669
 
                return NULL;
1670
 
 
1671
 
        /* get the packet pointer that corresponds to the rx descriptor */
1672
 
        rxp = di->rxp[i];
1673
 
        ASSERT(rxp);
1674
 
        di->rxp[i] = NULL;
1675
 
 
1676
 
        PHYSADDRLOSET(pa,
1677
 
                      (BUS_SWAP32(R_SM(&di->rxd64[i].addrlow)) -
1678
 
                       di->dataoffsetlow));
1679
 
        PHYSADDRHISET(pa,
1680
 
                      (BUS_SWAP32(R_SM(&di->rxd64[i].addrhigh)) -
1681
 
                       di->dataoffsethigh));
1682
 
 
1683
 
        /* clear this packet from the descriptor ring */
1684
 
        pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
1685
 
 
1686
 
        W_SM(&di->rxd64[i].addrlow, 0xdeadbeef);
1687
 
        W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef);
1688
 
 
1689
 
        di->rxin = NEXTRXD(i);
1690
 
 
1691
 
        return rxp;
1692
 
}
1693
 
 
1694
 
static bool _dma64_addrext(dma64regs_t *dma64regs)
1695
 
{
1696
 
        u32 w;
1697
 
        OR_REG(&dma64regs->control, D64_XC_AE);
1698
 
        w = R_REG(&dma64regs->control);
1699
 
        AND_REG(&dma64regs->control, ~D64_XC_AE);
1700
 
        return (w & D64_XC_AE) == D64_XC_AE;
1701
 
}
1702
 
 
1703
 
/*
1704
 
 * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
1705
 
 */
1706
 
static void dma64_txrotate(dma_info_t *di)
1707
 
{
1708
 
        u16 ad;
1709
 
        uint nactive;
1710
 
        uint rot;
1711
 
        u16 old, new;
1712
 
        u32 w;
1713
 
        u16 first, last;
1714
 
 
1715
 
        ASSERT(dma64_txsuspendedidle(di));
1716
 
 
1717
 
        nactive = _dma_txactive(di);
1718
 
        ad = (u16) (B2I
1719
 
                       ((((R_REG(&di->d64txregs->status1) &
1720
 
                           D64_XS1_AD_MASK)
1721
 
                          - di->xmtptrbase) & D64_XS1_AD_MASK), dma64dd_t));
1722
 
        rot = TXD(ad - di->txin);
1723
 
 
1724
 
        ASSERT(rot < di->ntxd);
1725
 
 
1726
 
        /* full-ring case is a lot harder - don't worry about this */
1727
 
        if (rot >= (di->ntxd - nactive)) {
1728
 
                DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
1729
 
                return;
1730
 
        }
1731
 
 
1732
 
        first = di->txin;
1733
 
        last = PREVTXD(di->txout);
1734
 
 
1735
 
        /* move entries starting at last and moving backwards to first */
1736
 
        for (old = last; old != PREVTXD(first); old = PREVTXD(old)) {
1737
 
                new = TXD(old + rot);
1738
 
 
1739
 
                /*
1740
 
                 * Move the tx dma descriptor.
1741
 
                 * EOT is set only in the last entry in the ring.
1742
 
                 */
1743
 
                w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl1)) & ~D64_CTRL1_EOT;
1744
 
                if (new == (di->ntxd - 1))
1745
 
                        w |= D64_CTRL1_EOT;
1746
 
                W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w));
1747
 
 
1748
 
                w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2));
1749
 
                W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w));
1750
 
 
1751
 
                W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow));
1752
 
                W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh));
1753
 
 
1754
 
                /* zap the old tx dma descriptor address field */
1755
 
                W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef));
1756
 
                W_SM(&di->txd64[old].addrhigh, BUS_SWAP32(0xdeadbeef));
1757
 
 
1758
 
                /* move the corresponding txp[] entry */
1759
 
                ASSERT(di->txp[new] == NULL);
1760
 
                di->txp[new] = di->txp[old];
1761
 
 
1762
 
                /* Move the map */
1763
 
                if (DMASGLIST_ENAB) {
1764
 
                        memcpy(&di->txp_dmah[new], &di->txp_dmah[old],
1765
 
                               sizeof(hnddma_seg_map_t));
1766
 
                        memset(&di->txp_dmah[old], 0, sizeof(hnddma_seg_map_t));
1767
 
                }
1768
 
 
1769
 
                di->txp[old] = NULL;
1770
 
        }
1771
 
 
1772
 
        /* update txin and txout */
1773
 
        di->txin = ad;
1774
 
        di->txout = TXD(di->txout + rot);
1775
 
        di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
1776
 
 
1777
 
        /* kick the chip */
1778
 
        W_REG(&di->d64txregs->ptr,
1779
 
              di->xmtptrbase + I2B(di->txout, dma64dd_t));
1780
 
}
1781
 
 
1782
 
uint dma_addrwidth(si_t *sih, void *dmaregs)
1783
 
{
1784
 
        /* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */
1785
 
        /* DMA engine is 64-bit capable */
1786
 
        if ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) {
1787
 
                /* backplane are 64-bit capable */
1788
 
                if (si_backplane64(sih))
1789
 
                        /* If bus is System Backplane or PCIE then we can access 64-bits */
1790
 
                        if ((sih->bustype == SI_BUS) ||
1791
 
                            ((sih->bustype == PCI_BUS) &&
1792
 
                             (sih->buscoretype == PCIE_CORE_ID)))
1793
 
                                return DMADDRWIDTH_64;
1794
 
        }
1795
 
        ASSERT(0); /* DMA hardware not supported by this driver*/
1796
 
        return DMADDRWIDTH_64;
1797
 
}
1798
 
 
1799
 
/*
1800
 
 * Mac80211 initiated actions sometimes require packets in the DMA queue to be
1801
 
 * modified. The modified portion of the packet is not under control of the DMA
1802
 
 * engine. This function calls a caller-supplied function for each packet in
1803
 
 * the caller specified dma chain.
1804
 
 */
1805
 
void dma_walk_packets(struct hnddma_pub *dmah, void (*callback_fnc)
1806
 
                      (void *pkt, void *arg_a), void *arg_a)
1807
 
{
1808
 
        dma_info_t *di = (dma_info_t *) dmah;
1809
 
        uint i =   di->txin;
1810
 
        uint end = di->txout;
1811
 
        struct sk_buff *skb;
1812
 
        struct ieee80211_tx_info *tx_info;
1813
 
 
1814
 
        while (i != end) {
1815
 
                skb = (struct sk_buff *)di->txp[i];
1816
 
                if (skb != NULL) {
1817
 
                        tx_info = (struct ieee80211_tx_info *)skb->cb;
1818
 
                        (callback_fnc)(tx_info, arg_a);
1819
 
                }
1820
 
                i = NEXTTXD(i);
1821
 
        }
1822
 
}