patch-2.4.3 linux/drivers/net/fmv18x.c

Next file: linux/drivers/net/hamachi.c
Previous file: linux/drivers/net/fc/iph5526.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.2/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c
@@ -52,6 +52,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/errno.h>
+#include <linux/spinlock.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -79,6 +80,7 @@
 	uint rx_started:1;			/* Packets are Rxing. */
 	uchar tx_queue;				/* Number of packet on the Tx queue. */
 	ushort tx_queue_len;		/* Current length of the Tx queue. */
+	spinlock_t lock;
 };
 
 
@@ -161,6 +163,7 @@
 	char irqmap[4] = {3, 7, 10, 15};
 	char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
 	unsigned int i, irq, retval;
+	struct net_local *lp;
 
 	/* Resetting the chip doesn't reset the ISA interface, so don't bother.
 	   That means we have to be careful with the register values we probe for.
@@ -268,6 +271,8 @@
 		goto out_irq;
 	}
 	memset(dev->priv, 0, sizeof(struct net_local));
+	lp = dev->priv;
+	spin_lock_init(&lp->lock);
 
 	dev->open		= net_open;
 	dev->stop		= net_close;
@@ -292,7 +297,7 @@
 
 static int net_open(struct net_device *dev)
 {
-	struct net_local *lp = (struct net_local *)dev->priv;
+	struct net_local *lp = dev->priv;
 	int ioaddr = dev->base_addr;
 
 	/* Set the configuration register 0 to 32K 100ns. byte-wide memory,
@@ -326,7 +331,7 @@
 
 static void net_timeout(struct net_device *dev)
 {
-	struct net_local *lp = (struct net_local *)dev->priv;
+	struct net_local *lp = dev->priv;
 	int ioaddr = dev->base_addr;
 	unsigned long flags;
 	
@@ -346,8 +351,7 @@
 		htons(inw(ioaddr+FJ_CONFIG0)));
 	lp->stats.tx_errors++;
 	/* ToDo: We should try to restart the adaptor... */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&lp->lock, flags);
 
 	/* Initialize LAN Controller and LAN Card */
 	outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
@@ -355,20 +359,21 @@
 	outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
 	outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
 	net_open(dev);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	netif_wake_queue(dev);
 }
 
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_local *lp = (struct net_local *)dev->priv;
+	struct net_local *lp = dev->priv;
 	int ioaddr = dev->base_addr;
 	short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 	unsigned char *buf = skb->data;
+	unsigned long flags;
 
 	/* Block a transmit from overlapping.  */
 	
-	netif_stop_queue(dev);
-	
 	if (length > ETH_FRAME_LEN) {
 		if (net_debug)
 			printk("%s: Attempting to send a large packet (%d bytes).\n",
@@ -383,6 +388,7 @@
 	   codes we possibly catch a Tx interrupt. Thus we flag off
 	   tx_queue_ready, so that we prevent the interrupt routine
 	   (net_interrupt) to start transmitting. */
+	spin_lock_irqsave(&lp->lock, flags);
 	lp->tx_queue_ready = 0;
 	{
 		outw(length, ioaddr + DATAPORT);
@@ -391,6 +397,8 @@
 		lp->tx_queue_len += length + 2;
 	}
 	lp->tx_queue_ready = 1;
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	if (lp->tx_started == 0) {
 		/* If the Tx is idle, always trigger a transmit. */
 		outb(0x80 | lp->tx_queue, ioaddr + TX_START);
@@ -398,10 +406,10 @@
 		lp->tx_queue_len = 0;
 		dev->trans_start = jiffies;
 		lp->tx_started = 1;
-		netif_wake_queue(dev);
 	} else if (lp->tx_queue_len < 4096 - 1502)
 		/* Yes, there is room for one more packet. */
-		netif_wake_queue(dev);
+	else
+		netif_stop_queue(dev);
 
 	dev_kfree_skb(skb);
 	return 0;
@@ -417,7 +425,7 @@
 	int ioaddr, status;
 
 	ioaddr = dev->base_addr;
-	lp = (struct net_local *)dev->priv;
+	lp = dev->priv;
 	status = inw(ioaddr + TX_STATUS);
 	outw(status, ioaddr + TX_STATUS);
 
@@ -447,6 +455,7 @@
 			lp->stats.collisions++;
 		}
 		if (status & 0x82) {
+			spin_lock(&lp->lock);
 			lp->stats.tx_packets++;
 			if (lp->tx_queue && lp->tx_queue_ready) {
 				outb(0x80 | lp->tx_queue, ioaddr + TX_START);
@@ -458,6 +467,7 @@
 				lp->tx_started = 0;
 				netif_wake_queue(dev);	/* Inform upper layers. */
 			}
+			spin_unlock(&lp->lock);
 		}
 	}
 	return;
@@ -466,7 +476,7 @@
 /* We have a good packet(s), get it/them out of the buffers. */
 static void net_rx(struct net_device *dev)
 {
-	struct net_local *lp = (struct net_local *)dev->priv;
+	struct net_local *lp = dev->priv;
 	int ioaddr = dev->base_addr;
 	int boguscount = 5;
 
@@ -581,7 +591,7 @@
    closed. */
 static struct net_device_stats *net_get_stats(struct net_device *dev)
 {
-	struct net_local *lp = (struct net_local *)dev->priv;
+	struct net_local *lp = dev->priv;
 	return &lp->stats;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)