patch-2.4.0-prerelease linux/drivers/net/atarilance.c

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

diff -u --recursive --new-file v2.4.0-test12/linux/drivers/net/atarilance.c linux/drivers/net/atarilance.c
@@ -119,6 +119,8 @@
 #define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
 #define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
 
+#define TX_TIMEOUT	20
+
 /* The LANCE Rx and Tx ring descriptors. */
 struct lance_rx_head {
 	unsigned short			base;		/* Low word of base addr */
@@ -220,14 +222,14 @@
 	enum lance_type		cardtype;
 	struct lance_ioreg	*iobase;
 	struct lance_memory	*mem;
-	int					cur_rx, cur_tx;	/* The next free ring entry */
-	int					dirty_tx;		/* Ring entries to be freed. */
-						/* copy function */
-	void				*(*memcpy_f)( void *, const void *, size_t );
+	int		 	cur_rx, cur_tx;	/* The next free ring entry */
+	int			dirty_tx;		/* Ring entries to be freed. */
+				/* copy function */
+	void			*(*memcpy_f)( void *, const void *, size_t );
 	struct net_device_stats stats;
-/* These two must be ints for set_bit() */
-	int					tx_full;
-	int					lock;
+/* This must be long for set_bit() */
+	long			tx_full;
+	spinlock_t		devlock;
 };
 
 /* I/O register access macros */
@@ -350,6 +352,7 @@
 static struct net_device_stats *lance_get_stats( struct net_device *dev );
 static void set_multicast_list( struct net_device *dev );
 static int lance_set_mac_address( struct net_device *dev, void *addr );
+static void lance_tx_timeout (struct net_device *dev);
 
 /************************* End of Prototypes **************************/
 
@@ -446,7 +449,7 @@
 
 
 static unsigned long __init lance_probe1( struct net_device *dev,
-								   struct lance_addr *init_rec )
+					   struct lance_addr *init_rec )
 {
 	volatile unsigned short *memaddr =
 		(volatile unsigned short *)init_rec->memaddr;
@@ -590,6 +593,8 @@
 		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );
 	}
 
+	lp->devlock = SPIN_LOCK_UNLOCKED;
+
 	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */
 	for( i = 0; i < 6; i++ )
 		MEM->init.hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
@@ -617,7 +622,15 @@
 	dev->get_stats = &lance_get_stats;
 	dev->set_multicast_list = &set_multicast_list;
 	dev->set_mac_address = &lance_set_mac_address;
+
+	/* XXX MSch */
+	dev->tx_timeout = lance_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+			
+
+#if 0
 	dev->start = 0;
+#endif
 
 	memset( &lp->stats, 0, sizeof(lp->stats) );
 
@@ -656,9 +669,7 @@
 	DREG = CSR0_STRT;
 	DREG = CSR0_INEA;
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue (dev);
 
 	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
 
@@ -674,7 +685,6 @@
 	int i;
 	unsigned offset;
 
-	lp->lock = 0;
 	lp->tx_full = 0;
 	lp->cur_rx = lp->cur_tx = 0;
 	lp->dirty_tx = 0;
@@ -714,29 +724,24 @@
 }
 
 
-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
-{	struct lance_private *lp = (struct lance_private *)dev->priv;
-	struct lance_ioreg	 *IO = lp->iobase;
-	int entry, len;
-	struct lance_tx_head *head;
-	unsigned long flags;
 
-	/* Transmitter timeout, serious problems. */
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 20)
-			return( 1 );
-		AREG = CSR0;
-		DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
-					  dev->name, DREG ));
-		DREG = CSR0_STOP;
-		/*
-		 * Always set BSWP after a STOP as STOP puts it back into
-		 * little endian mode.
-		 */
-		REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-		lp->stats.tx_errors++;
+static void lance_tx_timeout (struct net_device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	struct lance_ioreg	 *IO = lp->iobase;
+	
+	AREG = CSR0;
+	DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
+			  dev->name, DREG ));
+	DREG = CSR0_STOP;
+	/*
+	 * Always set BSWP after a STOP as STOP puts it back into
+	 * little endian mode.
+	 */
+	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
+	lp->stats.tx_errors++;
 #ifndef final_version
 		{	int i;
 			DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",
@@ -754,31 +759,29 @@
 							  -MEM->tx_head[i].length,
 							  MEM->tx_head[i].misc ));
 		}
