From: Nicolas Pitre <nico@cam.org>

This fixes remaining locking problems on SMP.

Thanks to Hirokazu Takata for testing.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/net/smc91x.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff -puN drivers/net/smc91x.c~smc91x-more-smp-locking-fixes drivers/net/smc91x.c
--- 25/drivers/net/smc91x.c~smc91x-more-smp-locking-fixes	Thu Sep 30 17:47:03 2004
+++ 25-akpm/drivers/net/smc91x.c	Thu Sep 30 17:47:03 2004
@@ -588,23 +588,26 @@ static void smc_hardware_send_pkt(unsign
 	struct net_device *dev = (struct net_device *)data;
 	struct smc_local *lp = netdev_priv(dev);
 	unsigned long ioaddr = dev->base_addr;
-	struct sk_buff *skb = lp->pending_tx_skb;
+	struct sk_buff *skb;
 	unsigned int packet_no, len;
 	unsigned char *buf;
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
 	if (!smc_special_trylock(&lp->lock)) {
+		netif_stop_queue(dev);
 		tasklet_schedule(&lp->tx_task);
 		return;
 	}
 
+	skb = lp->pending_tx_skb;
 	lp->pending_tx_skb = NULL;
 	packet_no = SMC_GET_AR();
 	if (unlikely(packet_no & AR_FAILED)) {
 		printk("%s: Memory allocation failed.\n", dev->name);
 		lp->stats.tx_errors++;
 		lp->stats.tx_fifo_errors++;
+		smc_special_unlock(&lp->lock);
 		goto done;
 	}
 
@@ -645,15 +648,15 @@ static void smc_hardware_send_pkt(unsign
 	/* queue the packet for TX */
 	SMC_SET_MMU_CMD(MC_ENQUEUE);
 	SMC_ACK_INT(IM_TX_EMPTY_INT);
-	SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
+	smc_special_unlock(&lp->lock);
 
 	dev->trans_start = jiffies;
 	lp->stats.tx_packets++;
 	lp->stats.tx_bytes += len;
 
-done:	smc_special_unlock(&lp->lock);
+	SMC_ENABLE_INT(IM_TX_INT | IM_TX_EMPTY_INT);
 
-	if (!THROTTLE_TX_PKTS)
+done:	if (!THROTTLE_TX_PKTS)
 		netif_wake_queue(dev);
 
 	dev_kfree_skb(skb);
@@ -1825,6 +1828,7 @@ static int __init smc_probe(struct net_d
 	/* fill in some of the fields */
 	dev->base_addr = ioaddr;
 	lp->version = revision_register & 0xff;
+	spin_lock_init(&lp->lock);
 
 	/* Get the MAC address */
 	SMC_SELECT_BANK(1);
@@ -1880,7 +1884,6 @@ static int __init smc_probe(struct net_d
 	dev->set_multicast_list = smc_set_multicast_list;
 	dev->ethtool_ops = &smc_ethtool_ops;
 
-	spin_lock_init(&lp->lock);
 	tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev);
 	INIT_WORK(&lp->phy_configure, smc_phy_configure, dev);
 	lp->mii.phy_id_mask = 0x1f;
_