From patchwork Mon Aug 26 22:45:26 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Herring X-Patchwork-Id: 269996 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 6DCB22C009A for ; Tue, 27 Aug 2013 08:47:57 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752594Ab3HZWrl (ORCPT ); Mon, 26 Aug 2013 18:47:41 -0400 Received: from mail-oa0-f45.google.com ([209.85.219.45]:37858 "EHLO mail-oa0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752589Ab3HZWqE (ORCPT ); Mon, 26 Aug 2013 18:46:04 -0400 Received: by mail-oa0-f45.google.com with SMTP id m1so1512225oag.32 for ; Mon, 26 Aug 2013 15:46:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=AhCInU36+ZA46m/v3f+dvbx4jqVDy/fUzxDDQdZUoiQ=; b=z7oYlM8QCCWA4u0Rbh5th9D9tSK11UwRxO1t+b8OJysSnhvsRU9+A23O7pdF7Mj21h RjyAarUYmk1x2PbPmPuPh4ebXFw3ttgqLTnJHYcTYGzy5KtO7ltCSNJHG8Z19/8Dq/vZ e+h3I+AbvmJ0ORA0L0guA5jPqDiDoc1q22mEg7QsCDULCGkyG97iPzHNBAWVal57HY6X i5J+zZEe7yZbNnsscLOUmRkKjJvZ+qpXnp7DuaFiUrn2zHVhHvbqvB3floY0sXR7zliq sYTzPdx+/aGpo96nPAPGJD1FvBKhWsdJnhnkVpXSVyw1fsf9UpHSKLwjS81YpW12fEYA eu7g== X-Received: by 10.60.124.14 with SMTP id me14mr16070716oeb.4.1377557163719; Mon, 26 Aug 2013 15:46:03 -0700 (PDT) Received: from rob-laptop.calxeda.com ([173.226.190.126]) by mx.google.com with ESMTPSA id d8sm6005992oeu.6.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 26 Aug 2013 15:46:02 -0700 (PDT) From: Rob Herring To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Andreas Herrmann , Lennert Buytenhek , Rob Herring Subject: [PATCH 11/11] net: calxedaxgmac: fix xgmac_xmit DMA mapping error handling Date: Mon, 26 Aug 2013 17:45:26 -0500 Message-Id: <1377557126-10716-11-git-send-email-robherring2@gmail.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1377557126-10716-1-git-send-email-robherring2@gmail.com> References: <1377557126-10716-1-git-send-email-robherring2@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Rob Herring On a DMA mapping error in xgmac_xmit, we should simply free the skb and return NETDEV_TX_OK rather than -EIO. In the case of errors in mapping frags, we need to undo everything that has been setup. Reported-by: Andreas Herrmann Signed-off-by: Rob Herring --- drivers/net/ethernet/calxeda/xgmac.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index f149c08..0022887 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -466,6 +466,13 @@ static inline void desc_set_tx_owner(struct xgmac_dma_desc *p, u32 flags) p->flags = cpu_to_le32(tmpflags); } +static inline void desc_clear_tx_owner(struct xgmac_dma_desc *p) +{ + u32 tmpflags = le32_to_cpu(p->flags); + tmpflags &= TXDESC_END_RING; + p->flags = cpu_to_le32(tmpflags); +} + static inline int desc_get_tx_ls(struct xgmac_dma_desc *p) { return le32_to_cpu(p->flags) & TXDESC_LAST_SEG; @@ -1103,7 +1110,7 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev) paddr = dma_map_single(priv->device, skb->data, len, DMA_TO_DEVICE); if (dma_mapping_error(priv->device, paddr)) { dev_kfree_skb(skb); - return -EIO; + return NETDEV_TX_OK; } priv->tx_skbuff[entry] = skb; desc_set_buf_addr_and_size(desc, paddr, len); @@ -1115,10 +1122,8 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev) paddr = skb_frag_dma_map(priv->device, frag, 0, len, DMA_TO_DEVICE); - if (dma_mapping_error(priv->device, paddr)) { - dev_kfree_skb(skb); - return -EIO; - } + if (dma_mapping_error(priv->device, paddr)) + goto dma_err; entry = dma_ring_incr(entry, DMA_TX_RING_SZ); desc = priv->dma_tx + entry; @@ -1154,6 +1159,22 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev) netif_wake_queue(dev); } return NETDEV_TX_OK; + +dma_err: + entry = priv->tx_head; + for ( ; i > 0; i--) { + entry = dma_ring_incr(entry, DMA_TX_RING_SZ); + desc = priv->dma_tx + entry; + priv->tx_skbuff[entry] = NULL; + dma_unmap_page(priv->device, desc_get_buf_addr(desc), + desc_get_buf_len(desc), DMA_TO_DEVICE); + desc_clear_tx_owner(desc); + } + desc = first; + dma_unmap_single(priv->device, desc_get_buf_addr(desc), + desc_get_buf_len(desc), DMA_TO_DEVICE); + dev_kfree_skb(skb); + return NETDEV_TX_OK; } static int xgmac_rx(struct xgmac_priv *priv, int limit)