diff options
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, |