diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2009-03-02 19:02:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-02 19:02:53 -0500 |
commit | 8ddc951c73cbc317148c0b9973dde81eece57e4c (patch) | |
tree | 509d5d6cc1319fb5cac8689c5276604cc193b0ea /drivers/net/e1000e/netdev.c | |
parent | 19147bb5f1f7e7ee79f0c92f59f67da8c0031dc0 (diff) |
e1000e: fix unmap bug
This is in reference to https://bugzilla.redhat.com/show_bug.cgi?id=484494
Also addresses issue show 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 <jesse.brandeburg@intel.com>
Acked-by: Bruce Allan <bruce.w.allan@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/e1000e/netdev.c')
-rw-r--r-- | drivers/net/e1000e/netdev.c | 62 |
1 files changed, 28 insertions, 34 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 1b5a0c8b34c8..e74eb3c606e0 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -566,12 +566,10 @@ next_desc: | |||
566 | static void e1000_put_txbuf(struct e1000_adapter *adapter, | 566 | static void e1000_put_txbuf(struct e1000_adapter *adapter, |
567 | struct e1000_buffer *buffer_info) | 567 | struct e1000_buffer *buffer_info) |
568 | { | 568 | { |
569 | if (buffer_info->dma) { | 569 | buffer_info->dma = 0; |
570 | pci_unmap_page(adapter->pdev, buffer_info->dma, | ||
571 | buffer_info->length, PCI_DMA_TODEVICE); | ||
572 | buffer_info->dma = 0; | ||
573 | } | ||
574 | if (buffer_info->skb) { | 570 | if (buffer_info->skb) { |
571 | skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, | ||
572 | DMA_TO_DEVICE); | ||
575 | dev_kfree_skb_any(buffer_info->skb); | 573 | dev_kfree_skb_any(buffer_info->skb); |
576 | buffer_info->skb = NULL; | 574 | buffer_info->skb = NULL; |
577 | } | 575 | } |
@@ -684,6 +682,11 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
684 | * check with the clearing of time_stamp and movement of i | 682 | * check with the clearing of time_stamp and movement of i |
685 | */ | 683 | */ |
686 | adapter->detect_tx_hung = 0; | 684 | adapter->detect_tx_hung = 0; |
685 | /* | ||
686 | * read barrier to make sure that the ->dma member and time | ||
687 | * stamp are updated fully | ||
688 | */ | ||
689 | smp_rmb(); | ||
687 | if (tx_ring->buffer_info[eop].dma && | 690 | if (tx_ring->buffer_info[eop].dma && |
688 | time_after(jiffies, tx_ring->buffer_info[eop].time_stamp | 691 | time_after(jiffies, tx_ring->buffer_info[eop].time_stamp |
689 | + (adapter->tx_timeout_factor * HZ)) | 692 | + (adapter->tx_timeout_factor * HZ)) |
@@ -3820,30 +3823,31 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
3820 | unsigned int mss) | 3823 | unsigned int mss) |
3821 | { | 3824 | { |
3822 | struct e1000_ring *tx_ring = adapter->tx_ring; | 3825 | struct e1000_ring *tx_ring = adapter->tx_ring; |
3823 | struct e1000_buffer *buffer_info; | 3826 | unsigned int len = skb_headlen(skb); |
3824 | unsigned int len = skb->len - skb->data_len; | 3827 | unsigned int offset, size, count = 0, i; |
3825 | unsigned int offset = 0, size, count = 0, i; | ||
3826 | unsigned int f; | 3828 | unsigned int f; |
3829 | dma_addr_t map; | ||
3827 | 3830 | ||
3828 | i = tx_ring->next_to_use; | 3831 | i = tx_ring->next_to_use; |
3829 | 3832 | ||
3833 | if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { | ||
3834 | dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); | ||
3835 | adapter->tx_dma_failed++; | ||
3836 | dev_kfree_skb(skb); | ||
3837 | return -2; | ||
3838 | } | ||
3839 | |||
3840 | map = skb_shinfo(skb)->dma_maps[0]; | ||
3841 | offset = 0; | ||
3842 | |||
3830 | while (len) { | 3843 | while (len) { |
3831 | buffer_info = &tx_ring->buffer_info[i]; | 3844 | struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; |
3832 | size = min(len, max_per_txd); | 3845 | size = min(len, max_per_txd); |
3833 | 3846 | ||
3834 | buffer_info->length = size; | 3847 | buffer_info->length = size; |
3835 | /* set time_stamp *before* dma to help avoid a possible race */ | 3848 | /* set time_stamp *before* dma to help avoid a possible race */ |
3836 | buffer_info->time_stamp = jiffies; | 3849 | buffer_info->time_stamp = jiffies; |
3837 | buffer_info->dma = | 3850 | buffer_info->dma = map + offset; |
3838 | pci_map_single(adapter->pdev, | ||
3839 | skb->data + offset, | ||
3840 | size, | ||
3841 | PCI_DMA_TODEVICE); | ||
3842 | if (pci_dma_mapping_error(adapter->pdev, buffer_info->dma)) { | ||
3843 | dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); | ||
3844 | adapter->tx_dma_failed++; | ||
3845 | return -1; | ||
3846 | } | ||
3847 | buffer_info->next_to_watch = i; | 3851 | buffer_info->next_to_watch = i; |
3848 | 3852 | ||
3849 | len -= size; | 3853 | len -= size; |
@@ -3859,28 +3863,17 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
3859 | 3863 | ||
3860 | frag = &skb_shinfo(skb)->frags[f]; | 3864 | frag = &skb_shinfo(skb)->frags[f]; |
3861 | len = frag->size; | 3865 | len = frag->size; |
3862 | offset = frag->page_offset; | 3866 | map = skb_shinfo(skb)->dma_maps[f + 1]; |
3867 | offset = 0; | ||
3863 | 3868 | ||
3864 | while (len) { | 3869 | while (len) { |
3870 | struct e1000_buffer *buffer_info; | ||
3865 | buffer_info = &tx_ring->buffer_info[i]; | 3871 | buffer_info = &tx_ring->buffer_info[i]; |
3866 | size = min(len, max_per_txd); | 3872 | size = min(len, max_per_txd); |
3867 | 3873 | ||
3868 | buffer_info->length = size; | 3874 | buffer_info->length = size; |
3869 | buffer_info->time_stamp = jiffies; | 3875 | buffer_info->time_stamp = jiffies; |
3870 | buffer_info->dma = | 3876 | buffer_info->dma = map + offset; |
3871 | pci_map_page(adapter->pdev, | ||
3872 | frag->page, | ||
3873 | offset, | ||
3874 | size, | ||
3875 | PCI_DMA_TODEVICE); | ||
3876 | if (pci_dma_mapping_error(adapter->pdev, | ||
3877 | buffer_info->dma)) { | ||
3878 | dev_err(&adapter->pdev->dev, | ||
3879 | "TX DMA page map failed\n"); | ||
3880 | adapter->tx_dma_failed++; | ||
3881 | return -1; | ||
3882 | } | ||
3883 | |||
3884 | buffer_info->next_to_watch = i; | 3877 | buffer_info->next_to_watch = i; |
3885 | 3878 | ||
3886 | len -= size; | 3879 | len -= size; |
@@ -3900,6 +3893,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
3900 | 3893 | ||
3901 | tx_ring->buffer_info[i].skb = skb; | 3894 | tx_ring->buffer_info[i].skb = skb; |
3902 | tx_ring->buffer_info[first].next_to_watch = i; | 3895 | tx_ring->buffer_info[first].next_to_watch = i; |
3896 | smp_wmb(); | ||
3903 | 3897 | ||
3904 | return count; | 3898 | return count; |
3905 | } | 3899 | } |