Level Triggered Interrupts

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

Interrupt Linux Kernel
Figure 14-6: Code flow diagram for handle_level_irq.

Note that level-triggered interrupts must be masked when they are processed, so the first thing that needs to be done is to call mask_ack_irq. This auxiliary function masks and acknowledges the IRQ by either calling chip->mask_ack or, if this is not available, chip->mask and chip->ack consecutively. On multiprocessor systems, a race condition might occur such that handle_edge_irq is called although the IRQ is already processed on another CPU. This can be detected by checking for the irq_inprogress flag, and the routine can immediately be left — the IRQ is already being processed on another CPU, in this case.

If no handler is registered for the IRQ, processing can also be aborted — there is nothing to do. One more reason to abort processing is when irq_disabled is set. Despite being disabled, broken hardware could nevertheless issue the IRQ, but it can be ignored.

Then the proper processing starts. irq_inprogress is set to signal that the IRQ is being processed, and the actual work is delegated to handle_IRQ_event. This triggers the high-level ISRs, as discussed below. The irq_inprogress can be removed after the ISRs are finished.

Finally, the IRQ needs to be unmasked. However, the kernel needs to consider that an ISR could have disabled the interrupt, and in this case, it needs to remain masked. Otherwise, the chip-specific unmask function chip->unmask is used.

Continue reading here: Other Types of Interrupts

Was this article helpful?

0 0