Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 14: Kernel Activities


*/
if (unlikely((desc->status &
(IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
(IRQ_PENDING | IRQ_MASKED))) {
desc->chip->unmask(irq);
desc->status &= ~IRQ_MASKED;
}

desc->status &= ~IRQ_PENDING;
action_ret = handle_IRQ_event(irq, action);
} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);

Processing the IRQ runs in a loop. Suppose we are at the point right beneath the call to
handle_IRQ_event. While the ISR handlers for the firstIRQ were running, a second IRQ could
have appeared as shown before. This is indicated byIRQ_PENDING. If the flag is set (and the IRQ has not
been disabled in the meantime), another IRQ is waiting to be processed, and the loop is started again
from the beginning.

In this case, however, the IRQ will have beenmasked. The IRQ must thus be unmasked with
chip->unmaskand theIRQ_MASKEDflag be removed. This guarantees that only one interrupt can occur
during the execution ofhandle_IRQ_event.

After removing theIRQ_PENDINGflag — technically, one IRQ is still pending right now, but it is going to
be processed immediately —handle_IRQ_eventcan also serve the second IRQ.

Level-Triggered Interrupts


Level-triggered interrupts are alittle easier to process than their edge-triggered relatives. This is
also reflected in the code flow diagram of the flow handlerhandle_level_irq, which is depicted in
Figure 14-6.

Abort processing

No ISR registered or IRQ disabled? Abort processing

Set IRQ_INPROGRESS

Remove IRQ_INPROGRESS

Irq not disabled? chip->unmask

handle_level_irq

mask_ack_irq

IRQ_INPROGRESS?

handle_IRQ_event

Figure 14-6: Code flow diagram forhandle_level_irq.

Note that level-triggered interrupts must be masked when they are processed, so the first thing that
needstobedoneistocallmask_ack_irq. This auxiliary function masks and acknowledges the IRQ by
Free download pdf