diff options
| author | Alexander Duyck <alexander.h.duyck@intel.com> | 2009-03-18 21:15:21 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-03-20 04:17:24 -0400 |
| commit | fe52eeb82b746de441ed27c54ace940efe86bc9a (patch) | |
| tree | e10b642cc9df4f479be0ee4ba2dfd378d51c0dd5 /drivers/net/ixgb | |
| parent | 5f66f208064f083aab5e55935d0575892e033b59 (diff) | |
ixgb: refactor tx path to use skb_dma_map/unmap
This code updates ixgb so that it can use the skb_dma_map/unmap functions
to map the buffers. In addition it also updates the tx hang logic to use
time_stamp instead of dma to determine if it has detected a tx hang.
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/ixgb')
| -rw-r--r-- | drivers/net/ixgb/ixgb_main.c | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index e2ef16b29700..4b0ea66d7a44 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c | |||
| @@ -887,19 +887,13 @@ static void | |||
| 887 | ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter, | 887 | ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter, |
| 888 | struct ixgb_buffer *buffer_info) | 888 | struct ixgb_buffer *buffer_info) |
| 889 | { | 889 | { |
| 890 | struct pci_dev *pdev = adapter->pdev; | ||
| 891 | |||
| 892 | if (buffer_info->dma) | ||
| 893 | pci_unmap_page(pdev, buffer_info->dma, buffer_info->length, | ||
| 894 | PCI_DMA_TODEVICE); | ||
| 895 | |||
| 896 | /* okay to call kfree_skb here instead of kfree_skb_any because | ||
| 897 | * this is never called in interrupt context */ | ||
| 898 | if (buffer_info->skb) | ||
| 899 | dev_kfree_skb(buffer_info->skb); | ||
| 900 | |||
| 901 | buffer_info->skb = NULL; | ||
| 902 | buffer_info->dma = 0; | 890 | buffer_info->dma = 0; |
| 891 | if (buffer_info->skb) { | ||
| 892 | skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb, | ||
| 893 | DMA_TO_DEVICE); | ||
| 894 | dev_kfree_skb_any(buffer_info->skb); | ||
| 895 | buffer_info->skb = NULL; | ||
| 896 | } | ||
| 903 | buffer_info->time_stamp = 0; | 897 | buffer_info->time_stamp = 0; |
| 904 | /* these fields must always be initialized in tx | 898 | /* these fields must always be initialized in tx |
| 905 | * buffer_info->length = 0; | 899 | * buffer_info->length = 0; |
| @@ -1275,17 +1269,23 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, | |||
| 1275 | { | 1269 | { |
| 1276 | struct ixgb_desc_ring *tx_ring = &adapter->tx_ring; | 1270 | struct ixgb_desc_ring *tx_ring = &adapter->tx_ring; |
| 1277 | struct ixgb_buffer *buffer_info; | 1271 | struct ixgb_buffer *buffer_info; |
| 1278 | int len = skb->len; | 1272 | int len = skb_headlen(skb); |
| 1279 | unsigned int offset = 0, size, count = 0, i; | 1273 | unsigned int offset = 0, size, count = 0, i; |
| 1280 | unsigned int mss = skb_shinfo(skb)->gso_size; | 1274 | unsigned int mss = skb_shinfo(skb)->gso_size; |
| 1281 | 1275 | ||
| 1282 | unsigned int nr_frags = skb_shinfo(skb)->nr_frags; | 1276 | unsigned int nr_frags = skb_shinfo(skb)->nr_frags; |
| 1283 | unsigned int f; | 1277 | unsigned int f; |
| 1284 | 1278 | dma_addr_t *map; | |
| 1285 | len -= skb->data_len; | ||
| 1286 | 1279 | ||
| 1287 | i = tx_ring->next_to_use; | 1280 | i = tx_ring->next_to_use; |
| 1288 | 1281 | ||
| 1282 | if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) { | ||
| 1283 | dev_err(&adapter->pdev->dev, "TX DMA map failed\n"); | ||
| 1284 | return 0; | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | map = skb_shinfo(skb)->dma_maps; | ||
| 1288 | |||
| 1289 | while (len) { | 1289 | while (len) { |
| 1290 | buffer_info = &tx_ring->buffer_info[i]; | 1290 | buffer_info = &tx_ring->buffer_info[i]; |
| 1291 | size = min(len, IXGB_MAX_DATA_PER_TXD); | 1291 | size = min(len, IXGB_MAX_DATA_PER_TXD); |
| @@ -1297,7 +1297,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, | |||
| 1297 | buffer_info->length = size; | 1297 | buffer_info->length = size; |
| 1298 | WARN_ON(buffer_info->dma != 0); | 1298 | WARN_ON(buffer_info->dma != 0); |
| 1299 | buffer_info->time_stamp = jiffies; | 1299 | buffer_info->time_stamp = jiffies; |
| 1300 | buffer_info->dma = | 1300 | buffer_info->dma = map[0] + offset; |
| 1301 | pci_map_single(adapter->pdev, | 1301 | pci_map_single(adapter->pdev, |
| 1302 | skb->data + offset, | 1302 | skb->data + offset, |
| 1303 | size, | 1303 | size, |
| @@ -1307,7 +1307,11 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, | |||
| 1307 | len -= size; | 1307 | len -= size; |
| 1308 | offset += size; | 1308 | offset += size; |
| 1309 | count++; | 1309 | count++; |
| 1310 | if (++i == tx_ring->count) i = 0; | 1310 | if (len) { |
| 1311 | i++; | ||
| 1312 | if (i == tx_ring->count) | ||
| 1313 | i = 0; | ||
| 1314 | } | ||
| 1311 | } | 1315 | } |
| 1312 | 1316 | ||
| 1313 | for (f = 0; f < nr_frags; f++) { | 1317 | for (f = 0; f < nr_frags; f++) { |
| @@ -1318,6 +1322,10 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, | |||
| 1318 | offset = 0; | 1322 | offset = 0; |
| 1319 | 1323 | ||
| 1320 | while (len) { | 1324 | while (len) { |
| 1325 | i++; | ||
| 1326 | if (i == tx_ring->count) | ||
| 1327 | i = 0; | ||
| 1328 | |||
| 1321 | buffer_info = &tx_ring->buffer_info[i]; | 1329 | buffer_info = &tx_ring->buffer_info[i]; |
| 1322 | size = min(len, IXGB_MAX_DATA_PER_TXD); | 1330 | size = min(len, IXGB_MAX_DATA_PER_TXD); |
| 1323 | 1331 | ||
| @@ -1329,21 +1337,14 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, | |||
| 1329 | 1337 | ||
| 1330 | buffer_info->length = size; | 1338 | buffer_info->length = size; |
| 1331 | buffer_info->time_stamp = jiffies; | 1339 | buffer_info->time_stamp = jiffies; |
| 1332 | buffer_info->dma = | 1340 | buffer_info->dma = map[f + 1] + offset; |
| 1333 | pci_map_page(adapter->pdev, | ||
| 1334 | frag->page, | ||
| 1335 | frag->page_offset + offset, | ||
| 1336 | size, | ||
| 1337 | PCI_DMA_TODEVICE); | ||
| 1338 | buffer_info->next_to_watch = 0; | 1341 | buffer_info->next_to_watch = 0; |
| 1339 | 1342 | ||
| 1340 | len -= size; | 1343 | len -= size; |
| 1341 | offset += size; | 1344 | offset += size; |
| 1342 | count++; | 1345 | count++; |
| 1343 | if (++i == tx_ring->count) i = 0; | ||
| 1344 | } | 1346 | } |
| 1345 | } | 1347 | } |
| 1346 | i = (i == 0) ? tx_ring->count - 1 : i - 1; | ||
| 1347 | tx_ring->buffer_info[i].skb = skb; | 1348 | tx_ring->buffer_info[i].skb = skb; |
| 1348 | tx_ring->buffer_info[first].next_to_watch = i; | 1349 | tx_ring->buffer_info[first].next_to_watch = i; |
| 1349 | 1350 | ||
| @@ -1445,6 +1446,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
| 1445 | unsigned int first; | 1446 | unsigned int first; |
| 1446 | unsigned int tx_flags = 0; | 1447 | unsigned int tx_flags = 0; |
| 1447 | int vlan_id = 0; | 1448 | int vlan_id = 0; |
| 1449 | int count = 0; | ||
| 1448 | int tso; | 1450 | int tso; |
| 1449 | 1451 | ||
| 1450 | if (test_bit(__IXGB_DOWN, &adapter->flags)) { | 1452 | if (test_bit(__IXGB_DOWN, &adapter->flags)) { |
| @@ -1479,13 +1481,19 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
| 1479 | else if (ixgb_tx_csum(adapter, skb)) | 1481 | else if (ixgb_tx_csum(adapter, skb)) |
| 1480 | tx_flags |= IXGB_TX_FLAGS_CSUM; | 1482 | tx_flags |= IXGB_TX_FLAGS_CSUM; |
| 1481 | 1483 | ||
| 1482 | ixgb_tx_queue(adapter, ixgb_tx_map(adapter, skb, first), vlan_id, | 1484 | count = ixgb_tx_map(adapter, skb, first); |
| 1483 | tx_flags); | ||
| 1484 | 1485 | ||
| 1485 | netdev->trans_start = jiffies; | 1486 | if (count) { |
| 1487 | ixgb_tx_queue(adapter, count, vlan_id, tx_flags); | ||
| 1488 | netdev->trans_start = jiffies; | ||
| 1489 | /* Make sure there is space in the ring for the next send. */ | ||
| 1490 | ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED); | ||
| 1486 | 1491 | ||
| 1487 | /* Make sure there is space in the ring for the next send. */ | 1492 | } else { |
| 1488 | ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED); | 1493 | dev_kfree_skb_any(skb); |
| 1494 | adapter->tx_ring.buffer_info[first].time_stamp = 0; | ||
| 1495 | adapter->tx_ring.next_to_use = first; | ||
| 1496 | } | ||
| 1489 | 1497 | ||
| 1490 | return NETDEV_TX_OK; | 1498 | return NETDEV_TX_OK; |
| 1491 | } | 1499 | } |
| @@ -1818,7 +1826,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter) | |||
| 1818 | /* detect a transmit hang in hardware, this serializes the | 1826 | /* detect a transmit hang in hardware, this serializes the |
| 1819 | * check with the clearing of time_stamp and movement of i */ | 1827 | * check with the clearing of time_stamp and movement of i */ |
| 1820 | adapter->detect_tx_hung = false; | 1828 | adapter->detect_tx_hung = false; |
| 1821 | if (tx_ring->buffer_info[eop].dma && | 1829 | if (tx_ring->buffer_info[eop].time_stamp && |
| 1822 | time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ) | 1830 | time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ) |
| 1823 | && !(IXGB_READ_REG(&adapter->hw, STATUS) & | 1831 | && !(IXGB_READ_REG(&adapter->hw, STATUS) & |
| 1824 | IXGB_STATUS_TXOFF)) { | 1832 | IXGB_STATUS_TXOFF)) { |
