From 187bd3cde6b9003b582b751ca685e3b13b65892b Mon Sep 17 00:00:00 2001 From: Wojciech Zajac Date: Tue, 19 Aug 2014 18:23:26 +0200 Subject: [PATCH] DDEKit interrupt fix - With this patch, DDEKit no longer uses IRQ number as interrupt ID and more IRQ numbers can be used with it - DDEKit IRQ code, will now check return values and panic on error Change-Id: I9ef5ab1ee2262242204bdd8c0a60459a19ddcc1b --- minix/lib/libddekit/src/irq.c | 92 ++++++++++++++++++++++++++--------- minix/lib/libddekit/src/irq.h | 2 +- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/minix/lib/libddekit/src/irq.c b/minix/lib/libddekit/src/irq.c index ed30d7163..b60981aeb 100644 --- a/minix/lib/libddekit/src/irq.c +++ b/minix/lib/libddekit/src/irq.c @@ -1,6 +1,7 @@ #include "common.h" #include #include +#include #include #include @@ -11,8 +12,9 @@ #include "debug.h" -struct ddekit_irq_s { +struct ddekit_irq_s { int irq; + int notify_id; int irq_hook; int shared; void(*thread_init)(void *); @@ -21,11 +23,15 @@ struct ddekit_irq_s { int enabled; ddekit_thread_t *th; ddekit_sem_t *sem; - struct ddekit_irq_s *next; + struct ddekit_irq_s *next; }; -static struct ddekit_irq_s *irqs = 0; -static ddekit_lock_t lock; +static struct ddekit_irq_s *irqs = 0; +static ddekit_lock_t lock; +static int next_notify_id = 0; /* TODO: This is only incremented and after + * enough interrupt attachments/detachments + * we can run out of legal IDs (this is however + * very atypical use case) */ /****************************************************************************** * Local helpers * @@ -35,6 +41,7 @@ static ddekit_lock_t lock; static void ddekit_irq_lock(void); static void ddekit_irq_unlock(void); static struct ddekit_irq_s* find_by_irq(int irq); +static struct ddekit_irq_s* find_by_irq_id(int irq_id); static void ddekit_irq_remove(struct ddekit_irq_s *irq_s); static void ddekit_irq_thread(void *data); @@ -72,7 +79,30 @@ static struct ddekit_irq_s * find_by_irq(int irq) break; irq_s = irq_s->next; } - + + ddekit_irq_unlock(); + return irq_s; +} + +/****************************************************************************** + * find_by_irq_id * + *****************************************************************************/ +static struct ddekit_irq_s * find_by_irq_id(int irq_id) +{ + struct ddekit_irq_s * irq_s; + ddekit_irq_lock(); + if (!irqs) { + return 0; + } + + irq_s = irqs; + + while(irq_s) { + if(irq_s->notify_id==irq_id) + break; + irq_s = irq_s->next; + } + ddekit_irq_unlock(); return irq_s; } @@ -142,20 +172,29 @@ static void ddekit_irq_thread(void *data) /****************************************************************************** * ddekit_interrupt_attach * *****************************************************************************/ -ddekit_thread_t *ddekit_interrupt_attach(int irq, +ddekit_thread_t *ddekit_interrupt_attach(int irq, int shared, void(*thread_init)(void *), void(*handler)(void *), - void *priv) + void *priv) { struct ddekit_irq_s *irq_s; + int err_code; char name[32]; - irq_s = (struct ddekit_irq_s *) + irq_s = (struct ddekit_irq_s *) ddekit_simple_malloc(sizeof(struct ddekit_irq_s)); irq_s->sem = ddekit_sem_init(0); - irq_s->irq = irq; - irq_s->irq_hook = irq; + irq_s->irq = irq; /* represents real IRQ number */ + ddekit_irq_lock(); + irq_s->notify_id = next_notify_id; /* represents kernel's IRQ ID */ + irq_s->irq_hook = next_notify_id; /* after given ID is passed to + * kernel, this field will be + * set to real irq_hook */ + next_notify_id++; /* next time, assign different + * ID so we can distinguish + * interrupts */ + ddekit_irq_unlock(); irq_s->shared = shared; irq_s->thread_init = thread_init; irq_s->handler = handler; @@ -165,12 +204,12 @@ ddekit_thread_t *ddekit_interrupt_attach(int irq, /* create interrupt thread */ snprintf(name, 32, "ddekit_irq_%d",irq); - irq_s->th = ddekit_thread_create(ddekit_irq_thread, irq_s, name); + irq_s->th = ddekit_thread_create(ddekit_irq_thread, irq_s, name); - /* attach to IRQ */ - sys_irqsetpolicy(irq, - 0, /* not automatically re-enable interupts */ - &irq_s->irq_hook); + /* try attaching to IRQ */ + /* do not automatically re-enable interupts */ + if (0 != (err_code = sys_irqsetpolicy(irq, 0, &irq_s->irq_hook))) + ddekit_panic("Failed to attach interrupt (ERROR %d)", err_code); /* add to IRQ list */ ddekit_irq_lock(); @@ -189,11 +228,13 @@ ddekit_thread_t *ddekit_interrupt_attach(int irq, void ddekit_interrupt_detach(int irq) { struct ddekit_irq_s *irq_s; + int err_code; irq_s = find_by_irq(irq); - - sys_irqrmpolicy(&irq_s->irq_hook); - + + if (0 != (err_code = sys_irqrmpolicy(&irq_s->irq_hook))) + ddekit_panic("Failed to detach interrupt (ERROR %d)", err_code); + ddekit_thread_terminate(irq_s->th); ddekit_irq_remove(irq_s); ddekit_simple_free(irq_s); @@ -239,16 +280,19 @@ void ddekit_init_irqs() /****************************************************************************** * _ddekit_interrupt_trigger * *****************************************************************************/ -void _ddekit_interrupt_trigger(int irq) -{ +void _ddekit_interrupt_trigger(int irq_id) +{ struct ddekit_irq_s *irq_s; + int err_code; - irq_s = find_by_irq(irq); - - if (irq_s) { + irq_s = find_by_irq_id(irq_id); + + if (irq_s) { DDEBUG_MSG_VERBOSE("Triggering IRQ %d", irq); ddekit_sem_up(irq_s->sem); - sys_irqenable(&irq_s->irq_hook); + if (0 != (err_code = sys_irqenable(&irq_s->irq_hook))) + ddekit_panic("Failed to enable interrupt " + "(ERROR %d)", err_code); } else { DDEBUG_MSG_WARN("no handler for IRQ %d", irq); } diff --git a/minix/lib/libddekit/src/irq.h b/minix/lib/libddekit/src/irq.h index be27a3302..50b6f270e 100644 --- a/minix/lib/libddekit/src/irq.h +++ b/minix/lib/libddekit/src/irq.h @@ -1,5 +1,5 @@ #ifndef DDEKIT_IRQ_MINIX_H #define DDEKIT_IRQ_MINIX_H 1 void ddekit_init_irqs(void); -void _ddekit_interrupt_trigger(int irq_hook); +void _ddekit_interrupt_trigger(int irq_id); #endif