From patchwork Thu Jan 28 16:54:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnd Bergmann X-Patchwork-Id: 101049 Delivered-To: patch@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp593777lbb; Thu, 28 Jan 2016 08:55:19 -0800 (PST) X-Received: by 10.98.13.77 with SMTP id v74mr6025847pfi.162.1454000119096; Thu, 28 Jan 2016 08:55:19 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c67si17901165pfj.246.2016.01.28.08.55.18; Thu, 28 Jan 2016 08:55:19 -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 S1161439AbcA1QzR (ORCPT + 30 others); Thu, 28 Jan 2016 11:55:17 -0500 Received: from mout.kundenserver.de ([212.227.17.24]:53973 "EHLO mout.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161172AbcA1QzN (ORCPT ); Thu, 28 Jan 2016 11:55:13 -0500 Received: from wuerfel.localnet ([78.42.132.4]) by mrelayeu.kundenserver.de (mreue103) with ESMTPSA (Nemesis) id 0LmwP6-1Zt5zV2Nga-00h4CD; Thu, 28 Jan 2016 17:54:37 +0100 From: Arnd Bergmann To: David Miller Cc: "linux-arm-kernel@lists.infradead.org" , "netdev@vger.kernel.org" , =?iso-8859-1?q?fran=E7ois?= romieu , "linux-kernel@vger.kernel.org" , David Laight Subject: [PATCHv2] net: moxart: use correct accessors for DMA memory Date: Thu, 28 Jan 2016 17:54:33 +0100 Message-ID: <2689110.SEuesVebGN@wuerfel> User-Agent: KMail/4.11.5 (Linux/3.16.0-10-generic; KDE/4.11.5; x86_64; ; ) MIME-Version: 1.0 X-Provags-ID: V03:K0:pZ+SnvIa2XDvpEpbquzojcKv6UE952qawryVSnlVai/CkHYhiBk CKEZ21bsRvp5i5a4gyoGNfBmEaXLGHCMOji6cbf/Be9EJzj8Rz0X5KEycmYBBKJoriQOovA GnagZz1/iKYzWPlyefDkwETC0WaXAjOQkZQCPCKNBOccA0G/+10bYeHyErvTWJDHblrKVy5 JLtpc4HwXrXd+PGqViaWg== X-UI-Out-Filterresults: notjunk:1; V01:K0:/EcXCBnthoM=:IgXm6zvXT69MFnCeE33305 Jhx3iIkjUeOMQnjagOeW5LkPdIrIbVBXeVzwtkRAKuf0PiEVDcLkj109a0aNXvbF6pUNqUYnk ZtscUuG0BImCjd79m3cQm8ttcIddegowYM25U6b5FPH00ql7ccFYGOmb2djVsb7SNkbirZ6/R V3mx22JKNcliIRzDpzaN3eeorONp+HHtLttfDweI1MBi25YZFop/hkh8V6zrL2erEovCugj5r qOcl67+Bds4tKDPD30bZ8DmVVtb7we2a239sAU1ej6T2aAiTaYpjbERz/ki3FbIoZI5juG1g1 wZ8iaLjrljSGiM03TYQeYzPv58hd8WFWKnsIHcDWyF/BWKu3QdZhvUIXCv1pMANOXdr/CoCof 7i1QNR9g1s2l0ixX6nRROvYB1Ra+1zkpXysB53Ku2kTgfk78sczN5qxQJjNtAV6PvkKhGGgSF OCTxk2nyWJidGVout44964E6ltsp4ctxG7JhspXeLkiW/ykuHzsZi5g9uONu7xLwS/3SXEuv7 OjIbjGiH1ePBunRJC5Pqc3vhzTXBOKbG2nu5S0IyYj1rw7D7m8F+kKFKBkXVi7fOrSflVl+ip mVAo2r2dAc5F0WJ4Vo2NY3qBmIDlunuONlPJ/wJO3sv5pDROiScNh8DqjCBgDtZ1Q+oWuPnZ+ TMeJNL9GQq1b596Cv5+9v7mXlzKjc8oWzBcosw0NFnIKEHgYMro3twt4iv5//hir5kuo+FWYx bIy96VoNXhdwu91I 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 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;