Path: blob/main/sys/contrib/dev/broadcom/brcm80211/brcmsmac/dma.c
178665 views
/*1* Copyright (c) 2010 Broadcom Corporation2*3* Permission to use, copy, modify, and/or distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES8* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF9* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY10* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES11* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION12* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN13* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.14*/1516#include <linux/slab.h>17#include <linux/delay.h>18#include <linux/pci.h>19#include <net/cfg80211.h>20#include <net/mac80211.h>2122#include <brcmu_utils.h>23#include <aiutils.h>24#include "types.h"25#include "main.h"26#include "dma.h"27#include "soc.h"28#include "scb.h"29#include "ampdu.h"30#include "debug.h"31#include "brcms_trace_events.h"3233/*34* dma register field offset calculation35*/36#define DMA64REGOFFS(field) offsetof(struct dma64regs, field)37#define DMA64TXREGOFFS(di, field) (di->d64txregbase + DMA64REGOFFS(field))38#define DMA64RXREGOFFS(di, field) (di->d64rxregbase + DMA64REGOFFS(field))3940/*41* DMA hardware requires each descriptor ring to be 8kB aligned, and fit within42* a contiguous 8kB physical address.43*/44#define D64RINGALIGN_BITS 1345#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS)46#define D64RINGALIGN (1 << D64RINGALIGN_BITS)4748#define D64MAXDD (D64MAXRINGSZ / sizeof(struct dma64desc))4950/* transmit channel control */51#define D64_XC_XE 0x00000001 /* transmit enable */52#define D64_XC_SE 0x00000002 /* transmit suspend request */53#define D64_XC_LE 0x00000004 /* loopback enable */54#define D64_XC_FL 0x00000010 /* flush request */55#define D64_XC_PD 0x00000800 /* parity check disable */56#define D64_XC_AE 0x00030000 /* address extension bits */57#define D64_XC_AE_SHIFT 165859/* transmit descriptor table pointer */60#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */6162/* transmit channel status */63#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */64#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */65#define D64_XS0_XS_SHIFT 2866#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */67#define D64_XS0_XS_ACTIVE 0x10000000 /* active */68#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */69#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */70#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */7172#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */73#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */74#define D64_XS1_XE_SHIFT 2875#define D64_XS1_XE_NOERR 0x00000000 /* no error */76#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */77#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */78#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */79#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */80#define D64_XS1_XE_COREE 0x50000000 /* core error */8182/* receive channel control */83/* receive enable */84#define D64_RC_RE 0x0000000185/* receive frame offset */86#define D64_RC_RO_MASK 0x000000fe87#define D64_RC_RO_SHIFT 188/* direct fifo receive (pio) mode */89#define D64_RC_FM 0x0000010090/* separate rx header descriptor enable */91#define D64_RC_SH 0x0000020092/* overflow continue */93#define D64_RC_OC 0x0000040094/* parity check disable */95#define D64_RC_PD 0x0000080096/* address extension bits */97#define D64_RC_AE 0x0003000098#define D64_RC_AE_SHIFT 1699100/* flags for dma controller */101/* partity enable */102#define DMA_CTRL_PEN (1 << 0)103/* rx overflow continue */104#define DMA_CTRL_ROC (1 << 1)105/* allow rx scatter to multiple descriptors */106#define DMA_CTRL_RXMULTI (1 << 2)107/* Unframed Rx/Tx data */108#define DMA_CTRL_UNFRAMED (1 << 3)109110/* receive descriptor table pointer */111#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */112113/* receive channel status */114#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */115#define D64_RS0_RS_MASK 0xf0000000 /* receive state */116#define D64_RS0_RS_SHIFT 28117#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */118#define D64_RS0_RS_ACTIVE 0x10000000 /* active */119#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */120#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */121#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */122123#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */124#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */125#define D64_RS1_RE_SHIFT 28126#define D64_RS1_RE_NOERR 0x00000000 /* no error */127#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */128#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */129#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */130#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */131#define D64_RS1_RE_COREE 0x50000000 /* core error */132133/* fifoaddr */134#define D64_FA_OFF_MASK 0xffff /* offset */135#define D64_FA_SEL_MASK 0xf0000 /* select */136#define D64_FA_SEL_SHIFT 16137#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */138#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */139#define D64_FA_SEL_RDD 0x40000 /* receive dma data */140#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */141#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */142#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */143#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */144#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */145#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */146#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */147148/* descriptor control flags 1 */149#define D64_CTRL_COREFLAGS 0x0ff00000 /* core specific flags */150#define D64_CTRL1_EOT ((u32)1 << 28) /* end of descriptor table */151#define D64_CTRL1_IOC ((u32)1 << 29) /* interrupt on completion */152#define D64_CTRL1_EOF ((u32)1 << 30) /* end of frame */153#define D64_CTRL1_SOF ((u32)1 << 31) /* start of frame */154155/* descriptor control flags 2 */156/* buffer byte count. real data len must <= 16KB */157#define D64_CTRL2_BC_MASK 0x00007fff158/* address extension bits */159#define D64_CTRL2_AE 0x00030000160#define D64_CTRL2_AE_SHIFT 16161/* parity bit */162#define D64_CTRL2_PARITY 0x00040000163164/* control flags in the range [27:20] are core-specific and not defined here */165#define D64_CTRL_CORE_MASK 0x0ff00000166167#define D64_RX_FRM_STS_LEN 0x0000ffff /* frame length mask */168#define D64_RX_FRM_STS_OVFL 0x00800000 /* RxOverFlow */169#define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /* no. of descriptors used - 1 */170#define D64_RX_FRM_STS_DATATYPE 0xf0000000 /* core-dependent data type */171172/*173* packet headroom necessary to accommodate the largest header174* in the system, (i.e TXOFF). By doing, we avoid the need to175* allocate an extra buffer for the header when bridging to WL.176* There is a compile time check in wlc.c which ensure that this177* value is at least as big as TXOFF. This value is used in178* dma_rxfill().179*/180181#define BCMEXTRAHDROOM 172182183#define MAXNAMEL 8 /* 8 char names */184185/* macros to convert between byte offsets and indexes */186#define B2I(bytes, type) ((bytes) / sizeof(type))187#define I2B(index, type) ((index) * sizeof(type))188189#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */190#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */191192#define PCI64ADDR_HIGH 0x80000000 /* address[63] */193#define PCI64ADDR_HIGH_SHIFT 31 /* address[63] */194195/*196* DMA Descriptor197* Descriptors are only read by the hardware, never written back.198*/199struct dma64desc {200__le32 ctrl1; /* misc control bits & bufcount */201__le32 ctrl2; /* buffer count and address extension */202__le32 addrlow; /* memory address of the date buffer, bits 31:0 */203__le32 addrhigh; /* memory address of the date buffer, bits 63:32 */204};205206/* dma engine software state */207struct dma_info {208struct dma_pub dma; /* exported structure */209char name[MAXNAMEL]; /* callers name for diag msgs */210211struct bcma_device *core;212struct device *dmadev;213214/* session information for AMPDU */215struct brcms_ampdu_session ampdu_session;216217bool dma64; /* this dma engine is operating in 64-bit mode */218bool addrext; /* this dma engine supports DmaExtendedAddrChanges */219220/* 64-bit dma tx engine registers */221uint d64txregbase;222/* 64-bit dma rx engine registers */223uint d64rxregbase;224/* pointer to dma64 tx descriptor ring */225struct dma64desc *txd64;226/* pointer to dma64 rx descriptor ring */227struct dma64desc *rxd64;228229u16 dmadesc_align; /* alignment requirement for dma descriptors */230231u16 ntxd; /* # tx descriptors tunable */232u16 txin; /* index of next descriptor to reclaim */233u16 txout; /* index of next descriptor to post */234/* pointer to parallel array of pointers to packets */235struct sk_buff **txp;236/* Aligned physical address of descriptor ring */237dma_addr_t txdpa;238/* Original physical address of descriptor ring */239dma_addr_t txdpaorig;240u16 txdalign; /* #bytes added to alloc'd mem to align txd */241u32 txdalloc; /* #bytes allocated for the ring */242u32 xmtptrbase; /* When using unaligned descriptors, the ptr register243* is not just an index, it needs all 13 bits to be244* an offset from the addr register.245*/246247u16 nrxd; /* # rx descriptors tunable */248u16 rxin; /* index of next descriptor to reclaim */249u16 rxout; /* index of next descriptor to post */250/* pointer to parallel array of pointers to packets */251struct sk_buff **rxp;252/* Aligned physical address of descriptor ring */253dma_addr_t rxdpa;254/* Original physical address of descriptor ring */255dma_addr_t rxdpaorig;256u16 rxdalign; /* #bytes added to alloc'd mem to align rxd */257u32 rxdalloc; /* #bytes allocated for the ring */258u32 rcvptrbase; /* Base for ptr reg when using unaligned descriptors */259260/* tunables */261unsigned int rxbufsize; /* rx buffer size in bytes, not including262* the extra headroom263*/264uint rxextrahdrroom; /* extra rx headroom, reverseved to assist upper265* stack, e.g. some rx pkt buffers will be266* bridged to tx side without byte copying.267* The extra headroom needs to be large enough268* to fit txheader needs. Some dongle driver may269* not need it.270*/271uint nrxpost; /* # rx buffers to keep posted */272unsigned int rxoffset; /* rxcontrol offset */273/* add to get dma address of descriptor ring, low 32 bits */274uint ddoffsetlow;275/* high 32 bits */276uint ddoffsethigh;277/* add to get dma address of data buffer, low 32 bits */278uint dataoffsetlow;279/* high 32 bits */280uint dataoffsethigh;281/* descriptor base need to be aligned or not */282bool aligndesc_4k;283};284285/* Check for odd number of 1's */286static u32 parity32(__le32 data)287{288/* no swap needed for counting 1's */289u32 par_data = *(u32 *)&data;290291par_data ^= par_data >> 16;292par_data ^= par_data >> 8;293par_data ^= par_data >> 4;294par_data ^= par_data >> 2;295par_data ^= par_data >> 1;296297return par_data & 1;298}299300static bool dma64_dd_parity(struct dma64desc *dd)301{302return parity32(dd->addrlow ^ dd->addrhigh ^ dd->ctrl1 ^ dd->ctrl2);303}304305/* descriptor bumping functions */306307static uint xxd(uint x, uint n)308{309return x & (n - 1); /* faster than %, but n must be power of 2 */310}311312static uint txd(struct dma_info *di, uint x)313{314return xxd(x, di->ntxd);315}316317static uint rxd(struct dma_info *di, uint x)318{319return xxd(x, di->nrxd);320}321322static uint nexttxd(struct dma_info *di, uint i)323{324return txd(di, i + 1);325}326327static uint prevtxd(struct dma_info *di, uint i)328{329return txd(di, i - 1);330}331332static uint nextrxd(struct dma_info *di, uint i)333{334return rxd(di, i + 1);335}336337static uint ntxdactive(struct dma_info *di, uint h, uint t)338{339return txd(di, t-h);340}341342static uint nrxdactive(struct dma_info *di, uint h, uint t)343{344return rxd(di, t-h);345}346347static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)348{349uint dmactrlflags;350351if (di == NULL)352return 0;353354dmactrlflags = di->dma.dmactrlflags;355dmactrlflags &= ~mask;356dmactrlflags |= flags;357358/* If trying to enable parity, check if parity is actually supported */359if (dmactrlflags & DMA_CTRL_PEN) {360u32 control;361362control = bcma_read32(di->core, DMA64TXREGOFFS(di, control));363bcma_write32(di->core, DMA64TXREGOFFS(di, control),364control | D64_XC_PD);365if (bcma_read32(di->core, DMA64TXREGOFFS(di, control)) &366D64_XC_PD)367/* We *can* disable it so it is supported,368* restore control register369*/370bcma_write32(di->core, DMA64TXREGOFFS(di, control),371control);372else373/* Not supported, don't allow it to be enabled */374dmactrlflags &= ~DMA_CTRL_PEN;375}376377di->dma.dmactrlflags = dmactrlflags;378379return dmactrlflags;380}381382static bool _dma64_addrext(struct dma_info *di, uint ctrl_offset)383{384u32 w;385bcma_set32(di->core, ctrl_offset, D64_XC_AE);386w = bcma_read32(di->core, ctrl_offset);387bcma_mask32(di->core, ctrl_offset, ~D64_XC_AE);388return (w & D64_XC_AE) == D64_XC_AE;389}390391/*392* return true if this dma engine supports DmaExtendedAddrChanges,393* otherwise false394*/395static bool _dma_isaddrext(struct dma_info *di)396{397/* DMA64 supports full 32- or 64-bit operation. AE is always valid */398399/* not all tx or rx channel are available */400if (di->d64txregbase != 0) {401if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control)))402brcms_dbg_dma(di->core,403"%s: DMA64 tx doesn't have AE set\n",404di->name);405return true;406} else if (di->d64rxregbase != 0) {407if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control)))408brcms_dbg_dma(di->core,409"%s: DMA64 rx doesn't have AE set\n",410di->name);411return true;412}413414return false;415}416417static bool _dma_descriptor_align(struct dma_info *di)418{419u32 addrl;420421/* Check to see if the descriptors need to be aligned on 4K/8K or not */422if (di->d64txregbase != 0) {423bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow), 0xff0);424addrl = bcma_read32(di->core, DMA64TXREGOFFS(di, addrlow));425if (addrl != 0)426return false;427} else if (di->d64rxregbase != 0) {428bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow), 0xff0);429addrl = bcma_read32(di->core, DMA64RXREGOFFS(di, addrlow));430if (addrl != 0)431return false;432}433return true;434}435436/*437* Descriptor table must start at the DMA hardware dictated alignment, so438* allocated memory must be large enough to support this requirement.439*/440static void *dma_alloc_consistent(struct dma_info *di, uint size,441u16 align_bits, uint *alloced,442dma_addr_t *pap)443{444if (align_bits) {445u16 align = (1 << align_bits);446if (!IS_ALIGNED(PAGE_SIZE, align))447size += align;448*alloced = size;449}450return dma_alloc_coherent(di->dmadev, size, pap, GFP_ATOMIC);451}452453static454u8 dma_align_sizetobits(uint size)455{456u8 bitpos = 0;457while (size >>= 1)458bitpos++;459return bitpos;460}461462/* This function ensures that the DMA descriptor ring will not get allocated463* across Page boundary. If the allocation is done across the page boundary464* at the first time, then it is freed and the allocation is done at465* descriptor ring size aligned location. This will ensure that the ring will466* not cross page boundary467*/468static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,469u16 *alignbits, uint *alloced,470dma_addr_t *descpa)471{472void *va;473u32 desc_strtaddr;474u32 alignbytes = 1 << *alignbits;475476va = dma_alloc_consistent(di, size, *alignbits, alloced, descpa);477478if (NULL == va)479return NULL;480481desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);482if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr483& boundary)) {484*alignbits = dma_align_sizetobits(size);485dma_free_coherent(di->dmadev, size, va, *descpa);486va = dma_alloc_consistent(di, size, *alignbits,487alloced, descpa);488}489return va;490}491492static bool dma64_alloc(struct dma_info *di, uint direction)493{494u16 size;495uint ddlen;496void *va;497uint alloced = 0;498u16 align;499u16 align_bits;500501ddlen = sizeof(struct dma64desc);502503size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);504align_bits = di->dmadesc_align;505align = (1 << align_bits);506507if (direction == DMA_TX) {508va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,509&alloced, &di->txdpaorig);510if (va == NULL) {511brcms_dbg_dma(di->core,512"%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",513di->name);514return false;515}516align = (1 << align_bits);517di->txd64 = (struct dma64desc *)518roundup((unsigned long)va, align);519di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);520di->txdpa = di->txdpaorig + di->txdalign;521di->txdalloc = alloced;522} else {523va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,524&alloced, &di->rxdpaorig);525if (va == NULL) {526brcms_dbg_dma(di->core,527"%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",528di->name);529return false;530}531align = (1 << align_bits);532di->rxd64 = (struct dma64desc *)533roundup((unsigned long)va, align);534di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);535di->rxdpa = di->rxdpaorig + di->rxdalign;536di->rxdalloc = alloced;537}538539return true;540}541542static bool _dma_alloc(struct dma_info *di, uint direction)543{544return dma64_alloc(di, direction);545}546547struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,548uint txregbase, uint rxregbase, uint ntxd, uint nrxd,549uint rxbufsize, int rxextheadroom,550uint nrxpost, uint rxoffset)551{552struct si_pub *sih = wlc->hw->sih;553struct bcma_device *core = wlc->hw->d11core;554struct dma_info *di;555u8 rev = core->id.rev;556uint size;557struct si_info *sii = container_of(sih, struct si_info, pub);558559/* allocate private info structure */560di = kzalloc(sizeof(*di), GFP_ATOMIC);561if (di == NULL)562return NULL;563564di->dma64 =565((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64);566567/* init dma reg info */568di->core = core;569di->d64txregbase = txregbase;570di->d64rxregbase = rxregbase;571572/*573* Default flags (which can be changed by the driver calling574* dma_ctrlflags before enable): For backwards compatibility575* both Rx Overflow Continue and Parity are DISABLED.576*/577_dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);578579brcms_dbg_dma(di->core, "%s: %s flags 0x%x ntxd %d nrxd %d "580"rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "581"txregbase %u rxregbase %u\n", name, "DMA64",582di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,583rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);584585/* make a private copy of our callers name */586strscpy(di->name, name, sizeof(di->name));587588di->dmadev = core->dma_dev;589590/* save tunables */591di->ntxd = (u16) ntxd;592di->nrxd = (u16) nrxd;593594/* the actual dma size doesn't include the extra headroom */595di->rxextrahdrroom =596(rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom;597if (rxbufsize > BCMEXTRAHDROOM)598di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom);599else600di->rxbufsize = (u16) rxbufsize;601602di->nrxpost = (u16) nrxpost;603di->rxoffset = (u8) rxoffset;604605/*606* figure out the DMA physical address offset for dd and data607* PCI/PCIE: they map silicon backplace address to zero608* based memory, need offset609* Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram610* swapped region for data buffer, not descriptor611*/612di->ddoffsetlow = 0;613di->dataoffsetlow = 0;614/* for pci bus, add offset */615if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) {616/* add offset for pcie with DMA64 bus */617di->ddoffsetlow = 0;618di->ddoffsethigh = SI_PCIE_DMA_H32;619}620di->dataoffsetlow = di->ddoffsetlow;621di->dataoffsethigh = di->ddoffsethigh;622623/* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */624if ((core->id.id == BCMA_CORE_SDIO_DEV)625&& ((rev > 0) && (rev <= 2)))626di->addrext = false;627else if ((core->id.id == BCMA_CORE_I2S) &&628((rev == 0) || (rev == 1)))629di->addrext = false;630else631di->addrext = _dma_isaddrext(di);632633/* does the descriptor need to be aligned and if yes, on 4K/8K or not */634di->aligndesc_4k = _dma_descriptor_align(di);635if (di->aligndesc_4k) {636di->dmadesc_align = D64RINGALIGN_BITS;637if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2))638/* for smaller dd table, HW relax alignment reqmnt */639di->dmadesc_align = D64RINGALIGN_BITS - 1;640} else {641di->dmadesc_align = 4; /* 16 byte alignment */642}643644brcms_dbg_dma(di->core, "DMA descriptor align_needed %d, align %d\n",645di->aligndesc_4k, di->dmadesc_align);646647/* allocate tx packet pointer vector */648if (ntxd) {649size = ntxd * sizeof(void *);650di->txp = kzalloc(size, GFP_ATOMIC);651if (di->txp == NULL)652goto fail;653}654655/* allocate rx packet pointer vector */656if (nrxd) {657size = nrxd * sizeof(void *);658di->rxp = kzalloc(size, GFP_ATOMIC);659if (di->rxp == NULL)660goto fail;661}662663/*664* allocate transmit descriptor ring, only need ntxd descriptors665* but it must be aligned666*/667if (ntxd) {668if (!_dma_alloc(di, DMA_TX))669goto fail;670}671672/*673* allocate receive descriptor ring, only need nrxd descriptors674* but it must be aligned675*/676if (nrxd) {677if (!_dma_alloc(di, DMA_RX))678goto fail;679}680681if ((di->ddoffsetlow != 0) && !di->addrext) {682if (di->txdpa > SI_PCI_DMA_SZ) {683brcms_dbg_dma(di->core,684"%s: txdpa 0x%x: addrext not supported\n",685di->name, (u32)di->txdpa);686goto fail;687}688if (di->rxdpa > SI_PCI_DMA_SZ) {689brcms_dbg_dma(di->core,690"%s: rxdpa 0x%x: addrext not supported\n",691di->name, (u32)di->rxdpa);692goto fail;693}694}695696/* Initialize AMPDU session */697brcms_c_ampdu_reset_session(&di->ampdu_session, wlc);698699brcms_dbg_dma(di->core,700"ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",701di->ddoffsetlow, di->ddoffsethigh,702di->dataoffsetlow, di->dataoffsethigh,703di->addrext);704705return (struct dma_pub *) di;706707fail:708dma_detach((struct dma_pub *)di);709return NULL;710}711712static inline void713dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring,714dma_addr_t pa, uint outidx, u32 *flags, u32 bufcount)715{716u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;717718/* PCI bus with big(>1G) physical address, use address extension */719if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) {720ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);721ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);722ddring[outidx].ctrl1 = cpu_to_le32(*flags);723ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);724} else {725/* address extension for 32-bit PCI */726u32 ae;727728ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;729pa &= ~PCI32ADDR_HIGH;730731ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;732ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);733ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);734ddring[outidx].ctrl1 = cpu_to_le32(*flags);735ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);736}737if (di->dma.dmactrlflags & DMA_CTRL_PEN) {738if (dma64_dd_parity(&ddring[outidx]))739ddring[outidx].ctrl2 =740cpu_to_le32(ctrl2 | D64_CTRL2_PARITY);741}742}743744/* !! may be called with core in reset */745void dma_detach(struct dma_pub *pub)746{747struct dma_info *di = container_of(pub, struct dma_info, dma);748749brcms_dbg_dma(di->core, "%s:\n", di->name);750751/* free dma descriptor rings */752if (di->txd64)753dma_free_coherent(di->dmadev, di->txdalloc,754((s8 *)di->txd64 - di->txdalign),755(di->txdpaorig));756if (di->rxd64)757dma_free_coherent(di->dmadev, di->rxdalloc,758((s8 *)di->rxd64 - di->rxdalign),759(di->rxdpaorig));760761/* free packet pointer vectors */762kfree(di->txp);763kfree(di->rxp);764765/* free our private info structure */766kfree(di);767768}769770/* initialize descriptor table base address */771static void772_dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)773{774if (!di->aligndesc_4k) {775if (direction == DMA_TX)776di->xmtptrbase = pa;777else778di->rcvptrbase = pa;779}780781if ((di->ddoffsetlow == 0)782|| !(pa & PCI32ADDR_HIGH)) {783if (direction == DMA_TX) {784bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),785pa + di->ddoffsetlow);786bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),787di->ddoffsethigh);788} else {789bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),790pa + di->ddoffsetlow);791bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),792di->ddoffsethigh);793}794} else {795/* DMA64 32bits address extension */796u32 ae;797798/* shift the high bit(s) from pa to ae */799ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;800pa &= ~PCI32ADDR_HIGH;801802if (direction == DMA_TX) {803bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),804pa + di->ddoffsetlow);805bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),806di->ddoffsethigh);807bcma_maskset32(di->core, DMA64TXREGOFFS(di, control),808D64_XC_AE, (ae << D64_XC_AE_SHIFT));809} else {810bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),811pa + di->ddoffsetlow);812bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),813di->ddoffsethigh);814bcma_maskset32(di->core, DMA64RXREGOFFS(di, control),815D64_RC_AE, (ae << D64_RC_AE_SHIFT));816}817}818}819820static void _dma_rxenable(struct dma_info *di)821{822uint dmactrlflags = di->dma.dmactrlflags;823u32 control;824825brcms_dbg_dma(di->core, "%s:\n", di->name);826827control = D64_RC_RE | (bcma_read32(di->core,828DMA64RXREGOFFS(di, control)) &829D64_RC_AE);830831if ((dmactrlflags & DMA_CTRL_PEN) == 0)832control |= D64_RC_PD;833834if (dmactrlflags & DMA_CTRL_ROC)835control |= D64_RC_OC;836837bcma_write32(di->core, DMA64RXREGOFFS(di, control),838((di->rxoffset << D64_RC_RO_SHIFT) | control));839}840841void dma_rxinit(struct dma_pub *pub)842{843struct dma_info *di = container_of(pub, struct dma_info, dma);844845brcms_dbg_dma(di->core, "%s:\n", di->name);846847if (di->nrxd == 0)848return;849850di->rxin = di->rxout = 0;851852/* clear rx descriptor ring */853memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc));854855/* DMA engine with out alignment requirement requires table to be inited856* before enabling the engine857*/858if (!di->aligndesc_4k)859_dma_ddtable_init(di, DMA_RX, di->rxdpa);860861_dma_rxenable(di);862863if (di->aligndesc_4k)864_dma_ddtable_init(di, DMA_RX, di->rxdpa);865}866867static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)868{869uint i, curr;870struct sk_buff *rxp;871dma_addr_t pa;872873i = di->rxin;874875/* return if no packets posted */876if (i == di->rxout)877return NULL;878879curr =880B2I(((bcma_read32(di->core,881DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) -882di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);883884/* ignore curr if forceall */885if (!forceall && (i == curr))886return NULL;887888/* get the packet pointer that corresponds to the rx descriptor */889rxp = di->rxp[i];890di->rxp[i] = NULL;891892pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow;893894/* clear this packet from the descriptor ring */895dma_unmap_single(di->dmadev, pa, di->rxbufsize, DMA_FROM_DEVICE);896897di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef);898di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef);899900di->rxin = nextrxd(di, i);901902return rxp;903}904905static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)906{907if (di->nrxd == 0)908return NULL;909910return dma64_getnextrxp(di, forceall);911}912913/*914* !! rx entry routine915* returns the number packages in the next frame, or 0 if there are no more916* if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is917* supported with pkts chain918* otherwise, it's treated as giant pkt and will be tossed.919* The DMA scattering starts with normal DMA header, followed by first920* buffer data. After it reaches the max size of buffer, the data continues921* in next DMA descriptor buffer WITHOUT DMA header922*/923int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)924{925struct dma_info *di = container_of(pub, struct dma_info, dma);926struct sk_buff_head dma_frames;927struct sk_buff *p, *next;928uint len;929uint pkt_len;930int resid = 0;931int pktcnt = 1;932933skb_queue_head_init(&dma_frames);934next_frame:935p = _dma_getnextrxp(di, false);936if (p == NULL)937return 0;938939len = le16_to_cpu(*(__le16 *) (p->data));940brcms_dbg_dma(di->core, "%s: dma_rx len %d\n", di->name, len);941dma_spin_for_len(len, p);942943/* set actual length */944pkt_len = min((di->rxoffset + len), di->rxbufsize);945__skb_trim(p, pkt_len);946skb_queue_tail(&dma_frames, p);947resid = len - (di->rxbufsize - di->rxoffset);948949/* check for single or multi-buffer rx */950if (resid > 0) {951while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {952pkt_len = min_t(uint, resid, di->rxbufsize);953__skb_trim(p, pkt_len);954skb_queue_tail(&dma_frames, p);955resid -= di->rxbufsize;956pktcnt++;957}958959#ifdef DEBUG960if (resid > 0) {961uint cur;962cur =963B2I(((bcma_read32(di->core,964DMA64RXREGOFFS(di, status0)) &965D64_RS0_CD_MASK) - di->rcvptrbase) &966D64_RS0_CD_MASK, struct dma64desc);967brcms_dbg_dma(di->core,968"rxin %d rxout %d, hw_curr %d\n",969di->rxin, di->rxout, cur);970}971#endif /* DEBUG */972973if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {974brcms_dbg_dma(di->core, "%s: bad frame length (%d)\n",975di->name, len);976skb_queue_walk_safe(&dma_frames, p, next) {977skb_unlink(p, &dma_frames);978brcmu_pkt_buf_free_skb(p);979}980di->dma.rxgiants++;981pktcnt = 1;982goto next_frame;983}984}985986skb_queue_splice_tail(&dma_frames, skb_list);987return pktcnt;988}989990static bool dma64_rxidle(struct dma_info *di)991{992brcms_dbg_dma(di->core, "%s:\n", di->name);993994if (di->nrxd == 0)995return true;996997return ((bcma_read32(di->core,998DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) ==999(bcma_read32(di->core, DMA64RXREGOFFS(di, ptr)) &1000D64_RS0_CD_MASK));1001}10021003static bool dma64_txidle(struct dma_info *di)1004{1005if (di->ntxd == 0)1006return true;10071008return ((bcma_read32(di->core,1009DMA64TXREGOFFS(di, status0)) & D64_XS0_CD_MASK) ==1010(bcma_read32(di->core, DMA64TXREGOFFS(di, ptr)) &1011D64_XS0_CD_MASK));1012}10131014/*1015* post receive buffers1016* Return false if refill failed completely or dma mapping failed. The ring1017* is empty, which will stall the rx dma and user might want to call rxfill1018* again asap. This is unlikely to happen on a memory-rich NIC, but often on1019* memory-constrained dongle.1020*/1021bool dma_rxfill(struct dma_pub *pub)1022{1023struct dma_info *di = container_of(pub, struct dma_info, dma);1024struct sk_buff *p;1025u16 rxin, rxout;1026u32 flags = 0;1027uint n;1028uint i;1029dma_addr_t pa;1030uint extra_offset = 0;1031bool ring_empty;10321033ring_empty = false;10341035/*1036* Determine how many receive buffers we're lacking1037* from the full complement, allocate, initialize,1038* and post them, then update the chip rx lastdscr.1039*/10401041rxin = di->rxin;1042rxout = di->rxout;10431044n = di->nrxpost - nrxdactive(di, rxin, rxout);10451046brcms_dbg_dma(di->core, "%s: post %d\n", di->name, n);10471048if (di->rxbufsize > BCMEXTRAHDROOM)1049extra_offset = di->rxextrahdrroom;10501051for (i = 0; i < n; i++) {1052/*1053* the di->rxbufsize doesn't include the extra headroom,1054* we need to add it to the size to be allocated1055*/1056p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);10571058if (p == NULL) {1059brcms_dbg_dma(di->core, "%s: out of rxbufs\n",1060di->name);1061if (i == 0 && dma64_rxidle(di)) {1062brcms_dbg_dma(di->core, "%s: ring is empty !\n",1063di->name);1064ring_empty = true;1065}1066di->dma.rxnobuf++;1067break;1068}1069/* reserve an extra headroom, if applicable */1070if (extra_offset)1071skb_pull(p, extra_offset);10721073/* Do a cached write instead of uncached write since DMA_MAP1074* will flush the cache.1075*/1076*(u32 *) (p->data) = 0;10771078pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,1079DMA_FROM_DEVICE);1080if (dma_mapping_error(di->dmadev, pa)) {1081brcmu_pkt_buf_free_skb(p);1082return false;1083}10841085/* save the free packet pointer */1086di->rxp[rxout] = p;10871088/* reset flags for each descriptor */1089flags = 0;1090if (rxout == (di->nrxd - 1))1091flags = D64_CTRL1_EOT;10921093dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,1094di->rxbufsize);1095rxout = nextrxd(di, rxout);1096}10971098di->rxout = rxout;10991100/* update the chip lastdscr pointer */1101bcma_write32(di->core, DMA64RXREGOFFS(di, ptr),1102di->rcvptrbase + I2B(rxout, struct dma64desc));11031104return ring_empty;1105}11061107void dma_rxreclaim(struct dma_pub *pub)1108{1109struct dma_info *di = container_of(pub, struct dma_info, dma);1110struct sk_buff *p;11111112brcms_dbg_dma(di->core, "%s:\n", di->name);11131114while ((p = _dma_getnextrxp(di, true)))1115brcmu_pkt_buf_free_skb(p);1116}11171118void dma_counterreset(struct dma_pub *pub)1119{1120/* reset all software counters */1121pub->rxgiants = 0;1122pub->rxnobuf = 0;1123pub->txnobuf = 0;1124}11251126/* get the address of the var in order to change later */1127unsigned long dma_getvar(struct dma_pub *pub, const char *name)1128{1129struct dma_info *di = container_of(pub, struct dma_info, dma);11301131if (!strcmp(name, "&txavail"))1132return (unsigned long)&(di->dma.txavail);1133return 0;1134}11351136/* 64-bit DMA functions */11371138void dma_txinit(struct dma_pub *pub)1139{1140struct dma_info *di = container_of(pub, struct dma_info, dma);1141u32 control = D64_XC_XE;11421143brcms_dbg_dma(di->core, "%s:\n", di->name);11441145if (di->ntxd == 0)1146return;11471148di->txin = di->txout = 0;1149di->dma.txavail = di->ntxd - 1;11501151/* clear tx descriptor ring */1152memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc)));11531154/* DMA engine with out alignment requirement requires table to be inited1155* before enabling the engine1156*/1157if (!di->aligndesc_4k)1158_dma_ddtable_init(di, DMA_TX, di->txdpa);11591160if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0)1161control |= D64_XC_PD;1162bcma_set32(di->core, DMA64TXREGOFFS(di, control), control);11631164/* DMA engine with alignment requirement requires table to be inited1165* before enabling the engine1166*/1167if (di->aligndesc_4k)1168_dma_ddtable_init(di, DMA_TX, di->txdpa);1169}11701171void dma_txsuspend(struct dma_pub *pub)1172{1173struct dma_info *di = container_of(pub, struct dma_info, dma);11741175brcms_dbg_dma(di->core, "%s:\n", di->name);11761177if (di->ntxd == 0)1178return;11791180bcma_set32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);1181}11821183void dma_txresume(struct dma_pub *pub)1184{1185struct dma_info *di = container_of(pub, struct dma_info, dma);11861187brcms_dbg_dma(di->core, "%s:\n", di->name);11881189if (di->ntxd == 0)1190return;11911192bcma_mask32(di->core, DMA64TXREGOFFS(di, control), ~D64_XC_SE);1193}11941195bool dma_txsuspended(struct dma_pub *pub)1196{1197struct dma_info *di = container_of(pub, struct dma_info, dma);11981199return (di->ntxd == 0) ||1200((bcma_read32(di->core,1201DMA64TXREGOFFS(di, control)) & D64_XC_SE) ==1202D64_XC_SE);1203}12041205void dma_txreclaim(struct dma_pub *pub, enum txd_range range)1206{1207struct dma_info *di = container_of(pub, struct dma_info, dma);1208struct sk_buff *p;12091210brcms_dbg_dma(di->core, "%s: %s\n",1211di->name,1212range == DMA_RANGE_ALL ? "all" :1213range == DMA_RANGE_TRANSMITTED ? "transmitted" :1214"transferred");12151216if (di->txin == di->txout)1217return;12181219while ((p = dma_getnexttxp(pub, range))) {1220/* For unframed data, we don't have any packets to free */1221if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED))1222brcmu_pkt_buf_free_skb(p);1223}1224}12251226bool dma_txreset(struct dma_pub *pub)1227{1228struct dma_info *di = container_of(pub, struct dma_info, dma);1229u32 status;12301231if (di->ntxd == 0)1232return true;12331234/* suspend tx DMA first */1235bcma_write32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);1236SPINWAIT(((status =1237(bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &1238D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED) &&1239(status != D64_XS0_XS_IDLE) && (status != D64_XS0_XS_STOPPED),124010000);12411242bcma_write32(di->core, DMA64TXREGOFFS(di, control), 0);1243SPINWAIT(((status =1244(bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &1245D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED), 10000);12461247/* wait for the last transaction to complete */1248udelay(300);12491250return status == D64_XS0_XS_DISABLED;1251}12521253bool dma_rxreset(struct dma_pub *pub)1254{1255struct dma_info *di = container_of(pub, struct dma_info, dma);1256u32 status;12571258if (di->nrxd == 0)1259return true;12601261bcma_write32(di->core, DMA64RXREGOFFS(di, control), 0);1262SPINWAIT(((status =1263(bcma_read32(di->core, DMA64RXREGOFFS(di, status0)) &1264D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED), 10000);12651266return status == D64_RS0_RS_DISABLED;1267}12681269static void dma_txenq(struct dma_info *di, struct sk_buff *p)1270{1271unsigned char *data;1272uint len;1273u16 txout;1274u32 flags = 0;1275dma_addr_t pa;12761277txout = di->txout;12781279if (WARN_ON(nexttxd(di, txout) == di->txin))1280return;12811282/*1283* obtain and initialize transmit descriptor entry.1284*/1285data = p->data;1286len = p->len;12871288/* get physical address of buffer start */1289pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);1290/* if mapping failed, free skb */1291if (dma_mapping_error(di->dmadev, pa)) {1292brcmu_pkt_buf_free_skb(p);1293return;1294}1295/* With a DMA segment list, Descriptor table is filled1296* using the segment list instead of looping over1297* buffers in multi-chain DMA. Therefore, EOF for SGLIST1298* is when end of segment list is reached.1299*/1300flags = D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF;1301if (txout == (di->ntxd - 1))1302flags |= D64_CTRL1_EOT;13031304dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);13051306txout = nexttxd(di, txout);13071308/* save the packet */1309di->txp[prevtxd(di, txout)] = p;13101311/* bump the tx descriptor index */1312di->txout = txout;1313}13141315static void ampdu_finalize(struct dma_info *di)1316{1317struct brcms_ampdu_session *session = &di->ampdu_session;1318struct sk_buff *p;13191320trace_brcms_ampdu_session(&session->wlc->hw->d11core->dev,1321session->max_ampdu_len,1322session->max_ampdu_frames,1323session->ampdu_len,1324skb_queue_len(&session->skb_list),1325session->dma_len);13261327if (WARN_ON(skb_queue_empty(&session->skb_list)))1328return;13291330brcms_c_ampdu_finalize(session);13311332while (!skb_queue_empty(&session->skb_list)) {1333p = skb_dequeue(&session->skb_list);1334dma_txenq(di, p);1335}13361337bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),1338di->xmtptrbase + I2B(di->txout, struct dma64desc));1339brcms_c_ampdu_reset_session(session, session->wlc);1340}13411342static void prep_ampdu_frame(struct dma_info *di, struct sk_buff *p)1343{1344struct brcms_ampdu_session *session = &di->ampdu_session;1345int ret;13461347ret = brcms_c_ampdu_add_frame(session, p);1348if (ret == -ENOSPC) {1349/*1350* AMPDU cannot accommodate this frame. Close out the in-1351* progress AMPDU session and start a new one.1352*/1353ampdu_finalize(di);1354ret = brcms_c_ampdu_add_frame(session, p);1355}13561357WARN_ON(ret);1358}13591360/* Update count of available tx descriptors based on current DMA state */1361static void dma_update_txavail(struct dma_info *di)1362{1363/*1364* Available space is number of descriptors less the number of1365* active descriptors and the number of queued AMPDU frames.1366*/1367di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) -1368skb_queue_len(&di->ampdu_session.skb_list) - 1;1369}13701371/*1372* !! tx entry routine1373* WARNING: call must check the return value for error.1374* the error(toss frames) could be fatal and cause many subsequent hard1375* to debug problems1376*/1377int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,1378struct sk_buff *p)1379{1380struct dma_info *di = container_of(pub, struct dma_info, dma);1381struct brcms_ampdu_session *session = &di->ampdu_session;1382struct ieee80211_tx_info *tx_info;1383bool is_ampdu;13841385/* no use to transmit a zero length packet */1386if (p->len == 0)1387return 0;13881389/* return nonzero if out of tx descriptors */1390if (di->dma.txavail == 0 || nexttxd(di, di->txout) == di->txin)1391goto outoftxd;13921393tx_info = IEEE80211_SKB_CB(p);1394is_ampdu = tx_info->flags & IEEE80211_TX_CTL_AMPDU;1395if (is_ampdu)1396prep_ampdu_frame(di, p);1397else1398dma_txenq(di, p);13991400/* tx flow control */1401dma_update_txavail(di);14021403/* kick the chip */1404if (is_ampdu) {1405/*1406* Start sending data if we've got a full AMPDU, there's1407* no more space in the DMA ring, or the ring isn't1408* currently transmitting.1409*/1410if (skb_queue_len(&session->skb_list) == session->max_ampdu_frames ||1411di->dma.txavail == 0 || dma64_txidle(di))1412ampdu_finalize(di);1413} else {1414bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),1415di->xmtptrbase + I2B(di->txout, struct dma64desc));1416}14171418return 0;14191420outoftxd:1421brcms_dbg_dma(di->core, "%s: out of txds !!!\n", di->name);1422brcmu_pkt_buf_free_skb(p);1423di->dma.txavail = 0;1424di->dma.txnobuf++;1425return -ENOSPC;1426}14271428int dma_txpending(struct dma_pub *pub)1429{1430struct dma_info *di = container_of(pub, struct dma_info, dma);1431return ntxdactive(di, di->txin, di->txout);1432}14331434/*1435* If we have an active AMPDU session and are not transmitting,1436* this function will force tx to start.1437*/1438void dma_kick_tx(struct dma_pub *pub)1439{1440struct dma_info *di = container_of(pub, struct dma_info, dma);1441struct brcms_ampdu_session *session = &di->ampdu_session;14421443if (!skb_queue_empty(&session->skb_list) && dma64_txidle(di))1444ampdu_finalize(di);1445}14461447/*1448* Reclaim next completed txd (txds if using chained buffers) in the range1449* specified and return associated packet.1450* If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be1451* transmitted as noted by the hardware "CurrDescr" pointer.1452* If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be1453* transferred by the DMA as noted by the hardware "ActiveDescr" pointer.1454* If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and1455* return associated packet regardless of the value of hardware pointers.1456*/1457struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)1458{1459struct dma_info *di = container_of(pub, struct dma_info, dma);1460u16 start, end, i;1461u16 active_desc;1462struct sk_buff *txp;14631464brcms_dbg_dma(di->core, "%s: %s\n",1465di->name,1466range == DMA_RANGE_ALL ? "all" :1467range == DMA_RANGE_TRANSMITTED ? "transmitted" :1468"transferred");14691470if (di->ntxd == 0)1471return NULL;14721473txp = NULL;14741475start = di->txin;1476if (range == DMA_RANGE_ALL)1477end = di->txout;1478else {1479end = (u16) (B2I(((bcma_read32(di->core,1480DMA64TXREGOFFS(di, status0)) &1481D64_XS0_CD_MASK) - di->xmtptrbase) &1482D64_XS0_CD_MASK, struct dma64desc));14831484if (range == DMA_RANGE_TRANSFERED) {1485active_desc =1486(u16)(bcma_read32(di->core,1487DMA64TXREGOFFS(di, status1)) &1488D64_XS1_AD_MASK);1489active_desc =1490(active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;1491active_desc = B2I(active_desc, struct dma64desc);1492if (end != active_desc)1493end = prevtxd(di, active_desc);1494}1495}14961497if ((start == 0) && (end > di->txout))1498goto bogus;14991500for (i = start; i != end && !txp; i = nexttxd(di, i)) {1501dma_addr_t pa;1502uint size;15031504pa = le32_to_cpu(di->txd64[i].addrlow) - di->dataoffsetlow;15051506size =1507(le32_to_cpu(di->txd64[i].ctrl2) &1508D64_CTRL2_BC_MASK);15091510di->txd64[i].addrlow = cpu_to_le32(0xdeadbeef);1511di->txd64[i].addrhigh = cpu_to_le32(0xdeadbeef);15121513txp = di->txp[i];1514di->txp[i] = NULL;15151516dma_unmap_single(di->dmadev, pa, size, DMA_TO_DEVICE);1517}15181519di->txin = i;15201521/* tx flow control */1522dma_update_txavail(di);15231524return txp;15251526bogus:1527brcms_dbg_dma(di->core, "bogus curr: start %d end %d txout %d\n",1528start, end, di->txout);1529return NULL;1530}15311532/*1533* Mac80211 initiated actions sometimes require packets in the DMA queue to be1534* modified. The modified portion of the packet is not under control of the DMA1535* engine. This function calls a caller-supplied function for each packet in1536* the caller specified dma chain.1537*/1538void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)1539(void *pkt, void *arg_a), void *arg_a)1540{1541struct dma_info *di = container_of(dmah, struct dma_info, dma);1542uint i = di->txin;1543uint end = di->txout;1544struct sk_buff *skb;1545struct ieee80211_tx_info *tx_info;15461547while (i != end) {1548skb = di->txp[i];1549if (skb != NULL) {1550tx_info = (struct ieee80211_tx_info *)skb->cb;1551(callback_fnc)(tx_info, arg_a);1552}1553i = nexttxd(di, i);1554}1555}155615571558