Messages in this thread Patch in this message | | | Date | Thu, 19 Aug 1999 02:04:39 +0200 (CEST) | From | Andrea Arcangeli <> | Subject | [patch] i386 longstanding irqs may be mistaken with spurious irqs |
| |
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 from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |