Re: Level-Triggered Interrupt Advice Seeked.

Richard B. Johnson (root@chaos.analogic.com)
Mon, 13 Jul 1998 10:00:52 -0400 (EDT)


On Mon, 13 Jul 1998, Jason Wohlgemuth wrote:

> I was directed to this mailing list for advice on a question I
> initially posted on comp.linux.development.system.
>
> Basically, When an interrupt is set by a PCI card I am working
> with some memory registers on the card must be manipulated before
> the interrupt is ACK'd. From reading past posts and just looking
> around I have found that Linux handles things in this order: MASK
> irq, ACK irq, run handler, UNMASK irq.

This is probably a semantics problem. Acking the interrupt is "resetting
the in-service flag" so that a subsequent interrupt can be "stored".
It makes no difference if you are looking at edges or are using levels.

The APIC code is not very clear, and its documentation is very sparse.
However, its logical operation is similar to the operation of the
regular PC/AT controllers which are easy to understand. Therefore,
I will use this controller as an example.

Acking the interrupt means nothing to the device that caused the
interrupt. It cannot possibly know that this operation occurred.

The interrupt service routine for the device should do whatever is
necessary to reset its interrupt output line (bit). It can do this in any
necessary order, defined by the hardware the ISR services. When all
the conditions that caused the interrupt request are satisfied, the
interrupt output line will be reset. This wire is usually the OR of
all the bits in some status register that could cause an interrupt.

The interrupt "mask" for the controller is a GATE! It is logically
connected to the input of the controller.

Let's say your device raised its interrupt output bit which is routed
to the controller. Since this bit is not masked, it is applied to
the controller's input and, when priority conditions are satisfied,
it raises the interrupt pin of the CPU.

The CPU branches to the common routine, which handles the interrupt
controller. This routine masks off the interrupt, i.e., turns OFF
the input bit. It then resets the in-service flag so that another
interrupt on this level COULD be stored. It won't be stored yet
because the input line is disconnected by the masking operation.
This is the so-called ACK. Your device can't possibly know about
this operation nor be affected in any adverse way.

The routine then calls your ISR software which handles the needs
of the hardware. If you complete the requirements of the hardware,
its interrupt request bit will go low. If something changes while
your ISR is executing, i.e., new data are available, the hardware's
interrupt request bit may not stay low. It makes no difference.

Once your routine returns to the kernel's common routine, the
input to the controller is reconnected by UN-masking that interrupt
line. If the line is still high (a new interrupt has occurred), this
event will now be latched, and once priority conditions are satisfied,
the whole event occurs again. Because the input to the controller was
disconnected, the in-service latch is reset, then the input is
reconnected, these operations even produce a new "edge". You will
never lose any interrupts.

>
> I need to run the interrupt handler before the interrupt is ACK'd.

This cannot be true. Your interrupt handler doesn't care about the
interrupt controller. It needs to satisfy the requirements of your
hardware only. Your hardware cannot possibly "know" about the state
of the interrupt controller.

There are a lot of interrupt service routines within the kernel that
are not good templates. Many do things that they really don't need to
do, or shouldn't be doing, but they get away with it. A typical
example is this:

while((status = read_hardware_status()))
{
handler(status);
}

Such loops within ISRs remove the advantage of the prioritized
interrupt controller and allow a single device to take unfair
advantage of the whole machine.

The other most common problem is that writers insist upon enabling
interrupts within the interrupt service routines. There may be some
very special circumstances where this is necessary, but the problem
is that, regardless of how the routine is "protected" against
reentry, etc., once you enable interrupts, the CPU WILL BE TAKEN AWAY!
This means that a carefully coded routine that should execute in
a new hundred microseconds, now takes many milliseconds to execute.

Cheers,
Dick Johnson
***** FILE SYSTEM MODIFIED *****
Penguin : Linux version 2.1.108 on an i586 machine (66.15 BogoMips).
Warning : It's hard to remain at the trailing edge of technology.

-
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.altern.org/andrebalsa/doc/lkml-faq.html