diff options
author | Justus Winter <justus@gnupg.org> | 2016-02-25 20:54:22 +0100 |
---|---|---|
committer | Justus Winter <justus@gnupg.org> | 2016-02-25 20:54:22 +0100 |
commit | 652cbc1f88f02f92096051a7ce13dcbf77e55fc4 (patch) | |
tree | c9072d5e57bf7b2e3a5b3ccb92341cdf93a0f898 /linux | |
parent | f7c2f4ba69c3ae7df8fddcc2969e2c21e109dbd1 (diff) |
Rework/comment on the userspace interrupt handling
Diffstat (limited to 'linux')
-rw-r--r-- | linux/dev/arch/i386/kernel/irq.c | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c index b7dfa1a..15f95c3 100644 --- a/linux/dev/arch/i386/kernel/irq.c +++ b/linux/dev/arch/i386/kernel/irq.c @@ -49,6 +49,7 @@ #include <linux/dev/glue/glue.h> #include <machine/machspl.h> +#include <device/interrupt.h> #if 0 /* XXX: This is the way it's done in linux 2.2. GNU Mach currently uses intr_count. It should be made using local_{bh/irq}_count instead (through hardirq_enter/exit) for SMP support. */ @@ -83,7 +84,7 @@ struct linux_action void *dev_id; struct linux_action *next; unsigned long flags; - volatile ipc_port_t delivery_port; + struct intr_entry *userspace_handler; }; static struct linux_action *irq_action[16] = @@ -117,31 +118,19 @@ linux_intr (int irq) { // TODO I might need to check whether the interrupt belongs to // the current device. But I don't do it for now. - if (action->delivery_port) + if (action->userspace_handler) { - /* The reference of the port was increased - * when the port was installed. - * If the reference is 1, it means the port should - * have been destroyed and I destroy it now. */ - if (action->delivery_port - && action->delivery_port->ip_references == 1) - { - mark_intr_removed (irq, action->delivery_port); - ipc_port_release (action->delivery_port); - *prev = action->next; - printk ("irq handler %d: release an dead delivery port\n", irq); - linux_kfree(action); - action = *prev; - continue; - } - else - { /* We disable the irq here and it will be enabled * after the interrupt is handled by the user space driver. */ disable_irq (irq); - queue_intr (irq, action->delivery_port); - } - + if (! queue_intr (action->userspace_handler)) + { + *prev = action->next; + linux_kfree(action); + action = *prev; + enable_irq (irq); + continue; + } } else if (action->handler) action->handler (irq, action->dev_id, ®s); @@ -285,26 +274,32 @@ setup_x86_irq (int irq, struct linux_action *new) int install_user_intr_handler (unsigned int irq, unsigned long flags, - ipc_port_t dest) + struct intr_entry *entry) { struct linux_action *action; +#if 0 struct linux_action *old; +#endif int retval; assert (irq < 16); - /* Test whether the irq handler has been set */ +#if 0 + /* Test whether the irq handler has already been set. */ + /* JW: Actually, that cannot happen. We test for that in + device_intr_register before calling this function. */ // TODO I need to protect the array when iterating it. old = irq_action[irq]; while (old) { - if (old->delivery_port == dest) + if (old->delivery_port == entry->dest) { printk ("The interrupt handler has been installed on line %d", irq); return linux_to_mach_error (-EAGAIN); } old = old->next; } +#endif /* * Hmm... Should I use `kalloc()' ? @@ -319,7 +314,7 @@ install_user_intr_handler (unsigned int irq, unsigned long flags, action->next = NULL; action->dev_id = NULL; action->flags = flags; - action->delivery_port = dest; + action->userspace_handler = entry; retval = setup_x86_irq (irq, action); if (retval) @@ -356,7 +351,7 @@ request_irq (unsigned int irq, void (*handler) (int, void *, struct pt_regs *), action->next = NULL; action->dev_id = dev_id; action->flags = flags; - action->delivery_port = NULL; + action->userspace_handler = NULL; retval = setup_x86_irq (irq, action); if (retval) |