/*
* 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)
{
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 */
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,
{
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,