Skip to content

Commit d24c8f2

Browse files
rjarzmikdavem330
authored andcommitted
net: smc91x: convert pxa dma to dmaengine
Convert the dma transfers to be dmaengine based, now pxa has a dmaengine slave driver. This makes this driver a bit more PXA agnostic. The driver was tested on pxa27x (mainstone) and pxa310 (zylonite), ie. only pxa platforms. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Cc: Russell King <linux@arm.linux.org.uk> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 37d2dbc commit d24c8f2

File tree

2 files changed

+84
-44
lines changed

2 files changed

+84
-44
lines changed

drivers/net/ethernet/smsc/smc91x.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,10 +2018,18 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
20182018
lp->cfg.flags |= SMC91X_USE_DMA;
20192019
# endif
20202020
if (lp->cfg.flags & SMC91X_USE_DMA) {
2021-
int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
2022-
smc_pxa_dma_irq, NULL);
2023-
if (dma >= 0)
2024-
dev->dma = dma;
2021+
dma_cap_mask_t mask;
2022+
struct pxad_param param;
2023+
2024+
dma_cap_zero(mask);
2025+
dma_cap_set(DMA_SLAVE, mask);
2026+
param.prio = PXAD_PRIO_LOWEST;
2027+
param.drcmr = -1UL;
2028+
2029+
lp->dma_chan =
2030+
dma_request_slave_channel_compat(mask, pxad_filter_fn,
2031+
&param, &dev->dev,
2032+
"data");
20252033
}
20262034
#endif
20272035

@@ -2032,8 +2040,8 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
20322040
version_string, revision_register & 0x0f,
20332041
lp->base, dev->irq);
20342042

2035-
if (dev->dma != (unsigned char)-1)
2036-
pr_cont(" DMA %d", dev->dma);
2043+
if (lp->dma_chan)
2044+
pr_cont(" DMA %p", lp->dma_chan);
20372045

20382046
pr_cont("%s%s\n",
20392047
lp->cfg.flags & SMC91X_NOWAIT ? " [nowait]" : "",
@@ -2058,8 +2066,8 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
20582066

20592067
err_out:
20602068
#ifdef CONFIG_ARCH_PXA
2061-
if (retval && dev->dma != (unsigned char)-1)
2062-
pxa_free_dma(dev->dma);
2069+
if (retval && lp->dma_chan)
2070+
dma_release_channel(lp->dma_chan);
20632071
#endif
20642072
return retval;
20652073
}
@@ -2370,6 +2378,7 @@ static int smc_drv_probe(struct platform_device *pdev)
23702378
struct smc_local *lp = netdev_priv(ndev);
23712379
lp->device = &pdev->dev;
23722380
lp->physaddr = res->start;
2381+
23732382
}
23742383
#endif
23752384

@@ -2406,8 +2415,8 @@ static int smc_drv_remove(struct platform_device *pdev)
24062415
free_irq(ndev->irq, ndev);
24072416

24082417
#ifdef CONFIG_ARCH_PXA
2409-
if (ndev->dma != (unsigned char)-1)
2410-
pxa_free_dma(ndev->dma);
2418+
if (lp->dma_chan)
2419+
dma_release_channel(lp->dma_chan);
24112420
#endif
24122421
iounmap(lp->base);
24132422

drivers/net/ethernet/smsc/smc91x.h

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#ifndef _SMC91X_H_
3434
#define _SMC91X_H_
3535

36+
#include <linux/dmaengine.h>
3637
#include <linux/smc91x.h>
3738

3839
/*
@@ -244,6 +245,7 @@ struct smc_local {
244245
u_long physaddr;
245246
struct device *device;
246247
#endif
248+
struct dma_chan *dma_chan;
247249
void __iomem *base;
248250
void __iomem *datacs;
249251

@@ -265,21 +267,47 @@ struct smc_local {
265267
* as RX which can overrun memory and lose packets.
266268
*/
267269
#include <linux/dma-mapping.h>
268-
#include <mach/dma.h>
270+
#include <linux/dma/pxa-dma.h>
269271

