diff options
Diffstat (limited to 'trunk/2.6.21/21358_linux-2.6-netdev-e1000e-09.patch')
-rw-r--r-- | trunk/2.6.21/21358_linux-2.6-netdev-e1000e-09.patch | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/trunk/2.6.21/21358_linux-2.6-netdev-e1000e-09.patch b/trunk/2.6.21/21358_linux-2.6-netdev-e1000e-09.patch new file mode 100644 index 0000000..44a8726 --- /dev/null +++ b/trunk/2.6.21/21358_linux-2.6-netdev-e1000e-09.patch @@ -0,0 +1,197 @@ +From: Auke Kok <auke-jan.h.kok@intel.com> +Date: Fri, 10 Aug 2007 20:01:02 +0000 (-0700) +Subject: e1000e: error handling for pci_map_single calls. +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjgarzik%2Fnetdev-2.6.git;a=commitdiff_plain;h=8136b0db9be68942380cac6925cf6dd6a2be9a8f + +e1000e: error handling for pci_map_single calls. + +Add proper error handling for various callers of pci_map_single. + +Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com> +Signed-off-by: Jeff Garzik <jeff@garzik.org> +--- + +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; + |