Commit 4f57ca6e authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by David S. Miller

ixgbe: fix unmap length bug

This patch addresses three WARN_ON statements from DMA-API debug code

ixgbe is mapping more than it unmaps, reduce the length of the map call and
remove the "used once" local variable.

found by Joerg Roedel <joerg.roedel@amd.com> in 2.6.30, so is a candidate
for -stable.

in addition, fix missing ->dma = 0 after unmap to prevent double free with
pci_unmap_single

and lastly, don't unmap (half) pages that aren't mapped.
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
CC: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a1f25324
...@@ -563,7 +563,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, ...@@ -563,7 +563,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
union ixgbe_adv_rx_desc *rx_desc; union ixgbe_adv_rx_desc *rx_desc;
struct ixgbe_rx_buffer *bi; struct ixgbe_rx_buffer *bi;
unsigned int i; unsigned int i;
unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN;
i = rx_ring->next_to_use; i = rx_ring->next_to_use;
bi = &rx_ring->rx_buffer_info[i]; bi = &rx_ring->rx_buffer_info[i];
...@@ -593,7 +592,9 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, ...@@ -593,7 +592,9 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
if (!bi->skb) { if (!bi->skb) {
struct sk_buff *skb; struct sk_buff *skb;
skb = netdev_alloc_skb(adapter->netdev, bufsz); skb = netdev_alloc_skb(adapter->netdev,
(rx_ring->rx_buf_len +
NET_IP_ALIGN));
if (!skb) { if (!skb) {
adapter->alloc_rx_buff_failed++; adapter->alloc_rx_buff_failed++;
...@@ -608,7 +609,8 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter, ...@@ -608,7 +609,8 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
skb_reserve(skb, NET_IP_ALIGN); skb_reserve(skb, NET_IP_ALIGN);
bi->skb = skb; bi->skb = skb;
bi->dma = pci_map_single(pdev, skb->data, bufsz, bi->dma = pci_map_single(pdev, skb->data,
rx_ring->rx_buf_len,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
} }
/* Refresh the desc even if buffer_addrs didn't change because /* Refresh the desc even if buffer_addrs didn't change because
...@@ -732,6 +734,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, ...@@ -732,6 +734,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
pci_unmap_single(pdev, rx_buffer_info->dma, pci_unmap_single(pdev, rx_buffer_info->dma,
rx_ring->rx_buf_len, rx_ring->rx_buf_len,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
rx_buffer_info->dma = 0;
skb_put(skb, len); skb_put(skb, len);
} }
...@@ -2815,9 +2818,11 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, ...@@ -2815,9 +2818,11 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
} }
if (!rx_buffer_info->page) if (!rx_buffer_info->page)
continue; continue;
pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2, if (rx_buffer_info->page_dma) {
PCI_DMA_FROMDEVICE); pci_unmap_page(pdev, rx_buffer_info->page_dma,
rx_buffer_info->page_dma = 0; PAGE_SIZE / 2, PCI_DMA_FROMDEVICE);
rx_buffer_info->page_dma = 0;
}
put_page(rx_buffer_info->page); put_page(rx_buffer_info->page);
rx_buffer_info->page = NULL; rx_buffer_info->page = NULL;
rx_buffer_info->page_offset = 0; rx_buffer_info->page_offset = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment