Re: Shared Interrupts - PCI

Linus Torvalds (Linus.Torvalds@cs.helsinki.fi)
Thu, 29 Jun 1995 10:03:04 +0300


davies@wanton.lkg.dec.com: "Shared Interrupts - PCI" (Jun 28, 15:27):
>
> I don't believe Linux currently allows shared interrupts (at least
> across different drivers; it's easy to implement if one driver controls
> multiple hardware using one IRQ).
>
> PCI requires interrupts to be shareable and I've just come across a
> case where it's necessary.
>
> Are there plans to include shareable interrupts soon - allow multiple
> interrupt routines to be registered with the kernel??

Hmm... It would be reasonably easy to change the current array of
interrupt handlers to an array of a linked list of interrupt handlers:
essentially just add a "struct irqaction * next" to the definition of
irqaction, and make the irqactions be allocated dynamically when adding
a new irq.

It would _also_ require that
- everything that shares an irq has the same "flags" (the irq_request()
function could check this easily), especially as you can't reasonably
mix slow and fast interrupts on the same line.
- a driver that is willing to share would set a "IRQ_SHARE" flag in the
flags value, in addition to the current "IRQ_FAST" (hardcoded to 1
right now). This way a driver that isn't expecting to be able to
share an interrupt will result in the proper EBUSY if somebody else
is already using it (or a driver trying to share will get the EBUSY
when there already is an exclusive irq registered).

Anyway, with that kind of setup I'd certainly have no problems with a
shared irq setup. I'm sending this to tytso as well, because if he
agrees with this, the serial card interrupt handling stuff might be done
this way instead of being done inside the serial driver.

Uhh.. Another thing: it would probably be a good idea to add a
"unsigned long data" entry to request_irq(), and put that in the "struct
irqaction" as well, and call the interrupts with

asmlinkage void do_IRQ(int irq)
{
struct irqaction * action = irq_action[irq];

kstat.interrupts[irq]++;
while (action) {
action->handler(irq, data, &pt_regs);
action = action->next;
}
}

The serial interrupts could use "data" to point to the per-port
information block, and the network interrupts could use it to point to
the device structure (instead of doing a lookup according to irq number,
which doesn't work if two identical net devices share the same irq:
unlikely, but still)

Anyway, if anybody is interested in doing something like this, I'm all
for it. Just expand the "request_irq()" call something like this:

- "irqflags" needs to be something else than just 0/1
- add the "data" field.
- you probably want to make it return the "struct irqaction" pointer
instead of an error code (NULL for error), to be able to free it by
irqaction instead of the current "free_irq(irq)" (which would be
ambiguous).

If somebody wants to try to do something like this..

Linus