3c59x.c stops interrupting on 2.1.103

Richard B. Johnson (root@chaos.analogic.com)
Wed, 27 May 1998 15:42:28 -0400 (EDT)


I am not very proud of this patch.
#include<disclaimer.h>

This patch "fixes" the problem with the 3c59x driver eventually dying
by failing to interrupt on a non-SMP Machine. My SMP machine works
fine with the unmodified driver (also works with the modified one).

Basically, I moved the test for additional interrupt status so that
any pending status will not be acked until it is actually acted upon.
Then I acked all possible interrupts, rather than just the ones with
bits set.

--- linux-2.1.103/drivers/net/3c59x.c.orig Wed May 27 13:23:50 1998
+++ linux-2.1.103/drivers/net/3c59x.c Wed May 27 15:28:30 1998
@@ -1482,14 +1482,14 @@
latency = inb(ioaddr + Timer);
lp = (struct vortex_private *)dev->priv;

- status = inw(ioaddr + EL3_STATUS);
-
- if (vortex_debug > 4)
+ while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete))
+ {
+ if (vortex_debug > 4)
printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name,
status, latency);
#ifdef notdef
/* This code guard against bogus hangs, but fails with shared IRQs. */
- if ((status & ~0xE000) == 0x0000) {
+ if ((status & ~0xE000) == 0x0000) {
static int donedidthis=0;
/* Some interrupt controllers store a bogus interrupt from boot-time.
Ignore a single early interrupt, but don't hang the machine for
@@ -1499,25 +1499,24 @@
dev->name, status, dev->start);
FREE_IRQ(dev->irq, dev);
}
- }
+ }
#endif

- do {
- if (vortex_debug > 5)
- printk("%s: In interrupt loop, status %4.4x.\n",
+ if (vortex_debug > 5)
+ printk("%s: In interrupt loop, status %4.4x.\n",
dev->name, status);
- if (status & RxComplete)
+ if (status & RxComplete)
vortex_rx(dev);

- if (status & TxAvailable) {
- if (vortex_debug > 5)
- printk(" TX room bit was handled.\n");
- /* There's room in the FIFO for a full-sized packet. */
+ if (status & TxAvailable) {
+ if (vortex_debug > 5)
+ printk(" TX room bit was handled.\n");
+ /* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
dev->tbusy = 0;
mark_bh(NET_BH);
- }
- if (status & TxComplete) { /* Really "TxError" for us. */
+ }
+ if (status & TxComplete) { /* Really "TxError" for us. */
unsigned char tx_status = inb(ioaddr + TxStatus);
/* Presumably a tx-timeout. We must merely re-enable. */
if (vortex_debug > 2
@@ -1528,9 +1527,9 @@
if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
outb(0, ioaddr + TxStatus);
outw(TxEnable, ioaddr + EL3_CMD);
- }
- if (status & DownComplete) {
- unsigned int dirty_tx = lp->dirty_tx;
+ }
+ if (status & DownComplete) {
+ unsigned int dirty_tx = lp->dirty_tx;

while (lp->cur_tx - dirty_tx > 0) {
int entry = dirty_tx % TX_RING_SIZE;
@@ -1551,20 +1550,20 @@
dev->tbusy = 0;
mark_bh(NET_BH);
}
- }
+ }
#ifdef VORTEX_BUS_MASTER
- if (status & DMADone) {
+ if (status & DMADone) {
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
dev->tbusy = 0;
dev_kfree_skb (lp->tx_skb); /* Release the transfered buffer */
mark_bh(NET_BH);
- }
+ }
#endif
- if (status & UpComplete) {
+ if (status & UpComplete) {
boomerang_rx(dev);
outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
- }
- if (status & (AdapterFailure | RxEarly | StatsFull)) {
+ }
+ if (status & (AdapterFailure | RxEarly | StatsFull)) {
/* Handle all uncommon interrupts at once. */
if (status & RxEarly) { /* Rx early is unused. */
vortex_rx(dev);
@@ -1630,19 +1629,21 @@
}
}

+ /* Acknowledge all possible IRQs. */
+#if 1
+ outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
+#else
+ outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+#endif
if (--i < 0) {
printk("%s: Too much work in interrupt, status %4.4x. "
"Disabling functions (%4.4x).\n",
dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
/* Disable all pending interrupts. */
outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
- outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
break;
}
- /* Acknowledge the IRQ. */
- outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
-
- } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+ }

if (vortex_debug > 4)
printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status);

Cheers,
Dick Johnson
***** FILE SYSTEM MODIFIED *****
Penguin : Linux version 2.1.103 on an i586 machine (66.15 BogoMips).
Warning : It's hard to remain at the trailing edge of technology.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu