summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorJustus Winter <justus@gnupg.org>2016-02-25 20:54:22 +0100
committerJustus Winter <justus@gnupg.org>2016-02-25 20:54:22 +0100
commit652cbc1f88f02f92096051a7ce13dcbf77e55fc4 (patch)
treec9072d5e57bf7b2e3a5b3ccb92341cdf93a0f898 /linux
parentf7c2f4ba69c3ae7df8fddcc2969e2c21e109dbd1 (diff)
Rework/comment on the userspace interrupt handling
Diffstat (limited to 'linux')
-rw-r--r--linux/dev/arch/i386/kernel/irq.c49
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, &regs);
@@ -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)