Date: Sat, 25 Feb 2006 19:03:42 GMT From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 92387 for review Message-ID: <200602251903.k1PJ3gJn021135@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=92387 Change 92387 by marcel@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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200602251903.k1PJ3gJn021135>