summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2019-11-12 00:16:06 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2019-11-12 00:16:06 +0100
commit72cb75d88122797e7988aac61315cd167d21b169 (patch)
treea17e53305804eb78f48d38e582e6958c674cf4a2
parentd84f24b13961c7a475662d77fc3656bb799d0974 (diff)
Make userland irqs use counting, so both Linux and dde can mask interrupt as appropriate
-rw-r--r--device/ds_routines.c17
-rw-r--r--device/intr.c6
-rw-r--r--linux/dev/arch/i386/kernel/irq.c4
3 files changed, 18 insertions, 9 deletions
diff --git a/device/ds_routines.c b/device/ds_routines.c
index 06fe4e96..e7bcc564 100644
--- a/device/ds_routines.c
+++ b/device/ds_routines.c
@@ -346,11 +346,18 @@ ds_device_intr_register (ipc_port_t master_port, int line,
// in order to handle the case that the device driver crashes and restarts.
ret = install_user_intr_handler (line, flags, receive_port);
- /* If the port is installed successfully, increase its reference by 1.
- * Thus, the port won't be destroyed after its task is terminated. */
if (ret == 0)
+ {
+ /* If the port is installed successfully, increase its reference by 1.
+ * Thus, the port won't be destroyed after its task is terminated. */
ip_reference (receive_port);
+ /* For now netdde calls device_intr_enable once after registration. Assume
+ * it does so for now. When we move to IRQ acknowledgment convention we will
+ * change this. */
+ __disable_irq (line);
+ }
+
return ret;
#endif /* MACH_XEN */
}
@@ -1844,11 +1851,13 @@ ds_device_intr_enable(ipc_port_t master_port, int line, char status)
if (master_port != master_device_port)
return D_INVALID_OPERATION;
+ /* FIXME: should count how many disable/enable was done for a given receiving
+ * port, to be able to restore proper count on crashes */
if (status)
/* TODO: better name for generic-to-arch-specific call */
- enable_irq (line);
+ __enable_irq (line);
else
- disable_irq (line);
+ __disable_irq (line);
return 0;
#endif /* MACH_XEN */
}
diff --git a/device/intr.c b/device/intr.c
index cf5d93f6..fb423282 100644
--- a/device/intr.c
+++ b/device/intr.c
@@ -41,7 +41,11 @@ queue_intr (int line, ipc_port_t dest)
{
extern void intr_thread ();
struct intr_entry *e;
-
+
+ /* Until userland has handled the IRQ in the driver, we have to keep it
+ * disabled. Level-triggered interrupts would keep raising otherwise. */
+ __disable_irq (line);
+
cli ();
e = search_intr (line, dest);
assert (e);
diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c
index 5a2e4ad0..ae3fa070 100644
--- a/linux/dev/arch/i386/kernel/irq.c
+++ b/linux/dev/arch/i386/kernel/irq.c
@@ -129,12 +129,8 @@ linux_intr (int irq)
}
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);
}
-
}
else if (action->handler)
action->handler (irq, action->dev_id, &regs);