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
This commit is contained in:
Wojciech Zajac 2014-08-19 18:23:26 +02:00 committed by Ben Gras
parent 29271eabe4
commit 187bd3cde6
2 changed files with 69 additions and 25 deletions

View file

@ -1,6 +1,7 @@
#include "common.h" #include "common.h"
#include <ddekit/interrupt.h> #include <ddekit/interrupt.h>
#include <ddekit/memory.h> #include <ddekit/memory.h>
#include <ddekit/panic.h>
#include <ddekit/semaphore.h> #include <ddekit/semaphore.h>
#include <ddekit/thread.h> #include <ddekit/thread.h>
@ -13,6 +14,7 @@
struct ddekit_irq_s { struct ddekit_irq_s {
int irq; int irq;
int notify_id;
int irq_hook; int irq_hook;
int shared; int shared;
void(*thread_init)(void *); void(*thread_init)(void *);
@ -26,6 +28,10 @@ struct ddekit_irq_s {
static struct ddekit_irq_s *irqs = 0; static struct ddekit_irq_s *irqs = 0;
static ddekit_lock_t lock; 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 * * Local helpers *
@ -35,6 +41,7 @@ static ddekit_lock_t lock;
static void ddekit_irq_lock(void); static void ddekit_irq_lock(void);
static void ddekit_irq_unlock(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(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_remove(struct ddekit_irq_s *irq_s);
static void ddekit_irq_thread(void *data); static void ddekit_irq_thread(void *data);
@ -77,6 +84,29 @@ static struct ddekit_irq_s * find_by_irq(int irq)
return irq_s; 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;
}
/****************************************************************************** /******************************************************************************
* ddekit_irq_remove * * ddekit_irq_remove *
*****************************************************************************/ *****************************************************************************/
@ -149,13 +179,22 @@ ddekit_thread_t *ddekit_interrupt_attach(int irq,
void *priv) void *priv)
{ {
struct ddekit_irq_s *irq_s; struct ddekit_irq_s *irq_s;
int err_code;
char name[32]; char name[32];
irq_s = (struct ddekit_irq_s *) irq_s = (struct ddekit_irq_s *)
ddekit_simple_malloc(sizeof(struct ddekit_irq_s)); ddekit_simple_malloc(sizeof(struct ddekit_irq_s));
irq_s->sem = ddekit_sem_init(0); irq_s->sem = ddekit_sem_init(0);
irq_s->irq = irq; irq_s->irq = irq; /* represents real IRQ number */
irq_s->irq_hook = irq; 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->shared = shared;
irq_s->thread_init = thread_init; irq_s->thread_init = thread_init;
irq_s->handler = handler; irq_s->handler = handler;
@ -167,10 +206,10 @@ ddekit_thread_t *ddekit_interrupt_attach(int irq,
snprintf(name, 32, "ddekit_irq_%d",irq); 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 */ /* try attaching to IRQ */
sys_irqsetpolicy(irq, /* do not automatically re-enable interupts */
0, /* not automatically re-enable interupts */ if (0 != (err_code = sys_irqsetpolicy(irq, 0, &irq_s->irq_hook)))
&irq_s->irq_hook); ddekit_panic("Failed to attach interrupt (ERROR %d)", err_code);
/* add to IRQ list */ /* add to IRQ list */
ddekit_irq_lock(); ddekit_irq_lock();
@ -189,10 +228,12 @@ ddekit_thread_t *ddekit_interrupt_attach(int irq,
void ddekit_interrupt_detach(int irq) void ddekit_interrupt_detach(int irq)
{ {
struct ddekit_irq_s *irq_s; struct ddekit_irq_s *irq_s;
int err_code;
irq_s = find_by_irq(irq); 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_thread_terminate(irq_s->th);
ddekit_irq_remove(irq_s); ddekit_irq_remove(irq_s);
@ -239,16 +280,19 @@ void ddekit_init_irqs()
/****************************************************************************** /******************************************************************************
* _ddekit_interrupt_trigger * * _ddekit_interrupt_trigger *
*****************************************************************************/ *****************************************************************************/
void _ddekit_interrupt_trigger(int irq) void _ddekit_interrupt_trigger(int irq_id)
{ {
struct ddekit_irq_s *irq_s; struct ddekit_irq_s *irq_s;
int err_code;
irq_s = find_by_irq(irq); irq_s = find_by_irq_id(irq_id);
if (irq_s) { if (irq_s) {
DDEBUG_MSG_VERBOSE("Triggering IRQ %d", irq); DDEBUG_MSG_VERBOSE("Triggering IRQ %d", irq);
ddekit_sem_up(irq_s->sem); 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 { } else {
DDEBUG_MSG_WARN("no handler for IRQ %d", irq); DDEBUG_MSG_WARN("no handler for IRQ %d", irq);
} }

View file

@ -1,5 +1,5 @@
#ifndef DDEKIT_IRQ_MINIX_H #ifndef DDEKIT_IRQ_MINIX_H
#define DDEKIT_IRQ_MINIX_H 1 #define DDEKIT_IRQ_MINIX_H 1
void ddekit_init_irqs(void); void ddekit_init_irqs(void);
void _ddekit_interrupt_trigger(int irq_hook); void _ddekit_interrupt_trigger(int irq_id);
#endif #endif