aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLendacky, Thomas <Thomas.Lendacky@amd.com>2015-01-16 13:46:55 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-16 22:24:20 -0500
commita83ef427b7d97314df30d6e25abc7aa3a80ffcfd (patch)
treef9e62392b9cbd429cd7543db19da44518650b1ec /drivers/net
parent270894e7dc7afad8fb79592fe02aa05e604ddfc8 (diff)
amd-xgbe: Remove need for Tx path spinlock
Since the Tx ring cleanup can run at the same time that data is being transmitted, a spin lock was used to protect the ring. This patch eliminates the need for Tx spinlocks by updating the current ring position only after all ownership bits for data being transmitted have been set. This will insure that ring operations in the Tx cleanup path do not interfere with the ring operations in the Tx transmit path. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-dev.c17
-rw-r--r--drivers/net/ethernet/amd/xgbe/xgbe-drv.c21
2 files changed, 10 insertions, 28 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index e424997afc55..5dff127a0823 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -1359,6 +1359,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
1359 unsigned int tso_context, vlan_context; 1359 unsigned int tso_context, vlan_context;
1360 unsigned int tx_set_ic; 1360 unsigned int tx_set_ic;
1361 int start_index = ring->cur; 1361 int start_index = ring->cur;
1362 int cur_index = ring->cur;
1362 int i; 1363 int i;
1363 1364
1364 DBGPR("-->xgbe_dev_xmit\n"); 1365 DBGPR("-->xgbe_dev_xmit\n");
@@ -1401,7 +1402,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
1401 else 1402 else
1402 tx_set_ic = 0; 1403 tx_set_ic = 0;
1403 1404
1404 rdata = XGBE_GET_DESC_DATA(ring, ring->cur); 1405 rdata = XGBE_GET_DESC_DATA(ring, cur_index);
1405 rdesc = rdata->rdesc; 1406 rdesc = rdata->rdesc;
1406 1407
1407 /* Create a context descriptor if this is a TSO packet */ 1408 /* Create a context descriptor if this is a TSO packet */
@@ -1444,8 +1445,8 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
1444 ring->tx.cur_vlan_ctag = packet->vlan_ctag; 1445 ring->tx.cur_vlan_ctag = packet->vlan_ctag;
1445 } 1446 }
1446 1447
1447 ring->cur++; 1448 cur_index++;
1448 rdata = XGBE_GET_DESC_DATA(ring, ring->cur); 1449 rdata = XGBE_GET_DESC_DATA(ring, cur_index);
1449 rdesc = rdata->rdesc; 1450 rdesc = rdata->rdesc;
1450 } 1451 }
1451 1452
@@ -1473,7 +1474,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
1473 XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT, 0); 1474 XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, CTXT, 0);
1474 1475
1475 /* Set OWN bit if not the first descriptor */ 1476 /* Set OWN bit if not the first descriptor */
1476 if (ring->cur != start_index) 1477 if (cur_index != start_index)
1477 XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1); 1478 XGMAC_SET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN, 1);
1478 1479
1479 if (tso) { 1480 if (tso) {
@@ -1497,9 +1498,9 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
1497 packet->length); 1498 packet->length);
1498 } 1499 }
1499 1500
1500 for (i = ring->cur - start_index + 1; i < packet->rdesc_count; i++) { 1501 for (i = cur_index - start_index + 1; i < packet->rdesc_count; i++) {
1501 ring->cur++; 1502 cur_index++;
1502 rdata = XGBE_GET_DESC_DATA(ring, ring->cur); 1503 rdata = XGBE_GET_DESC_DATA(ring, cur_index);
1503 rdesc = rdata->rdesc; 1504 rdesc = rdata->rdesc;
1504 1505
1505 /* Update buffer address */ 1506 /* Update buffer address */
@@ -1551,7 +1552,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
1551 /* Make sure ownership is written to the descriptor */ 1552 /* Make sure ownership is written to the descriptor */
1552 wmb(); 1553 wmb();
1553 1554
1554 ring->cur++; 1555 ring->cur = cur_index + 1;
1555 if (!packet->skb->xmit_more || 1556 if (!packet->skb->xmit_more ||
1556 netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev, 1557 netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev,
1557 channel->queue_index))) 1558 channel->queue_index)))
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index e2f560ff5104..c036a0e61bba 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -415,17 +415,13 @@ static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer)
415 struct xgbe_channel *channel = container_of(timer, 415 struct xgbe_channel *channel = container_of(timer,
416 struct xgbe_channel, 416 struct xgbe_channel,
417 tx_timer); 417 tx_timer);
418 struct xgbe_ring *ring = channel->tx_ring;
419 struct xgbe_prv_data *pdata = channel->pdata; 418 struct xgbe_prv_data *pdata = channel->pdata;
420 struct napi_struct *napi; 419 struct napi_struct *napi;
421 unsigned long flags;
422 420
423 DBGPR("-->xgbe_tx_timer\n"); 421 DBGPR("-->xgbe_tx_timer\n");
424 422
425 napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi; 423 napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi;
426 424
427 spin_lock_irqsave(&ring->lock, flags);
428
429 if (napi_schedule_prep(napi)) { 425 if (napi_schedule_prep(napi)) {
430 /* Disable Tx and Rx interrupts */ 426 /* Disable Tx and Rx interrupts */
431 if (pdata->per_channel_irq) 427 if (pdata->per_channel_irq)
@@ -439,8 +435,6 @@ static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer)
439 435
440 channel->tx_timer_active = 0; 436 channel->tx_timer_active = 0;
441 437
442 spin_unlock_irqrestore(&ring->lock, flags);
443
444 DBGPR("<--xgbe_tx_timer\n"); 438 DBGPR("<--xgbe_tx_timer\n");
445 439
446 return HRTIMER_NORESTART; 440 return HRTIMER_NORESTART;
@@ -1450,7 +1444,6 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
1450 struct xgbe_ring *ring; 1444 struct xgbe_ring *ring;
1451 struct xgbe_packet_data *packet; 1445 struct xgbe_packet_data *packet;
1452 struct netdev_queue *txq; 1446 struct netdev_queue *txq;
1453 unsigned long flags;
1454 int ret; 1447 int ret;
1455 1448
1456 DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len); 1449 DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len);
@@ -1462,8 +1455,6 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
1462 1455
1463 ret = NETDEV_TX_OK; 1456 ret = NETDEV_TX_OK;
1464 1457
1465 spin_lock_irqsave(&ring->lock, flags);
1466
1467 if (skb->len == 0) { 1458 if (skb->len == 0) {
1468 netdev_err(netdev, "empty skb received from stack\n"); 1459 netdev_err(netdev, "empty skb received from stack\n");
1469 dev_kfree_skb_any(skb); 1460 dev_kfree_skb_any(skb);
@@ -1510,10 +1501,6 @@ static int xgbe_xmit(struct sk_buff *skb, struct net_device *netdev)
1510 ret = NETDEV_TX_OK; 1501 ret = NETDEV_TX_OK;
1511 1502
1512tx_netdev_return: 1503tx_netdev_return:
1513 spin_unlock_irqrestore(&ring->lock, flags);
1514
1515 DBGPR("<--xgbe_xmit\n");
1516
1517 return ret; 1504 return ret;
1518} 1505}
1519 1506
@@ -1841,7 +1828,6 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
1841 struct xgbe_ring_desc *rdesc; 1828 struct xgbe_ring_desc *rdesc;
1842 struct net_device *netdev = pdata->netdev; 1829 struct net_device *netdev = pdata->netdev;
1843 struct netdev_queue *txq; 1830 struct netdev_queue *txq;
1844 unsigned long flags;
1845 int processed = 0; 1831 int processed = 0;
1846 unsigned int tx_packets = 0, tx_bytes = 0; 1832 unsigned int tx_packets = 0, tx_bytes = 0;
1847 1833
@@ -1853,8 +1839,6 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
1853 1839
1854 txq = netdev_get_tx_queue(netdev, channel->queue_index); 1840 txq = netdev_get_tx_queue(netdev, channel->queue_index);
1855 1841
1856 spin_lock_irqsave(&ring->lock, flags);
1857
1858 while ((processed < XGBE_TX_DESC_MAX_PROC) && 1842 while ((processed < XGBE_TX_DESC_MAX_PROC) &&
1859 (ring->dirty != ring->cur)) { 1843 (ring->dirty != ring->cur)) {
1860 rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); 1844 rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
@@ -1885,7 +1869,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
1885 } 1869 }
1886 1870
1887 if (!processed) 1871 if (!processed)
1888 goto unlock; 1872 return 0;
1889 1873
1890 netdev_tx_completed_queue(txq, tx_packets, tx_bytes); 1874 netdev_tx_completed_queue(txq, tx_packets, tx_bytes);
1891 1875
@@ -1897,9 +1881,6 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
1897 1881
1898 DBGPR("<--xgbe_tx_poll: processed=%d\n", processed); 1882 DBGPR("<--xgbe_tx_poll: processed=%d\n", processed);
1899 1883
1900unlock:
1901 spin_unlock_irqrestore(&ring->lock, flags);
1902
1903 return processed; 1884 return processed;
1904} 1885}
1905 1886