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:
parent
29271eabe4
commit
187bd3cde6
2 changed files with 69 additions and 25 deletions
|
@ -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>
|
||||||
|
|
||||||
|
@ -11,8 +12,9 @@
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
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 *);
|
||||||
|
@ -21,11 +23,15 @@ struct ddekit_irq_s {
|
||||||
int enabled;
|
int enabled;
|
||||||
ddekit_thread_t *th;
|
ddekit_thread_t *th;
|
||||||
ddekit_sem_t *sem;
|
ddekit_sem_t *sem;
|
||||||
struct ddekit_irq_s *next;
|
struct ddekit_irq_s *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@ -72,7 +79,30 @@ static struct ddekit_irq_s * find_by_irq(int irq)
|
||||||
break;
|
break;
|
||||||
irq_s = irq_s->next;
|
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();
|
ddekit_irq_unlock();
|
||||||
return irq_s;
|
return irq_s;
|
||||||
}
|
}
|
||||||
|
@ -142,20 +172,29 @@ static void ddekit_irq_thread(void *data)
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* ddekit_interrupt_attach *
|
* ddekit_interrupt_attach *
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
ddekit_thread_t *ddekit_interrupt_attach(int irq,
|
ddekit_thread_t *ddekit_interrupt_attach(int irq,
|
||||||
int shared,
|
int shared,
|
||||||
void(*thread_init)(void *),
|
void(*thread_init)(void *),
|
||||||
void(*handler)(void *),
|
void(*handler)(void *),
|
||||||
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;
|
||||||
|
@ -165,12 +204,12 @@ ddekit_thread_t *ddekit_interrupt_attach(int irq,
|
||||||
|
|
||||||
/* create interrupt thread */
|
/* create interrupt thread */
|
||||||
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,11 +228,13 @@ 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);
|
||||||
ddekit_simple_free(irq_s);
|
ddekit_simple_free(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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue