diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2008-12-15 04:00:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-15 04:00:57 -0500 |
commit | 5ecc361444a0c641a73cce05fb652d0e3c944451 (patch) | |
tree | ac050461c79434c101042bb954f694f90c13d885 /drivers/net/ixgbe | |
parent | a7276db6adfded660eec1e1629710b8b82d83455 (diff) |
ixgbe: fix dma mapping unbalance
This issue was initially reported by Joerg Roedel <joerg.roedel@amd.com>
It appears that ixgbe has had a long standing bug where it was unmapping a different size than it had mapped.
ixgbe 0000:02:00.0: PCI-DMA: device driver frees DMA memory with different sizes than it mapped.
ixgbe 0000:02:00.0: PCI-DMA: device driver frees DMA memory with different size [device address=0x0000000003fed812] [map size=258 bytes] [unmap size=256 bytes]
Pid: 6178, comm: rmmod Not tainted 2.6.28-rc5 #4 Call Trace:
[<ffffffff8022a2ae>] iommu_queue_inv_iommu_pages+0x5e/0x70
[<ffffffff80225956>] check_unmap+0x1c6/0x240 [<ffffffff80225ff5>] debug_unmap_single+0xb5/0x110 [<ffffffffa0213997>] ixgbe_clean_rx_ring+0x147/0x220 [<ffffffffa0214d7d>] ixgbe_down+0x2fd/0x3d0 [ixgbe] [<ffffffffa02150b3>] ixgbe_close+0x13/0xc0 [ixgbe] [<ffffffff80431326>] dev_close+0x56/0xa0 [<ffffffff804313b3>] rollback_registered+0x43/0x220 [<ffffffff804315a5>] unregister_netdevice+0x15/0x60 [<ffffffff80431601>] unregister_netdev+0x11/0x20 [<ffffffffa021aef8>] ixgbe_remove+0x48/0x16e [ixgbe] [<ffffffff80386ffc>] pci_device_remove+0x2c/0x60 [<ffffffff803ef929>] __device_release_driver+0x99/0x100
[<ffffffff803efa48>] driver_detach+0xb8/0xc0 [<ffffffff803eea6e>] bus_remove_driver+0x8e/0xd0 [<ffffffff80387374>] pci_unregister_driver+0x34/0x90 [<ffffffff8026c6c7>] sys_delete_module+0x1c7/0x2a0 [<ffffffff802a9ce9>] do_munmap+0x349/0x390 [<ffffffff80374481>] __up_write+0x21/0x150 [<ffffffff8020c30b>] system_call_fastpath+0x16/0x1b
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>
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d6f666ae38d..92b35cfc7a4 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -479,7 +479,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, | |||
479 | union ixgbe_adv_rx_desc *rx_desc; | 479 | union ixgbe_adv_rx_desc *rx_desc; |
480 | struct ixgbe_rx_buffer *bi; | 480 | struct ixgbe_rx_buffer *bi; |
481 | unsigned int i; | 481 | unsigned int i; |
482 | unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN; | ||
483 | 482 | ||
484 | i = rx_ring->next_to_use; | 483 | i = rx_ring->next_to_use; |
485 | bi = &rx_ring->rx_buffer_info[i]; | 484 | bi = &rx_ring->rx_buffer_info[i]; |
@@ -508,8 +507,10 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, | |||
508 | } | 507 | } |
509 | 508 | ||
510 | if (!bi->skb) { | 509 | if (!bi->skb) { |
511 | struct sk_buff *skb = netdev_alloc_skb(adapter->netdev, | 510 | struct sk_buff *skb; |
512 | bufsz); | 511 | skb = netdev_alloc_skb(adapter->netdev, |
512 | (rx_ring->rx_buf_len + | ||
513 | NET_IP_ALIGN)); | ||
513 | 514 | ||
514 | if (!skb) { | 515 | if (!skb) { |
515 | adapter->alloc_rx_buff_failed++; | 516 | adapter->alloc_rx_buff_failed++; |
@@ -524,7 +525,8 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, | |||
524 | skb_reserve(skb, NET_IP_ALIGN); | 525 | skb_reserve(skb, NET_IP_ALIGN); |
525 | 526 | ||
526 | bi->skb = skb; | 527 | bi->skb = skb; |
527 | bi->dma = pci_map_single(pdev, skb->data, bufsz, | 528 | bi->dma = pci_map_single(pdev, skb->data, |
529 | rx_ring->rx_buf_len, | ||
528 | PCI_DMA_FROMDEVICE); | 530 | PCI_DMA_FROMDEVICE); |
529 | } | 531 | } |
530 | /* Refresh the desc even if buffer_addrs didn't change because | 532 | /* Refresh the desc even if buffer_addrs didn't change because |
@@ -615,7 +617,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, | |||
615 | 617 | ||
616 | if (len && !skb_shinfo(skb)->nr_frags) { | 618 | if (len && !skb_shinfo(skb)->nr_frags) { |
617 | pci_unmap_single(pdev, rx_buffer_info->dma, | 619 | pci_unmap_single(pdev, rx_buffer_info->dma, |
618 | rx_ring->rx_buf_len + NET_IP_ALIGN, | 620 | rx_ring->rx_buf_len, |
619 | PCI_DMA_FROMDEVICE); | 621 | PCI_DMA_FROMDEVICE); |
620 | skb_put(skb, len); | 622 | skb_put(skb, len); |
621 | } | 623 | } |