diff --git a/sys/arm/arm/intr.c b/sys/arm/arm/intr.c index 75ed8938a13b..cb941f736917 100644 --- a/sys/arm/arm/intr.c +++ b/sys/arm/arm/intr.c @@ -54,21 +54,6 @@ static struct ithd *ithreads[NIRQ]; static int intrcnt_tab[NIRQ]; static int intrcnt_index = 0; static int last_printed = 0; -struct arm_intr { - driver_intr_t *handler; - void *arg; - void *cookiep; - int irq; -}; - -static void -arm_intr_handler(void *arg) -{ - struct arm_intr *intr = (struct arm_intr *)arg; - - intr->handler(intr->arg); - arm_unmask_irqs(1 << intr->irq); -} void arm_handler_execute(void *, int); @@ -77,17 +62,14 @@ arm_setup_irqhandler(const char *name, void (*hand)(void*), void *arg, int irq, int flags, void **cookiep) { struct ithd *cur_ith; - struct arm_intr *intr = NULL; int error; if (irq < 0 || irq >= NIRQ) return; - if (!(flags & INTR_FAST)) - intr = malloc(sizeof(*intr), M_DEVBUF, M_WAITOK); cur_ith = ithreads[irq]; if (cur_ith == NULL) { - error = ithread_create(&cur_ith, irq, 0, NULL, NULL, "intr%d:", - irq); + error = ithread_create(&cur_ith, irq, 0, arm_mask_irq, + arm_unmask_irq, "intr%d:", irq); if (error) return; ithreads[irq] = cur_ith; @@ -100,16 +82,14 @@ arm_setup_irqhandler(const char *name, void (*hand)(void*), void *arg, intrcnt_index++; } - if (!(flags & INTR_FAST)) { - intr->handler = hand; - intr->arg = arg; - intr->irq = irq; - intr->cookiep = *cookiep; - ithread_add_handler(cur_ith, name, arm_intr_handler, intr, - ithread_priority(flags), flags, cookiep); - } else - ithread_add_handler(cur_ith, name, hand, arg, - ithread_priority(flags), flags, cookiep); + ithread_add_handler(cur_ith, name, hand, arg, + ithread_priority(flags), flags, cookiep); +} + +int +arm_remove_irqhandler(void *cookie) +{ + return (ithread_remove_handler(cookie)); } void dosoftints(void); @@ -127,13 +107,8 @@ arm_handler_execute(void *frame, int irqnb) struct thread *td = curthread; td->td_intr_nesting_level++; - if (irqnb == 0) - irqnb = arm_get_irqnb(frame); - while (irqnb != 0) { - arm_mask_irqs(irqnb); - i = ffs(irqnb) - 1; + while ((i = arm_get_next_irq()) != -1) { intrcnt[intrcnt_tab[i]]++; - irqnb &= ~(1U << i); ithd = ithreads[i]; if (!ithd) continue; @@ -144,10 +119,10 @@ arm_handler_execute(void *frame, int irqnb) ih->ih_handler(ih->ih_argument ? ih->ih_argument : frame); } - arm_unmask_irqs(1 << i); - } else if (ih) + } else if (ih) { + arm_mask_irq(i); ithread_schedule(ithd); - irqnb |= arm_get_irqnb(frame); + } } td->td_intr_nesting_level--; } diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c index dd47101f083f..131bbc61c664 100644 --- a/sys/arm/arm/nexus.c +++ b/sys/arm/arm/nexus.c @@ -83,6 +83,9 @@ static int nexus_activate_resource(device_t, device_t, int, int, static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_intr_t *intr, void *arg, void **cookiep); +static int +nexus_teardown_intr(device_t, device_t, struct resource *, void *); + static device_method_t nexus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, nexus_probe), @@ -93,6 +96,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), DEVMETHOD(bus_activate_resource, nexus_activate_resource), DEVMETHOD(bus_setup_intr, nexus_setup_intr), + DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), { 0, 0 } }; @@ -129,6 +133,15 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, return (0); } +static int +nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) +{ + int error; + + arm_mask_irq(r->r_start); + error = arm_remove_irqhandler(ih); + return (error); +} static int nexus_attach(device_t dev) diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h index cd31eae4877b..dc08c7f717ae 100644 --- a/sys/arm/include/intr.h +++ b/sys/arm/include/intr.h @@ -47,10 +47,10 @@ #include -int arm_get_irqnb(void *); -void arm_mask_irqs(int); -void arm_unmask_irqs(int); -void set_splmasks(void); +int arm_get_next_irq(void); +void arm_mask_irq(uintptr_t); +void arm_unmask_irq(uintptr_t); void arm_setup_irqhandler(const char *, void (*)(void*), void *, int, int, void **); +int arm_remove_irqhandler(void *); #endif /* _MACHINE_INTR_H */ diff --git a/sys/arm/sa11x0/sa11x0_irqhandler.c b/sys/arm/sa11x0/sa11x0_irqhandler.c index a3f7db41b7cb..5cda4c6d299e 100644 --- a/sys/arm/sa11x0/sa11x0_irqhandler.c +++ b/sys/arm/sa11x0/sa11x0_irqhandler.c @@ -102,37 +102,35 @@ int current_intr_depth; extern struct sa11x0_softc *sa11x0_softc; -/* Recalculate the interrupt masks from scratch. - * We could code special registry and deregistry versions of this function that - * would be faster, but the code would be nastier, and we don't expect this to - * happen very much anyway. - */ -int -arm_get_irqnb(void *frame) -{ - struct sa11x0_softc *sc = sa11x0_softc; - - return(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SAIPIC_IP)); -} - static uint32_t sa11x0_irq_mask = 0xfffffff; extern vm_offset_t saipic_base; +int +arm_get_next_irq() +{ + int irq; + + if ((irq = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SAIPIC_IP) & + sa11x0_irq_mask)) != 0) + return (ffs(irq) - 1); + return (-1); +} + void -arm_mask_irqs(int irq) +arm_mask_irq(uintptr_t irq) { - sa11x0_irq_mask &= ~irq; + sa11x0_irq_mask &= ~(1 << irq); __asm __volatile("str %0, [%1, #0x04]" /* SAIPIC_MR */ : : "r" (sa11x0_irq_mask), "r" (saipic_base)); } void -arm_unmask_irqs(int irq) +arm_unmask_irq(uintptr_t irq) { - sa11x0_irq_mask |= irq; + sa11x0_irq_mask |= (1 << irq); __asm __volatile("str %0, [%1, #0x04]" /* SAIPIC_MR */ : : "r" (sa11x0_irq_mask), "r" (saipic_base)); } diff --git a/sys/arm/xscale/i80321/i80321.c b/sys/arm/xscale/i80321/i80321.c index 23d25a110fc3..dfd03a1013fb 100644 --- a/sys/arm/xscale/i80321/i80321.c +++ b/sys/arm/xscale/i80321/i80321.c @@ -259,10 +259,11 @@ i80321_iintsrc_read(void) } int -arm_get_irqnb(void *clockframe) +arm_get_next_irq() { + int irq; - return (i80321_iintsrc_read()); + if ((irq = i80321_iintsrc_read())) + return (ffs(irq) - 1); + return (-1); } - - diff --git a/sys/arm/xscale/i80321/i80321_pci.c b/sys/arm/xscale/i80321/i80321_pci.c index 0bb781067fc8..50ebe494db77 100644 --- a/sys/arm/xscale/i80321/i80321_pci.c +++ b/sys/arm/xscale/i80321/i80321_pci.c @@ -426,6 +426,14 @@ i80321_pci_setup_intr(device_t dev, device_t child, return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, intr, arg, cookiep)); } + +static int +i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); +} + static device_method_t i80321_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, i80321_pci_probe), @@ -443,7 +451,7 @@ static device_method_t i80321_pci_methods[] = { DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr), /* pcib interface */ DEVMETHOD(pcib_maxslots, i80321_pci_maxslots), diff --git a/sys/arm/xscale/i80321/iq80321.c b/sys/arm/xscale/i80321/iq80321.c index 20a11c790978..32924063d91c 100644 --- a/sys/arm/xscale/i80321/iq80321.c +++ b/sys/arm/xscale/i80321/iq80321.c @@ -263,19 +263,20 @@ iq80321_attach(device_t dev) } void -arm_mask_irqs(int nb) +arm_mask_irq(uintptr_t nb) { - intr_enabled &= ~nb; + intr_enabled &= ~(1 << nb); i80321_set_intrmask(); } void -arm_unmask_irqs(int nb) +arm_unmask_irq(uintptr_t nb) { - intr_enabled |= nb; + intr_enabled |= (1 << nb); i80321_set_intrmask(); } + void cpu_reset() { @@ -311,12 +312,21 @@ iq80321_setup_intr(device_t dev, device_t child, return (0); } + +static int +iq80321_teardown_intr(device_t dev, device_t child, struct resource *res, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); +} + static device_method_t iq80321_methods[] = { DEVMETHOD(device_probe, iq80321_probe), DEVMETHOD(device_attach, iq80321_attach), DEVMETHOD(device_identify, iq80321_identify), DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource), DEVMETHOD(bus_setup_intr, iq80321_setup_intr), + DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr), {0, 0}, };