From patchwork Mon Apr 17 12:55:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergei Shtylyov X-Patchwork-Id: 9683829 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 67A57602C2 for ; Mon, 17 Apr 2017 12:55:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4968A2654B for ; Mon, 17 Apr 2017 12:55:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3ADDB26E16; Mon, 17 Apr 2017 12:55:40 +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 9313D2654B for ; Mon, 17 Apr 2017 12:55:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752051AbdDQMzj (ORCPT ); Mon, 17 Apr 2017 08:55:39 -0400 Received: from mail-lf0-f46.google.com ([209.85.215.46]:33863 "EHLO mail-lf0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751603AbdDQMzi (ORCPT ); Mon, 17 Apr 2017 08:55:38 -0400 Received: by mail-lf0-f46.google.com with SMTP id t144so64954426lff.1 for ; Mon, 17 Apr 2017 05:55:37 -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=NbXmkwHYcMCv6HfJVCgbK/AEEhAugNlNgKxKfTAp908=; b=UR3HNQi5Wj6mWr2GSBFR2NGwD9+PMlJvqvAd5ipHuTZBA+AhTtaCb3oTp2MNe/xRno L67olG505Avv0oFYfHmtDL0hOFgAv4xKVgNWH/sePkB8RjNEUT4h9S4GZGS5Gi7yVDsi u/4eVfVoElV/VogCakWGo/eqig7S7J1unrqL/tbcd9FP+EOD/BOpXhVkIyR4foYJzC1w fjHnvU6BW71VCuihMlSGg3BKNeQz/j74NfPqjMiwe5KHG0zt2T3kQdf1AfBGDeKkRh8L WUjd7TqtmQUt5417m+SR8sd1YZEBtpxwDUTJwlfmOuLyJG9JYXF1BKGqkSQaEhbyS3JP agow== 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=NbXmkwHYcMCv6HfJVCgbK/AEEhAugNlNgKxKfTAp908=; b=Q4c8wt0YIEpUgE6GyhTEHwhfB51zNgET7/ND5BgYPkJt+SypcvX3u6eqKesOCGvlko Tj8H6DUpItm7UTp16HTO8HpB2is2o8nPYZ+XjnNZ0U1qqxKV3YTVo2XLRN+ksFDxaaW0 88A4QcX0H7mBwwEi4uHXHbCir2DlmVf9Jl68WZ8k0wXyY2qDHHwrN2H36Senef8WxTPM MjbkJJFeJVQUQ1M8ecEqV82fKaRsyijklNNAz2yeQNazt4+cZ2lFpvyw9lda8iAudIQr 4Fh8neNJ15FENfXCq4LV+miUD7oHjAAbvzIgaYrz5JpTeESFcXiv35lkOb43crclzbkt YLWQ== X-Gm-Message-State: AN3rC/68oruQBInaBTTj8L1Sfohoo78gInHICVKc/YJoYHRnu08f9x1H 1pMcwhEmAhSCvQ== X-Received: by 10.46.32.156 with SMTP id g28mr2535405lji.86.1492433736479; Mon, 17 Apr 2017 05:55:36 -0700 (PDT) Received: from wasted.cogentembedded.com ([31.173.80.148]) by smtp.gmail.com with ESMTPSA id 91sm122404lja.53.2017.04.17.05.55.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Apr 2017 05:55:35 -0700 (PDT) From: Sergei Shtylyov X-Google-Original-From: "Sergei Shtylyov" Received: by wasted.cogentembedded.com (sSMTP sendmail emulation); Mon, 17 Apr 2017 15:55:32 +0300 Message-Id: <20170417125532.826640693@cogentembedded.com> User-Agent: quilt/0.64 Date: Mon, 17 Apr 2017 15:55:22 +0300 To: netdev@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, Simon Horman , Sergei Shtylyov Subject: [PATCH v2] sh_eth: unmap DMA buffers when freeing rings MIME-Version: 1.0 Content-Disposition: inline; filename=sh_eth-unmap-DMA-buffers-when-freeing-rings-v2.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 --- This patch is against DaveM's 'net.git' repo. Changed in version 2: - fixed the "packet sent" condition in sh_eth_tx_free(). 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);