e1000e: fix unmap bug From: Jesse Brandeburg this is in reference to https://bugzilla.redhat.com/show_bug.cgi?id=484494 also addresses issue shown in kerneloops the e1000e transmit code was calling pci_unmap_page on dma handles that it might have called pci_map_single on. Signed-off-by: Jesse Brandeburg --- drivers/net/e1000e/netdev.c | 56 +++++++++++++++++-------------------------- 1 files changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ef8d2c5..7ef8519 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -565,12 +565,10 @@ next_desc: static void e1000_put_txbuf(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info) { - if (buffer_info->dma) { - pci_unmap_page(adapter->pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } + buffer_info->dma = 0; if (buffer_info->skb) { + skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, + DMA_TO_DEVICE); dev_kfree_skb_any(buffer_info->skb); buffer_info->skb = NULL; } @@ -3831,30 +3829,31 @@ static int e1000_tx_map(struct e1000_adapter *adapter, unsigned int mss) { struct e1000_ring *tx_ring = adapter->tx_ring; - struct e1000_buffer *buffer_info; - unsigned int len = skb->len - skb->data_len; - unsigned int offset = 0, size, count = 0, i; + unsigned int len = skb_headlen(skb); + unsigned int offset, size, count = 0, i; unsigned int f; + dma_addr_t map; i = tx_ring->next_to_use; + if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { + dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); + adapter->tx_dma_failed++; + dev_kfree_skb(skb); + return -2; + } + + map = skb_shinfo(skb)->dma_maps[0]; + offset = 0; + while (len) { - buffer_info = &tx_ring->buffer_info[i]; + struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); buffer_info->length = size; /* set time_stamp *before* dma to help avoid a possible race */ buffer_info->time_stamp = jiffies; - buffer_info->dma = - pci_map_single(adapter->pdev, - skb->data + offset, - size, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) { - dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); - adapter->tx_dma_failed++; - return -1; - } + buffer_info->dma = map + offset; buffer_info->next_to_watch = i; len -= size; @@ -3870,28 +3869,17 @@ static int e1000_tx_map(struct e1000_adapter *adapter, frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = frag->page_offset; + map = skb_shinfo(skb)->dma_maps[f + 1]; + offset = 0; while (len) { + struct e1000_buffer *buffer_info; buffer_info = &tx_ring->buffer_info[i]; size = min(len, max_per_txd); buffer_info->length = size; buffer_info->time_stamp = jiffies; - buffer_info->dma = - pci_map_page(adapter->pdev, - frag->page, - offset, - size, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(adapter->pdev, - buffer_info->dma)) { - dev_err(&adapter->pdev->dev, - "TX DMA page map failed\n"); - adapter->tx_dma_failed++; - return -1; - } - + buffer_info->dma = map + offset; buffer_info->next_to_watch = i; len -= size;