PERFORCE change 95806 for review
Marcel Moolenaar
marcel at FreeBSD.org
Fri Apr 21 18:01:08 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=95806
Change 95806 by marcel at marcel_nfs on 2006/04/21 18:00:26
Brainwave: have puc_intr() only handle serdev devices. Non-serdev
devices (including non-serdev serial drivers) will have their
interrupt handler setup by the bus implementation. This makes
live so much easier as it assures that serdev devices with fast
interrupt handlers don't get pessimized by Giant-locked parallel
ports (by virtue of having puc(4) re-setup its interrupt handler
as MPSAFE). If there are no serdev children, puc(4) tears down
its handler.
Affected files ...
.. //depot/projects/uart/dev/puc/puc.c#33 edit
Differences ...
==== //depot/projects/uart/dev/puc/puc.c#33 (text+ko) ====
@@ -58,8 +58,6 @@
int p_rclk;
int p_hasintr:1;
- int p_fastintr:1;
- int p_giantintr:1;
driver_intr_t *p_ih;
serdev_intr_t *p_ihsrc[PUC_ISRCCNT];
@@ -135,7 +133,6 @@
u_long dev, devs;
int i, idx, ipend, isrc;
- /* handle serdev I/F compliant devices first. */
ipend = 0;
idx = 0, dev = 1UL;
devs = sc->sc_serdevs;
@@ -148,26 +145,6 @@
ipend |= port->p_ipend;
}
- if (ipend == 0) {
- idx = 0, dev = 1UL;
- devs = ~sc->sc_serdevs & ((1UL << sc->sc_nports) - 1);
- while (devs != 0UL) {
- while ((devs & dev) == 0UL)
- idx++, dev <<= 1;
- devs &= ~dev;
- port = &sc->sc_port[idx];
- if (port->p_ih != NULL) {
- if (port->p_giantintr) {
- mtx_lock(&Giant);
- (*port->p_ih)(port->p_iharg);
- mtx_unlock(&Giant);
- } else
- (*port->p_ih)(port->p_iharg);
- }
- }
- return;
- }
-
i = 0, isrc = SER_INT_OVERRUN;
while (ipend) {
while (i < PUC_ISRCCNT && !(ipend & isrc))
@@ -322,6 +299,13 @@
}
}
+ /*
+ * If there are no serdev devices, then our interrupt handler
+ * will do nothing. Tear it down.
+ */
+ if (sc->sc_serdevs == 0UL)
+ bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
+
return (0);
fail:
@@ -375,7 +359,8 @@
if (error)
return (error);
- bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
+ if (sc->sc_serdevs != 0UL)
+ bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires);
for (idx = 0; idx < PUC_PCI_BARS; idx++) {
@@ -550,7 +535,7 @@
struct puc_port *port;
struct puc_softc *sc;
device_t originator;
- int i, isrc;
+ int i, isrc, serdev;
sc = device_get_softc(dev);
@@ -570,37 +555,35 @@
return (ENXIO);
/*
- * If one of our children doesn't have a fast interrupt handler,
- * downgrade our interrupt handler from a fast handler to a
- * MP safe handler. We acquire giant on a need to have basis.
+ * Have non-serdev ports handled by the bus implementation. It
+ * supports multiple handlers for a single interrupt as it is,
+ * so we wouldn't add value if we did it ourselves.
*/
- if (sc->sc_fastintr && !(flags & INTR_FAST)) {
- sc->sc_fastintr = 0;
- bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
- bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE,
- puc_intr, sc, &sc->sc_icookie);
- }
-
- port->p_hasintr = 1;
- port->p_fastintr = (flags & INTR_FAST) ? 1 : 0;
- port->p_giantintr = (flags & (INTR_FAST | INTR_MPSAFE)) ? 0 : 1;
- port->p_ih = ihand;
- port->p_iharg = arg;
-
- *cookiep = originator;
-
+ serdev = 0;
if (port->p_type == PUC_TYPE_SERIAL) {
i = 0, isrc = SER_INT_OVERRUN;
while (i < PUC_ISRCCNT) {
port->p_ihsrc[i] = SERDEV_IHAND(originator, isrc);
- if (port->p_ihsrc[i] != NULL) {
- sc->sc_serdevs |= 1UL << (port->p_nr - 1);
- port->p_ih = NULL;
- }
+ if (port->p_ihsrc[i] != NULL)
+ serdev = 1;
i++, isrc <<= 1;
}
}
+ if (!serdev)
+ return (BUS_SETUP_INTR(device_get_parent(dev), originator,
+ sc->sc_ires, flags, ihand, arg, cookiep));
+
+ /* We demand that serdev devices use fast interrupts. */
+ if (!(flags & INTR_FAST))
+ return (ENXIO);
+
+ sc->sc_serdevs |= 1UL << (port->p_nr - 1);
+
+ port->p_hasintr = 1;
+ port->p_ih = ihand;
+ port->p_iharg = arg;
+ *cookiep = port;
return (0);
}
@@ -609,9 +592,12 @@
void *cookie)
{
struct puc_port *port;
+ struct puc_softc *sc;
device_t originator;
int i;
+ sc = device_get_softc(dev);
+
/* Get our immediate child. */
originator = child;
while (child != NULL && device_get_parent(child) != dev)
@@ -622,23 +608,24 @@
port = device_get_ivars(child);
KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
- if (res != port->p_ires || cookie != originator)
+ if (res != port->p_ires)
return (EINVAL);
if (rman_get_device(port->p_ires) != originator)
return (ENXIO);
+
if (!port->p_hasintr)
- return (ENXIO);
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), originator,
+ sc->sc_ires, cookie));
+
+ if (cookie != port)
+ return (EINVAL);
port->p_hasintr = 0;
- port->p_fastintr = 0;
- port->p_giantintr = 0;
port->p_ih = NULL;
port->p_iharg = NULL;
- if (port->p_type == PUC_TYPE_SERIAL) {
- for (i = 0; i < PUC_ISRCCNT; i++)
- port->p_ihsrc[i] = NULL;
- }
+ for (i = 0; i < PUC_ISRCCNT; i++)
+ port->p_ihsrc[i] = NULL;
return (0);
}
More information about the p4-projects
mailing list