Re: Shared Interrupts - PCI

Linus Torvalds (Linus.Torvalds@cs.helsinki.fi)
Wed, 5 Jul 1995 11:16:32 +0300


"Theodore Ts'o": "Re: Shared Interrupts - PCI" (Jul 4, 13:01):
> Date: Mon, 3 Jul 1995 15:42:28 +0200 (MET DST)
> From: Kurt Wachmann <Kurt.Wachmann@netman.dk>
>
> Is it possible to first acknowledge the interrupt and then scan for
> devices to service on this interrupt. This way you may get an interrupt
> that has already been serviced, but you will never loose any service
> requests.
>
> We are acknowledging the interrupt first and then scanning for devices
> to service on the interrupt. However, this doesn't seem to prevent the
> problem, from empiracal observation.
>
> I confess that I haven't made a detailed study of the PC hardware
> architecture to figure out why it doesn't work, but nevertheless, it
> doesn't work.

The reason it doesn't work is that the interrupt controllers are set up
to be edge-sensitive, and the controller won't notice a new interrupt
even if it has been acknowledged if the irq line doesn't go down in
between the ack and the new interrupt.

So with two serial cards sharing the same interrupt:

- card 2 asserts irq. Controller reacts, tells the CPU about it
- CPU acks the interrupt, masks the irq, and starts the interrupt.
- card 1 hasn't posted anything, so the interrupt routine skips it and
goes on to handle card 2 (correctly).
- card 1 asserts irq just before the interrupt routine reads the status
from card 2. irq line stays asserted.
- irq handler reads status from card 2, de-asserting card 2's irq.
- the interrupt controller never notices the pending interrupt, as the
irq line never went down.
- if the shared interrupt handler now doesn't go back to check card 1,
we'll never get any more interrupts on that irq because the irq
controller has decided that although the irq line is asserted, it
won't react to it.

Anyway, it's easy enough to program the irq controller to do
level-triggered interrupts, but the problem with this is that some of
the hardware doesn't like that. Notably, the timer irq is often
connected to a square wave generator, so if we have level-triggered
interrupts, we will get timer interrupts 50% of the time rather than
just once per timer tick.

On EISA and PCI machines, you can program the controller to do
level/egde triggering on a per-irq basis, so you can program those
interrupts that you expect to share as level-triggered, and program the
timer irq to be edge-triggered.

Linus