aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2009-08-14 18:33:19 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-14 18:33:19 -0400
commit481cea4a4d72aabe76dbb86b1a64f4e8931eca25 (patch)
tree6dcc70186cdca997df18399bbda806339100f2ea /drivers/net/sky2.c
parentaf18d8b89930aecc742982634adaf97dfb43ed3b (diff)
sky2: lock less transmit completion
Transmit completion can safely run lockless against transmit start. In the normal case, completion is done from NAPI and only looks at elements that are at the tail of the ring. When doing shutdown or reset, the transmiter should be completely block by NAPI disable and blocking of transmit queue. Based on earlier work by Mike McCormack. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c25
1 files changed, 9 insertions, 16 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 301f8a6f8c08..4944fcc6b076 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1741,8 +1741,12 @@ mapping_error:
1741/* 1741/*
1742 * Free ring elements from starting at tx_cons until "done" 1742 * Free ring elements from starting at tx_cons until "done"
1743 * 1743 *
1744 * NB: the hardware will tell us about partial completion of multi-part 1744 * NB:
1745 * 1. The hardware will tell us about partial completion of multi-part
1745 * buffers so make sure not to free skb to early. 1746 * buffers so make sure not to free skb to early.
1747 * 2. This may run in parallel start_xmit because the it only
1748 * looks at the tail of the queue of FIFO (tx_cons), not
1749 * the head (tx_prod)
1746 */ 1750 */
1747static void sky2_tx_complete(struct sky2_port *sky2, u16 done) 1751static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1748{ 1752{
@@ -1800,16 +1804,6 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1800 netif_wake_queue(dev); 1804 netif_wake_queue(dev);
1801} 1805}
1802 1806
1803/* Cleanup all untransmitted buffers, assume transmitter not running */
1804static void sky2_tx_clean(struct net_device *dev)
1805{
1806 struct sky2_port *sky2 = netdev_priv(dev);
1807
1808 netif_tx_lock_bh(dev);
1809 sky2_tx_complete(sky2, sky2->tx_prod);
1810 netif_tx_unlock_bh(dev);
1811}
1812
1813static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) 1807static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
1814{ 1808{
1815 /* Disable Force Sync bit and Enable Alloc bit */ 1809 /* Disable Force Sync bit and Enable Alloc bit */
@@ -1901,7 +1895,9 @@ static int sky2_down(struct net_device *dev)
1901 1895
1902 sky2_tx_reset(hw, port); 1896 sky2_tx_reset(hw, port);
1903 1897
1904 sky2_tx_clean(dev); 1898 /* Free any pending frames stuck in HW queue */
1899 sky2_tx_complete(sky2, sky2->tx_prod);
1900
1905 sky2_rx_clean(sky2); 1901 sky2_rx_clean(sky2);
1906 1902
1907 pci_free_consistent(hw->pdev, RX_LE_BYTES, 1903 pci_free_consistent(hw->pdev, RX_LE_BYTES,
@@ -2378,11 +2374,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
2378{ 2374{
2379 struct sky2_port *sky2 = netdev_priv(dev); 2375 struct sky2_port *sky2 = netdev_priv(dev);
2380 2376
2381 if (likely(netif_running(dev) && !sky2->restarting)) { 2377 if (likely(netif_running(dev) && !sky2->restarting))
2382 netif_tx_lock(dev);
2383 sky2_tx_complete(sky2, last); 2378 sky2_tx_complete(sky2, last);
2384 netif_tx_unlock(dev);
2385 }
2386} 2379}
2387 2380
2388static inline void sky2_skb_rx(const struct sky2_port *sky2, 2381static inline void sky2_skb_rx(const struct sky2_port *sky2,