Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 14: Kernel Activities


❑ set_irq_chipassociates an IRQ chip in the form of anirq_chipinstance with a specific inter-
rupt. Besides picking the proper element fromirq_descand setting thechippointer, the func-
tion also inserts default handler functions if no chip-specific implementation is supplied.
If aNULLpointer is given for the chip, then the generic ‘‘no controller’’ variantno_irq_chip,
which provides only no-op operations, is used.
❑ set_irq_handlerandset_irq_chained_handlerset the flow handler function for a given IRQ
number. The second variant is required to signal that the handler must deal with shared inter-
rupts. This enables the flagsIRQ_NOREQUESTandIRQ_NOPROBEinirq_desc[irq]->status:the
first one because shared interrupts cannot be reserved for exclusive use, and the second one
because it is obviously a bad idea to use interrupt probing on lines where multiple devices are
present.
Both functions use__set_irq_handlerinternally, which performs some sanity checks and sets
irq_desc[irq]->handle_irq.
❑ set_chip_and_handleris a convenient shortcut used instead of calling the functions discussed
above one after another. The_namevariant works identically, but allows for specifying a name
for the flow handler that is stored inirq_desc[irq]->name.

Flow Handling


Before discussing how flow handlers are implemented, we need to introduce the type used for them.
irq_flow_handler_tspecifies the signature of IRQ flow handler functions:

<irq.h>
typedef void fastcall (*irq_flow_handler_t)(unsigned int irq,
struct irq_desc *desc);
Flow handlers get both the IRQ number and a pointer to theirq_handlerinstance that is responsible for
the interrupt. This information can then be used to implement proper flow handling.

Recall that different hardware requires different approaches to flow handling — edge- and level-
triggering need to be dealt with differently, for instance. The kernel provides several default flow
handlers for various types. They have one thingin common: Every flow handler is responsible to
call the high-level ISRs once its work is finished.handle_IRQ_eventis responsible to activate the
high-level handlers; this is discussed this in Section 14.1.7. For now, let us examine how flow handling is
performed.

Edge-Triggered Interrupts


Edge-triggered interrupts are most common on the majority of today’s hardware, so I consider this
type first. The default handler is implemented inhandle_edge_irq. The code flow diagram is shown in
Figure 14-5.

Edge-triggered IRQs are not masked when they are processed — in contrast to level-triggered IRQs,
there is no need to do so. This has one important implication for SMP systems: When an IRQ is handled
on one CPU, another IRQ with the same number can appear on another CPU that we denote as thesecond
CPU. This implies that the flow handler will be called once more while it is still running on the CPU
that triggered the first IRQ. But why should two CPUs be engaged with running the same IRQ handler
simultaneously? The kernel wants to avoid this situation: The handler should only be processed on a
single CPU. The initial portion ofhandle_edge_irqhas to deal with this case. If theIRQ_INPROGRESS
flag is set, the IRQ is already being processed on another CPU. By setting theIRQ_PENDINGflag, the
Free download pdf