-#endif
-		lance_init_ring(dev);
-		REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
+#endif 	 
+	/* XXX MSch: maybe purge/reinit ring here */
+	/* lance_restart, essentially */
+	lance_init_ring(dev);
+	REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
+	dev->trans_start = jiffies;
+	netif_start_queue (dev);
+}
 
-		dev->tbusy = 0;
-		dev->trans_start = jiffies;
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
-		return( 0 );
-	}
+static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	struct lance_ioreg	 *IO = lp->iobase;
+	int entry, len;
+	struct lance_tx_head *head;
+	unsigned long flags;
 
 	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
 				  dev->name, DREG ));
 
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit( 0, (void*)&dev->tbusy ) != 0) {
-		DPRINTK( 0, ( "%s: Transmitter access conflict.\n", dev->name ));
-		return 1;
-	}
-
-	if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {
-		DPRINTK( 0, ( "%s: tx queue lock!.\n", dev->name ));
-		/* don't clear dev->tbusy flag. */
-		return 1;
-	}
+	netif_stop_queue (dev);
 
 	/* Fill in a Tx ring entry */
 	if (lance_debug >= 3) {
@@ -797,8 +800,7 @@
 
 	/* We're not prepared for the int until the last flags are set/reset. And
 	 * the int may happen already after setting the OWN_CHIP... */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave (&lp->devlock, flags);
 
 	/* Mask to ring buffer boundary. */
 	entry = lp->cur_tx & TX_RING_MOD_MASK;
@@ -830,13 +832,12 @@
 	DREG = CSR0_INEA | CSR0_TDMD;
 	dev->trans_start = jiffies;
 
-	lp->lock = 0;
 	if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
 		TMD1_OWN_HOST)
-		dev->tbusy = 0;
+		netif_start_queue (dev);
 	else
 		lp->tx_full = 1;
-	restore_flags(flags);
+	spin_unlock_irqrestore (&lp->devlock, flags);
 
 	return 0;
 }
@@ -857,11 +858,9 @@
 
 	lp = (struct lance_private *)dev->priv;
 	IO = lp->iobase;
-	AREG = CSR0;
+	spin_lock (&lp->devlock);
 
-	if (dev->interrupt)
-		DPRINTK( 2, ( "%s: Re-entering the interrupt handler.\n", dev->name ));
-	dev->interrupt = 1;
+	AREG = CSR0;
 
 	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
 		   --boguscnt >= 0) {
@@ -908,6 +907,8 @@
 						lp->stats.collisions++;
 					lp->stats.tx_packets++;
 				}
+
+				/* XXX MSch: free skb?? */
 				dirty_tx++;
 			}
 
@@ -920,12 +921,11 @@
 			}
 #endif
 
-			if (lp->tx_full && dev->tbusy
+			if (lp->tx_full && (netif_queue_stopped(dev))
 				&& dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
 				/* The ring is no longer full, clear tbusy. */
 				lp->tx_full = 0;
-				dev->tbusy = 0;
-				mark_bh( NET_BH );
+				netif_wake_queue (dev);
 			}
 
 			lp->dirty_tx = dirty_tx;
@@ -948,8 +948,8 @@
 
 	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
 				  dev->name, DREG ));
-	dev->interrupt = 0;
-	return;
+
+	spin_unlock (&lp->devlock);
 }
 
 
@@ -1051,8 +1051,7 @@
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue (dev);
 
 	AREG = CSR0;
 
@@ -1087,7 +1086,7 @@
 {	struct lance_private *lp = (struct lance_private *)dev->priv;
 	struct lance_ioreg	 *IO = lp->iobase;
 
-	if (!dev->start)
+	if (netif_running(dev))
 		/* Only possible if board is already started */
 		return;
 
@@ -1133,7 +1132,7 @@
 	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
 		return( -EOPNOTSUPP );
 
-	if (dev->start) {
+	if (netif_running(dev)) {
 		/* Only possible while card isn't started */
 		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
 					  dev->name ));

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