From mboxrd@z Thu Jan 1 00:00:00 1970 From: Neil Horman Subject: [net PATCH v2] 8139cp: Add dma_mapping_error checking Date: Fri, 26 Jul 2013 10:28:38 -0400 Message-ID: <1374848918-17183-1-git-send-email-nhorman@tuxdriver.com> References: <1374516882-19131-1-git-send-email-nhorman@tuxdriver.com> Cc: Neil Horman , "David S. Miller" , Francois Romieu To: netdev@vger.kernel.org Return-path: Received: from charlotte.tuxdriver.com ([70.61.120.58]:52790 "EHLO smtp.tuxdriver.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757202Ab3GZO3F (ORCPT ); Fri, 26 Jul 2013 10:29:05 -0400 In-Reply-To: <1374516882-19131-1-git-send-email-nhorman@tuxdriver.com> Sender: netdev-owner@vger.kernel.org List-ID: Self explanitory dma_mapping_error addition to the 8139 driver, based on this: https://bugzilla.redhat.com/show_bug.cgi?id=947250 It showed several backtraces arising for dma_map_* usage without checking the return code on the mapping. Add the check and abort the rx/tx operation if its failed. Untested as I have no hardware and the reporter has wandered off, but seems pretty straightforward. Signed-off-by: Neil Horman CC: "David S. Miller" CC: Francois Romieu --- Change notes: v2) Added stats update for tx_dropped as per Francois Romieu --- drivers/net/ethernet/realtek/8139cp.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 0352345..ba0570a 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -533,6 +533,11 @@ rx_status_loop: mapping = dma_map_single(&cp->pdev->dev, new_skb->data, buflen, PCI_DMA_FROMDEVICE); + if (dma_mapping_error(&cp->pdev->dev, mapping)) { + kfree_skb(skb); + break; + } + cp->rx_skb[rx_tail] = new_skb; cp_rx_skb(cp, skb, desc); @@ -749,6 +754,12 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, len = skb->len; mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&cp->pdev->dev, mapping)) { + kfree_skb(skb); + cp->dev->stats.tx_dropped++; + goto out_unlock; + } + txd->opts2 = opts2; txd->addr = cpu_to_le64(mapping); wmb(); @@ -786,6 +797,12 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, first_len = skb_headlen(skb); first_mapping = dma_map_single(&cp->pdev->dev, skb->data, first_len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&cp->pdev->dev, first_mapping)) { + kfree_skb(skb); + cp->dev->stats.tx_dropped++; + goto out_unlock; + } + cp->tx_skb[entry] = skb; entry = NEXT_TX(entry); @@ -799,6 +816,21 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, mapping = dma_map_single(&cp->pdev->dev, skb_frag_address(this_frag), len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&cp->pdev->dev, mapping)) { + /* Unwind the mappnigs we have */ + for (frag = 0; frag+first_entry < entry; frag++) { + cp->tx_skb[frag+first_entry] = NULL; + txd = &cp->tx_ring[frag+first_entry]; + this_frag = &skb_shinfo(skb)->frags[frag]; + dma_unmap_single(&cp->pdev->dev, le64_to_cpu(txd->addr), + skb_frag_size(this_frag), PCI_DMA_TODEVICE); + } + + cp->dev->stats.tx_dropped++; + kfree_skb(skb); + goto out_unlock; + } + eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; ctrl = eor | len | DescOwn; @@ -859,6 +891,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); +out_unlock: spin_unlock_irqrestore(&cp->lock, intr_flags); cpw8(TxPoll, NormalTxPoll); @@ -1054,6 +1087,10 @@ static int cp_refill_rx(struct cp_private *cp) mapping = dma_map_single(&cp->pdev->dev, skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE); + if (dma_mapping_error(&cp->pdev->dev, mapping)) { + kfree_skb(skb); + goto err_out; + } cp->rx_skb[i] = skb; cp->rx_ring[i].opts2 = 0; -- 1.8.1.4