Re: better leve triggered IRQ management needed

From: Linus Torvalds
Date: Sun Apr 30 2006 - 02:59:09 EST




On Sun, 30 Apr 2006, Neil Brown wrote:
>
> The thing is: This is exactly what I am currently doing to solve the
> problem.

I'm not entirely surprised. As mentioned, the ELCR register _originally_
selected between EISA (level) and ISA (edge) interrupts.

But EISA (and later PCI) interrupts were not just level, they were level
active _low_. While old ISA interrupts are edge-triggered, active _high_.

Which explains why it not only changes the trigger, but also the polarity.

Now, fast-forward a decade or two, and imagine that the world is 99% PCI,
and nobody really has any devices that are _electrically_ ISA any more,
but there are some legacy stuff that _looks_ like ISA. What would you do
to simplify your life from a hw perspective?

I suspect that the thing to do is to internally just say that all
interrupts are active low. There's no reason to _really_ have active high,
because there are no real devices left that drive the irq line that way.

Now, the _sane_ thing to do would be to also make all interrupts be
level-triggered, and make the whole ELCR register be a total dummy
register. But you can't really do that without being worried about
breaking compatibility (for example, the timer interrupt is a 50%
duty-cycle on/off thing, so it really _does_ end up being edge-triggered).

So you leave the ELCR register mattering for a edge/level thing, but the
polarity issue is just gone.

But then on _other_ southbridges, you'll have the old behaviour, and there
simply is no way for the OS to know. Yeah, we could look at the
nortbridge and southbridge combination, and perhaps know that some of them
always have a "active low" polarity regardless of ELCR. But nobody even
_documents_ these things, exactly because it's not supposed to matter.

So we're kind of screwed. We have to _act_ as if we still lived in the
middle ages, and people still used edge-triggered active-high interrupts.
Even when it's not necessarily the case any more..

Gaah.

That said, I'm surprised that the kernel doesn't set ELCR for you. If it
sees a PCI device, it really should know that it's a PCI interrupt. I
wonder if we should do the following.. (Does this automatically make it do
the right thing on your machine?)

Linus

---
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 7323544..6e3eaef 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -881,6 +881,7 @@ static int pcibios_lookup_irq(struct pci
((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
DBG(" -> got IRQ %d\n", irq);
msg = "Found";
+ eisa_set_level_irq(newirq);
} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
DBG(" -> assigning IRQ %d", newirq);
if (r->set(pirq_router_dev, dev, pirq, newirq)) {
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/