[514] in linux-net channel archive
8390.c change for "Interrupted while interrupts are masked" msg
daemon@ATHENA.MIT.EDU (Ken Raeburn)
Thu Jun 15 21:20:23 1995
From: Ken Raeburn <raeburn@cygnus.com>
Date: Thu, 15 Jun 1995 20:41:23 -0400
To: linux-net@vger.rutgers.edu
Cc: dhinds@allegro.stanford.edu, Linus.Torvalds@helsinki.fi
Using my (NE2000-emulating) Socket EA card under pcmcia-cs-2.6.2 and
linux-1.2.10 on my NEC Versa M (486 DX/4, 75MHz), I see this message from
the 8390 driver now and then, mostly while doing large file transfers.
The reported ISR varies, but the IMR is always zero.
(I see the "too much work at interrupt" messages also now, but haven't
investigated those at all.)
My guess is that the "outb" to disable interrupts finishes (as far as the
CPU knows) before the card has actually completed the task of disabling
interrupts, leaving a race condition whereby an interrupt can come in just
after the "outb", sometimes after "irqlock" gets set. Whether my guess is
correct or not, this patch does seem to eliminate these messages. (The
linux-1.3.1 kernel appears to have the same driver code, almost exactly,
but I can't really try it out until umsdos is available.) I suspect the
"inb" is sufficient; I put in the test just to be paranoid.
I don't know if there's any significant performance cost to this patch.
My tests with ftp report such wildly varying transfer rates (at least on
this network, with our site's main fileserver as the remote end -- 100K/s
to 450K/s) that any variation between the two versions of the driver is
completely lost. Can someone else try it out under more controlled
conditions?
Ken
--- 8390.c.CLEAN Thu Jun 15 17:12:08 1995
+++ 8390.c Thu Jun 15 19:19:41 1995
@@ -128,7 +128,7 @@ static int ei_start_xmit(struct sk_buff
{
int e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
- int length, send_length;
+ int length, send_length, imr;
unsigned long flags;
/*
@@ -191,6 +191,11 @@ static int ei_start_xmit(struct sk_buff
/* Mask interrupts from the ethercard. */
outb(0x00, e8390_base + EN0_IMR);
+ /* Delay setting irqlock until card has settled. */
+ imr = inb (e8390_base + EN0_IMR);
+ if (imr != 0)
+ printk ("%s: Interrupt mask didn't take? (imr=0x%02x)\n",
+ dev->name, imr);
ei_local->irqlock = 1;
restore_flags(flags);