PERFORCE change 111664 for review
Paolo Pisati
piso at FreeBSD.org
Wed Dec 13 14:39:58 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=111664
Change 111664 by piso at 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;
More information about the p4-projects
mailing list