diff --git a/sys/arm/allwinner/aw_nmi.c b/sys/arm/allwinner/aw_nmi.c index febf970c7ffbc2..466d12ac725c1e 100644 --- a/sys/arm/allwinner/aw_nmi.c +++ b/sys/arm/allwinner/aw_nmi.c @@ -255,7 +255,8 @@ aw_nmi_setup_intr(device_t dev, struct intr_irqsrc *isrc, return (EINVAL); /* Compare config if this is not first setup. */ - if (isrc->isrc_handlers != 0) { + if (nmi_intr->pol != INTR_POLARITY_INVALID || + nmi_intr->tri != INTR_TRIGGER_INVALID) { if (pol != nmi_intr->pol || trig != nmi_intr->tri) return (EINVAL); else @@ -290,9 +291,9 @@ aw_nmi_teardown_intr(device_t dev, struct intr_irqsrc *isrc, sc = device_get_softc(dev); - if (isrc->isrc_handlers == 0) { - sc->intr.pol = INTR_POLARITY_CONFORM; - sc->intr.tri = INTR_TRIGGER_CONFORM; + if (ISRC_NO_HANDLER(isrc)) { + sc->intr.pol = INTR_POLARITY_INVALID; + sc->intr.tri = INTR_TRIGGER_INVALID; SC_NMI_WRITE(sc, sc->cfg->enable_reg, ~NMI_IRQ_ENABLE); } @@ -371,8 +372,8 @@ aw_nmi_attach(device_t dev) xref = OF_xref_from_node(ofw_bus_get_node(dev)); /* Register our isrc */ sc->intr.irq = 0; - sc->intr.pol = INTR_POLARITY_CONFORM; - sc->intr.tri = INTR_TRIGGER_CONFORM; + sc->intr.pol = INTR_POLARITY_INVALID; + sc->intr.tri = INTR_TRIGGER_INVALID; if (intr_isrc_register(&sc->intr.isrc, sc->dev, 0, "%s,%u", device_get_nameunit(sc->dev), sc->intr.irq) != 0) goto error; diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c index b1b7aacd63abb2..1015e9f7de090c 100644 --- a/sys/arm/arm/gic.c +++ b/sys/arm/arm/gic.c @@ -254,8 +254,8 @@ arm_gic_register_isrcs(struct arm_gic_softc *sc, uint32_t num) name = device_get_nameunit(sc->gic_dev); for (irq = 0; irq < num; irq++) { irqs[irq].gi_irq = irq; - irqs[irq].gi_pol = INTR_POLARITY_CONFORM; - irqs[irq].gi_trig = INTR_TRIGGER_CONFORM; + irqs[irq].gi_pol = INTR_POLARITY_INVALID; + irqs[irq].gi_trig = INTR_TRIGGER_INVALID; isrc = &irqs[irq].gi_isrc; if (irq <= GIC_LAST_SGI) { @@ -291,7 +291,7 @@ arm_gic_reserve_msi_range(device_t dev, u_int start, u_int count) ("%s: Trying to allocate too many MSI IRQs: %d + %d > %d", __func__, start, count, sc->nirqs)); for (i = 0; i < count; i++) { - KASSERT(sc->gic_irqs[start + i].gi_isrc.isrc_handlers == 0, + KASSERT(ISRC_NO_HANDLER(&sc->gic_irqs[start + i].gi_isrc), ("%s: MSI interrupt %d already has a handler", __func__, count + i)); KASSERT(sc->gic_irqs[start + i].gi_pol == INTR_POLARITY_CONFORM, @@ -867,7 +867,8 @@ arm_gic_setup_intr(device_t dev, struct intr_irqsrc *isrc, } /* Compare config if this is not first setup. */ - if (isrc->isrc_handlers != 0) { + if (gi->gi_pol != INTR_POLARITY_INVALID || + gi->gi_trig != INTR_TRIGGER_INVALID) { if ((pol != INTR_POLARITY_CONFORM && pol != gi->gi_pol) || (trig != INTR_TRIGGER_CONFORM && trig != gi->gi_trig)) return (EINVAL); @@ -911,9 +912,9 @@ arm_gic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, { struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc; - if (isrc->isrc_handlers == 0 && (gi->gi_flags & GI_FLAG_MSI) == 0) { - gi->gi_pol = INTR_POLARITY_CONFORM; - gi->gi_trig = INTR_TRIGGER_CONFORM; + if (ISRC_NO_HANDLER(isrc) && (gi->gi_flags & GI_FLAG_MSI) == 0) { + gi->gi_pol = INTR_POLARITY_INVALID; + gi->gi_trig = INTR_TRIGGER_INVALID; } return (0); } diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c index e4fc57b79ba58a..52d27905d64b27 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c @@ -998,7 +998,7 @@ bcm_gpio_pic_attach(struct bcm_gpio_softc *sc) for (irq = 0; irq < sc->sc_maxpins; irq++) { sc->sc_isrcs[irq].bgi_irq = irq; sc->sc_isrcs[irq].bgi_mask = BCM_GPIO_MASK(irq); - sc->sc_isrcs[irq].bgi_mode = GPIO_INTR_CONFORM; + sc->sc_isrcs[irq].bgi_mode = GPIO_INTR_INVALID; error = intr_isrc_register(&sc->sc_isrcs[irq].bgi_isrc, sc->sc_dev, 0, "%s,%u", name, irq); @@ -1211,7 +1211,7 @@ bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, * If this is a setup for another handler, * only check that its configuration match. */ - if (isrc->isrc_handlers != 0) + if (bgi->bgi_mode == GPIO_INTR_INVALID) return (bgi->bgi_mode == mode ? 0 : EINVAL); bcm_gpio_pic_config_intr(sc, bgi, mode); @@ -1225,7 +1225,7 @@ bcm_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, struct bcm_gpio_softc *sc = device_get_softc(dev); struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc; - if (isrc->isrc_handlers == 0) + if (ISRC_NO_HANDLER(isrc)) bcm_gpio_pic_config_intr(sc, bgi, GPIO_INTR_CONFORM); return (0); } diff --git a/sys/arm/broadcom/bcm2835/bcm2836.c b/sys/arm/broadcom/bcm2835/bcm2836.c index 7ed9dedaa77ebb..889745031b82da 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836.c +++ b/sys/arm/broadcom/bcm2835/bcm2836.c @@ -506,7 +506,7 @@ bcm_lintc_setup_intr(device_t dev, struct intr_irqsrc *isrc, { struct bcm_lintc_softc *sc; - if (isrc->isrc_handlers == 0 && isrc->isrc_flags & INTR_ISRCF_PPI) { + if (ISRC_NO_HANDLER(isrc) && isrc->isrc_flags & INTR_ISRCF_PPI) { sc = device_get_softc(dev); BCM_LINTC_LOCK(sc); CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu); diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c index 7610d28af90e99..cab3f68496967f 100644 --- a/sys/arm/freescale/imx/imx_gpio.c +++ b/sys/arm/freescale/imx/imx_gpio.c @@ -301,9 +301,9 @@ gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, struct gpio_irqsrc *gi; sc = device_get_softc(dev); - if (isrc->isrc_handlers == 0) { + if (ISRC_NO_HANDLER(isrc)) { gi = (struct gpio_irqsrc *)isrc; - gi->gi_mode = GPIO_INTR_CONFORM; + gi->gi_mode = GPIO_INTR_INVALID; // XXX Not sure this is necessary mtx_lock_spin(&sc->sc_mtx); @@ -338,7 +338,7 @@ gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, return (EINVAL); /* Compare config if this is not first setup. */ - if (isrc->isrc_handlers != 0) + if (gi->gi_mode == GPIO_INTR_INVALID) return (gi->gi_mode == mode ? 0 : EINVAL); gi->gi_mode = mode; @@ -497,7 +497,7 @@ gpio_pic_register_isrcs(struct imx51_gpio_softc *sc) name = device_get_nameunit(sc->dev); for (irq = 0; irq < NGPIO; irq++) { sc->gpio_pic_irqsrc[irq].gi_irq = irq; - sc->gpio_pic_irqsrc[irq].gi_mode = GPIO_INTR_CONFORM; + sc->gpio_pic_irqsrc[irq].gi_mode = GPIO_INTR_INVALID; error = intr_isrc_register(&sc->gpio_pic_irqsrc[irq].gi_isrc, sc->dev, 0, "%s,%u", name, irq); diff --git a/sys/arm/mv/mvebu_gpio.c b/sys/arm/mv/mvebu_gpio.c index a2001589867c0b..cef27050434766 100644 --- a/sys/arm/mv/mvebu_gpio.c +++ b/sys/arm/mv/mvebu_gpio.c @@ -86,6 +86,7 @@ struct mvebu_gpio_irqsrc { u_int irq; bool is_level; bool is_inverted; + bool is_setup; }; struct mvebu_gpio_softc; @@ -359,6 +360,7 @@ mvebu_gpio_pic_attach(struct mvebu_gpio_softc *sc) sc->isrcs[irq].irq = irq; sc->isrcs[irq].is_level = false; sc->isrcs[irq].is_inverted = false; + sc->isrcs[irq].is_setup = false; rv = intr_isrc_register(&sc->isrcs[irq].isrc, sc->dev, 0, "%s,%u", name, irq); if (rv != 0) @@ -597,13 +599,14 @@ mvebu_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, * If this is a setup for another handler, * only check that its configuration match. */ - if (isrc->isrc_handlers != 0) + if (mgi->is_setup) return ( mgi->is_level == level && mgi->is_inverted == inverted ? 0 : EINVAL); mgi->is_level = level; mgi->is_inverted = inverted; + mgi->is_setup = true; GPIO_LOCK(sc); intr_modify(sc, GPIO_DATA_IN_POL, mgi, inverted ? 1 : 0); @@ -623,8 +626,10 @@ mvebu_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, sc = device_get_softc(dev); mgi = (struct mvebu_gpio_irqsrc *)isrc; - if (isrc->isrc_handlers == 0) + if (ISRC_NO_HANDLER(isrc)) { mvebu_gpio_isrc_mask(sc, mgi, 0); + mgi->is_setup = false; + } return (0); } diff --git a/sys/arm/nvidia/tegra_gpio.c b/sys/arm/nvidia/tegra_gpio.c index 29bc8624e27ad5..e55170fe23828c 100644 --- a/sys/arm/nvidia/tegra_gpio.c +++ b/sys/arm/nvidia/tegra_gpio.c @@ -97,6 +97,8 @@ #define GPIO_MSK_INT_ENB 0xD0 #define GPIO_MSK_INT_LVL 0xE0 +#define GPIO_UNSET 0xFFFFFFFF + char *tegra_gpio_port_names[] = { "A", "B", "C", "D", /* Bank 0 */ "E", "F", "G", "H", /* Bank 1 */ @@ -443,7 +445,7 @@ tegra_gpio_pic_attach(struct tegra_gpio_softc *sc) name = device_get_nameunit(sc->dev); for (irq = 0; irq < sc->gpio_npins; irq++) { sc->isrcs[irq].irq = irq; - sc->isrcs[irq].cfgreg = 0; + sc->isrcs[irq].cfgreg = GPIO_UNSET; error = intr_isrc_register(&sc->isrcs[irq].isrc, sc->dev, 0, "%s,%u", name, irq); if (error != 0) @@ -672,12 +674,11 @@ tegra_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, * If this is a setup for another handler, * only check that its configuration match. */ - if (isrc->isrc_handlers != 0) + if (tgi->cfgreg != GPIO_UNSET) return (tgi->cfgreg == cfgreg ? 0 : EINVAL); tgi->cfgreg = cfgreg; intr_write_modify(sc, GPIO_INT_LVL, tgi, cfgreg, GPIO_INT_LVL_MASK); - tegra_gpio_pic_enable_intr(dev, isrc); return (0); } @@ -686,14 +687,13 @@ static int tegra_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { - struct tegra_gpio_softc *sc; struct tegra_gpio_irqsrc *tgi; - sc = device_get_softc(dev); tgi = (struct tegra_gpio_irqsrc *)isrc; - if (isrc->isrc_handlers == 0) - tegra_gpio_isrc_mask(sc, tgi, 0); + if (ISRC_NO_HANDLER(isrc)) + tgi->cfgreg = GPIO_UNSET; + return (0); } diff --git a/sys/arm/nvidia/tegra_pcie.c b/sys/arm/nvidia/tegra_pcie.c index 2a91a81d40a913..e368768965a44a 100644 --- a/sys/arm/nvidia/tegra_pcie.c +++ b/sys/arm/nvidia/tegra_pcie.c @@ -709,6 +709,7 @@ tegra_pcib_msi_pre_ithread(device_t dev, struct intr_irqsrc *isrc) { } +#if defined(WITNESS) || defined(INVARIANTS) static int tegra_pcib_msi_setup_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) @@ -716,26 +717,9 @@ tegra_pcib_msi_setup_intr(device_t dev, struct intr_irqsrc *isrc, if (data == NULL || data->type != INTR_MAP_DATA_MSI) return (ENOTSUP); - if (isrc->isrc_handlers == 0) - tegra_pcib_msi_enable_intr(dev, isrc); - - return (0); -} - -static int -tegra_pcib_msi_teardown_intr(device_t dev, struct intr_irqsrc *isrc, - struct resource *res, struct intr_map_data *data) -{ - struct tegra_pcib_softc *sc; - struct tegra_pcib_irqsrc *tgi; - - sc = device_get_softc(dev); - tgi = (struct tegra_pcib_irqsrc *)isrc; - - if (isrc->isrc_handlers == 0) - tegra_pcib_isrc_mask(sc, tgi, 0); return (0); } +#endif static int tegra_pcib_msi_alloc_msi(device_t dev, device_t child, int count, int maxcount, @@ -1602,8 +1586,9 @@ static device_method_t tegra_pcib_methods[] = { /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, tegra_pcib_msi_disable_intr), DEVMETHOD(pic_enable_intr, tegra_pcib_msi_enable_intr), +#if defined(WITNESS) || defined(INVARIANTS) DEVMETHOD(pic_setup_intr, tegra_pcib_msi_setup_intr), - DEVMETHOD(pic_teardown_intr, tegra_pcib_msi_teardown_intr), +#endif DEVMETHOD(pic_post_filter, tegra_pcib_msi_post_filter), DEVMETHOD(pic_post_ithread, tegra_pcib_msi_post_ithread), DEVMETHOD(pic_pre_ithread, tegra_pcib_msi_pre_ithread), diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c index 964a129111e274..1bfac900e5ccb3 100644 --- a/sys/arm64/arm64/gic_v3.c +++ b/sys/arm64/arm64/gic_v3.c @@ -276,7 +276,7 @@ gic_v3_reserve_msi_range(device_t dev, u_int start, u_int count) ("%s: Trying to allocate too many MSI IRQs: %d + %d > %d", __func__, start, count, sc->gic_nirqs)); for (i = 0; i < count; i++) { - KASSERT(sc->gic_irqs[start + i].gi_isrc.isrc_handlers == 0, + KASSERT(ISRC_NO_HANDLER(&sc->gic_irqs[start + i].gi_isrc), ("%s: MSI interrupt %d already has a handler", __func__, count + i)); KASSERT(sc->gic_irqs[start + i].gi_pol == INTR_POLARITY_CONFORM, @@ -360,8 +360,8 @@ gic_v3_attach(device_t dev) struct intr_irqsrc *isrc; sc->gic_irqs[irq].gi_irq = irq; - sc->gic_irqs[irq].gi_pol = INTR_POLARITY_CONFORM; - sc->gic_irqs[irq].gi_trig = INTR_TRIGGER_CONFORM; + sc->gic_irqs[irq].gi_pol = INTR_POLARITY_INVALID; + sc->gic_irqs[irq].gi_trig = INTR_TRIGGER_INVALID; isrc = &sc->gic_irqs[irq].gi_isrc; if (irq <= GIC_LAST_SGI) { @@ -913,7 +913,8 @@ gic_v3_setup_intr(device_t dev, struct intr_irqsrc *isrc, return (EINVAL); /* Compare config if this is not first setup. */ - if (isrc->isrc_handlers != 0) { + if (gi->gi_pol != INTR_POLARITY_INVALID || + gi->gi_trig != INTR_TRIGGER_INVALID) { if (pol != gi->gi_pol || trig != gi->gi_trig) return (EINVAL); else @@ -950,9 +951,9 @@ gic_v3_teardown_intr(device_t dev, struct intr_irqsrc *isrc, { struct gic_v3_irqsrc *gi = (struct gic_v3_irqsrc *)isrc; - if (isrc->isrc_handlers == 0 && (gi->gi_flags & GI_FLAG_MSI) == 0) { - gi->gi_pol = INTR_POLARITY_CONFORM; - gi->gi_trig = INTR_TRIGGER_CONFORM; + if (ISRC_NO_HANDLER(isrc) && (gi->gi_flags & GI_FLAG_MSI) == 0) { + gi->gi_pol = INTR_POLARITY_INVALID; + gi->gi_trig = INTR_TRIGGER_INVALID; } return (0); diff --git a/sys/arm64/qoriq/qoriq_gpio_pic.c b/sys/arm64/qoriq/qoriq_gpio_pic.c index ec84d2a14ae7ae..570d6ee78d30bb 100644 --- a/sys/arm64/qoriq/qoriq_gpio_pic.c +++ b/sys/arm64/qoriq/qoriq_gpio_pic.c @@ -266,7 +266,7 @@ qoriq_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, sc = device_get_softc(dev); qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc; - if (isrc->isrc_handlers > 0) + if (!ISRC_NO_HANDLER(isrc)) return (0); GPIO_LOCK(&sc->base); diff --git a/sys/arm64/rockchip/rk_gpio.c b/sys/arm64/rockchip/rk_gpio.c index a86392f1662406..dd60898963c51f 100644 --- a/sys/arm64/rockchip/rk_gpio.c +++ b/sys/arm64/rockchip/rk_gpio.c @@ -347,7 +347,7 @@ rk_gpio_attach(device_t dev) for (i = 0; i < RK_GPIO_MAX_PINS; i++) { sc->isrcs[i].irq = i; - sc->isrcs[i].mode = GPIO_INTR_CONFORM; + sc->isrcs[i].mode = GPIO_INTR_INVALID; if ((err = intr_isrc_register(RK_GPIO_ISRC(sc, i), dev, 0, "%s", device_get_nameunit(dev)))) { device_printf(dev, "Can not register isrc %d\n", err); @@ -697,7 +697,7 @@ rk_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, return (EINVAL); } - if (isrc->isrc_handlers != 0) { + if (rkisrc->mode == GPIO_INTR_INVALID) { device_printf(dev, "Handler already attached\n"); return (rkisrc->mode == mode ? 0 : EINVAL); } @@ -762,8 +762,8 @@ rk_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, irqsrc = (struct rk_pin_irqsrc *)isrc; - if (isrc->isrc_handlers == 0) { - irqsrc->mode = GPIO_INTR_CONFORM; + if (ISRC_NO_HANDLER(isrc)) { + irqsrc->mode = GPIO_INTR_INVALID; RK_GPIO_LOCK(sc); rk_gpio_write_bit(sc, RK_GPIO_INTEN, irqsrc->irq, 0); rk_gpio_write_bit(sc, RK_GPIO_INTMASK, irqsrc->irq, 0); diff --git a/sys/dev/gpio/pl061.c b/sys/dev/gpio/pl061.c index cc39790322b6b1..ac2c7368caa446 100644 --- a/sys/dev/gpio/pl061.c +++ b/sys/dev/gpio/pl061.c @@ -318,7 +318,7 @@ pl061_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, return (EINVAL); } - if (isrc->isrc_handlers != 0) { + if (irqsrc->mode == GPIO_INTR_INVALID) { dprintf("%s: handler already attached\n", __func__); return (irqsrc->mode == mode ? 0 : EINVAL); } @@ -363,8 +363,8 @@ pl061_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, dprintf("%s: calling teardown interrupt %#x\n", __func__, mask); sc = device_get_softc(dev); - if (isrc->isrc_handlers == 0) { - irqsrc->mode = GPIO_INTR_CONFORM; + if (ISRC_NO_HANDLER(isrc)) { + irqsrc->mode = GPIO_INTR_INVALID; PL061_LOCK(sc); mask_and_set(sc, PL061_INTMASK, mask, 0); PL061_UNLOCK(sc); @@ -478,7 +478,7 @@ pl061_attach(device_t dev) "trying to register pin %d name %s\n", irq, name); } sc->sc_isrcs[irq].irq = irq; - sc->sc_isrcs[irq].mode = GPIO_INTR_CONFORM; + sc->sc_isrcs[irq].mode = GPIO_INTR_INVALID; ret = intr_isrc_register(PIC_INTR_ISRC(sc, irq), dev, 0, "%s", name); if (ret) { diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index b8d85bf20f289b..9477d997ba1e25 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -568,7 +568,7 @@ bool intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu) { - if (isrc->isrc_handlers == 0) + if (ISRC_NO_HANDLER(isrc)) return (false); if ((isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI)) == 0) return (false); @@ -1091,6 +1091,7 @@ intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, struct intr_irqsrc *isrc; const char *name; u_int res_id; + bool startempty; KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); @@ -1105,6 +1106,8 @@ intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, data = rman_get_virtual(res); name = device_get_nameunit(dev); + startempty = ISRC_NO_HANDLER(isrc); + #ifdef INTR_SOLO /* * Standard handling is done through MI interrupt framework. However, @@ -1139,8 +1142,7 @@ intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, mtx_lock(&isrc_table_lock); error = PIC_SETUP_INTR(isrc->isrc_dev, isrc, res, data); if (error == 0) { - isrc->isrc_handlers++; - if (isrc->isrc_handlers == 1) + if (startempty) PIC_ENABLE_INTR(isrc->isrc_dev, isrc); } mtx_unlock(&isrc_table_lock); @@ -1162,7 +1164,7 @@ intr_teardown_irq(device_t dev, struct resource *res, void *cookie) res_id = (u_int)rman_get_start(res); isrc = intr_map_get_isrc(res_id); - if (isrc == NULL || isrc->isrc_handlers == 0) + if (isrc == NULL || ISRC_NO_HANDLER(isrc)) return (EINVAL); data = rman_get_virtual(res); @@ -1189,8 +1191,7 @@ intr_teardown_irq(device_t dev, struct resource *res, void *cookie) error = intr_event_remove_handler(cookie); if (error == 0) { mtx_lock(&isrc_table_lock); - isrc->isrc_handlers--; - if (isrc->isrc_handlers == 0) + if (ISRC_NO_HANDLER(isrc)) PIC_DISABLE_INTR(isrc->isrc_dev, isrc); PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data); intrcnt_updatename(isrc); @@ -1212,7 +1213,7 @@ intr_describe_irq(device_t dev, struct resource *res, void *cookie, res_id = (u_int)rman_get_start(res); isrc = intr_map_get_isrc(res_id); - if (isrc == NULL || isrc->isrc_handlers == 0) + if (isrc == NULL || ISRC_NO_HANDLER(isrc)) return (EINVAL); #ifdef INTR_SOLO if (isrc->isrc_filter != NULL) { @@ -1246,7 +1247,7 @@ intr_bind_irq(device_t dev, struct resource *res, int cpu) res_id = (u_int)rman_get_start(res); isrc = intr_map_get_isrc(res_id); - if (isrc == NULL || isrc->isrc_handlers == 0) + if (isrc == NULL || ISRC_NO_HANDLER(isrc)) return (EINVAL); #ifdef INTR_SOLO if (isrc->isrc_filter != NULL) @@ -1300,7 +1301,7 @@ intr_irq_shuffle(void *arg __unused) irq_assign_cpu = true; for (i = 0; i < intr_nirq; i++) { isrc = irq_sources[i]; - if (isrc == NULL || isrc->isrc_handlers == 0 || + if (isrc == NULL || ISRC_NO_HANDLER(isrc) || isrc->isrc_flags & (INTR_ISRCF_PPI | INTR_ISRCF_IPI)) continue; @@ -1871,6 +1872,21 @@ intr_ipi_pic_register(device_t dev, u_int priority) return (0); } +/* + * Handler for flagging IPIs called via intr_event_handle() as stray. + */ +static int +isrc_ipi_strayfunc(void *_isrc) +{ + struct intr_irqsrc *isrc = _isrc; + + printf("ERROR: %s(): IPI for \"%s\" called via intr_event_handle()!\n", + __func__, isrc->isrc_event->ie_name); + + /* ensure PIC_DISABLE_INTR() is NOT called */ + return (FILTER_HANDLED); +} + /* * Setup IPI handler on interrupt controller. * @@ -1898,7 +1914,8 @@ intr_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand, if (error != 0) return; - isrc->isrc_handlers++; + intr_event_add_handler(isrc->isrc_event, name, isrc_ipi_strayfunc, + NULL, isrc, PI_INTR, 0, NULL); ii = intr_ipi_lookup(ipi); KASSERT(ii->ii_count == NULL, ("%s: ipi %u reused", __func__, ipi)); diff --git a/sys/sys/bus.h b/sys/sys/bus.h index 1f5e074cfe5a04..4dd28babf84710 100644 --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -291,6 +291,7 @@ enum intr_trigger { }; enum intr_polarity { + INTR_POLARITY_INVALID = -1, INTR_POLARITY_CONFORM = 0, INTR_POLARITY_HIGH = 1, INTR_POLARITY_LOW = 2 diff --git a/sys/sys/gpio.h b/sys/sys/gpio.h index 1a9e998a0e5692..f3b9919f72ff58 100644 --- a/sys/sys/gpio.h +++ b/sys/sys/gpio.h @@ -63,6 +63,7 @@ #define GPIOMAXNAME 64 /* GPIO pin configuration flags */ +#define GPIO_PIN_INVALID 0x0000FFFF /* invalid pin value */ #define GPIO_PIN_INPUT 0x00000001 /* input direction */ #define GPIO_PIN_OUTPUT 0x00000002 /* output direction */ #define GPIO_PIN_OPENDRAIN 0x00000004 /* open-drain output */ @@ -77,6 +78,7 @@ #define GPIO_PIN_PRESET_HIGH 0x00000800 /* low before enabling output */ /* GPIO interrupt capabilities */ #define GPIO_INTR_NONE 0x00000000 /* no interrupt support */ +#define GPIO_INTR_INVALID 0xFFFF0000 /* invalid interrupt value */ #define GPIO_INTR_LEVEL_LOW 0x00010000 /* level trigger, low */ #define GPIO_INTR_LEVEL_HIGH 0x00020000 /* level trigger, high */ #define GPIO_INTR_EDGE_RISING 0x00040000 /* edge trigger, rising */ diff --git a/sys/sys/intr.h b/sys/sys/intr.h index f11e96777927a9..e0bff6546f5146 100644 --- a/sys/sys/intr.h +++ b/sys/sys/intr.h @@ -34,6 +34,8 @@ #endif #include +#include +#include #include @@ -90,7 +92,6 @@ struct intr_irqsrc { cpuset_t isrc_cpu; /* on which CPUs is enabled */ u_int isrc_index; u_long * isrc_count; - u_int isrc_handlers; struct intr_event * isrc_event; #ifdef INTR_SOLO intr_irq_filter_t * isrc_filter; @@ -100,6 +101,9 @@ struct intr_irqsrc { void * isrc_iommu; }; +/* Macros for PIC usage. */ +#define ISRC_NO_HANDLER(isrc) CK_SLIST_EMPTY(&(isrc)->isrc_event->ie_handlers) + /* Intr interface for PIC. */ int intr_isrc_deregister(struct intr_irqsrc *); int intr_isrc_register(struct intr_irqsrc *, device_t, u_int, const char *, ...) diff --git a/sys/x86/include/intr_machdep.h b/sys/x86/include/intr_machdep.h index d7bfcdc126a9e4..89859804e0ff7f 100644 --- a/sys/x86/include/intr_machdep.h +++ b/sys/x86/include/intr_machdep.h @@ -111,7 +111,6 @@ struct intsrc { u_long *is_count; u_long *is_straycount; u_int is_index; - u_int is_handlers; u_int is_domain; u_int is_cpu; }; diff --git a/sys/x86/isa/clock.c b/sys/x86/isa/clock.c index 68d6085d5891e0..419a32aa50e620 100644 --- a/sys/x86/isa/clock.c +++ b/sys/x86/isa/clock.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -557,6 +558,15 @@ attimer_probe(device_t dev) return (result); } +/* Dirty hack, to make bus_setup_intr to not enable source. */ +static int +empty_handler(void *unused) +{ + + /* ensure disable is NOT called */ + return (FILTER_HANDLED); +} + static int attimer_attach(device_t dev) { @@ -586,6 +596,8 @@ attimer_attach(device_t dev) } if (resource_int_value(device_get_name(dev), device_get_unit(dev), "clock", &i) != 0 || i != 0) { + void *cookie; + sc->intr_rid = 0; while (bus_get_resource(dev, SYS_RES_IRQ, sc->intr_rid, &s, NULL) == 0 && s != 0) @@ -596,16 +608,17 @@ attimer_attach(device_t dev) return (0); } /* Dirty hack, to make bus_setup_intr to not enable source. */ - i8254_intsrc->is_handlers++; + intr_event_add_handler(i8254_intsrc->is_event, "", + empty_handler, NULL, NULL, PI_INTR, 0, &cookie); if ((bus_setup_intr(dev, sc->intr_res, INTR_MPSAFE | INTR_TYPE_CLK, (driver_filter_t *)clkintr, NULL, sc, &sc->intr_handler))) { device_printf(dev, "Can't setup interrupt.\n"); - i8254_intsrc->is_handlers--; + intr_event_remove_handler(cookie); return (0); } - i8254_intsrc->is_handlers--; + intr_event_remove_handler(cookie); i8254_intsrc->is_pic->pic_enable_intr(i8254_intsrc); sc->et.et_name = "i8254"; sc->et.et_flags = ET_FLAGS_PERIODIC; diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c index 023c3df22580de..9a9b479b56239f 100644 --- a/sys/x86/x86/intr_machdep.c +++ b/sys/x86/x86/intr_machdep.c @@ -240,7 +240,6 @@ intr_register_source(struct intsrc *isrc) } intrcnt_register(isrc); interrupt_sources[vector] = isrc; - isrc->is_handlers = 0; sx_xunlock(&intrsrc_lock); return (0); } @@ -259,6 +258,7 @@ intr_add_handler(struct intsrc *isrc, const char *name, driver_filter_t filter, driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep, int domain) { + bool startempty = CK_SLIST_EMPTY(&isrc->is_event->ie_handlers); int error; error = intr_event_add_handler(isrc->is_event, name, filter, handler, @@ -266,8 +266,7 @@ intr_add_handler(struct intsrc *isrc, const char *name, driver_filter_t filter, if (error == 0) { sx_xlock(&intrsrc_lock); intrcnt_updatename(isrc); - isrc->is_handlers++; - if (isrc->is_handlers == 1) { + if (startempty) { isrc->is_domain = domain; isrc->is_pic->pic_enable_intr(isrc); isrc->is_pic->pic_enable_source(isrc); @@ -287,8 +286,7 @@ intr_remove_handler(void *cookie) error = intr_event_remove_handler(cookie); if (error == 0) { sx_xlock(&intrsrc_lock); - isrc->is_handlers--; - if (isrc->is_handlers == 0) { + if (CK_SLIST_EMPTY(&isrc->is_event->ie_handlers)) { isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI); isrc->is_pic->pic_disable_intr(isrc); } diff --git a/sys/x86/x86/io_apic.c b/sys/x86/x86/io_apic.c index 525547f9482a91..6c12ee1baa0d92 100644 --- a/sys/x86/x86/io_apic.c +++ b/sys/x86/x86/io_apic.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include @@ -473,7 +475,7 @@ ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id) intpin->io_cpu = apic_id; intpin->io_vector = new_vector; - if (isrc->is_handlers > 0) + if (!CK_SLIST_EMPTY(&isrc->is_event->ie_handlers)) apic_enable_vector(intpin->io_cpu, intpin->io_vector); if (bootverbose) { printf("ioapic%u: routing intpin %u (", io->io_id, @@ -490,7 +492,7 @@ ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id) * to prevent races where we could miss an interrupt. */ if (old_vector) { - if (isrc->is_handlers > 0) + if (!CK_SLIST_EMPTY(&isrc->is_event->ie_handlers)) apic_disable_vector(old_id, old_vector); apic_free_vector(old_id, old_vector, intpin->io_irq); } diff --git a/sys/x86/x86/msi.c b/sys/x86/x86/msi.c index 9d5a51f9753c2b..5cfc7406216a06 100644 --- a/sys/x86/x86/msi.c +++ b/sys/x86/x86/msi.c @@ -42,6 +42,8 @@ #include #include +#include +#include #include #include #include @@ -502,7 +504,7 @@ msi_alloc(device_t dev, int count, int maxcount, int *irqs) "msi: routing MSI IRQ %d to local APIC %u vector %u\n", msi->msi_irq, msi->msi_cpu, msi->msi_vector); msi->msi_first = fsrc; - KASSERT(msi->msi_intsrc.is_handlers == 0, + KASSERT(CK_SLIST_EMPTY(&msi->msi_intsrc.is_event->ie_handlers), ("dead MSI has handlers")); } fsrc->msi_count = count; @@ -742,7 +744,8 @@ msix_alloc(device_t dev, int *irq) msi->msi_maxcount = 1; msi->msi_irqs = NULL; - KASSERT(msi->msi_intsrc.is_handlers == 0, ("dead MSI-X has handlers")); + KASSERT(CK_SLIST_EMPTY(&msi->msi_intsrc.is_event->ie_handlers), + ("dead MSI-X has handlers")); mtx_unlock(&msi_lock); *irq = i; diff --git a/sys/x86/xen/xen_arch_intr.c b/sys/x86/xen/xen_arch_intr.c index dcf8b4aa35f160..0125641905196c 100644 --- a/sys/x86/xen/xen_arch_intr.c +++ b/sys/x86/xen/xen_arch_intr.c @@ -330,7 +330,7 @@ xen_arch_intr_alloc(void) KASSERT(isrc->xi_arch.intsrc.is_pic == &xen_intr_pic, ("interrupt not owned by Xen code?")); - KASSERT(isrc->xi_arch.intsrc.is_handlers == 0, + KASSERT(CK_SLIST_EMPTY(&isrc->xi_arch.intsrc.is_event->ie_handlers), ("Free evtchn still has handlers")); return (isrc); @@ -367,7 +367,7 @@ void xen_arch_intr_release(struct xenisrc *isrc) { - KASSERT(isrc->xi_arch.intsrc.is_handlers == 0, + KASSERT(CK_SLIST_EMPTY(&isrc->xi_arch.intsrc.is_event->ie_handlers), ("Release called, but xenisrc still in use")); _Static_assert(sizeof(struct xenisrc) >= sizeof(struct avail_list),