PERFORCE change 92387 for review
Marcel Moolenaar
marcel at FreeBSD.org
Sat Feb 25 11:03:44 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=92387
Change 92387 by marcel at marcel_nfs on 2006/02/25 19:03:20
Flesh out the interrupt handler setup code a bit more.
scc(4) now sets up the interrupt handler after all children
are attached. If any of the children has a MPSAFE handler
(i.e. non-FAST), then scc(4) will be MPSAFE.
Affected files ...
.. //depot/projects/uart/dev/scc/scc_bfe.h#9 edit
.. //depot/projects/uart/dev/scc/scc_core.c#10 edit
Differences ...
==== //depot/projects/uart/dev/scc/scc_bfe.h#9 (text+ko) ====
@@ -70,6 +70,8 @@
int m_alloc_rres:1;
int m_attached:1;
int m_probed:1;
+ int m_hasintr:1;
+ int m_fastintr:1;
driver_intr_t *ih;
driver_intr_t *ih_overrun;
==== //depot/projects/uart/dev/scc/scc_core.c#10 (text+ko) ====
@@ -99,7 +99,7 @@
const char *sep;
bus_space_handle_t bh;
u_long base, size, start;
- int c, error, mode, reset;
+ int c, error, intr, mode, reset;
/*
* The sc_class field defines the type of SCC we're going to work
@@ -141,32 +141,6 @@
sc->sc_irid = 0;
sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
RF_ACTIVE | RF_SHAREABLE);
- if (sc->sc_ires != NULL) {
-#if 0
- error = BUS_SETUP_INTR(device_get_parent(dev), dev,
- sc->sc_ires, INTR_TYPE_TTY | INTR_FAST, scc_bfe_intr,
- sc, &sc->sc_icookie);
-#else
- error = -1;
-#endif
- if (error)
- error = BUS_SETUP_INTR(device_get_parent(dev), dev,
- sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE,
- scc_bfe_intr, sc, &sc->sc_icookie);
- else
- sc->sc_fastintr = 1;
-
- if (error) {
- device_printf(dev, "could not activate interrupt\n");
- bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
- sc->sc_ires);
- sc->sc_ires = NULL;
- }
- }
- if (sc->sc_ires == NULL) {
- /* XXX no interrupt resource. Force polled mode. */
- sc->sc_polled = 1;
- }
/*
* Create the control structures for our children. Probe devices
@@ -209,10 +183,10 @@
m->m_probed = 1;
reset = (reset && SERDEV_RESET(m->m_dev));
}
- }
+ }
start += (cl->cl_range < 0) ? -size : size;
- }
+ }
/*
* Have the hardware driver initialize the hardware. Tell it
@@ -226,23 +200,12 @@
if (error)
goto fail;
- if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
- sep = "";
- device_print_prettyname(dev);
- if (sc->sc_fastintr) {
- printf("%sfast interrupt", sep);
- sep = ", ";
- }
- if (sc->sc_polled) {
- printf("%spolled mode", sep);
- sep = ", ";
- }
- printf("\n");
- }
-
/*
* Attach all child devices that were probed successfully.
+ * Keep track of whether we can setup a fast interrupt
+ * handler ourselves.
*/
+ intr = INTR_MPSAFE;
for (c = 0; c < cl->cl_channels; c++) {
ch = &sc->sc_chan[c];
for (mode = 0; mode < SCC_NMODES; mode++) {
@@ -253,12 +216,51 @@
if (error)
continue;
m->m_attached = 1;
- m->ih_break = SERDEV_IHAND(m->m_dev, SER_INT_BREAK);
- m->ih_overrun = SERDEV_IHAND(m->m_dev, SER_INT_OVERRUN);
- m->ih_rxready = SERDEV_IHAND(m->m_dev, SER_INT_RXREADY);
- m->ih_sigchg = SERDEV_IHAND(m->m_dev, SER_INT_SIGCHG);
- m->ih_txidle = SERDEV_IHAND(m->m_dev, SER_INT_TXIDLE);
+ if (m->m_hasintr && !m->m_fastintr)
+ intr = INTR_MPSAFE;
+ }
+ }
+
+ /*
+ * Setup our interrupt handler. Make it FAST if all our
+ * children are fast as well. Otherwise make it MPSAFE.
+ */
+ if (sc->sc_ires != NULL) {
+ error = BUS_SETUP_INTR(device_get_parent(dev), dev,
+ sc->sc_ires, INTR_TYPE_TTY | intr, scc_bfe_intr,
+ sc, &sc->sc_icookie);
+ if (error && intr == INTR_FAST) {
+ intr = INTR_MPSAFE;
+ error = BUS_SETUP_INTR(device_get_parent(dev), dev,
+ sc->sc_ires, INTR_TYPE_TTY | intr, scc_bfe_intr,
+ sc, &sc->sc_icookie);
+ }
+ if (error) {
+ device_printf(dev, "could not activate interrupt\n");
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
+ sc->sc_ires);
+ sc->sc_ires = NULL;
+ }
+ else
+ sc->sc_fastintr = (intr == INTR_FAST) ? 1 : 0;
+ }
+ if (sc->sc_ires == NULL) {
+ /* XXX no interrupt resource. Force polled mode. */
+ sc->sc_polled = 1;
+ }
+
+ if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
+ sep = "";
+ device_print_prettyname(dev);
+ if (sc->sc_fastintr) {
+ printf("%sfast interrupt", sep);
+ sep = ", ";
+ }
+ if (sc->sc_polled) {
+ printf("%spolled mode", sep);
+ sep = ", ";
}
+ printf("\n");
}
sc->sc_leaving = 0;
@@ -349,14 +351,13 @@
struct scc_chan *ch;
struct scc_mode *m;
+ if (device_get_parent(child) != dev)
+ return (NULL);
+
/* We only support default allocations. */
if (start != 0UL || end != ~0UL)
return (NULL);
- /* We don't support any grandchildren or children thereof. */
- if (device_get_parent(child) != dev)
- return (NULL);
-
m = device_get_ivars(child);
ch = m->m_chan;
rle = resource_list_find(&ch->ch_rlist, type, 0);
@@ -374,7 +375,6 @@
struct scc_chan *ch;
struct scc_mode *m;
- /* We don't support any grandchildren or children thereof. */
if (device_get_parent(child) != dev)
return (EINVAL);
@@ -399,6 +399,9 @@
struct scc_mode *m;
struct scc_softc *sc;
+ if (device_get_parent(child) != dev)
+ return (EINVAL);
+
sc = device_get_softc(dev);
cl = sc->sc_class;
m = device_get_ivars(child);
@@ -434,7 +437,6 @@
struct scc_chan *ch;
struct scc_mode *m;
- /* We don't support any grandchildren or children thereof. */
if (device_get_parent(child) != dev)
return (EINVAL);
@@ -450,13 +452,24 @@
{
struct scc_mode *m;
- /* We don't support any grandchildren or children thereof. */
if (device_get_parent(child) != dev)
return (EINVAL);
+ /* Interrupt handlers must be FAST or MPSAFE. */
+ if ((flags & (INTR_FAST|INTR_MPSAFE)) == 0)
+ return (EINVAL);
+
m = device_get_ivars(child);
+ m->m_hasintr = 1;
+ m->m_fastintr = (flags & INTR_FAST) ? 1 : 0;
m->ih = ihand;
m->ih_arg = arg;
+
+ m->ih_break = SERDEV_IHAND(child, SER_INT_BREAK);
+ m->ih_overrun = SERDEV_IHAND(child, SER_INT_OVERRUN);
+ m->ih_rxready = SERDEV_IHAND(child, SER_INT_RXREADY);
+ m->ih_sigchg = SERDEV_IHAND(child, SER_INT_SIGCHG);
+ m->ih_txidle = SERDEV_IHAND(child, SER_INT_TXIDLE);
return (0);
}
@@ -464,6 +477,23 @@
scc_bus_teardown_intr(device_t dev, device_t child, struct resource *r,
void *cookie)
{
+ struct scc_mode *m;
- return (ENXIO);
+ if (device_get_parent(child) != dev)
+ return (EINVAL);
+
+ m = device_get_ivars(child);
+ if (!m->m_hasintr)
+ return (EINVAL);
+
+ m->m_hasintr = 0;
+ m->m_fastintr = 0;
+ m->ih = NULL;
+ m->ih_arg = NULL;
+ m->ih_break = NULL;
+ m->ih_overrun = NULL;
+ m->ih_rxready = NULL;
+ m->ih_sigchg = NULL;
+ m->ih_txidle = NULL;
+ return (0);
}
More information about the p4-projects
mailing list