From patchwork Fri Jan 29 11:39:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 101043 Delivered-To: patch@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp1058024lbb; Fri, 29 Jan 2016 03:40:25 -0800 (PST) X-Received: by 10.98.44.195 with SMTP id s186mr12802628pfs.0.1454067625199; Fri, 29 Jan 2016 03:40:25 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id tl4si1755803pab.219.2016.01.29.03.40.24; Fri, 29 Jan 2016 03:40:25 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755997AbcA2LkQ (ORCPT + 30 others); Fri, 29 Jan 2016 06:40:16 -0500 Received: from mout.kundenserver.de ([212.227.126.134]:57270 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755871AbcA2LkK (ORCPT ); Fri, 29 Jan 2016 06:40:10 -0500 Received: from wuerfel.lan. ([78.42.132.4]) by mrelayeu.kundenserver.de (mreue005) with ESMTPA (Nemesis) id 0M4DMF-1a6lCh1x7j-00rmlB; Fri, 29 Jan 2016 12:39:40 +0100 From: Arnd Bergmann To: David Miller Cc: linux-arm-kernel@lists.infradead.org, Arnd Bergmann , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/7] net: moxart: use correct accessors for DMA memory Date: Fri, 29 Jan 2016 12:39:09 +0100 Message-Id: <1454067557-3546883-2-git-send-email-arnd@arndb.de> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1454067557-3546883-1-git-send-email-arnd@arndb.de> References: <1454067557-3546883-1-git-send-email-arnd@arndb.de> X-Provags-ID: V03:K0:Xj3Lqvjj94lb84yGUXIhxgophH2PJ/IF+jwHvqsP8uBTMUQrUUC 7tXXUeJlP7Q0Df6eHaWoKHqX2Ke60+7VeaBSv9bfOEGPioTuK4y8bi0Pq5gpTROf3ztSTB9 yA9HqaoQ7GFz8s6WWv1+JFC5kX4jx+Le1VYfveII1oHeXRGncenDz2Bw1VGL5DFB8etzqgH bzX7Vp23M7KhMPpAO5skw== X-UI-Out-Filterresults: notjunk:1; V01:K0:SFRUXAaexvs=:TirvPcum8QvDBbFadNThY3 6chO06wLPPc3xvjLfz5S11teWX8722jOugZRoehc5HhnJCtpI6zO6t0qDSGrHdvm8QRIcooym 5qsHCSNBjY6HBuO91zx7qPy3s2RRS1GntzymMeVgEgj36Tuo77gHGwUWPIg1aywSmzYqV5IKM qNgLTZ+uBaNxIXgKCY96x/gTiPHY4TgEVxpqK+ZgLMxz8bl6WrI32aB/UR+JW/12EmvC2LF4r F0uiiH+sW1URmTewR7rhQzEeNRiUOpRvwwCsd/uao97eb2OMsTu2S9TuEbdgR4cZSlgMDmQiF P7tn4iCzP3QwszL4ytZd3xPBb32D3hDF6WxT2XYSG3IgTeRl3BzmqCu3T3qy01bvAX1UYylR0 gyls3h9NMtHCfI27Zzs4eSK8dznITiioJh8qOb+GyH1QwL5LI2BzftI9izYOQyQsxGcGs6Y0y RzWQEuvlT1lFPeMVBYeL3B9LTZlI8p5Rqwa0pxsGJ/Ro/QlEx2p3QOgJmezfYHDxhZYC17/SK aicvlXX3jKgLPFmf/gCIcdHFmM9wgvMTQWAOOcow38U8OMqOlXPt8AqJKWXvN9330GebMfy/L 5IcjsaliqSrK8OY+DhdzqUF8510GhXIoFF9l0pn2fCw49ceY2sKO5VT8tcgGhNhaN/B1zaM0l 7zrCB7JHY26FdkgReftw+VmnixaU7siitN7rjdm5W+80NkMdmGuP2P5PQXDj2kOkzeOY= Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The moxart ethernet driver confuses coherent DMA buffers with MMIO registers. moxart_ether.c: In function 'moxart_mac_setup_desc_ring': moxart_ether.c:146:428: error: passing argument 1 of '__fswab32' makes integer from pointer without a cast [-Werror=int-conversion] moxart_ether.c:74:39: warning: incorrect type in argument 3 (different address spaces) moxart_ether.c:74:39: expected void *cpu_addr moxart_ether.c:74:39: got void [noderef] *tx_desc_base This leaves the basic logic alone and uses normal pointers for the virtual address of the descriptor. As we cannot use readl/writel to access them, we also introduce our own moxart_desc_read moxart_desc_write helpers that perform the same endianess swap as the original code, but without the address space conversion. The barriers are made explicit here where needed: Even in the worst-case scenario, we just have to use a rmb() after checking ownership so we don't read any input data before we are sure it is value, and we use wmb() before transferring ownership back to the device. Signed-off-by: Arnd Bergmann --- drivers/net/ethernet/moxa/moxart_ether.c | 46 +++++++++++++++++++++----------- drivers/net/ethernet/moxa/moxart_ether.h | 4 +-- 2 files changed, 32 insertions(+), 18 deletions(-) -- 2.7.0 diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index a10c928bbd6b..00cfd95ca59d 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -28,6 +28,16 @@ #include "moxart_ether.h" +static inline void moxart_desc_write(u32 data, u32 *desc) +{ + *desc = cpu_to_le32(data); +} + +static inline u32 moxart_desc_read(u32 *desc) +{ + return le32_to_cpu(*desc); +} + static inline void moxart_emac_write(struct net_device *ndev, unsigned int reg, unsigned long value) { @@ -112,7 +122,7 @@ static void moxart_mac_enable(struct net_device *ndev) static void moxart_mac_setup_desc_ring(struct net_device *ndev) { struct moxart_mac_priv_t *priv = netdev_priv(ndev); - void __iomem *desc; + void *desc; int i; for (i = 0; i < TX_DESC_NUM; i++) { @@ -121,7 +131,7 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev) priv->tx_buf[i] = priv->tx_buf_base + priv->tx_buf_size * i; } - writel(TX_DESC1_END, desc + TX_REG_OFFSET_DESC1); + moxart_desc_write(TX_DESC1_END, desc + TX_REG_OFFSET_DESC1); priv->tx_head = 0; priv->tx_tail = 0; @@ -129,8 +139,8 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev) for (i = 0; i < RX_DESC_NUM; i++) { desc = priv->rx_desc_base + i * RX_REG_DESC_SIZE; memset(desc, 0, RX_REG_DESC_SIZE); - writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); - writel(RX_BUF_SIZE & RX_DESC1_BUF_SIZE_MASK, + moxart_desc_write(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); + moxart_desc_write(RX_BUF_SIZE & RX_DESC1_BUF_SIZE_MASK, desc + RX_REG_OFFSET_DESC1); priv->rx_buf[i] = priv->rx_buf_base + priv->rx_buf_size * i; @@ -141,12 +151,12 @@ static void moxart_mac_setup_desc_ring(struct net_device *ndev) if (dma_mapping_error(&ndev->dev, priv->rx_mapping[i])) netdev_err(ndev, "DMA mapping error\n"); - writel(priv->rx_mapping[i], + moxart_desc_write(priv->rx_mapping[i], desc + RX_REG_OFFSET_DESC2 + RX_DESC2_ADDRESS_PHYS); - writel(priv->rx_buf[i], + moxart_desc_write((uintptr_t)priv->rx_buf[i], desc + RX_REG_OFFSET_DESC2 + RX_DESC2_ADDRESS_VIRT); } - writel(RX_DESC1_END, desc + RX_REG_OFFSET_DESC1); + moxart_desc_write(RX_DESC1_END, desc + RX_REG_OFFSET_DESC1); priv->rx_head = 0; @@ -201,14 +211,15 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) napi); struct net_device *ndev = priv->ndev; struct sk_buff *skb; - void __iomem *desc; + void *desc; unsigned int desc0, len; int rx_head = priv->rx_head; int rx = 0; while (rx < budget) { desc = priv->rx_desc_base + (RX_REG_DESC_SIZE * rx_head); - desc0 = readl(desc + RX_REG_OFFSET_DESC0); + desc0 = moxart_desc_read(desc + RX_REG_OFFSET_DESC0); + rmb(); /* ensure desc0 is up to date */ if (desc0 & RX_DESC0_DMA_OWN) break; @@ -250,7 +261,8 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget) priv->stats.multicast++; rx_next: - writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); + wmb(); /* prevent setting ownership back too early */ + moxart_desc_write(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0); rx_head = RX_NEXT(rx_head); priv->rx_head = rx_head; @@ -310,7 +322,7 @@ static irqreturn_t moxart_mac_interrupt(int irq, void *dev_id) static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct moxart_mac_priv_t *priv = netdev_priv(ndev); - void __iomem *desc; + void *desc; unsigned int len; unsigned int tx_head = priv->tx_head; u32 txdes1; @@ -319,11 +331,12 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) desc = priv->tx_desc_base + (TX_REG_DESC_SIZE * tx_head); spin_lock_irq(&priv->txlock); - if (readl(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) { + if (moxart_desc_read(desc + TX_REG_OFFSET_DESC0) & TX_DESC0_DMA_OWN) { net_dbg_ratelimited("no TX space for packet\n"); priv->stats.tx_dropped++; goto out_unlock; } + rmb(); /* ensure data is only read that had TX_DESC0_DMA_OWN cleared */ len = skb->len > TX_BUF_SIZE ? TX_BUF_SIZE : skb->len; @@ -337,9 +350,9 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) priv->tx_len[tx_head] = len; priv->tx_skb[tx_head] = skb; - writel(priv->tx_mapping[tx_head], + moxart_desc_write(priv->tx_mapping[tx_head], desc + TX_REG_OFFSET_DESC2 + TX_DESC2_ADDRESS_PHYS); - writel(skb->data, + moxart_desc_write((uintptr_t)skb->data, desc + TX_REG_OFFSET_DESC2 + TX_DESC2_ADDRESS_VIRT); if (skb->len < ETH_ZLEN) { @@ -354,8 +367,9 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev) txdes1 = TX_DESC1_LTS | TX_DESC1_FTS | (len & TX_DESC1_BUF_SIZE_MASK); if (tx_head == TX_DESC_NUM_MASK) txdes1 |= TX_DESC1_END; - writel(txdes1, desc + TX_REG_OFFSET_DESC1); - writel(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0); + moxart_desc_write(txdes1, desc + TX_REG_OFFSET_DESC1); + wmb(); /* flush descriptor before transferring ownership */ + moxart_desc_write(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0); /* start to send packet */ writel(0xffffffff, priv->base + REG_TX_POLL_DEMAND); diff --git a/drivers/net/ethernet/moxa/moxart_ether.h b/drivers/net/ethernet/moxa/moxart_ether.h index 2be9280d608c..93a9563ac7c6 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.h +++ b/drivers/net/ethernet/moxa/moxart_ether.h @@ -300,7 +300,7 @@ struct moxart_mac_priv_t { dma_addr_t rx_base; dma_addr_t rx_mapping[RX_DESC_NUM]; - void __iomem *rx_desc_base; + void *rx_desc_base; unsigned char *rx_buf_base; unsigned char *rx_buf[RX_DESC_NUM]; unsigned int rx_head; @@ -308,7 +308,7 @@ struct moxart_mac_priv_t { dma_addr_t tx_base; dma_addr_t tx_mapping[TX_DESC_NUM]; - void __iomem *tx_desc_base; + void *tx_desc_base; unsigned char *tx_buf_base; unsigned char *tx_buf[RX_DESC_NUM]; unsigned int tx_head;