From patchwork Wed Aug 7 15:34:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Mack X-Patchwork-Id: 2840418 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 140309F479 for ; Wed, 7 Aug 2013 17:31:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id AAE8C20423 for ; Wed, 7 Aug 2013 17:31:20 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8D96A20430 for ; Wed, 7 Aug 2013 17:31:17 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V75pF-0007CY-Uu; Wed, 07 Aug 2013 15:39:03 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1V75o9-00041T-S4; Wed, 07 Aug 2013 15:37:53 +0000 Received: from svenfoo.org ([82.94.215.22] helo=mail.zonque.de) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V75la-0003in-Cr; Wed, 07 Aug 2013 15:35:37 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.zonque.de (Postfix) with ESMTP id 281C6C05A7; Wed, 7 Aug 2013 17:34:54 +0200 (CEST) Received: from mail.zonque.de ([127.0.0.1]) by localhost (rambrand.bugwerft.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QTYZ2UXPVeTK; Wed, 7 Aug 2013 17:34:54 +0200 (CEST) Received: from tamtam.fritz.box (p5DDC7ADB.dip0.t-ipconnect.de [93.220.122.219]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.zonque.de (Postfix) with ESMTPSA id EAE72C05A4; Wed, 7 Aug 2013 17:34:51 +0200 (CEST) From: Daniel Mack To: haojian.zhuang@linaro.org, eric.y.miao@gmail.com, linux-arm-kernel@lists.infradead.org Subject: [PATCH 12/20] net: smc911x.c: switch to dmaengine API Date: Wed, 7 Aug 2013 17:34:01 +0200 Message-Id: <1375889649-14638-13-git-send-email-zonque@gmail.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1375889649-14638-1-git-send-email-zonque@gmail.com> References: <1375889649-14638-1-git-send-email-zonque@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130807_113515_286127_FD0CC38D X-CRM114-Status: GOOD ( 19.22 ) X-Spam-Score: 1.5 (+) Cc: mark.rutland@arm.com, s.neumann@raumfeld.com, linux-mtd@lists.infradead.org, Daniel Mack , cxie4@marvell.com, lars@metafoo.de, nico@linaro.org, vinod.koul@intel.com, marek.vasut@gmail.com, ezequiel.garcia@free-electrons.com, rmk+kernel@arm.linux.org.uk, devicetree@vger.kernel.org, samuel@sortiz.org, arnd@arndb.de, broonie@kernel.org, mika.westerberg@linux.intel.com, thomas.petazzoni@free-electrons.com, gregkh@linuxfoundation.org, g.liakhovetski@gmx.de, sachin.kamat@linaro.org, kernel@pengutronix.de, djbw@fb.com, davem@davemloft.net X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, FREEMAIL_FROM,KHOP_BIG_TO_CC,RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Drop all PXA-DMA specific implementation details and switch over to generic dmaengine usage. This patch is only compile-tested. Signed-off-by: Daniel Mack --- drivers/net/ethernet/smsc/smc911x.c | 80 ++++++++++++++++++++++------------- drivers/net/ethernet/smsc/smc911x.h | 83 ++++++++++++++++++++----------------- 2 files changed, 98 insertions(+), 65 deletions(-) diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 345558f..19cdf8f 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -1178,9 +1178,9 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id) #ifdef SMC_USE_DMA static void -smc911x_tx_dma_irq(int dma, void *data) +smc911x_tx_dma_irq(void *param) { - struct net_device *dev = (struct net_device *)data; + struct net_device *dev = (struct net_device *) param; struct smc911x_local *lp = netdev_priv(dev); struct sk_buff *skb = lp->current_tx_skb; unsigned long flags; @@ -1189,7 +1189,6 @@ smc911x_tx_dma_irq(int dma, void *data) DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name); /* Clear the DMA interrupt sources */ - SMC_DMA_ACK_IRQ(dev, dma); BUG_ON(skb == NULL); dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE); dev->trans_start = jiffies; @@ -1212,10 +1211,9 @@ smc911x_tx_dma_irq(int dma, void *data) "%s: TX DMA irq completed\n", dev->name); } static void -smc911x_rx_dma_irq(int dma, void *data) +smc911x_rx_dma_irq(void *param) { - struct net_device *dev = (struct net_device *)data; - unsigned long ioaddr = dev->base_addr; + struct net_device *dev = (struct net_device *) param; struct smc911x_local *lp = netdev_priv(dev); struct sk_buff *skb = lp->current_rx_skb; unsigned long flags; @@ -1224,7 +1222,6 @@ smc911x_rx_dma_irq(int dma, void *data) DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__); DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name); /* Clear the DMA interrupt sources */ - SMC_DMA_ACK_IRQ(dev, dma); dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE); BUG_ON(skb == NULL); lp->current_rx_skb = NULL; @@ -1754,6 +1751,37 @@ static int smc911x_findirq(struct net_device *dev) return probe_irq_off(cookie); } +#ifdef SMC_USE_DMA +static void smc_alloc_dma(struct net_device *dev, + struct smc911x_local *lp) +{ + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_MEMCPY, mask); + + lp->rxdma = dma_request_channel(mask, NULL, NULL); + if (!lp->rxdma) { + printk("%s(): unable to allocate RX channel\n", __func__); + return; + } + + lp->txdma = dma_request_channel(mask, NULL, NULL); + if (!lp->txdma) { + printk("%s(): unable to allocate TX channel\n", __func__); + return; + } + + lp->rxdma_active = 0; + lp->txdma_active = 0; +} +#else +static inline void smc_alloc_dma(struct net_device *dev, + struct smc911x_local *lp) +{ +} +#endif + static const struct net_device_ops smc911x_netdev_ops = { .ndo_open = smc911x_open, .ndo_stop = smc911x_close, @@ -1969,13 +1997,7 @@ static int smc911x_probe(struct net_device *dev) if (retval) goto err_out; -#ifdef SMC_USE_DMA - lp->rxdma = SMC_DMA_REQUEST(dev, smc911x_rx_dma_irq); - lp->txdma = SMC_DMA_REQUEST(dev, smc911x_tx_dma_irq); - lp->rxdma_active = 0; - lp->txdma_active = 0; - dev->dma = lp->rxdma; -#endif + smc_alloc_dma(dev, lp); retval = register_netdev(dev); if (retval == 0) { @@ -1985,11 +2007,11 @@ static int smc911x_probe(struct net_device *dev) dev->base_addr, dev->irq); #ifdef SMC_USE_DMA - if (lp->rxdma != -1) - printk(" RXDMA %d ", lp->rxdma); + if (lp->rxdma) + printk(" RXDMA %p", lp->rxdma); - if (lp->txdma != -1) - printk("TXDMA %d", lp->txdma); + if (lp->txdma) + printk("TXDMA %p", lp->txdma); #endif printk("\n"); if (!is_valid_ether_addr(dev->dev_addr)) { @@ -2013,11 +2035,14 @@ static int smc911x_probe(struct net_device *dev) err_out: #ifdef SMC_USE_DMA if (retval) { - if (lp->rxdma != -1) { - SMC_DMA_FREE(dev, lp->rxdma); + if (lp->rxdma) { + dmaengine_terminate_all(lp->rxdma); + dma_release_channel(lp->rxdma); } - if (lp->txdma != -1) { - SMC_DMA_FREE(dev, lp->txdma); + + if (lp->txdma) { + dmaengine_terminate_all(lp->txdma); + dma_release_channel(lp->txdma); } } #endif @@ -2119,12 +2144,11 @@ static int smc911x_drv_remove(struct platform_device *pdev) #ifdef SMC_USE_DMA { - if (lp->rxdma != -1) { - SMC_DMA_FREE(dev, lp->rxdma); - } - if (lp->txdma != -1) { - SMC_DMA_FREE(dev, lp->txdma); - } + if (lp->rxdma) + dma_release_channel(lp->rxdma); + + if (lp->txdma) + dma_release_channel(lp->txdma); } #endif iounmap(lp->base); diff --git a/drivers/net/ethernet/smsc/smc911x.h b/drivers/net/ethernet/smsc/smc911x.h index d51261b..9323f1d 100644 --- a/drivers/net/ethernet/smsc/smc911x.h +++ b/drivers/net/ethernet/smsc/smc911x.h @@ -29,6 +29,7 @@ #ifndef _SMC911X_H_ #define _SMC911X_H_ +#include #include /* * Use the DMA feature on PXA chips @@ -102,8 +103,8 @@ struct smc911x_local { #ifdef SMC_USE_DMA /* DMA needs the physical address of the chip */ u_long physaddr; - int rxdma; - int txdma; + struct dma_chan *rxdma; + struct dma_chan *txdma; int rxdma_active; int txdma_active; struct sk_buff *current_rx_skb; @@ -211,27 +212,6 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg, #ifdef SMC_USE_PXA_DMA -#include - -/* - * Define the request and free functions - * These are unfortunately architecture specific as no generic allocation - * mechanism exits - */ -#define SMC_DMA_REQUEST(dev, handler) \ - pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev) - -#define SMC_DMA_FREE(dev, dma) \ - pxa_free_dma(dma) - -#define SMC_DMA_ACK_IRQ(dev, dma) \ -{ \ - if (DCSR(dma) & DCSR_BUSERR) { \ - printk("%s: DMA %d bus error!\n", dev->name, dma); \ - } \ - DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; \ -} - /* * Use a DMA for RX and TX packets. */ @@ -240,6 +220,9 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg, static dma_addr_t rx_dmabuf, tx_dmabuf; static int rx_dmalen, tx_dmalen; +static void smc911x_tx_dma_irq(void *param); +static void smc911x_rx_dma_irq(void *param); + #ifdef SMC_insl #undef SMC_insl #define SMC_insl(lp, r, p, l) \ @@ -247,8 +230,17 @@ static int rx_dmalen, tx_dmalen; static inline void smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr, - int reg, int dma, u_char *buf, int len) + int reg, struct dma_chan *chan, u_char *buf, int len) { + struct dma_async_tx_descriptor *tx; + struct dma_slave_config conf; + + memset(&conf, 0, sizeof(conf)); + + conf.direction = DMA_DEV_TO_MEM; + conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + conf.src_maxburst = 32; + /* 64 bit alignment is required for memory to memory DMA */ if ((long)buf & 4) { *((u32 *)buf) = SMC_inl(lp, reg); @@ -259,12 +251,16 @@ smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr, len *= 4; rx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_FROM_DEVICE); rx_dmalen = len; - DCSR(dma) = DCSR_NODESC; - DTADR(dma) = rx_dmabuf; - DSADR(dma) = physaddr + reg; - DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | - DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen)); - DCSR(dma) = DCSR_NODESC | DCSR_RUN; + + dmaengine_slave_config(chan, &conf); + tx = chan->device->device_prep_dma_memcpy(chan, rx_dmabuf, + physaddr + reg, len, 0); + + tx->callback = smc911x_rx_dma_irq; + tx->callback_param = lp->netdev; + + dmaengine_submit(tx); + dma_async_issue_pending(chan); } #endif @@ -275,8 +271,17 @@ smc_pxa_dma_insl(struct smc911x_local *lp, u_long physaddr, static inline void smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr, - int reg, int dma, u_char *buf, int len) + int reg, struct dma_chan *chan, u_char *buf, int len) { + struct dma_async_tx_descriptor *tx; + struct dma_slave_config conf; + + memset(&conf, 0, sizeof(conf)); + + conf.direction = DMA_MEM_TO_DEV; + conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + conf.dst_maxburst = 32; + /* 64 bit alignment is required for memory to memory DMA */ if ((long)buf & 4) { SMC_outl(*((u32 *)buf), lp, reg); @@ -287,12 +292,16 @@ smc_pxa_dma_outsl(struct smc911x_local *lp, u_long physaddr, len *= 4; tx_dmabuf = dma_map_single(lp->dev, buf, len, DMA_TO_DEVICE); tx_dmalen = len; - DCSR(dma) = DCSR_NODESC; - DSADR(dma) = tx_dmabuf; - DTADR(dma) = physaddr + reg; - DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 | - DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen)); - DCSR(dma) = DCSR_NODESC | DCSR_RUN; + + dmaengine_slave_config(chan, &conf); + tx = chan->device->device_prep_dma_memcpy(chan, physaddr + reg, + tx_dmabuf, len, 0); + + tx->callback = smc911x_tx_dma_irq; + tx->callback_param = lp->netdev; + + dmaengine_submit(tx); + dma_async_issue_pending(chan); } #endif #endif /* SMC_USE_PXA_DMA */