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
- Lines: 290
- Date:
Fri Dec 29 14:07:22 2000
- Orig file:
v2.4.0-test12/linux/drivers/net/atarilance.c
- Orig date:
Sun Nov 19 18:44:10 2000
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)