diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2009-03-02 19:03:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-02 19:03:21 -0500 |
commit | d20b606c99c7fd9f1b6c6ec43c877eaae827d169 (patch) | |
tree | 8f7e64519cd5928a57f86efd1a1026bf41fc0953 /drivers | |
parent | 8ddc951c73cbc317148c0b9973dde81eece57e4c (diff) |
e1000: fix unmap bug
This is in reference to the issue shown in kerneloops (search e1000 unmap)
The e1000 transmit code was calling pci_unmap_page on dma handles that it
might have called pci_map_single on.
Same bug as e1000e
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')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 61b56ca00051..1f390ceb4869 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -2049,14 +2049,10 @@ void e1000_free_all_tx_resources(struct e1000_adapter *adapter) | |||
2049 | static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, | 2049 | static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, |
2050 | struct e1000_buffer *buffer_info) | 2050 | struct e1000_buffer *buffer_info) |
2051 | { | 2051 | { |
2052 | if (buffer_info->dma) { | 2052 | buffer_info->dma = 0; |
2053 | pci_unmap_page(adapter->pdev, | ||
2054 | buffer_info->dma, | ||
2055 | buffer_info->length, | ||
2056 | PCI_DMA_TODEVICE); | ||
2057 | buffer_info->dma = 0; | ||
2058 | } | ||
2059 | if (buffer_info->skb) { | 2053 | if (buffer_info->skb) { |
2054 | skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, | ||
2055 | DMA_TO_DEVICE); | ||
2060 | dev_kfree_skb_any(buffer_info->skb); | 2056 | dev_kfree_skb_any(buffer_info->skb); |
2061 | buffer_info->skb = NULL; | 2057 | buffer_info->skb = NULL; |
2062 | } | 2058 | } |
@@ -2907,16 +2903,24 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
2907 | unsigned int mss) | 2903 | unsigned int mss) |
2908 | { | 2904 | { |
2909 | struct e1000_hw *hw = &adapter->hw; | 2905 | struct e1000_hw *hw = &adapter->hw; |
2910 | struct e1000_buffer *buffer_info; | 2906 | unsigned int len = skb_headlen(skb); |
2911 | unsigned int len = skb->len; | 2907 | unsigned int offset, size, count = 0, i; |
2912 | unsigned int offset = 0, size, count = 0, i; | ||
2913 | unsigned int f; | 2908 | unsigned int f; |
2914 | len -= skb->data_len; | 2909 | dma_addr_t map; |
2915 | 2910 | ||
2916 | i = tx_ring->next_to_use; | 2911 | i = tx_ring->next_to_use; |
2917 | 2912 | ||
2913 | if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { | ||
2914 | dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); | ||
2915 | dev_kfree_skb(skb); | ||
2916 | return -2; | ||
2917 | } | ||
2918 | |||
2919 | map = skb_shinfo(skb)->dma_maps[0]; | ||
2920 | offset = 0; | ||
2921 | |||
2918 | while (len) { | 2922 | while (len) { |
2919 | buffer_info = &tx_ring->buffer_info[i]; | 2923 | struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; |
2920 | size = min(len, max_per_txd); | 2924 | size = min(len, max_per_txd); |
2921 | /* Workaround for Controller erratum -- | 2925 | /* Workaround for Controller erratum -- |
2922 | * descriptor for non-tso packet in a linear SKB that follows a | 2926 | * descriptor for non-tso packet in a linear SKB that follows a |
@@ -2949,11 +2953,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
2949 | size -= 4; | 2953 | size -= 4; |
2950 | 2954 | ||
2951 | buffer_info->length = size; | 2955 | buffer_info->length = size; |
2952 | buffer_info->dma = | 2956 | buffer_info->dma = map + offset; |
2953 | pci_map_single(adapter->pdev, | ||
2954 | skb->data + offset, | ||
2955 | size, | ||
2956 | PCI_DMA_TODEVICE); | ||
2957 | buffer_info->time_stamp = jiffies; | 2957 | buffer_info->time_stamp = jiffies; |
2958 | buffer_info->next_to_watch = i; | 2958 | buffer_info->next_to_watch = i; |
2959 | 2959 | ||
@@ -2968,9 +2968,11 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
2968 | 2968 | ||
2969 | frag = &skb_shinfo(skb)->frags[f]; | 2969 | frag = &skb_shinfo(skb)->frags[f]; |
2970 | len = frag->size; | 2970 | len = frag->size; |
2971 | offset = frag->page_offset; | 2971 | map = skb_shinfo(skb)->dma_maps[f + 1]; |
2972 | offset = 0; | ||
2972 | 2973 | ||
2973 | while (len) { | 2974 | while (len) { |
2975 | struct e1000_buffer *buffer_info; | ||
2974 | buffer_info = &tx_ring->buffer_info[i]; | 2976 | buffer_info = &tx_ring->buffer_info[i]; |
2975 | size = min(len, max_per_txd); | 2977 | size = min(len, max_per_txd); |
2976 | /* Workaround for premature desc write-backs | 2978 | /* Workaround for premature desc write-backs |
@@ -2986,12 +2988,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
2986 | size -= 4; | 2988 | size -= 4; |
2987 | 2989 | ||
2988 | buffer_info->length = size; | 2990 | buffer_info->length = size; |
2989 | buffer_info->dma = | 2991 | buffer_info->dma = map + offset; |
2990 | pci_map_page(adapter->pdev, | ||
2991 | frag->page, | ||
2992 | offset, | ||
2993 | size, | ||
2994 | PCI_DMA_TODEVICE); | ||
2995 | buffer_info->time_stamp = jiffies; | 2992 | buffer_info->time_stamp = jiffies; |
2996 | buffer_info->next_to_watch = i; | 2993 | buffer_info->next_to_watch = i; |
2997 | 2994 | ||
@@ -3005,6 +3002,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, | |||
3005 | i = (i == 0) ? tx_ring->count - 1 : i - 1; | 3002 | i = (i == 0) ? tx_ring->count - 1 : i - 1; |
3006 | tx_ring->buffer_info[i].skb = skb; | 3003 | tx_ring->buffer_info[i].skb = skb; |
3007 | tx_ring->buffer_info[first].next_to_watch = i; | 3004 | tx_ring->buffer_info[first].next_to_watch = i; |
3005 | smp_wmb(); | ||
3008 | 3006 | ||
3009 | return count; | 3007 | return count; |
3010 | } | 3008 | } |
@@ -3844,6 +3842,11 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, | |||
3844 | /* Detect a transmit hang in hardware, this serializes the | 3842 | /* Detect a transmit hang in hardware, this serializes the |
3845 | * check with the clearing of time_stamp and movement of i */ | 3843 | * check with the clearing of time_stamp and movement of i */ |
3846 | adapter->detect_tx_hung = false; | 3844 | adapter->detect_tx_hung = false; |
3845 | /* | ||
3846 | * read barrier to make sure that the ->dma member and time | ||
3847 | * stamp are updated fully | ||
3848 | */ | ||
3849 | smp_rmb(); | ||
3847 | if (tx_ring->buffer_info[eop].dma && | 3850 | if (tx_ring->buffer_info[eop].dma && |
3848 | time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + | 3851 | time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + |
3849 | (adapter->tx_timeout_factor * HZ)) | 3852 | (adapter->tx_timeout_factor * HZ)) |