Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Apr 2006 05:56:53 GMT
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 95480 for review
Message-ID:  <200604180556.k3I5urRL076583@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=95480

Change 95480 by marcel@marcel_nfs on 2006/04/18 05:55:54

	o  Implement puc_bus_setup_intr()
	o  Implement puc_bus_teardown_intr()

Affected files ...

.. //depot/projects/uart/dev/puc/puc.c#25 edit

Differences ...

==== //depot/projects/uart/dev/puc/puc.c#25 (text+ko) ====

@@ -56,6 +56,10 @@
 	int		p_type;
 	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];
 	void		*p_iharg;
@@ -392,6 +396,8 @@
 	} else if (type == SYS_RES_IRQ) {
 		if (res != port->p_ires)
 			return (EINVAL);
+		if (port->p_hasintr)
+			return (EBUSY);
 	} else
 		return (EINVAL);
 
@@ -445,6 +451,7 @@
 	struct puc_port *port;
 	struct puc_softc *sc;
 	device_t originator;
+	int i, isrc;
 
 	sc = device_get_softc(dev);
 
@@ -463,6 +470,36 @@
 	if (rman_get_device(port->p_ires) != originator)
 		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.
+	 */
+	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_MPSAFE) ? 0 : 1;
+	port->p_ih = ihand;
+	port->p_iharg = arg;
+
+	*cookiep = originator;
+
+	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)
+				port->p_ih = NULL;
+			i++, isrc <<= 1;
+		}
+	}
+
 	return (0);
 }
 
@@ -472,6 +509,7 @@
 {
 	struct puc_port *port;
 	device_t originator;
+	int i;
 
 	/* Get our immediate child. */
 	originator = child;
@@ -483,8 +521,23 @@
 	port = device_get_ivars(child);
 	KASSERT(port != NULL, ("%s %d", __func__, __LINE__));
 
-	if (res == NULL || cookie == NULL)
+	if (res != port->p_ires || cookie != originator)
 		return (EINVAL);
+	if (rman_get_device(port->p_ires) != originator)
+		return (ENXIO);
+	if (!port->p_hasintr)
+		return (ENXIO);
+
+	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;
+	}
 
 	return (ENXIO);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604180556.k3I5urRL076583>