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