Managing IRQs

EVL has no specific API for managing out-of-band interrupts. The regular kernel API

  • with the Dovetail extensions - is still used for this purpose.

A real-time driver would most likely want to deal with incoming interrupt events coming from the device(s) it manages directly from the out-of-band stage, so that no delay is incurred. When registering an interrupt handler via the generic interrupt API routines, the interrupt type flag IRQF_OOB tells the underlying Dovetail layer that out-of-band handling is required. The registration calls accepting this flag are, namely:

  • setup_irq() for early registration of special interrupts
  • request_irq() for device interrupts
  • __request_percpu_irq() for per-CPU interrupts

An IRQ action handler bearing this flag runs on the out-of-band stage, regardless of the current interrupt state of the in-band stage. In other words, this handler may preempt any type of in-band activity, including sections of code which are normally deemed interrupt-free in-band wise.

Conversely, out-of-band handlers are dismissed using the usual calls, such as:

  • free_irq() for device interrupts
  • free_percpu_irq() for per-CPU interrupts

Out-of-band IRQ handling has the following constraints:

  • If the IRQ is shared, with multiple action handlers registered for the same event, all other handlers on the same interrupt channel must bear the IRQF_OOB flag too, or the request will fail.

Because meeting real-time requirements is your goal, sharing an IRQ line among multiple devices operating from different execution stages (in-band vs out-of-band) would not work out of the box. You might be able to resort to such sharing with some kludge, but only to address desperate situation with your hardware configuration.

  • Out-of-band handlers cannot be threaded (IRQF_NO_THREAD is implicit, IRQF_ONESHOT is ignored).

Installing an out-of-band handler for a device interrupt

#include <linux/interrupt.h>

static irqreturn_t oob_interrupt_handler(int irq, void *dev_id)
{
	...
	return IRQ_HANDLED;
}

init __init driver_init_routine(void)
{
	int ret;

	...
	ret = request_irq(DEVICE_IRQ, oob_interrupt_handler,
			  IRQF_OOB, "Out-of-band device IRQ",
			  device_data);
	if (ret)
		goto fail;

	return 0;
fail:
	/* Unwind upon error. */
	...
}

More details about how interrupts are managed and handled by Dovetail are available from this document.


int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *dev_name, void *dev)

Add a handler for a common device interrupt line, from the [generic IRQ API] (https://www.kernel.org/doc/html/latest/core-api/genericirq.html). OR’ing IRQF_OOB to the flags argument tells Dovetail to run the handler from the out-of-band stage immediately on interrupt receipt, which guarantees that no in-band activity can delay the event.

  • irq

    The interrupt line to request.

  • handler

    The routine to be called when the IRQ occurs.

  • flags

    A set of handling flags. For out-of-band interrupts, IRQF_OOB must be OR’ed into this value.

  • dev_name

    Name of the device generating this interrupt.

  • dev_id

    A cookie passed to the handler() identifying the device.

  • Returns zero on success, otherwise -EINVAL is returned if some parameter is invalid.


    int __request_percpu_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *dev_name, void __percpu *percpu_dev_id)

    Add a handler for a per-CPU device interrupt line, from the [generic IRQ API] (https://www.kernel.org/doc/html/latest/core-api/genericirq.html). OR’ing IRQF_OOB to the flags argument tells Dovetail to run the handler from the out-of-band stage immediately on interrupt receipt, which guarantees that no in-band activity can delay the event.

  • irq

    The interrupt line to request.

  • handler

    The routine to be called when the IRQ occurs.

  • flags

    A set of handling flags. For out-of-band interrupts, IRQF_OOB must be OR’ed into this value.

  • dev_name

    Name of the device generating this interrupt.

  • percpu_dev_id

    A per-CPU cookie passed to the handler() identifying the device.

  • Returns zero on success, otherwise -EINVAL is returned if some parameter is invalid.


    const void *free_irq(unsigned int irq)

    Release an interrupt line previously allocated with request_irq. This call can be used for out-of-band interrupts (IRQF_OOB).

  • irq

    The interrupt line to release.

  • The device name corresponding to the released interrupt line is returned on success, NULL otherwise if irq is invalid.


    void free_percpu_irq(unsigned int irq)

    Release a per-CPU interrupt line previously allocated with __request_percpu_irq. This call can be used for out-of-band interrupts (IRQF_OOB).

  • irq

    The interrupt line to release.


  • Last modified: Sat, 04 Mar 2023 16:43:20 +0100