From 618f2b4d5555a7aa1709da3de032b607f4d3dc36 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 10 Jan 2008 23:43:47 +0000 Subject: [PATCH] Work around problems with the ppbus(4)'s interesting way of managing interrupt handlers for child devices by adding a dummy handler that is always present so that the underlying interrupt thread is always around avoiding panics from stray interrupts. MFC after: 3 days --- sys/dev/ppbus/ppbconf.c | 37 +++++++++++++++++++++++++++++++++++++ sys/dev/ppbus/ppbconf.h | 3 +++ 2 files changed, 40 insertions(+) diff --git a/sys/dev/ppbus/ppbconf.c b/sys/dev/ppbus/ppbconf.c index cb5da93528f5..2ad164c3961d 100644 --- a/sys/dev/ppbus/ppbconf.c +++ b/sys/dev/ppbus/ppbconf.c @@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include + +#include #include #include @@ -380,9 +383,38 @@ ppb_scan_bus(device_t bus) #endif /* !DONTPROBE_1284 */ +static void +ppbus_dummy_intr(void *arg) +{ +} + static int ppbus_attach(device_t dev) { + struct ppb_data *ppb = (struct ppb_data *)device_get_softc(dev); + uintptr_t irq; + int error, rid; + + /* Attach a dummy interrupt handler to suck up any stray interrupts. */ + BUS_READ_IVAR(device_get_parent(dev), dev, PPC_IVAR_IRQ, &irq); + + if (irq > 0) { + rid = 0; + ppb->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, + irq, 1, RF_SHAREABLE); + if (ppb->irq_res != NULL) { + error = bus_setup_intr(dev, ppb->irq_res, + INTR_TYPE_TTY | INTR_MPSAFE, NULL, ppbus_dummy_intr, + ppb, &ppb->intr_cookie); + if (error) { + device_printf(dev, + "failed to setup interrupt handler\n"); + bus_release_resource(dev, SYS_RES_IRQ, 0, + ppb->irq_res); + return (error); + } + } + } /* Locate our children */ bus_generic_probe(dev); @@ -401,6 +433,7 @@ ppbus_attach(device_t dev) static int ppbus_detach(device_t dev) { + struct ppb_data *ppb = (struct ppb_data *)device_get_softc(dev); device_t *children; int nchildren, i; @@ -412,6 +445,10 @@ ppbus_detach(device_t dev) free(children, M_TEMP); } + if (ppb->irq_res != NULL) { + bus_teardown_intr(dev, ppb->irq_res, ppb->intr_cookie); + bus_release_resource(dev, SYS_RES_IRQ, 0, ppb->irq_res); + } return (0); } diff --git a/sys/dev/ppbus/ppbconf.h b/sys/dev/ppbus/ppbconf.h index eb1f64ec68ae..5f7a20196395 100644 --- a/sys/dev/ppbus/ppbconf.h +++ b/sys/dev/ppbus/ppbconf.h @@ -248,6 +248,9 @@ struct ppb_data { * NIBBLE, PS2, EPP or ECP */ void *ppb_owner; /* device which owns the bus */ + + struct resource *irq_res; + void *intr_cookie; }; #ifdef _KERNEL