Add proper error handling for various callers of pci_map_single. Signed-off-by: Auke Kok <[EMAIL PROTECTED]> ---
drivers/net/e1000e/e1000.h | 2 ++ drivers/net/e1000e/ethtool.c | 16 +++++++++++--- drivers/net/e1000e/netdev.c | 49 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 3475e48..e3cd877 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -220,6 +220,7 @@ struct e1000_adapter { u32 tx_fifo_head; u32 tx_head_addr; u32 tx_fifo_size; + u32 tx_dma_failed; /* * RX @@ -241,6 +242,7 @@ struct e1000_adapter { u64 gorcl_old; u32 gorcl; u32 alloc_rx_buff_failed; + u32 rx_dma_failed; unsigned int rx_ps_pages; u16 rx_ps_bsize0; diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index d14cc4b..0e80406 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -91,6 +91,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "tx_smbus", E1000_STAT(stats.mgptc) }, { "rx_smbus", E1000_STAT(stats.mgprc) }, { "dropped_smbus", E1000_STAT(stats.mgpdc) }, + { "rx_dma_failed", E1000_STAT(rx_dma_failed) }, + { "tx_dma_failed", E1000_STAT(tx_dma_failed) }, }; #define E1000_GLOBAL_STATS_LEN \ @@ -1042,6 +1044,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) tx_ring->buffer_info[i].dma = pci_map_single(pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(tx_ring->buffer_info[i].dma)) { + ret_val = 4; + goto err_nomem; + } tx_desc->buffer_addr = cpu_to_le64( tx_ring->buffer_info[i].dma); tx_desc->lower.data = cpu_to_le32(skb->len); @@ -1059,7 +1065,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) size = rx_ring->count * sizeof(struct e1000_buffer); rx_ring->buffer_info = kmalloc(size, GFP_KERNEL); if (!rx_ring->buffer_info) { - ret_val = 4; + ret_val = 5; goto err_nomem; } memset(rx_ring->buffer_info, 0, size); @@ -1068,7 +1074,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, &rx_ring->dma, GFP_KERNEL); if (!rx_ring->desc) { - ret_val = 5; + ret_val = 6; goto err_nomem; } memset(rx_ring->desc, 0, rx_ring->size); @@ -1093,7 +1099,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL); if (!skb) { - ret_val = 6; + ret_val = 7; goto err_nomem; } skb_reserve(skb, NET_IP_ALIGN); @@ -1101,6 +1107,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter) rx_ring->buffer_info[i].dma = pci_map_single(pdev, skb->data, 2048, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(rx_ring->buffer_info[i].dma)) { + ret_val = 8; + goto err_nomem; + } rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma); memset(skb->data, 0x00, skb->len); diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 51c9024..8ebe238 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -195,6 +195,11 @@ map_skb: buffer_info->dma = pci_map_single(pdev, skb->data, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(buffer_info->dma)) { + dev_err(&pdev->dev, "RX DMA map failed\n"); + adapter->rx_dma_failed++; + break; + } rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); @@ -255,6 +260,13 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, ps_page->page, 0, PAGE_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error( + ps_page->dma)) { + dev_err(&adapter->pdev->dev, + "RX DMA page map failed\n"); + adapter->rx_dma_failed++; + goto no_buffers; + } } /* * Refresh the desc even if buffer_addrs @@ -286,6 +298,14 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, buffer_info->dma = pci_map_single(pdev, skb->data, adapter->rx_ps_bsize0, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(buffer_info->dma)) { + dev_err(&pdev->dev, "RX DMA map failed\n"); + adapter->rx_dma_failed++; + /* cleanup skb */ + dev_kfree_skb_any(skb); + buffer_info->skb = NULL; + break; + } rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); @@ -374,6 +394,11 @@ check_page: buffer_info->page, 0, PAGE_SIZE, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(buffer_info->dma)) { + dev_err(&adapter->pdev->dev, "RX DMA page map failed\n"); + adapter->rx_dma_failed++; + break; + } rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); @@ -3214,6 +3239,11 @@ static int e1000_tx_map(struct e1000_adapter *adapter, skb->data + offset, size, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(buffer_info->dma)) { + dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); + adapter->tx_dma_failed++; + return -1; + } buffer_info->next_to_watch = i; len -= size; @@ -3247,6 +3277,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, offset, size, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(buffer_info->dma)) { + dev_err(&adapter->pdev->dev, + "TX DMA page map failed\n"); + adapter->tx_dma_failed++; + return -1; + } + buffer_info->next_to_watch = i; len -= size; @@ -3512,9 +3549,15 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (skb->protocol == htons(ETH_P_IP)) tx_flags |= E1000_TX_FLAGS_IPV4; - e1000_tx_queue(adapter, tx_flags, - e1000_tx_map(adapter, skb, first, - max_per_txd, nr_frags, mss)); + count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss); + if (count < 0) { + /* handle pci_map_single() error in e1000_tx_map */ + dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&adapter->tx_queue_lock, irq_flags); + return NETDEV_TX_BUSY; + } + + e1000_tx_queue(adapter, tx_flags, count); netdev->trans_start = jiffies; - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html