Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Dec 2006 22:39:51 GMT
From:      Paolo Pisati <piso@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 111664 for review
Message-ID:  <200612132239.kBDMdp7Q080619@repoman.freebsd.org>

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

Change 111664 by piso@piso_newluxor on 2006/12/13 22:38:54

	Teach scc about filters: 
	
	o added a new wrapper function (scc_bfe_ihand()) for ithread 
	  handler.
	o axe the condition into which bus_setup_intr() could fail
	  to setup a filter.
	o teach scc_bfe_filter() to return the filter return codes.
	  filters.
	o put an XXX comment in case different filters attached to the
	  same scc would return opposite values (STRAY and any other 
	  values).

Affected files ...

.. //depot/projects/soc2006/intr_filter/dev/scc/scc_bfe.h#4 edit
.. //depot/projects/soc2006/intr_filter/dev/scc/scc_core.c#11 edit

Differences ...

==== //depot/projects/soc2006/intr_filter/dev/scc/scc_bfe.h#4 (text) ====

@@ -72,10 +72,12 @@
 	u_int		m_mode;
 	int		m_attached:1;
 	int		m_hasintr:1;
+	int		m_hasihand:1;
 	int		m_probed:1;
 	int		m_sysdev:1;
 
-	driver_intr_t	*ih;
+	driver_filter_t	*ihf;
+	driver_intr_t	*ih;	
 	serdev_intr_t	*ih_src[SCC_ISRCCNT];
 	void		*ih_arg;
 };

==== //depot/projects/soc2006/intr_filter/dev/scc/scc_core.c#11 (text) ====

@@ -51,14 +51,32 @@
 
 MALLOC_DEFINE(M_SCC, "SCC", "SCC driver");
 
+static void
+scc_bfe_ihand(void *arg)
+{
+	struct scc_softc *sc = arg;
+	struct scc_class *cl;
+	struct scc_mode *m;
+	int c;
+
+	cl = sc->sc_class;
+	for (c = 0; c < cl->cl_channels; c++) {
+		m = &sc->sc_chan[c].ch_mode[0];
+		if (m->m_hasihand) {
+			(*m->ih)(m->ih_arg);
+			m->m_hasihand = 0;
+		}
+	}
+}
+
 static int
-scc_bfe_intr(void *arg)
+scc_bfe_filter(void *arg)
 {
 	struct scc_softc *sc = arg;
 	struct scc_chan *ch;
 	struct scc_class *cl;
 	struct scc_mode *m;
-	int c, i, ipend, isrc;
+	int c, i, ipend, isrc, res;
 
 	cl = sc->sc_class;
 	while (!sc->sc_leaving && (ipend = SCC_IPEND(sc)) != 0) {
@@ -79,19 +97,34 @@
 					ch->ch_ipend &= ~isrc;
 			}
 		}
+		res = FILTER_HANDLED;
 		for (c = 0; c < cl->cl_channels; c++) {
 			ch = &sc->sc_chan[c];
 			if (!ch->ch_ipend)
 				continue;
 			m = &ch->ch_mode[0];
-			if (m->ih != NULL)
-				(*m->ih)(m->ih_arg);
-			else
+			// XXX propagation of filter return value is broken:
+			// XXX what if one handler returns STRAY and another
+			// XXX one returns HANDLED | SCHEDULE_THREAD?
+			// XXX what i'm supposed to do? for now, just OR all
+			// XXX the return values.
+			m->m_hasihand = 0;
+			if (m->ihf != NULL) {
+				res |= (*m->ihf)(m->ih_arg);
+				if (res & FILTER_SCHEDULE_THREAD)
+					m->m_hasihand = 1;
+			} else {
+				if (m->ih != NULL) {
+					res |= FILTER_HANDLED | 
+					    FILTER_SCHEDULE_THREAD;
+					m->m_hasihand = 1;
+				}
 				SCC_ICLEAR(sc, ch);
+			}
 		}
-		return(FILTER_HANDLED);
+		return (res);
 	}
-	return(FILTER_STRAY);
+	return (FILTER_STRAY);
 }
 
 int
@@ -220,15 +253,8 @@
 		if (ch->ch_ires == NULL)
 			continue;
 		error = bus_setup_intr(dev, ch->ch_ires,
-		    INTR_TYPE_TTY, scc_bfe_intr, NULL,
+		    INTR_TYPE_TTY, scc_bfe_filter, scc_bfe_ihand,
 		    sc, &ch->ch_icookie);
-		if (error) {
-			error = bus_setup_intr(dev, ch->ch_ires,
-			    INTR_TYPE_TTY | INTR_MPSAFE, 
-			    NULL, (driver_intr_t *)scc_bfe_intr, sc, 
-			    &ch->ch_icookie);			    
-		} else
-			sc->sc_fastintr = 1;
 
 		if (error) {
 			device_printf(dev, "could not activate interrupt\n");
@@ -502,40 +528,24 @@
     driver_filter_t *filter, void (*ihand)(void *), void *arg, 
     void **cookiep)
 {
-	struct scc_chan *ch;
 	struct scc_mode *m;
 	struct scc_softc *sc;
-	int c, i, isrc;
+	int i, isrc;
 
 	if (device_get_parent(child) != dev)
 		return (EINVAL);
 
 	/* Interrupt handlers must be FAST or MPSAFE. */
-	if (!(IS_FAST(filter, ihand)) || ((flags & INTR_MPSAFE) == 0))
+	if ((filter == NULL) && !(flags & INTR_MPSAFE))
 		return (EINVAL);
 
 	sc = device_get_softc(dev);
 	if (sc->sc_polled)
 		return (ENXIO);
 
-	if (sc->sc_fastintr && !(IS_FAST(filter, ihand))) {
-		sc->sc_fastintr = 0;
-		for (c = 0; c < sc->sc_class->cl_channels; c++) {
-			ch = &sc->sc_chan[c];
-			if (ch->ch_ires == NULL)
-				continue;
-			bus_teardown_intr(dev, ch->ch_ires, ch->ch_icookie);
-			bus_setup_intr(dev, ch->ch_ires,
-			    INTR_TYPE_TTY | INTR_MPSAFE, 
-			    scc_bfe_intr, NULL, sc, &ch->ch_icookie);			    
-		}
-	}
-
 	m = device_get_ivars(child);
 	m->m_hasintr = 1;
-	/*
-	 * XXX_FILTER this code doesn't take care of filters.
-	 */
+	m->ihf = filter;
 	m->ih = ihand;
 	m->ih_arg = arg;
 



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