diff options
| author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-12-02 11:47:37 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-12-02 22:57:13 -0500 |
| commit | a7d5ca40ff56e2cd4e30bbe91f2d0deab6bfc006 (patch) | |
| tree | fb3ab31e49cbcadc682ca7c7defd6286f251c2a9 /drivers/net/igbvf | |
| parent | 6366ad331f436388129dfc044db871de79604e4d (diff) | |
igbvf: remove skb_dma_map/unmap call from drivers
This patch removes the skb_dma_map/unmap calls from the igbvf driver due to
the fact that it does not play well with HW IOMMU when combined with
transmitting cloned skbs.
Signed-off-by: Alexander Duyck <alexander.h.duyck@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/igbvf')
| -rw-r--r-- | drivers/net/igbvf/igbvf.h | 1 | ||||
| -rw-r--r-- | drivers/net/igbvf/netdev.c | 65 |
2 files changed, 52 insertions, 14 deletions
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h index 8e9b67ebbf8b..3d1ee7a8478e 100644 --- a/drivers/net/igbvf/igbvf.h +++ b/drivers/net/igbvf/igbvf.h | |||
| @@ -117,6 +117,7 @@ struct igbvf_buffer { | |||
| 117 | unsigned long time_stamp; | 117 | unsigned long time_stamp; |
| 118 | u16 length; | 118 | u16 length; |
| 119 | u16 next_to_watch; | 119 | u16 next_to_watch; |
| 120 | u16 mapped_as_page; | ||
| 120 | }; | 121 | }; |
| 121 | /* Rx */ | 122 | /* Rx */ |
| 122 | struct { | 123 | struct { |
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index e01f44597a26..cf26f92e3235 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c | |||
| @@ -366,10 +366,20 @@ next_desc: | |||
| 366 | static void igbvf_put_txbuf(struct igbvf_adapter *adapter, | 366 | static void igbvf_put_txbuf(struct igbvf_adapter *adapter, |
| 367 | struct igbvf_buffer *buffer_info) | 367 | struct igbvf_buffer *buffer_info) |
| 368 | { | 368 | { |
| 369 | buffer_info->dma = 0; | 369 | if (buffer_info->dma) { |
| 370 | if (buffer_info->mapped_as_page) | ||
| 371 | pci_unmap_page(adapter->pdev, | ||
| 372 | buffer_info->dma, | ||
| 373 | buffer_info->length, | ||
| 374 | PCI_DMA_TODEVICE); | ||
| 375 | else | ||
| 376 | pci_unmap_single(adapter->pdev, | ||
| 377 | buffer_info->dma, | ||
| 378 | buffer_info->length, | ||
| 379 | PCI_DMA_TODEVICE); | ||
| 380 | buffer_info->dma = 0; | ||
| 381 | } | ||
| 370 | if (buffer_info->skb) { | 382 | if (buffer_info->skb) { |
| 371 | skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, | ||
| 372 | DMA_TO_DEVICE); | ||
| 373 | dev_kfree_skb_any(buffer_info->skb); | 383 | dev_kfree_skb_any(buffer_info->skb); |
| 374 | buffer_info->skb = NULL; | 384 | buffer_info->skb = NULL; |
| 375 | } | 385 | } |
| @@ -2088,27 +2098,24 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, | |||
| 2088 | unsigned int first) | 2098 | unsigned int first) |
| 2089 | { | 2099 | { |
| 2090 | struct igbvf_buffer *buffer_info; | 2100 | struct igbvf_buffer *buffer_info; |
| 2101 | struct pci_dev *pdev = adapter->pdev; | ||
| 2091 | unsigned int len = skb_headlen(skb); | 2102 | unsigned int len = skb_headlen(skb); |
| 2092 | unsigned int count = 0, i; | 2103 | unsigned int count = 0, i; |
| 2093 | unsigned int f; | 2104 | unsigned int f; |
| 2094 | dma_addr_t *map; | ||
| 2095 | 2105 | ||
| 2096 | i = tx_ring->next_to_use; | 2106 | i = tx_ring->next_to_use; |
| 2097 | 2107 | ||
| 2098 | if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { | ||
| 2099 | dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); | ||
| 2100 | return 0; | ||
| 2101 | } | ||
| 2102 | |||
| 2103 | map = skb_shinfo(skb)->dma_maps; | ||
| 2104 | |||
| 2105 | buffer_info = &tx_ring->buffer_info[i]; | 2108 | buffer_info = &tx_ring->buffer_info[i]; |
| 2106 | BUG_ON(len >= IGBVF_MAX_DATA_PER_TXD); | 2109 | BUG_ON(len >= IGBVF_MAX_DATA_PER_TXD); |
| 2107 | buffer_info->length = len; | 2110 | buffer_info->length = len; |
| 2108 | /* set time_stamp *before* dma to help avoid a possible race */ | 2111 | /* set time_stamp *before* dma to help avoid a possible race */ |
| 2109 | buffer_info->time_stamp = jiffies; | 2112 | buffer_info->time_stamp = jiffies; |
| 2110 | buffer_info->next_to_watch = i; | 2113 | buffer_info->next_to_watch = i; |
| 2111 | buffer_info->dma = skb_shinfo(skb)->dma_head; | 2114 | buffer_info->dma = pci_map_single(pdev, skb->data, len, |
| 2115 | PCI_DMA_TODEVICE); | ||
| 2116 | if (pci_dma_mapping_error(pdev, buffer_info->dma)) | ||
| 2117 | goto dma_error; | ||
| 2118 | |||
| 2112 | 2119 | ||
| 2113 | for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { | 2120 | for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { |
| 2114 | struct skb_frag_struct *frag; | 2121 | struct skb_frag_struct *frag; |
| @@ -2125,14 +2132,44 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter, | |||
| 2125 | buffer_info->length = len; | 2132 | buffer_info->length = len; |
| 2126 | buffer_info->time_stamp = jiffies; | 2133 | buffer_info->time_stamp = jiffies; |
| 2127 | buffer_info->next_to_watch = i; | 2134 | buffer_info->next_to_watch = i; |
| 2128 | buffer_info->dma = map[count]; | 2135 | buffer_info->mapped_as_page = true; |
| 2136 | buffer_info->dma = pci_map_page(pdev, | ||
| 2137 | frag->page, | ||
| 2138 | frag->page_offset, | ||
| 2139 | len, | ||
| 2140 | PCI_DMA_TODEVICE); | ||
| 2141 | if (pci_dma_mapping_error(pdev, buffer_info->dma)) | ||
| 2142 | goto dma_error; | ||
| 2129 | count++; | 2143 | count++; |
| 2130 | } | 2144 | } |
| 2131 | 2145 | ||
| 2132 | tx_ring->buffer_info[i].skb = skb; | 2146 | tx_ring->buffer_info[i].skb = skb; |
| 2133 | tx_ring->buffer_info[first].next_to_watch = i; | 2147 | tx_ring->buffer_info[first].next_to_watch = i; |
| 2134 | 2148 | ||
| 2135 | return count + 1; | 2149 | return ++count; |
| 2150 | |||
| 2151 | dma_error: | ||
| 2152 | dev_err(&pdev->dev, "TX DMA map failed\n"); | ||
| 2153 | |||
| 2154 | /* clear timestamp and dma mappings for failed buffer_info mapping */ | ||
| 2155 | buffer_info->dma = 0; | ||
| 2156 | buffer_info->time_stamp = 0; | ||
| 2157 | buffer_info->length = 0; | ||
| 2158 | buffer_info->next_to_watch = 0; | ||
| 2159 | buffer_info->mapped_as_page = false; | ||
| 2160 | count--; | ||
| 2161 | |||
| 2162 | /* clear timestamp and dma mappings for remaining portion of packet */ | ||
| 2163 | while (count >= 0) { | ||
| 2164 | count--; | ||
| 2165 | i--; | ||
| 2166 | if (i < 0) | ||
| 2167 | i += tx_ring->count; | ||
| 2168 | buffer_info = &tx_ring->buffer_info[i]; | ||
| 2169 | igbvf_put_txbuf(adapter, buffer_info); | ||
| 2170 | } | ||
| 2171 | |||
| 2172 | return 0; | ||
| 2136 | } | 2173 | } |
| 2137 | 2174 | ||
| 2138 | static inline void igbvf_tx_queue_adv(struct igbvf_adapter *adapter, | 2175 | static inline void igbvf_tx_queue_adv(struct igbvf_adapter *adapter, |
