When request_irq() fails with -EINVAL

This post was written by eli on October 17, 2011
Posted Under: ARM,Linux kernel

It may help investigating the interrupt descriptors. For a 2.6.38 kernel, putting this in a kernel module load supplies some information (includes, declarations and code mixed below. Organize properly in your own module)

#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/irq.h>

int i;
struct irq_desc *desc;

for_each_irq_desc(i, desc) {
 if (!desc)
   continue;
 printk(KERN_INFO "%d: status=%08x, chip=%08x, handle_irq=%08x\n",
        i, (u32) desc->status, (u32) desc->chip, (u32) desc->handle_irq );
 }

This dumps some meta information about all possible IRQs on the system. Also be sure to look at /proc/interrupts.

Have a look in include/linux/irq.h for the meaning of the flags in desc->status and possibly include/linux/irqdesc.h for the irq_desc structure.

request_irq() may very well fail because the IRQ_NOREQUEST flag was set in status. On ARM architecture, this can be fixed by calling set_irq_flags(irq, IRQF_VALID) assuming that you have a fairly good idea of what you’re doing.

Note that set_irq_chip_and_handler() is usually called before validating an IRQ, so that Linux knows what to do with the interrupt as it happens. Looking at chip and handle_irq in the dump may give a clue about how necessary this is. Searching for the value of handle_irq in /proc/kallsyms (with a simple grep) tells who handles each interrupt.

The “chip” structure is a container for information and methods specific to the interrupt’s owner. In old days, these belonged to peripheral chips, but a “chip” is many times just a group of interrupts having a common way of handling them (setting trigger type, masking etc.).

A final note: It looks like the API is changing vividly in this area, so don’t expect things to be exactly the same on other kernels.

Add a Comment

required, use real name
required, will not be published
optional, your blog address