--- p4_head/sys/sparc64/fhc/fhc.c Sun Jan 21 15:20:43 2007 +++ p4_head_intr/sys/sparc64/fhc/fhc.c Fri Jan 26 13:54:09 2007 @@ -50,7 +50,7 @@ #include struct fhc_clr { - driver_intr_t *fc_func; + driver_filter_t *fc_func; void *fc_arg; void *fc_cookie; bus_space_tag_t fc_bt; @@ -62,7 +62,7 @@ struct resource_list fdi_rl; }; -static void fhc_intr_stub(void *); +static int fhc_intr_stub(void *); static void fhc_led_func(void *, int); static int fhc_print_res(struct fhc_devinfo *); @@ -206,7 +206,7 @@ int fhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags, - driver_intr_t *func, void *arg, void **cookiep) + driver_filter_t *filt, driver_intr_t *func, void *arg, void **cookiep) { struct fhc_softc *sc; struct fhc_clr *fc; @@ -217,6 +217,9 @@ long vec; uint32_t inr; + if (filt != NULL && func != NULL) + return (EINVAL); + sc = device_get_softc(bus); vec = rman_get_start(r); @@ -238,7 +241,7 @@ fc = malloc(sizeof(*fc), M_DEVBUF, M_WAITOK | M_ZERO); if (fc == NULL) return (0); - fc->fc_func = func; + fc->fc_func = (filt != NULL) ? filt : (driver_filter_t *)func; fc->fc_arg = arg; fc->fc_bt = bt; fc->fc_bh = bh; @@ -246,8 +249,12 @@ bus_space_write_4(bt, bh, FHC_IMAP, inr); bus_space_read_4(bt, bh, FHC_IMAP); - error = bus_generic_setup_intr(bus, child, r, flags, fhc_intr_stub, - fc, cookiep); + if (filt != NULL) + error = bus_generic_setup_intr(bus, child, r, flags, + fhc_intr_stub, NULL, fc, cookiep); + else + error = bus_generic_setup_intr(bus, child, r, flags, + NULL, (driver_intr_t *)fhc_intr_stub, fc, cookiep); if (error != 0) { free(fc, M_DEVBUF); return (error); @@ -276,7 +283,7 @@ return (error); } -static void +static int fhc_intr_stub(void *arg) { struct fhc_clr *fc = arg; @@ -285,6 +292,7 @@ bus_space_write_4(fc->fc_bt, fc->fc_bh, FHC_ICLR, 0x0); bus_space_read_4(fc->fc_bt, fc->fc_bh, FHC_ICLR); + return (FILTER_HANDLED); } struct resource * --- p4_head/sys/sparc64/include/intr_machdep.h Sun Jan 21 15:20:43 2007 +++ p4_head_intr/sys/sparc64/include/intr_machdep.h Fri Jan 26 13:54:09 2007 @@ -81,8 +81,8 @@ void *iva); void intr_init1(void); void intr_init2(void); -int inthand_add(const char *name, int vec, void (*handler)(void *), - void *arg, int flags, void **cookiep); +int inthand_add(const char *name, int vec, int (*filt)(void *), + void (*handler)(void *), void *arg, int flags, void **cookiep); int inthand_remove(int vec, void *cookie); ih_func_t intr_fast; --- p4_head/sys/sparc64/isa/isa.c Sun Jan 21 15:20:44 2007 +++ p4_head_intr/sys/sparc64/isa/isa.c Fri Jan 26 13:54:09 2007 @@ -387,8 +387,8 @@ int isa_setup_intr(device_t dev, device_t child, - struct resource *irq, int flags, - driver_intr_t *intr, void *arg, void **cookiep) + struct resource *irq, int flags, driver_filter_t *filter, + driver_intr_t *intr, void *arg, void **cookiep) { /* @@ -397,8 +397,8 @@ * The interrupt had been routed before it was added to the * resource list of the child. */ - return (BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags, intr, - arg, cookiep)); + return (BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags, + filter, intr, arg, cookiep)); } int --- p4_head/sys/sparc64/pci/psycho.c Sun Jan 21 15:20:44 2007 +++ p4_head_intr/sys/sparc64/pci/psycho.c Mon Feb 19 12:50:14 2007 @@ -81,20 +81,20 @@ const char *); static const struct psycho_desc *psycho_get_desc(phandle_t, const char *); static void psycho_set_intr(struct psycho_softc *, int, bus_addr_t, int, - driver_intr_t); + driver_filter_t); static int psycho_find_intrmap(struct psycho_softc *, int, bus_addr_t *, bus_addr_t *, u_long *); -static void psycho_intr_stub(void *); +static int psycho_intr_stub(void *); static bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int); /* Interrupt handlers */ -static void psycho_ue(void *); -static void psycho_ce(void *); -static void psycho_pci_bus(void *); -static void psycho_powerfail(void *); -static void psycho_overtemp(void *); +static int psycho_ue(void *); +static int psycho_ce(void *); +static int psycho_pci_bus(void *); +static int psycho_powerfail(void *); +static int psycho_overtemp(void *); #ifdef PSYCHO_MAP_WAKEUP -static void psycho_wakeup(void *); +static int psycho_wakeup(void *); #endif /* IOMMU support */ @@ -170,7 +170,7 @@ struct psycho_clr { struct psycho_softc *pci_sc; bus_addr_t pci_clr; /* clear register */ - driver_intr_t *pci_handler; /* handler to call */ + driver_filter_t *pci_handler; /* handler to call */ void *pci_arg; /* argument for the handler */ void *pci_cookie; /* parent bus int. cookie */ device_t pci_ppb; /* farest PCI-PCI bridge */ @@ -216,8 +216,11 @@ * On UltraII machines, there can be any number of "Psycho+" ICs, each * providing two PCI buses. */ + +#define FAST 0x66600000 + #ifdef DEBUGGER_ON_POWERFAIL -#define PSYCHO_PWRFAIL_INT_FLAGS INTR_FAST +#define PSYCHO_PWRFAIL_INT_FLAGS FAST #else #define PSYCHO_PWRFAIL_INT_FLAGS 0 #endif @@ -507,7 +510,7 @@ * interrupt but they are also only used for PCI bus A. */ psycho_set_intr(sc, 0, sc->sc_half == 0 ? PSR_PCIAERR_INT_MAP : - PSR_PCIBERR_INT_MAP, INTR_FAST, psycho_pci_bus); + PSR_PCIBERR_INT_MAP, FAST, psycho_pci_bus); /* * If we're a Hummingbird/Sabre or the first of a pair of Psycho's to @@ -523,7 +526,7 @@ * XXX Not all controllers have these, but installing them * is better than trying to sort through this mess. */ - psycho_set_intr(sc, 1, PSR_UE_INT_MAP, INTR_FAST, psycho_ue); + psycho_set_intr(sc, 1, PSR_UE_INT_MAP, FAST, psycho_ue); psycho_set_intr(sc, 2, PSR_CE_INT_MAP, 0, psycho_ce); psycho_set_intr(sc, 3, PSR_POWER_INT_MAP, PSYCHO_PWRFAIL_INT_FLAGS, psycho_powerfail); @@ -538,7 +541,7 @@ * The spare hardware interrupt is used for the * over-temperature interrupt. */ - psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, INTR_FAST, + psycho_set_intr(sc, 4, PSR_SPARE_INT_MAP, FAST, psycho_overtemp); #ifdef PSYCHO_MAP_WAKEUP /* @@ -678,19 +681,30 @@ static void psycho_set_intr(struct psycho_softc *sc, int index, bus_addr_t map, int iflags, - driver_intr_t handler) + driver_filter_t handler) { - int rid, vec; + int rid, vec, res; uint64_t mr; + res = EINVAL; rid = index; mr = PSYCHO_READ8(sc, map); vec = INTVEC(mr); sc->sc_irq_res[index] = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ, &rid, vec, vec, 1, RF_ACTIVE); - if (sc->sc_irq_res[index] == NULL || - bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC | - iflags, handler, sc, &sc->sc_ihand[index]) != 0) + if (sc->sc_irq_res[index] != NULL) { + if (iflags & FAST) { + iflags &= ~FAST; + res = bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], + INTR_TYPE_MISC | iflags, handler, NULL, sc, + &sc->sc_ihand[index]); + } else + res = bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], + INTR_TYPE_MISC | iflags, NULL, + (driver_intr_t *)handler, sc, + &sc->sc_ihand[index]); + } + if (res) panic("%s: failed to set up interrupt", __func__); PSYCHO_WRITE8(sc, map, INTMAP_ENABLE(mr, PCPU_GET(mid))); } @@ -749,7 +763,7 @@ /* * Interrupt handlers */ -static void +static int psycho_ue(void *arg) { struct psycho_softc *sc = arg; @@ -767,9 +781,10 @@ iommu_decode_fault(sc->sc_is, afar); panic("%s: uncorrectable DMA error AFAR %#lx AFSR %#lx", device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr); + return (FILTER_HANDLED); } -static void +static int psycho_ce(void *arg) { struct psycho_softc *sc = arg; @@ -782,9 +797,10 @@ /* Clear the error bits that we caught. */ PSYCHO_WRITE8(sc, PSR_CE_AFS, afsr & CEAFSR_ERRMASK); PSYCHO_WRITE8(sc, PSR_CE_INT_CLR, 0); + return (FILTER_HANDLED); } -static void +static int psycho_pci_bus(void *arg) { struct psycho_softc *sc = arg; @@ -795,9 +811,10 @@ panic("%s: PCI bus %c error AFAR %#lx AFSR %#lx", device_get_name(sc->sc_dev), 'A' + sc->sc_half, (u_long)afar, (u_long)afsr); + return (FILTER_HANDLED); } -static void +static int psycho_powerfail(void *arg) { @@ -810,18 +827,20 @@ printf("Power Failure Detected: Shutting down NOW.\n"); shutdown_nice(0); #endif + return (FILTER_HANDLED); } -static void +static int psycho_overtemp(void *arg) { printf("DANGER: OVER TEMPERATURE detected.\nShutting down NOW.\n"); shutdown_nice(RB_POWEROFF); + return (FILTER_HANDLED); } #ifdef PSYCHO_MAP_WAKEUP -static void +static int psycho_wakeup(void *arg) { struct psycho_softc *sc = arg; @@ -829,6 +848,7 @@ PSYCHO_WRITE8(sc, PSR_PWRMGT_INT_CLR, 0); /* Gee, we don't really have a framework to deal with this properly. */ device_printf(sc->sc_dev, "power management wakeup\n"); + return (FILTER_HANDLED); } #endif /* PSYCHO_MAP_WAKEUP */ @@ -988,7 +1008,7 @@ } /* Write to the correct clr register, and call the actual handler. */ -static void +static int psycho_intr_stub(void *arg) { struct psycho_clr *pc = arg; @@ -1000,11 +1020,13 @@ } pc->pci_handler(pc->pci_arg); PSYCHO_WRITE8(pc->pci_sc, pc->pci_clr, 0); + return (FILTER_HANDLED); } static int psycho_setup_intr(device_t dev, device_t child, struct resource *ires, - int flags, driver_intr_t *intr, void *arg, void **cookiep) + int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, + void **cookiep) { struct { int apb:1; @@ -1019,6 +1041,9 @@ uint64_t mr; int error, ino; + if (filt != NULL && intr != NULL) + return (EINVAL); + sc = device_get_softc(dev); pc = malloc(sizeof(*pc), M_DEVBUF, M_NOWAIT | M_ZERO); if (pc == NULL) @@ -1048,7 +1073,7 @@ pc->pci_sc = sc; pc->pci_arg = arg; - pc->pci_handler = intr; + pc->pci_handler = (filt != NULL) ? filt : (driver_filter_t *)intr; pc->pci_clr = intrclrptr; /* @@ -1104,8 +1129,12 @@ /* Disable the interrupt while we fiddle with it. */ mr = PSYCHO_READ8(sc, intrmapptr); PSYCHO_WRITE8(sc, intrmapptr, mr & ~INTMAP_V); - error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, - psycho_intr_stub, pc, cookiep); + if (filt != NULL) + error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, + psycho_intr_stub, NULL, pc, cookiep); + else + error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, + NULL, (driver_intr_t *)psycho_intr_stub, pc, cookiep); if (error != 0) { free(pc, M_DEVBUF); return (error); --- p4_head/sys/sparc64/sbus/sbus.c Sun Jan 21 15:20:45 2007 +++ p4_head_intr/sys/sparc64/sbus/sbus.c Mon Feb 19 13:49:46 2007 @@ -181,7 +181,7 @@ struct sbus_clr { struct sbus_softc *scl_sc; bus_addr_t scl_clr; /* clear register */ - driver_intr_t *scl_handler; /* handler to call */ + driver_filter_t *scl_handler; /* handler to call */ void *scl_arg; /* argument for the handler */ void *scl_cookie; /* parent bus int. cookie */ }; @@ -209,10 +209,10 @@ static struct sbus_devinfo * sbus_setup_dinfo(device_t, struct sbus_softc *, phandle_t); static void sbus_destroy_dinfo(struct sbus_devinfo *); -static void sbus_intr_stub(void *); +static int sbus_intr_stub(void *); static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *); -static void sbus_overtemp(void *); -static void sbus_pwrfail(void *); +static int sbus_overtemp(void *); +static int sbus_pwrfail(void *); static int sbus_print_res(struct sbus_devinfo *); static device_method_t sbus_methods[] = { @@ -433,8 +433,8 @@ sc->sc_ot_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, vec, vec, 1, RF_ACTIVE); if (sc->sc_ot_ires == NULL || - bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_FAST, - sbus_overtemp, sc, &sc->sc_ot_ihand) != 0) + bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC, + sbus_overtemp, NULL, sc, &sc->sc_ot_ihand) != 0) panic("%s: failed to set up temperature interrupt", __func__); SYSIO_WRITE8(sc, SBR_THERM_INT_MAP, INTMAP_ENABLE(mr, PCPU_GET(mid))); rid = 0; @@ -443,8 +443,8 @@ sc->sc_pf_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, vec, vec, 1, RF_ACTIVE); if (sc->sc_pf_ires == NULL || - bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_FAST, - sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0) + bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC, + sbus_pwrfail, NULL, sc, &sc->sc_pf_ihand) != 0) panic("%s: failed to set up power fail interrupt", __func__); SYSIO_WRITE8(sc, SBR_POWER_INT_MAP, INTMAP_ENABLE(mr, PCPU_GET(mid))); @@ -637,7 +637,7 @@ } /* Write to the correct clr register, and call the actual handler. */ -static void +static int sbus_intr_stub(void *arg) { struct sbus_clr *scl; @@ -645,11 +645,12 @@ scl = (struct sbus_clr *)arg; scl->scl_handler(scl->scl_arg); SYSIO_WRITE8(scl->scl_sc, scl->scl_clr, 0); + return (FILTER_HANDLED); } static int sbus_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, - driver_intr_t *intr, void *arg, void **cookiep) + driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { struct sbus_softc *sc; struct sbus_clr *scl; @@ -659,6 +660,8 @@ int error, i; long vec; + if (filt != NULL && intr != NULL) + return (EINVAL); sc = device_get_softc(dev); scl = (struct sbus_clr *)malloc(sizeof(*scl), M_DEVBUF, M_NOWAIT); if (scl == NULL) @@ -697,12 +700,17 @@ scl->scl_sc = sc; scl->scl_arg = arg; - scl->scl_handler = intr; + scl->scl_handler = (filt != NULL) ? filt : (driver_filter_t *)intr; scl->scl_clr = intrclrptr; /* Disable the interrupt while we fiddle with it */ SYSIO_WRITE8(sc, intrmapptr, intrmap & ~INTMAP_V); - error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, - sbus_intr_stub, scl, cookiep); + if (filt != NULL) + error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, + flags, sbus_intr_stub, NULL, scl, cookiep); + else + error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, + flags, NULL, (driver_intr_t *)sbus_intr_stub, scl, + cookiep); if (error != 0) { free(scl, M_DEVBUF); return (error); @@ -913,21 +921,23 @@ * This handles the interrupt and powers off the machine. * The same needs to be done to PCI controller drivers. */ -static void +static int sbus_overtemp(void *arg) { printf("DANGER: OVER TEMPERATURE detected\nShutting down NOW.\n"); shutdown_nice(RB_POWEROFF); + return (FILTER_HANDLED); } /* Try to shut down in time in case of power failure. */ -static void +static int sbus_pwrfail(void *arg) { printf("Power failure detected\nShutting down NOW.\n"); shutdown_nice(0); + return (FILTER_HANDLED); } static bus_space_tag_t --- p4_head/sys/sparc64/sparc64/intr_machdep.c Sun Jan 21 15:20:45 2007 +++ p4_head_intr/sys/sparc64/sparc64/intr_machdep.c Fri Jan 26 13:54:09 2007 @@ -248,14 +248,14 @@ /* Execute fast interrupt handlers directly. */ thread = 0; TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { - if (!(ih->ih_flags & IH_FAST)) { + if (ih->ih_filter == NULL) { thread = 1; continue; } - MPASS(ih->ih_flags & IH_FAST && ih->ih_argument != NULL); + MPASS(ih->ih_filter != NULL && ih->ih_argument != NULL); CTR3(KTR_INTR, "%s: executing handler %p(%p)", __func__, - ih->ih_handler, ih->ih_argument); - ih->ih_handler(ih->ih_argument); + ih->ih_filter, ih->ih_argument); + ih->ih_filter(ih->ih_argument); } /* Schedule a heavyweight interrupt process. */ @@ -270,8 +270,8 @@ } int -inthand_add(const char *name, int vec, void (*handler)(void *), void *arg, - int flags, void **cookiep) +inthand_add(const char *name, int vec, driver_filter_t *filt, + void (*handler)(void *), void *arg, int flags, void **cookiep) { struct intr_vector *iv; struct intr_event *ie; /* descriptor for the IRQ */ @@ -303,12 +303,12 @@ } } - errcode = intr_event_add_handler(ie, name, handler, arg, + errcode = intr_event_add_handler(ie, name, filt, handler, arg, intr_priority(flags), flags, cookiep); if (errcode) return (errcode); - intr_setup(flags & INTR_FAST ? PIL_FAST : PIL_ITHREAD, intr_fast, vec, + intr_setup(filt != NULL ? PIL_FAST : PIL_ITHREAD, intr_fast, vec, intr_execute_handlers, iv); intr_stray_count[vec] = 0; --- p4_head/sys/sparc64/sparc64/nexus.c Sun Jan 21 15:20:46 2007 +++ p4_head_intr/sys/sparc64/sparc64/nexus.c Fri Jan 26 13:54:09 2007 @@ -313,7 +313,7 @@ static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, - driver_intr_t *intr, void *arg, void **cookiep) + driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { int error; @@ -329,7 +329,7 @@ return (error); error = inthand_add(device_get_nameunit(child), rman_get_start(res), - intr, arg, flags, cookiep); + filt, intr, arg, flags, cookiep); return (error); } --- p4_head/sys/sparc64/sparc64/upa.c Sun Jan 21 15:20:46 2007 +++ p4_head_intr/sys/sparc64/sparc64/upa.c Fri Jan 26 13:54:09 2007 @@ -401,7 +401,7 @@ static int upa_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, - driver_intr_t *func, void *arg, void **cookiep) + driver_filter_t *filt, driver_intr_t *func, void *arg, void **cookiep) { struct upa_softc *sc; uint64_t intrmap; @@ -427,7 +427,7 @@ UPA_WRITE(sc, imr, 0x0, intrmap & ~INTMAP_V); (void)UPA_READ(sc, imr, 0x0); - error = bus_generic_setup_intr(dev, child, ires, flags, func, arg, + error = bus_generic_setup_intr(dev, child, ires, flags, filt, func, arg, cookiep); if (error != 0) return (error);