2013-03-06 8 views
9

Ich schreibe ein einfaches Kernel-Modul, das einen Interrupt registrieren und damit umgehen könnte. Allerdings, wenn ich versuche Interrupt zu registrieren, indem die request_irq Funktion aufrufen, es gibt Fehlercode -22:Einfache Interrupt-Handler: request_irq gibt Fehlercode -22

ERROR: Cannot request IRQ 30 - code -22 , EIO 5 , EINVAL 22

Ich glaube, dieser Fehlercode gleich EINVAL (ungültiges Argument)

Bitte sagen ich, was ich falsch mache. Hier ist ein Modul:

#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); 

Antwort

12

Sie können keine NULL-Kontext (letzte Parameter des request_irq() -Aufruf) passieren, wenn sie mit einer gemeinsamen Interrupt-Leitung handelt (IRQF_SHARED Flag aktiviert ist).

Um zu verstehen, warum das folgende Szenario in Betracht ziehen: Sie haben zwei identische Netzwerkkarten, die den gleichen IRQ teilen. Derselbe Treiber wird die gleiche Interrupt-Handler-Funktion, die gleiche IRQ-Nummer und die gleiche Beschreibung übergeben. Es gibt keine Möglichkeit, die beiden Instanzen der Registrierung zu unterscheiden, außer über den Kontextparameter.

Daher können Sie vorsichtshalber keinen NULL-Kontextparameter übergeben, wenn Sie das IRQF_SHARED-Flag übergeben.

+0

Vielen Dank! Nachdem ich 'irqflags = IRQF_NO_SUSPEND;' geändert habe, funktioniert es endlich! –

+0

Selbst nach dem Anwenden der Änderung, die im letzten Kommentar erwähnt wurde, bekomme ich immer noch die gleiche Fehlermeldung ("ERROR: Kann IRQ 68 nicht anfordern - Code -22, EIO 5, EINVAL 22"). Weißt du, was das verursachen kann? (Btw, ich benutze Kernel-Version 2.6.32, also einige der enthaltenen Dateien existiert hier nicht, vielleicht ist das relevant) – jaff

+0

Das Problem hatte mit der IRQ-Nummer zu tun. Nach dem Betrachten von http://www.webopedia.com/quick_ref/IRQnumbers.asp und Ändern der IRQ-Nummer auf 10, statt 0f 68, funktioniert alles. – jaff

-2

irqflags hat eine Art von unsigned int, aber ursprünglich hatte es Typ long.

die folgende Anweisung versuchen, es wird auf jeden Fall funktionieren:

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