DocValle DocValle - 1 year ago 113
C Question

Interrupt-handling within kernel-module: request_irq() returns -22, Invalid Parameter

I'm trying to set up an interrupt-handler within a kernel-module that gets triggered by a gpio-interrupt, but it seems that I don't use the

-function right...
I'm getting my irq-number via
and this seems to work.
Then I'm calling

request_irq(irqNumber, handler, 0, "GPIO_Test", NULL);

but It returns -22, Invalid parameters.
I think it might be the handler-function because I'm not sure about it's signature - Sometimes it's defined as
void handler (int irq, void *dev_id, struct pt_regs *regs)
, sometimes as
static irqreturn_t handler(int irq, void *data)
- Which one is the correct one to use in this case and why are there these two totally different variations?
I tried both, but always got the same Invalid-parameters-error.

The compiler gives me a warning about the return-type of my handler-function:
when using:

static irqreturn_t handler(int irq, void *data)


»irq_handler_t« expected, but argument has type »enum irqreturn_t (* (*)(int, void *))(int, void *)«

...and when using:

void handler (int irq, void *dev_id, struct pt_regs *regs){/*interrupt-handling*/}

»irq_handler_t« expected, but argument has type »void (*)(int, void *, struct pt_regs *)«

Thank you for your support ;)

pah pah
Answer Source

The issue (-EINVAL) isn't being caused by the handler, as there's no way for the kernel to determine its signature at runtime.

Also, handler is never called while requesting an IRQ via request_irq() (unless CONFIG_DEBUG_SHIRQ_FIXME is defined, and [with the wrong signature] that would only lead to undefined behaviour AFTER parameter validation, not before, so it would be very unlikely to return an -EINVAL at this point).

There are 4 key points that are validated before an IRQ is properly setup:

  • irqflags - You've none set, that passes the check.
  • irq_to_desc() - Will perform a lookup over irq_desc_tree for irq. Will return -EINVAL if not found. Otherwise, returns a pointer to an irq descriptor structure (struct irq_desc *)
  • irq_settings_can_request() - Check if the IRQ can be requested. You can easily rule out this by calling int can_request_irq(unsigned int irq, unsigned long irqflags) before request_irq().
  • handler - Will check if handler is NULL. In your case, it is not.

So basically you've only two possible checks that may be causing the issue, and one of them you can easily rule out using can_request_irq() before calling request_irq().

If can_request_irq() check passes, the only check that is causing the issue is irq_to_desc(), meaning that irq is invalid.

Can't extended this answer much more, as there's no more information I can work with from your question, but I hope it helps you to get in the right track.

By the way, just to point out the typedef of irq_handler_t in the case it may be useful:

include/linux/interrupt.h:92 (on 4.5 tree):

typedef irqreturn_t (*irq_handler_t)(int, void *);