diff --git a/[refs] b/[refs] index fa3edb94a981..105dafc9c075 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: af18d8b89930aecc742982634adaf97dfb43ed3b +refs/heads/master: 481cea4a4d72aabe76dbb86b1a64f4e8931eca25 diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index 301f8a6f8c08..4944fcc6b076 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -1741,8 +1741,12 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) /* * Free ring elements from starting at tx_cons until "done" * - * NB: the hardware will tell us about partial completion of multi-part + * NB: + * 1. The hardware will tell us about partial completion of multi-part * buffers so make sure not to free skb to early. + * 2. This may run in parallel start_xmit because the it only + * looks at the tail of the queue of FIFO (tx_cons), not + * the head (tx_prod) */ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) { @@ -1800,16 +1804,6 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) netif_wake_queue(dev); } -/* Cleanup all untransmitted buffers, assume transmitter not running */ -static void sky2_tx_clean(struct net_device *dev) -{ - struct sky2_port *sky2 = netdev_priv(dev); - - netif_tx_lock_bh(dev); - sky2_tx_complete(sky2, sky2->tx_prod); - netif_tx_unlock_bh(dev); -} - static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) { /* Disable Force Sync bit and Enable Alloc bit */ @@ -1901,7 +1895,9 @@ static int sky2_down(struct net_device *dev) sky2_tx_reset(hw, port); - sky2_tx_clean(dev); + /* Free any pending frames stuck in HW queue */ + sky2_tx_complete(sky2, sky2->tx_prod); + sky2_rx_clean(sky2); pci_free_consistent(hw->pdev, RX_LE_BYTES, @@ -2378,11 +2374,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) { struct sky2_port *sky2 = netdev_priv(dev); - if (likely(netif_running(dev) && !sky2->restarting)) { - netif_tx_lock(dev); + if (likely(netif_running(dev) && !sky2->restarting)) sky2_tx_complete(sky2, last); - netif_tx_unlock(dev); - } } static inline void sky2_skb_rx(const struct sky2_port *sky2,