]> Zhao Yanbai Git Server - minix.git/commitdiff
DDEKit interrupt fix 15/2715/1
authorWojciech Zajac <wmzdev@gmail.com>
Tue, 19 Aug 2014 16:23:26 +0000 (18:23 +0200)
committerBen Gras <beng@shrike-systems.com>
Tue, 19 Aug 2014 16:24:29 +0000 (18:24 +0200)
    - 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
minix/lib/libddekit/src/irq.h

index ed30d71633208db5d9d952d5eeb9c61081701291..b60981aebe3161a0ff4cd515d42d1456d1853dc4 100644 (file)
@@ -1,6 +1,7 @@
 #include "common.h"
 #include <ddekit/interrupt.h>
 #include <ddekit/memory.h>
+#include <ddekit/panic.h>
 #include <ddekit/semaphore.h>
 #include <ddekit/thread.h>
 
@@ -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);
        }
index be27a3302724efdc280db1b74bb7ffd74bd95b58..50b6f270e931d2e15097091746afd3d8a6a5fc61 100644 (file)
@@ -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