From patchwork Fri Jun 20 12:12:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King X-Patchwork-Id: 362196 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id CC781140084 for ; Fri, 20 Jun 2014 22:12:41 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S967337AbaFTMMh (ORCPT ); Fri, 20 Jun 2014 08:12:37 -0400 Received: from gw-1.arm.linux.org.uk ([78.32.30.217]:36344 "EHLO pandora.arm.linux.org.uk" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S967320AbaFTMMg (ORCPT ); Fri, 20 Jun 2014 08:12:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=pandora; h=Date:Sender:Message-Id:Subject:Cc:To:From:References:In-Reply-To; bh=5rRBqwMdRcFnQOLvSErvg3MFg/cnuPz97FFNI1oLp8k=; b=TeXTSk6vgH/nNdDog+7jh0dkBGFZ7i41kHSu6cjWcZE3/6fsOfZPDf7bt6tZ9ZnlOewO8rBL1qM8MVbGJJrgr4iqW4QhlavydA/kQVcmoI70sk72REP/OzdWQKHPwJUs0xl469Rgqi5jW8ZZ+qHhtW7jD7orkLrfgKkx4tz0QME=; Received: from e0022681537dd.dyn.arm.linux.org.uk ([2002:4e20:1eda:1:222:68ff:fe15:37dd]:54338 helo=rmk-PC.arm.linux.org.uk) by pandora.arm.linux.org.uk with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.76) (envelope-from ) id 1WxxgI-0001Cs-Kd; Fri, 20 Jun 2014 13:12:34 +0100 Received: from rmk by rmk-PC.arm.linux.org.uk with local (Exim 4.76) (envelope-from ) id 1WxxgI-0005XT-9C; Fri, 20 Jun 2014 13:12:34 +0100 In-Reply-To: <20140620121118.GR32514@n2100.arm.linux.org.uk> References: <20140620121118.GR32514@n2100.arm.linux.org.uk> From: Russell King To: linux-arm-kernel@lists.infradead.org Cc: Fugang Duan , netdev@vger.kernel.org Subject: [PATCH RFC 10/30] net: fec: make rx skb handling more robust Message-Id: Date: Fri, 20 Jun 2014 13:12:34 +0100 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Allocate, and then map the receive skb before writing any data to the ring descriptor or storing the skb. When freeing the receive ring entries, unmap and free the skb, and then clear the stored skb pointer. This means we have ring data and skb pointer in one of two states: either both fully setup, or nothing setup. This simplifies the cleanup, as we can use just the skb pointer to indicate whether the descriptor is setup, and thus avoids potentially calling dma_unmap_single() on a DMA error value. Signed-off-by: Russell King --- drivers/net/ethernet/freescale/fec_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 309aa2ff8cc9..70853a59627a 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2066,12 +2066,12 @@ static void fec_enet_free_buffers(struct net_device *ndev) bdp = fep->rx_bd_base; for (i = 0; i < fep->rx_ring_size; i++) { skb = fep->rx_skbuff[i]; - - if (bdp->cbd_bufaddr) + fep->rx_skbuff[i] = NULL; + if (skb) { dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - if (skb) dev_kfree_skb(skb); + } bdp = fec_enet_get_nextdesc(bdp, fep); } @@ -2089,21 +2089,26 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) bdp = fep->rx_bd_base; for (i = 0; i < fep->rx_ring_size; i++) { + dma_addr_t addr; + skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); if (!skb) { fec_enet_free_buffers(ndev); return -ENOMEM; } - fep->rx_skbuff[i] = skb; - bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, + addr = dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { + if (dma_mapping_error(&fep->pdev->dev, addr)) { + dev_kfree_skb(skb); fec_enet_free_buffers(ndev); if (net_ratelimit()) netdev_err(ndev, "Rx DMA memory map failed\n"); return -ENOMEM; } + + fep->rx_skbuff[i] = skb; + bdp->cbd_bufaddr = addr; bdp->cbd_sc = BD_ENET_RX_EMPTY; if (fep->bufdesc_ex) {