Controlador de interrupción simple: request_irq devuelve el código de error-22
linux module (2)
No puede pasar un contexto NULL (últimos parámetros de la llamada request_irq ()) cuando se trata de una línea de interrupción compartida (el indicador IRQF_SHARED está activado).
Para comprender por qué, considere la siguiente situación: tiene dos tarjetas de red idénticas que comparten la misma IRQ. El mismo controlador pasará la misma función de controlador de interrupción, el mismo número irq y la misma descripción. No hay forma de distinguir las dos instancias del registro, excepto a través del parámetro de contexto.
Por lo tanto, como medida de precaución, no puede pasar un parámetro de contexto NULL si pasa el indicador IRQF_SHARED.
Estoy escribiendo un módulo kernel simple, que podría registrar una interrupción y manejarlo. Sin embargo, cuando intento registrar interrupt llamando a la función request_irq, devuelve el código de error -22:
ERROR: No se puede solicitar IRQ 30 - código -22, EIO 5, EINVAL 22
Creo que este código de error es igual a EINVAL (argumento no válido)
Por favor dime, lo que estoy haciendo mal. Aquí hay un módulo:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <asm/exception.h>
#include <asm/mach/irq.h>
void int068_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
printk("Interrupt should be handled there/n");
}
static int __init
clcdint_init(void)
{
unsigned int irq;
unsigned int irqflags;
int ret;
irq=68;
irqflags=IRQF_SHARED | IRQF_NO_SUSPEND;
ret = request_irq(irq, int068_interrupt,
irqflags, "clcdint-int068", NULL);
if (ret!=0) {
printk("ERROR: Cannot request IRQ %d", irq);
printk(" - code %d , EIO %d , EINVAL %d/n", ret, EIO, EINVAL);
}
printk("CLCDINT_INIT/n");
return 0;
}
module_init(clcdint_init);
static void __exit
clcdint_exit(void)
{
unsigned int irq;
irq=68;
free_irq(irq, NULL);
printk("CLCDINT_EXIT/n");
}
module_exit(clcdint_exit);
irqflags
tiene un tipo de unsigned int
, pero originalmente tenía un tipo long
.
Pruebe la siguiente declaración, definitivamente funcionará:
request_irq(irq, int068_interrupt,IRQF_SHARED | IRQF_NO_SUSPEND, "clcdint-int068", NULL);