diff options
Diffstat (limited to 'drivers/net/7990.c')
-rw-r--r-- | drivers/net/7990.c | 96 |
1 files changed, 45 insertions, 51 deletions
diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 118f92af3..1c53a8a4c 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -100,7 +100,6 @@ static void load_csrs (struct lance_private *lp) /* #define to 0 or 1 appropriately */ #define DEBUG_IRING 0 /* Set up the Lance Rx and Tx rings and the init block */ -/* Sets dev->tbusy */ static void lance_init_ring (struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; @@ -111,8 +110,6 @@ static void lance_init_ring (struct net_device *dev) aib = lp->lance_init_block; - /* Lock out other processes while setting up hardware */ - dev->tbusy = 1; lp->rx_new = lp->tx_new = 0; lp->rx_old = lp->tx_old = 0; @@ -143,6 +140,7 @@ static void lance_init_ring (struct net_device *dev) if (DEBUG_IRING) printk ("TX rings:\n"); + lp->tx_full = 0; /* Setup the Tx ring entries */ for (i = 0; i < (1<<lp->lance_log_tx_bufs); i++) { leptr = LANCE_ADDR(&aib->tx_buf[i][0]); @@ -232,9 +230,6 @@ static int lance_reset (struct net_device *dev) load_csrs (lp); lance_init_ring (dev); dev->trans_start = jiffies; - dev->interrupt = 0; - dev->start = 1; - dev->tbusy = 0; status = init_restart_lance (lp); #ifdef DEBUG_DRIVER printk ("Lance restart=%d\n", status); @@ -409,19 +404,18 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) struct lance_private *lp = (struct lance_private *)dev->priv; int csr0; DECLARE_LL; - + + spin_lock (&lp->devlock); + WRITERAP(LE_CSR0); /* LANCE Controller Status */ csr0 = READRDP(); PRINT_RINGS(); - if (!(csr0 & LE_C0_INTR)) /* Check if any interrupt has */ + if (!(csr0 & LE_C0_INTR)) { /* Check if any interrupt has */ + spin_lock (&lp->devlock); return; /* been generated by the Lance. */ - - if (dev->interrupt) - printk ("%s: again", dev->name); - - dev->interrupt = 1; + } /* Acknowledge all the interrupt sources ASAP */ WRITERDP(csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT)); @@ -449,27 +443,32 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs) WRITERDP(LE_C0_STRT); } - if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { - dev->tbusy = 0; - mark_bh (NET_BH); + if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) { + lp->tx_full = 0; + netif_wake_queue (dev); } WRITERAP(LE_CSR0); WRITERDP(LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA); - - dev->interrupt = 0; + + spin_unlock (&lp->devlock); } int lance_open (struct net_device *dev) { struct lance_private *lp = (struct lance_private *)dev->priv; + int res; DECLARE_LL; /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */ if (request_irq(lp->irq, lance_interrupt, 0, lp->name, dev)) return -EAGAIN; - return lance_reset(dev); + res = lance_reset(dev); + lp->devlock = SPIN_LOCK_UNLOCKED; + netif_start_queue (dev); + + return res; } int lance_close (struct net_device *dev) @@ -477,8 +476,7 @@ int lance_close (struct net_device *dev) struct lance_private *lp = (struct lance_private *) dev->priv; DECLARE_LL; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue (dev); /* Stop the LANCE */ WRITERAP(LE_CSR0); @@ -489,41 +487,30 @@ int lance_close (struct net_device *dev) return 0; } +void lance_tx_timeout(struct net_device *dev) +{ + printk("lance_tx_timeout\n"); + lance_reset(dev); + dev->trans_start = jiffies; + netif_start_queue (dev); +} + + int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) { struct lance_private *lp = (struct lance_private *)dev->priv; volatile struct lance_init_block *ib = lp->init_block; int entry, skblen, len; - int status = 0; static int outs; + unsigned long flags; DECLARE_LL; - lance_reset(dev); - - /* Transmitter timeout, serious problems */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - - if (tickssofar < 100) { - status = -1; - } else { - printk ("%s: transmit timed out, status %04x, resetting\n", - dev->name, READRDP()); - lance_reset (dev); - } - return status; - } - - /* Block a timer-based transmit from overlapping. */ - if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) { - printk ("Transmitter access conflict.\n"); + if (!TX_BUFFS_AVAIL) return -1; - } - skblen = skb->len; + netif_stop_queue (dev); - if (!TX_BUFFS_AVAIL) - return -1; + skblen = skb->len; #ifdef DEBUG_DRIVER /* dump the packet */ @@ -554,10 +541,14 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; dev_kfree_skb (skb); + spin_lock_irqsave (&lp->devlock, flags); if (TX_BUFFS_AVAIL) - dev->tbusy = 0; + netif_start_queue (dev); + else + lp->tx_full = 1; + spin_unlock_irqrestore (&lp->devlock, flags); - return status; + return 0; } struct net_device_stats *lance_get_stats (struct net_device *dev) @@ -623,11 +614,12 @@ void lance_set_multicast (struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib = lp->init_block; + int stopped; DECLARE_LL; - while (dev->tbusy) - schedule(); - set_bit (0, (void *) &dev->tbusy); + stopped = netif_queue_stopped(dev); + if (!stopped) + netif_stop_queue (dev); while (lp->tx_old != lp->tx_new) schedule(); @@ -644,6 +636,8 @@ void lance_set_multicast (struct net_device *dev) } load_csrs (lp); init_restart_lance (lp); - dev->tbusy = 0; + + if (!stopped) + netif_start_queue (dev); } |