Простой обработчик прерываний: запрос irq возвращает код ошибки -22

Я пишу простой модуль ядра, который может зарегистрировать прерывание и обработать его. Однако, когда я пытаюсь зарегистрировать прерывание, вызывая функцию request_irq, она возвращает код ошибки -22 :

ошибка: не удается запросить IRQ 30-code -22, EIO 5, EINVAL 22

Я считаю, что этот код ошибки равен EINVAL (недопустимый аргумент)

Пожалуйста, скажи мне, что я делаю неправильно. Вот модуль:

#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 theren");
}

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 %dn", ret, EIO, EINVAL);
    }

    printk("CLCDINT_INITn");
    return 0;
}

module_init(clcdint_init);

static void __exit
clcdint_exit(void)
{
    unsigned int irq;
    irq=68;
    free_irq(irq, NULL);
    printk("CLCDINT_EXITn");
}

module_exit(clcdint_exit);

2 ответов


вы не можете передать нулевой контекст (последние параметры вызова request_irq ()) при работе с общей линией прерывания (флаг IRQF_SHARED включен).

чтобы понять почему, рассмотрим следующий сценарий: у вас есть две одинаковые сетевые карты, разделяющих один и тот же IRQ. Тот же драйвер передаст ту же функцию обработчика прерываний, тот же номер irq и то же описание. Невозможно провести различие между двумя экземплярами регистрации, кроме как через контекст параметр.

поэтому, в качестве меры предосторожности, вы не можете передать нулевой параметр контекста, если вы передаете флаг IRQF_SHARED.


irqflags имеет вид unsigned int, но первоначально он имел тип long.

попробуйте следующее утверждение, оно определенно будет работать:

request_irq(irq, int068_interrupt,IRQF_SHARED | IRQF_NO_SUSPEND, "clcdint-int068", NULL);