summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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.patch197
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;
+