270272
#ifdef SMC_insl
271273
#undef SMC_insl
272274
#define SMC_insl(a, r, p, l) \
273275
smc_pxa_dma_insl(a, lp, r, dev->dma, p, l)
276+
static inline void
277+
smc_pxa_dma_inpump(struct smc_local *lp, u_char *buf, int len)
278+
{
279+
dma_addr_t dmabuf;
280+
struct dma_async_tx_descriptor *tx;
281+
dma_cookie_t cookie;
282+
enum dma_status status;
283+
struct dma_tx_state state;
284+
285+
dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
286+
tx = dmaengine_prep_slave_single(lp->dma_chan, dmabuf, len,
287+
DMA_DEV_TO_MEM, 0);
288+
if (tx) {
289+
cookie = dmaengine_submit(tx);
290+
dma_async_issue_pending(lp->dma_chan);
291+
do {
292+
status = dmaengine_tx_status(lp->dma_chan, cookie,
293+
&state);
294+
cpu_relax();
295+
} while (status != DMA_COMPLETE && status != DMA_ERROR &&
296+
state.residue);
297+
dmaengine_terminate_all(lp->dma_chan);
298+
}
299+
dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
300+
}
301+
274302
static inline void
275303
smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
276304
u_char *buf, int len)
277305
{
278-
u_long physaddr = lp->physaddr;
279-
dma_addr_t dmabuf;
306+
struct dma_slave_config config;
307+
int ret;
280308

281309
/* fallback if no DMA available */
282-
if (dma == (unsigned char)-1) {
310+
if (!lp->dma_chan) {
283311
readsl(ioaddr + reg, buf, len);
284312
return;
285313
}
@@ -291,18 +319,22 @@ smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
291319
len--;
292320
}
293321

322+
memset(&config, 0, sizeof(config));
323+
config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
324+
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
325+
config.src_addr = lp->physaddr + reg;
326+
config.dst_addr = lp->physaddr + reg;
327+
config.src_maxburst = 32;
328+
config.dst_maxburst = 32;
329+
ret = dmaengine_slave_config(lp->dma_chan, &config);
330+
if (ret) {
331+
dev_err(lp->device, "dma channel configuration failed: %d\n",
332+
ret);
333+
return;
334+
}
335+
294336
len *= 4;
295-
dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
296-
DCSR(dma) = DCSR_NODESC;
297-
DTADR(dma) = dmabuf;
298-
DSADR(dma) = physaddr + reg;
299-
DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
300-
DCMD_WIDTH4 | (DCMD_LENGTH & len));
301-
DCSR(dma) = DCSR_NODESC | DCSR_RUN;
302-
while (!(DCSR(dma) & DCSR_STOPSTATE))
303-
cpu_relax();
304-
DCSR(dma) = 0;
305-
dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
337+
smc_pxa_dma_inpump(lp, buf, len);
306338
}
307339
#endif
308340

@@ -314,11 +346,11 @@ static inline void
314346
smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
315347
u_char *buf, int len)
316348
{
317-
u_long physaddr = lp->physaddr;
318-
dma_addr_t dmabuf;
349+
struct dma_slave_config config;
350+
int ret;
319351

320352
/* fallback if no DMA available */
321-
if (dma == (unsigned char)-1) {
353+
if (!lp->dma_chan) {
322354
readsw(ioaddr + reg, buf, len);
323355
return;
324356
}
@@ -330,26 +362,25 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
330362
len--;
331363
}
332364

365+
memset(&config, 0, sizeof(config));
366+
config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
367+
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
368+
config.src_addr = lp->physaddr + reg;
369+
config.dst_addr = lp->physaddr + reg;
370+
config.src_maxburst = 32;
371+
config.dst_maxburst = 32;
372+
ret = dmaengine_slave_config(lp->dma_chan, &config);
373+
if (ret) {
374+
dev_err(lp->device, "dma channel configuration failed: %d\n",
375+
ret);
376+
return;
377+
}
378+
333379
len *= 2;
334-
dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
335-
DCSR(dma) = DCSR_NODESC;
336-
DTADR(dma) = dmabuf;
337-
DSADR(dma) = physaddr + reg;
338-
DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
339-
DCMD_WIDTH2 | (DCMD_LENGTH & len));
340-
DCSR(dma) = DCSR_NODESC | DCSR_RUN;
341-
while (!(DCSR(dma) & DCSR_STOPSTATE))
342-
cpu_relax();
343-
DCSR(dma) = 0;
344-
dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
380+
smc_pxa_dma_inpump(lp, buf, len);
345381
}
346382
#endif
347383

348-
static void
349-
smc_pxa_dma_irq(int dma, void *dummy)
350-
{
351-
DCSR(dma) = 0;
352-
}
353384
#endif /* CONFIG_ARCH_PXA */
354385

355386

0 commit comments

Comments
 (0)