Andrea Arcangeli (andrea@suse.de)
Thu, 19 Aug 1999 02:04:39 +0200 (CEST)
Some day ago I received the below patch from Egbert. He reported me that
the parport irq probing for ECP was working _fine_ but only by using two
probe_irq_on() in the irq-probing code. At the _second_ run of
probe_irq_on() the irq was detected correctly (the first probe was
failing).
Egbert is right in telling that "Somehow probe_irq_on() got spurious
interrupts from the parport device.". The problem is that the interrupt
was pending before probe_irq_on got run. So it wasn't a random/spurious
interrupt, but it was a _well_ known interrupt waiting to be run.
We still don't know how the interrupt got generated in the parallel port,
but IMO it would be better to handle the case where there is an interrupt
pending for the device we are going to irq-probe. It may be possible to
trigger irqs by disconnecting/connecting cables for example (I know the
user shouldn't do that but being robust against such things is nicer
IMHO). Probably in our case the irq is generated by mistake by parport_pc
doing some probe on Egbert's hardware (I suppose other hardware doesn't
show the same behaviour since the ECP-irq-probe is reported working
somewhere in the source code.. ;).
So my idea is been to change the irq-probe logic enabling all not
registered irqs and then waiting some time (20msec) with the irqs unmasked
to allow longstanding-pending-irqs to trigger before going to check
for spurious interrupts. (works for Egbert on 2.2.x)
(the patch will apply cleanly in both 2.2.x and 2.3.x)
Comments?
diff -urN 2.3.14-pre2/arch/i386/kernel/irq.c 2.3.14-pre2-probeirq/arch/i386/kernel/irq.c
--- 2.3.14-pre2/arch/i386/kernel/irq.c Thu Aug 12 02:53:17 1999
+++ 2.3.14-pre2-probeirq/arch/i386/kernel/irq.c Thu Aug 19 01:37:05 1999
@@ -960,8 +960,24 @@
unsigned int i;
unsigned long delay;
+ /*
+ * something may have generated an irq long ago and we want to
+ * flush such a longstanding irq before considering it as spurious.
+ */
+ spin_lock_irq(&irq_controller_lock);
+ for (i = NR_IRQS-1; i > 0; i--)
+ if (!irq_desc[i].action)
+ irq_desc[i].handler->startup(i);
+ spin_unlock_irq(&irq_controller_lock);
+
+ /* Wait for longstanding interrupts to trigger. */
+ for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+ /* about 20ms delay */ synchronize_irq();
+
/*
- * first, enable any unassigned irqs
+ * enable any unassigned irqs
+ * (we must startup again here because if a longstanding irq
+ * happened in the previous stage, it may have masked itself)
*/
spin_lock_irq(&irq_controller_lock);
for (i = NR_IRQS-1; i > 0; i--) {
Andrea
The below one is the fix sent me by Egbert in his original email.
---------- Forwarded message ----------
*** parport_pc.c.org Wed Jun 2 01:43:43 1999
--- parport_pc.c Mon Aug 16 02:42:55 1999
***************
*** 612,617 ****
--- 612,623 ----
int irqs, i;
sti();
+ /*
+ * Hack to catch spurious interrupts.
+ */
+ irqs = probe_irq_on();
+ probe_irq_off(irqs);
+
irqs = probe_irq_on();
parport_pc_write_econtrol(pb, 0x00); /* Reset FIFO */
***************
*** 648,653 ****
--- 654,665 ----
oecr = parport_pc_read_econtrol(pb);
sti();
+ /*
+ * Hack to catch spurious interrupts.
+ */
+ irqs = probe_irq_on();
+ probe_irq_off(irqs);
+
irqs = probe_irq_on();
if (pb->modes & PARPORT_MODE_PCECR)
-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2.0b3 on Wed 18 Aug 1999 - 20:11:15 EDT