===== drivers/net/sungem.c 1.71 vs edited =====
--- 1.71/drivers/net/sungem.c	2004-11-14 10:45:36 +01:00
+++ edited/drivers/net/sungem.c	2005-01-03 00:00:22 +01:00
@@ -950,6 +950,7 @@
 	return 0;
 }
 
+/* Called with dev->queue_lock held */
 static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct gem *gp = dev->priv;
@@ -976,8 +977,16 @@
 		return NETDEV_TX_LOCKED;
 	}
 
+	/* We can now drop queue_lock since tx_lock protects us. But remember
+	 * that queue_lock must be reacquired before we return. Moreover we
+	 * must reacquire it before releasing tx_lock to avoid being called
+	 * with the queue stopped.
+	 */
+	spin_unlock(&dev->queue_lock);
+
 	/* This is a hard error, log it. */
 	if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
+		spin_lock(&dev->queue_lock);
 		netif_stop_queue(dev);
 		spin_unlock_irqrestore(&gp->tx_lock, flags);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
@@ -1066,6 +1075,7 @@
 		       dev->name, entry, skb->len);
 	mb();
 	writel(gp->tx_new, gp->regs + TXDMA_KICK);
+	spin_lock(&dev->queue_lock);
 	spin_unlock_irqrestore(&gp->tx_lock, flags);
 
 	dev->trans_start = jiffies;
