diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2009-06-30 08:45:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-30 22:46:58 -0400 |
commit | 679be3ba0c493eb66d22c206273729ce50925e85 (patch) | |
tree | 0248f05b482e2877009c89ec6c70d7dfbd3ae7e5 | |
parent | 91615f765a2935b6cbae424b9eee1585ed681ae6 (diff) |
e1000: fix unmap bug
as reported by kerneloops.org
[ 121.781161] ------------[ cut here ]------------
[ 121.781171] WARNING: at lib/dma-debug.c:793 check_unmap+0x14e/0x577()
[ 121.781173] Hardware name: S5520HC
[ 121.781177] e1000 0000:0a:00.0: DMA-API: device driver tries to free DMA
memory it has not allocated [device address=0x00000001d688b0fa] [size=1522
bytes]
[ 121.781180] Modules linked in: e1000 mdio dca [last unloaded: ixgbe]
[ 121.781187] Pid: 4793, comm: bash Tainted: P 2.6.30-master-06161113 #3
[ 121.781190] Call Trace:
[ 121.781195] [<ffffffff8123056f>] ? check_unmap+0x14e/0x577
[ 121.781201] [<ffffffff81057a19>] warn_slowpath_common+0x77/0x8f
[ 121.781205] [<ffffffff81057ae1>] warn_slowpath_fmt+0x9f/0xa1
[ 121.781212] [<ffffffff81477ce2>] ? _spin_lock_irqsave+0x3f/0x49
[ 121.781216] [<ffffffff8122fa97>] ? get_hash_bucket+0x28/0x33
[ 121.781220] [<ffffffff8123056f>] check_unmap+0x14e/0x577
[ 121.781225] [<ffffffff810e4f48>] ? check_bytes_and_report+0x38/0xcb
[ 121.781230] [<ffffffff81230bbf>] debug_dma_unmap_page+0x80/0x92
[ 121.781234] [<ffffffff8122e549>] ? unmap_single+0x1a/0x4e
[ 121.781239] [<ffffffff813901e1>] ? __kfree_skb+0x74/0x78
[ 121.781250] [<ffffffffa00662ef>] pci_unmap_single+0x64/0x6d [e1000]
[ 121.781259] [<ffffffffa0066344>] e1000_clean_rx_ring+0x4c/0xbf [e1000]
[ 121.781268] [<ffffffffa00663df>] e1000_clean_all_rx_rings+0x28/0x36 [e1000]
[ 121.781277] [<ffffffffa0067464>] e1000_down+0x138/0x141 [e1000]
[ 121.781286] [<ffffffffa00681c2>] __e1000_shutdown+0x6b/0x198 [e1000]
[ 121.781296] [<ffffffffa0068405>] e1000_suspend+0x17/0x50 [e1000]
[ 121.781301] [<ffffffff81237665>] pci_legacy_suspend+0x3b/0xbe
[ 121.781305] [<ffffffff81237bc6>] pci_pm_suspend+0x3e/0xf1
[ 121.781310] [<ffffffff812eaf1c>] pm_op+0x57/0xde
[ 121.781314] [<ffffffff812eb444>] dpm_suspend_start+0x31e/0x470
[ 121.781319] [<ffffffff810877da>] suspend_devices_and_enter+0x3e/0x1a2
[ 121.781323] [<ffffffff81087a0f>] enter_state+0xd1/0x127
[ 121.781327] [<ffffffff8108717a>] state_store+0xa7/0xc9
[ 121.781332] [<ffffffff81221843>] kobj_attr_store+0x17/0x19
[ 121.781336] [<ffffffff8113c01e>] sysfs_write_file+0xe5/0x121
[ 121.781341] [<ffffffff810ed165>] vfs_write+0xab/0x105
[ 121.781344] [<ffffffff810ed279>] sys_write+0x47/0x6d
[ 121.781349] [<ffffffff81027aab>] system_call_fastpath+0x16/0x1b
[ 121.781352] ---[ end trace 97bacaaac2ed7786 ]---
Fix is to correctly zero out internal ->dma value when unmapping
and make sure never to unmap unless there specifically was a mapping done.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5e3356f8eb5a..972e06d984c8 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -2185,12 +2185,16 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter, | |||
2185 | /* Free all the Rx ring sk_buffs */ | 2185 | /* Free all the Rx ring sk_buffs */ |
2186 | for (i = 0; i < rx_ring->count; i++) { | 2186 | for (i = 0; i < rx_ring->count; i++) { |
2187 | buffer_info = &rx_ring->buffer_info[i]; | 2187 | buffer_info = &rx_ring->buffer_info[i]; |
2188 | if (buffer_info->skb) { | 2188 | if (buffer_info->dma) { |
2189 | pci_unmap_single(pdev, | 2189 | pci_unmap_single(pdev, |
2190 | buffer_info->dma, | 2190 | buffer_info->dma, |
2191 | buffer_info->length, | 2191 | buffer_info->length, |
2192 | PCI_DMA_FROMDEVICE); | 2192 | PCI_DMA_FROMDEVICE); |
2193 | } | ||
2193 | 2194 | ||
2195 | buffer_info->dma = 0; | ||
2196 | |||
2197 | if (buffer_info->skb) { | ||
2194 | dev_kfree_skb(buffer_info->skb); | 2198 | dev_kfree_skb(buffer_info->skb); |
2195 | buffer_info->skb = NULL; | 2199 | buffer_info->skb = NULL; |
2196 | } | 2200 | } |
@@ -4033,6 +4037,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
4033 | buffer_info->dma, | 4037 | buffer_info->dma, |
4034 | buffer_info->length, | 4038 | buffer_info->length, |
4035 | PCI_DMA_FROMDEVICE); | 4039 | PCI_DMA_FROMDEVICE); |
4040 | buffer_info->dma = 0; | ||
4036 | 4041 | ||
4037 | length = le16_to_cpu(rx_desc->length); | 4042 | length = le16_to_cpu(rx_desc->length); |
4038 | /* !EOP means multiple descriptors were used to store a single | 4043 | /* !EOP means multiple descriptors were used to store a single |
@@ -4222,6 +4227,7 @@ map_skb: | |||
4222 | pci_unmap_single(pdev, buffer_info->dma, | 4227 | pci_unmap_single(pdev, buffer_info->dma, |
4223 | adapter->rx_buffer_len, | 4228 | adapter->rx_buffer_len, |
4224 | PCI_DMA_FROMDEVICE); | 4229 | PCI_DMA_FROMDEVICE); |
4230 | buffer_info->dma = 0; | ||
4225 | 4231 | ||
4226 | break; /* while !buffer_info->skb */ | 4232 | break; /* while !buffer_info->skb */ |
4227 | } | 4233 | } |