Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 14: Kernel Activities


Calling the High-levelISR


Recall from above that the various flow handler routines all have one thing in common: They employ
handle_IRQ_eventto activate the high-level ISRs associated with a particular IRQ. The time has come to
examine this function a little more closly. The function requires the IRQ number and the action chain to
be passed as parameters:

kernel/irq/handle.c
irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);

handle_IRQ_eventperforms various actions:

❑ IfIRQF_DISABLEDwasnotset in the first handler function, the interrupts (for the current CPU)
are enabled withlocal_irq_enable_in_hardirq; in other words, the handlers can be inter-
rupted by other IRQs. However, depending on the flow type, it is possible that the IRQ just
processed is always masked out.
❑ Theactionfunctions of the registered IRQ handlers are invoked one after the other.
❑ IfIRQF_SAMPLE_RANDOMis set for the IRQ,add_interrupt_randomnessis called in order to use
the time of the event as a source for the entropy pool (interrupts are an ideal source if they occur
randomly).
❑ local_irq_disabledisables the interrupts. Because enabling and disabling of interrupts
is not nested, it is irrelevant whether they were enabled or not at the start of processing.
handle_IRQ_eventwas called with interrupts disabled, and is also expected to leave again with
interrupts disabled.

With shared IRQs the kernel has no way of finding out which device raised the request. This is left
entirely to the handler routines that use device-specific registers or other hardware characteristics to find
the source. Routines not affected also recognize that the interrupt was not intended for them and return
control as quickly as possible. Neither is there any way that a handler routine can report to higher-level
code that the interrupt was intended for it or not. The kernel always executesallhandler routines in turn,
regardless of whether the first or the last leads to success.

Nevertheless, the kernel can check whetheranyhandler was found to be responsible for the IRQ.
irqreturn_tis defined as the return type of handler functions and boils down to a simple integer
variable.ItacceptsthevalueIRQ_NONEorIRQ_HANDLED, depending on whether the IRQ was serviced by
the handler routine or not.

During servicing of all handler routines, the kernel combines the results with a logical ‘‘or’’ operation.
This is how it is finally able to determine whether the IRQ was serviced or not.

kernel/irq/handle.c
irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
{
...
do {
ret = action->handler(irq, action->dev_id);
if (ret == IRQ_HANDLED)
status |= action->flags;
retval |= ret;
action = action->next;
Free download pdf