summaryrefslogtreecommitdiffstats
path: root/drivers/net/7990.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/7990.c')
-rw-r--r--drivers/net/7990.c96
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);
}