From patchwork Sun Apr 16 20:01:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergei Shtylyov X-Patchwork-Id: 9683099 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4A32E602CB for ; Sun, 16 Apr 2017 20:03:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F3DE27C05 for ; Sun, 16 Apr 2017 20:03:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0F7BC27D0C; Sun, 16 Apr 2017 20:03:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.4 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23F0427C05 for ; Sun, 16 Apr 2017 20:03:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756644AbdDPUCF (ORCPT ); Sun, 16 Apr 2017 16:02:05 -0400 Received: from mail-lf0-f43.google.com ([209.85.215.43]:33812 "EHLO mail-lf0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756638AbdDPUCD (ORCPT ); Sun, 16 Apr 2017 16:02:03 -0400 Received: by mail-lf0-f43.google.com with SMTP id t144so58326487lff.1 for ; Sun, 16 Apr 2017 13:02:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cogentembedded-com.20150623.gappssmtp.com; s=20150623; h=from:message-id:user-agent:date:to:cc:subject:mime-version :content-disposition; bh=7kiUBrm7b45nGwzdTKe8V7niKHcJisWmLl+79/+mYOw=; b=RVMX1ciYlnVtKE8eUqDMnjmeoGr1YcJuJZEULfCK9psSSdWUE0fgQIifyFNnWndjQd Vtt1UbgEZIvPALjYAnchTa90WxtJMA6WNtPJ7ntE68rDWq811cgrh549YkU96TItmFQD j2bILJsLMliJX8K+dwdzFajTyq1x1YdAMxAwwARBJN7tVuzxvks8Ox0DM3kkCeJiI552 adnGksghOnlRuUYHKZHLXZ7rv5t1QI1v4a02MtNCZxqOFCxcmaOnul/hZgQTTdb5M7Rs TRRWDZiRX0c8DBI8Cm3wwlWzUCG5j3jLYf91K+UhFFMr9VdO9iZe95hGc5tYHeVBJ9SD ym6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:user-agent:date:to:cc:subject :mime-version:content-disposition; bh=7kiUBrm7b45nGwzdTKe8V7niKHcJisWmLl+79/+mYOw=; b=csV6I0si7zInJGbVxlJpgAXs1KnNPwYr68JDwheajcJnrerf94jcdWd+YYETGaaSIs QtOLZKFGYr9fFjMn1F/Q6e1rwo1t2ARMOa8+Wj/tQJ8dp+dBwxTS24PF9fegPyVqJ0hM lfwlsuEi+p3Hj6LqMn8uz65aIyGPpVBCi4P9FYnc0kzrjCXTbpfvWppSVEXN1UFi7EFs QwR/BrsHyPXRQPpnv/60g7bHSS+GfMVNJJLIbLUV0hurgCdIFW8B6Rq4YapWvqPXEkfz dj9S7enQPIk+q6TJY8jIHwxXKITHq4GE3HrBEyirQpnl8uIXeT6/znu8t+tQkAdihse0 k4yg== X-Gm-Message-State: AN3rC/48KtM7f/2d2fjD+SzyKriIHcQ+mlB5LyYWI/k3Vc8KQZXAjRiM W55pHAnrGcphFg== X-Received: by 10.25.20.42 with SMTP id k42mr1868249lfi.8.1492372921819; Sun, 16 Apr 2017 13:02:01 -0700 (PDT) Received: from wasted.cogentembedded.com ([31.173.80.143]) by smtp.gmail.com with ESMTPSA id q66sm1555053ljb.31.2017.04.16.13.01.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 16 Apr 2017 13:02:00 -0700 (PDT) From: Sergei Shtylyov X-Google-Original-From: "Sergei Shtylyov" Received: by wasted.cogentembedded.com (sSMTP sendmail emulation); Sun, 16 Apr 2017 23:01:57 +0300 Message-Id: <20170416200157.111095876@cogentembedded.com> User-Agent: quilt/0.64 Date: Sun, 16 Apr 2017 23:01:48 +0300 To: netdev@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, Sergei Shtylyov Subject: [PATCH] sh_eth: unmap DMA buffers when freeing rings MIME-Version: 1.0 Content-Disposition: inline; filename=sh_eth-unmap-DMA-buffers-when-freeing-rings.patch Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The DMA API debugging (when enabled) causes: WARNING: CPU: 0 PID: 1445 at lib/dma-debug.c:519 add_dma_entry+0xe0/0x12c DMA-API: exceeded 7 overlapping mappings of cacheline 0x01b2974d to be printed after repeated initialization of the Ether device, e.g. suspend/resume or 'ifconfig' up/down. This is because DMA buffers mapped using dma_map_single() in sh_eth_ring_format() and sh_eth_start_xmit() are never unmapped. Resolve this problem by unmapping the buffers when freeing the descriptor rings; in order to do it right, we'd have to add an extra parameter to sh_eth_txfree() (we rename this function to sh_eth_tx_free(), while at it). Based on the commit a47b70ea86bd ("ravb: unmap descriptors when freeing rings"). Signed-off-by: Sergei Shtylyov --- drivers/net/ethernet/renesas/sh_eth.c | 122 ++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 55 deletions(-) Index: net/drivers/net/ethernet/renesas/sh_eth.c =================================================================== --- net.orig/drivers/net/ethernet/renesas/sh_eth.c +++ net/drivers/net/ethernet/renesas/sh_eth.c @@ -1127,12 +1127,70 @@ static struct mdiobb_ops bb_ops = { .get_mdio_data = sh_get_mdio, }; +/* free Tx skb function */ +static int sh_eth_tx_free(struct net_device *ndev, bool sent_only) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + struct sh_eth_txdesc *txdesc; + int free_num = 0; + int entry; + bool sent; + + for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) { + entry = mdp->dirty_tx % mdp->num_tx_ring; + txdesc = &mdp->tx_ring[entry]; + sent = txdesc->status & cpu_to_le32(TD_TACT); + if (sent_only && !sent) + break; + /* TACT bit must be checked before all the following reads */ + dma_rmb(); + netif_info(mdp, tx_done, ndev, + "tx entry %d status 0x%08x\n", + entry, le32_to_cpu(txdesc->status)); + /* Free the original skb. */ + if (mdp->tx_skbuff[entry]) { + dma_unmap_single(&ndev->dev, le32_to_cpu(txdesc->addr), + le32_to_cpu(txdesc->len) >> 16, + DMA_TO_DEVICE); + dev_kfree_skb_irq(mdp->tx_skbuff[entry]); + mdp->tx_skbuff[entry] = NULL; + free_num++; + } + txdesc->status = cpu_to_le32(TD_TFP); + if (entry >= mdp->num_tx_ring - 1) + txdesc->status |= cpu_to_le32(TD_TDLE); + + if (sent) { + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += le32_to_cpu(txdesc->len) >> 16; + } + } + return free_num; +} + /* free skb and descriptor buffer */ static void sh_eth_ring_free(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); int ringsize, i; + if (mdp->rx_ring) { + for (i = 0; i < mdp->num_rx_ring; i++) { + if (mdp->rx_skbuff[i]) { + struct sh_eth_rxdesc *rxdesc = &mdp->rx_ring[i]; + + dma_unmap_single(&ndev->dev, + le32_to_cpu(rxdesc->addr), + ALIGN(mdp->rx_buf_sz, 32), + DMA_FROM_DEVICE); + } + } + ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; + dma_free_coherent(NULL, ringsize, mdp->rx_ring, + mdp->rx_desc_dma); + mdp->rx_ring = NULL; + } + /* Free Rx skb ringbuffer */ if (mdp->rx_skbuff) { for (i = 0; i < mdp->num_rx_ring; i++) @@ -1141,27 +1199,18 @@ static void sh_eth_ring_free(struct net_ kfree(mdp->rx_skbuff); mdp->rx_skbuff = NULL; - /* Free Tx skb ringbuffer */ - if (mdp->tx_skbuff) { - for (i = 0; i < mdp->num_tx_ring; i++) - dev_kfree_skb(mdp->tx_skbuff[i]); - } - kfree(mdp->tx_skbuff); - mdp->tx_skbuff = NULL; - - if (mdp->rx_ring) { - ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; - dma_free_coherent(NULL, ringsize, mdp->rx_ring, - mdp->rx_desc_dma); - mdp->rx_ring = NULL; - } - if (mdp->tx_ring) { + sh_eth_tx_free(ndev, false); + ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; dma_free_coherent(NULL, ringsize, mdp->tx_ring, mdp->tx_desc_dma); mdp->tx_ring = NULL; } + + /* Free Tx skb ringbuffer */ + kfree(mdp->tx_skbuff); + mdp->tx_skbuff = NULL; } /* format skb and descriptor buffer */ @@ -1409,43 +1458,6 @@ static void sh_eth_dev_exit(struct net_d update_mac_address(ndev); } -/* free Tx skb function */ -static int sh_eth_txfree(struct net_device *ndev) -{ - struct sh_eth_private *mdp = netdev_priv(ndev); - struct sh_eth_txdesc *txdesc; - int free_num = 0; - int entry; - - for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) { - entry = mdp->dirty_tx % mdp->num_tx_ring; - txdesc = &mdp->tx_ring[entry]; - if (txdesc->status & cpu_to_le32(TD_TACT)) - break; - /* TACT bit must be checked before all the following reads */ - dma_rmb(); - netif_info(mdp, tx_done, ndev, - "tx entry %d status 0x%08x\n", - entry, le32_to_cpu(txdesc->status)); - /* Free the original skb. */ - if (mdp->tx_skbuff[entry]) { - dma_unmap_single(&ndev->dev, le32_to_cpu(txdesc->addr), - le32_to_cpu(txdesc->len) >> 16, - DMA_TO_DEVICE); - dev_kfree_skb_irq(mdp->tx_skbuff[entry]); - mdp->tx_skbuff[entry] = NULL; - free_num++; - } - txdesc->status = cpu_to_le32(TD_TFP); - if (entry >= mdp->num_tx_ring - 1) - txdesc->status |= cpu_to_le32(TD_TDLE); - - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += le32_to_cpu(txdesc->len) >> 16; - } - return free_num; -} - /* Packet receive function */ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) { @@ -1690,7 +1702,7 @@ static void sh_eth_error(struct net_devi intr_status, mdp->cur_tx, mdp->dirty_tx, (u32)ndev->state, edtrr); /* dirty buffer free */ - sh_eth_txfree(ndev); + sh_eth_tx_free(ndev, true); /* SH7712 BUG */ if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) { @@ -1751,7 +1763,7 @@ static irqreturn_t sh_eth_interrupt(int /* Clear Tx interrupts */ sh_eth_write(ndev, intr_status & cd->tx_check, EESR); - sh_eth_txfree(ndev); + sh_eth_tx_free(ndev, true); netif_wake_queue(ndev); } @@ -2412,7 +2424,7 @@ static int sh_eth_start_xmit(struct sk_b spin_lock_irqsave(&mdp->lock, flags); if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) { - if (!sh_eth_txfree(ndev)) { + if (!sh_eth_tx_free(ndev, true)) { netif_warn(mdp, tx_queued, ndev, "TxFD exhausted.\n"); netif_stop_queue(ndev); spin_unlock_irqrestore(&mdp->lock, flags);