summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/patches/refactor-irq300
-rw-r--r--debian/patches/series1
2 files changed, 301 insertions, 0 deletions
diff --git a/debian/patches/refactor-irq b/debian/patches/refactor-irq
new file mode 100644
index 00000000..5c79aac7
--- /dev/null
+++ b/debian/patches/refactor-irq
@@ -0,0 +1,300 @@
+--- a/pci-userspace/src-gnu/pci_user-gnu.c
++++ b/pci-userspace/src-gnu/pci_user-gnu.c
+@@ -69,12 +69,10 @@
+ #include <device/device.h>
+ #include <mach/gnumach.h>
+ #include "mach_debug_U.h"
+-#include "acpi_U.h"
++#include <hurd/irqhelp.h>
+ #include <mach/vm_param.h>
+ #include <mach.h>
+
+-#define RUMP_IRQ_PRIO 2
+-
+ #define PCI_COMMAND 0x04
+ #define PCI_COMMAND_INT_DISABLE 0x400
+
+@@ -90,10 +88,7 @@
+ /* number of pci devices */
+ static int numdevs = -1;
+
+-static mach_port_t master_host;
+-static mach_port_t master_device;
+-static device_t irq_dev;
+-static device_t acpi_dev;
++mach_port_t master_host;
+
+ #define PCI_CFG1_START 0xcf8
+ #define PCI_CFG1_END 0xcff
+@@ -149,23 +144,12 @@
+
+ MACH_PRINT("pci_userspace_init\n");
+
+- if ((ret = get_privileged_ports (&master_host, &master_device))) {
+- errno = ret;
++ if (get_privileged_ports (&master_host, NULL))
+ err(1, "get_privileged_ports");
+- }
+-
+- if ((ret = device_open (master_device, D_READ, "irq", &irq_dev))) {
+- errno = ret;
+- err(2, "device_open irq");
+- }
+-
+- /* Optional */
+- if (device_open (master_device, D_READ, "acpi", &acpi_dev)) {
+- MACH_PRINT("device_open acpi failed... continue\n");
+- acpi_dev = MACH_PORT_NULL;
+- }
+
++ irqhelp_init();
+ pci_system_init ();
++
+ struct pci_device_iterator *dev_iter;
+ struct pci_device *pci_dev;
+ dev_iter = pci_slot_match_iterator_create (NULL);
+@@ -280,115 +264,56 @@
+ return 0;
+ }
+
+-/* this is a multifunction data structure! */
++struct wrapped {
++ int (*raw_handler)(void *);
++ void *raw_data;
++};
++
++static void
++wrapped_handler(void *arg)
++{
++ struct wrapped *w = (struct wrapped *)arg;
++
++ rumpuser_component_schedule(NULL);
++ w->raw_handler(w->raw_data);
++ rumpuser_component_unschedule();
++
++}
++
++/* enough to peek at gsi */
+ struct irq {
++ void (*handler)(void *);
++ void *context;
++ int gsi;
++};
++
++/* this is a multifunction data structure! */
++struct irq_multi {
+ unsigned magic_cookie;
+ unsigned bus;
+ unsigned dev;
+ unsigned fun;
+
+- int (*handler)(void *);
+- void *data;
++ struct wrapped w;
+ int intrline;
+- mach_port_t irqport;
++ struct irq *irqhelp;
+ sem_t sema;
+
+- LIST_ENTRY(irq) entries;
++ LIST_ENTRY(irq_multi) entries;
+ };
+-static LIST_HEAD(, irq) irqs = LIST_HEAD_INITIALIZER(&irqs);
++static LIST_HEAD(, irq_multi) irqs = LIST_HEAD_INITIALIZER(&irqs);
+
+ static void *
+ intrthread(void *arg)
+ {
+- struct irq *irq = arg;
+- mach_port_t delivery_port;
+- mach_port_t pset, psetcntl;
+- int ret;
+- uint32_t val;
++ struct irq_multi *irq = arg;
+
+ MACH_PRINT("intrthread\n");
+
+ rumpuser_component_kthread();
+
+- ret = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+- &delivery_port);
+- if (ret) {
+- MACH_PRINT("mach_port_allocate\n");
+- return 0;
+- }
+-
+- irq->irqport = delivery_port;
+-
+- ret = thread_get_assignment (mach_thread_self (), &pset);
+- if (ret) {
+- MACH_PRINT("thread_get_assignment\n");
+- return 0;
+- }
+- ret = host_processor_set_priv (master_host, pset, &psetcntl);
+- if (ret) {
+- MACH_PRINT("host_processor_set_priv\n");
+- return 0;
+- }
+- thread_max_priority (mach_thread_self (), psetcntl, 0);
+- ret = thread_priority (mach_thread_self (), RUMP_IRQ_PRIO, 0);
+- if (ret) {
+- MACH_PRINT("thread_priority\n");
+- return 0;
+- }
+-
+- ret = device_intr_register(irq_dev, irq->intrline,
+- 0, irq->irqport,
+- MACH_MSG_TYPE_MAKE_SEND);
+- if (ret) {
+- MACH_PRINT("device_intr_register\n");
+- return 0;
+- }
+-
+- int irq_server (mach_msg_header_t *inp, mach_msg_header_t *outp) {
+- char interrupt[4];
+-
+- device_intr_notification_t *n = (device_intr_notification_t *) inp;
+-
+- ((mig_reply_header_t *) outp)->RetCode = MIG_NO_REPLY;
+- if (n->intr_header.msgh_id != DEVICE_INTR_NOTIFY) {
+- MACH_PRINT("not an interrupt\n");
+- return 0;
+- }
+-
+- /* It's an interrupt not for us. It shouldn't happen. */
+- /* FIXME: id <-> line now has an indirection, assuming 1:1 */
+- if (n->id != irq->intrline) {
+- MACH_PRINT("interrupt not for us\n");
+- return 0;
+- }
+-
+- sprintf(interrupt, "%d\n", n->id);
+- MACH_PRINT("irq fired: ");
+- MACH_PRINT(interrupt);
+-
+- rumpcomp_pci_confread(irq->bus, irq->dev, irq->fun, PCI_COMMAND, &val);
+- if (val & PCI_COMMAND_INT_DISABLE) {
+- MACH_PRINT("interrupt disabled!\n");
+- val &= ~PCI_COMMAND_INT_DISABLE;
+- rumpcomp_pci_confwrite(irq->bus, irq->dev, irq->fun, PCI_COMMAND, val);
+- }
+-
+- MACH_PRINT("k_handle...");
+- rumpuser_component_schedule(NULL);
+- irq->handler(irq->data);
+- rumpuser_component_unschedule();
+- MACH_PRINT("k_done\n");
+-
+- device_intr_ack (irq_dev, irq->irqport, MACH_MSG_TYPE_MAKE_SEND);
+-
+- return 1;
+- }
+-
+ sem_post(&irq->sema);
+- MACH_PRINT("done init\n");
+-
+- /* Server loop */
+- mach_msg_server (irq_server, 0, delivery_port);
++ irqhelp_server_loop(irq->irqhelp);
+
+ rumpuser_component_kthread_release();
+ return NULL;
+@@ -398,8 +323,7 @@
+ rumpcomp_pci_irq_map(unsigned bus, unsigned dev, unsigned fun,
+ int intrline, unsigned cookie)
+ {
+- int ret;
+- struct irq *irq;
++ struct irq_multi *irq;
+ irq = malloc(sizeof(*irq));
+ if (irq == NULL)
+ return ENOENT;
+@@ -410,15 +334,6 @@
+ irq->fun = fun;
+ irq->intrline = intrline;
+
+- /* We can do better by reading irq from acpi device, but with fallback */
+- if (acpi_dev != MACH_PORT_NULL) {
+- ret = acpi_get_pci_irq (acpi_dev, bus, dev, fun, &irq->intrline);
+- if (ret) {
+- MACH_PRINT("acpi_get_pci_irq failed, continue with intrline\n");
+- irq->intrline = intrline;
+- }
+- }
+-
+ pthread_mutex_lock(&genericmtx);
+ LIST_INSERT_HEAD(&irqs, irq, entries);
+ pthread_mutex_unlock(&genericmtx);
+@@ -429,8 +344,8 @@
+ void *
+ rumpcomp_pci_irq_establish(unsigned cookie, int (*handler)(void *), void *data)
+ {
+- struct irq *irq;
+- void *cookie2;
++ struct irq_multi *irq;
++ void *cookie2;
+ pthread_t pt;
+
+ cookie2 = rumpuser_component_unschedule();
+@@ -443,16 +358,34 @@
+ break;
+ }
+ pthread_mutex_unlock(&genericmtx);
+- if (!irq)
++ if (!irq) {
++ rumpuser_component_schedule(cookie2);
+ return NULL;
++ }
+
+- irq->handler = handler;
+- irq->data = data;
++ irq->w.raw_handler = handler;
++ irq->w.raw_data = data;
++
++ /* We can do better by trying acpi, but with fallback */
++ irq->irqhelp = irqhelp_install_interrupt_handler(-1, irq->bus, irq->dev, irq->fun, wrapped_handler, &irq->w);
++ if (irq->irqhelp) {
++ irq->intrline = irq->irqhelp->gsi;
++ } else {
++ MACH_PRINT("acpi_get_pci_irq failed, continue with intrline\n");
++ irq->irqhelp = irqhelp_install_interrupt_handler(irq->intrline, -1, -1, -1, wrapped_handler, &irq->w);
++ if (!irq->irqhelp) {
++ MACH_PRINT("irqhelp failed to register handler\n");
++ free(irq);
++ rumpuser_component_schedule(cookie2);
++ return NULL;
++ }
++ }
+
+ sem_init(&irq->sema, 0, 0);
+
+ if (pthread_create(&pt, NULL, intrthread, irq) != 0) {
+- MACH_PRINT("interrupt thread create");
++ MACH_PRINT("interrupt thread create failed\n");
++ irqhelp_remove_interrupt_handler(irq->irqhelp);
+ free(irq);
+ rumpuser_component_schedule(cookie2);
+ return NULL;
+--- a/pci-userspace/src-gnu/Makefile.inc
++++ b/pci-userspace/src-gnu/Makefile.inc
+@@ -7,7 +7,7 @@
+ RUMPCOMP_USER_CPPFLAGS+=-I${PCIDIR} -I${DESTDIR}/usr/include
+ RUMPCOMP_CPPFLAGS+= -I${PCIDIR} -I${DESTDIR}/usr/include
+ CPPFLAGS+= -I${PCIDIR}
+-LDFLAGS+= -lmachuser -Wl,--no-as-needed -lpciaccess -Wl,--as-needed
++LDFLAGS+= -lmachuser -lirqhelp -Wl,--no-as-needed -lpciaccess -Wl,--as-needed
+ MIG=mig
+
+ mach_debugUser.c:
+@@ -17,11 +17,3 @@
+ -user mach_debugUser.c \
+ -server /dev/null \
+ -header mach_debug_U.h
+-
+-acpiUser.c:
+- echo '#include <hurd/acpi.defs>' \
+- | ${CC} -E -x c - -o - \
+- | $(MIG) -cc cat - /dev/null -subrprefix __ \
+- -user acpiUser.c \
+- -server /dev/null \
+- -header acpi_U.h
diff --git a/debian/patches/series b/debian/patches/series
index 6c86979c..7fe8ac9d 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -24,3 +24,4 @@ clean_external
PAE
vm_allocate_contiguous_align
err
+refactor-irq