> > > Somebody should fix the driver so that zshard() does not call > > > device_lookup_private(). It seems entirely unnecessary. > > > > There is a dumb hack in sun3 derived zs driver. > > > > All zs devices on sun machines have the same interrupt sources > > so ancient zs drivers tried to reduce overhead on interrupts > > by sharing one interrupt handler among all zs devices. > > > > We can simpley fix it to make it call softint_establish() and > > bus_intr_establish() per each zs device, as macppc and news68k etc. do. > > i don't understand. > > the macppc and news68k zshard()'s get the actual zsc_softc * as > the (void *arg), but sparc does not.
So we should make sparc zs do so. It looks multiple interrupt handlers against the same interrupt level are properly queued and handled in sparc/intr.c:ih_insert(), so no need to prepare own queue in zs.c. The attached patch works on tme-0.8 emulating SS2. (Hehe, a comment still says "autovectored" derived from sun3 ;-) --- Index: dev/zs.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/dev/zs.c,v retrieving revision 1.118 diff -u -r1.118 zs.c --- dev/zs.c 4 Jun 2010 06:04:15 -0000 1.118 +++ dev/zs.c 20 Jun 2010 01:58:29 -0000 @@ -171,12 +171,8 @@ extern struct cfdriver zs_cd; -/* softintr(9) cookie, shared by all instances of this driver */ -static void *zs_sicookie; - /* Interrupt handlers. */ static int zshard(void *); -static void zssoft(void *); static int zs_get_speed(struct zs_chanstate *); @@ -396,7 +392,6 @@ struct zsc_attach_args zsc_args; struct zs_chanstate *cs; int channel; - static int didintr, prevpri; #if (NKBD > 0) || (NMS > 0) int ch0_is_cons = 0; #endif @@ -407,12 +402,11 @@ return; } - if (!didintr) { - zs_sicookie = softint_establish(SOFTINT_SERIAL, zssoft, NULL); - if (zs_sicookie == NULL) { - aprint_error(": cannot establish soft int handler\n"); - return; - } + zsc->zsc_sicookie = softint_establish(SOFTINT_SERIAL, + (void (*)(void *))zsc_intr_soft, zsc); + if (zsc->zsc_sicookie == NULL) { + aprint_error(": cannot establish soft int handler\n"); + return; } aprint_normal(" softpri %d\n", IPL_SOFTSERIAL); @@ -566,17 +560,9 @@ } /* - * Now safe to install interrupt handlers. Note the arguments - * to the interrupt handlers aren't used. Note, we only do this - * once since both SCCs interrupt at the same level and vector. + * Now safe to install interrupt handlers. */ - if (!didintr) { - didintr = 1; - prevpri = pri; - bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, - zshard, NULL); - } else if (pri != prevpri) - panic("broken zs interrupt scheme"); + bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, zshard, zsc); evcnt_attach_dynamic(&zsc->zsc_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(zsc->zsc_dev), "intr"); @@ -625,81 +611,29 @@ static volatile int zssoftpending; /* - * Our ZS chips all share a common, autovectored interrupt, - * so we have to look at all of them on each interrupt. + * Our ZS chips all share a common interrupt level, + * but we establish zshard handler per each ZS chips + * to avoid holding unnecessary locks in interrupt context. */ static int zshard(void *arg) { - struct zsc_softc *zsc; - int unit, rr3, rval, softreq; - - rval = softreq = 0; - for (unit = 0; unit < zs_cd.cd_ndevs; unit++) { - struct zs_chanstate *cs; + struct zsc_softc *zsc = arg; + int rr3, rval; - zsc = device_lookup_private(&zs_cd, unit); - if (zsc == NULL) - continue; - rr3 = zsc_intr_hard(zsc); - /* Count up the interrupts. */ - if (rr3) { - rval |= rr3; - zsc->zsc_intrcnt.ev_count++; - } - if ((cs = zsc->zsc_cs[0]) != NULL) - softreq |= cs->cs_softreq; - if ((cs = zsc->zsc_cs[1]) != NULL) - softreq |= cs->cs_softreq; - } - - /* We are at splzs here, so no need to lock. */ - if (softreq && (zssoftpending == 0)) { - zssoftpending = 1; - softint_schedule(zs_sicookie); + rval = 0; + rr3 = zsc_intr_hard(zsc); + /* Count up the interrupts. */ + if (rr3) { + rval = rr3; + zsc->zsc_intrcnt.ev_count++; } + if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq) + softint_schedule(zsc->zsc_sicookie); return (rval); } /* - * Similar scheme as for zshard (look at all of them) - */ -static void -zssoft(void *arg) -{ - struct zsc_softc *zsc; - int unit; - - /* This is not the only ISR on this IPL. */ - if (zssoftpending == 0) - return; - - /* - * The soft intr. bit will be set by zshard only if - * the variable zssoftpending is zero. The order of - * these next two statements prevents our clearing - * the soft intr bit just after zshard has set it. - */ - /* ienab_bic(IE_ZSSOFT); */ - zssoftpending = 0; - -#if 0 /* not yet */ - /* Make sure we call the tty layer with tty_lock held. */ - mutex_spin_enter(&tty_lock); -#endif - for (unit = 0; unit < zs_cd.cd_ndevs; unit++) { - zsc = device_lookup_private(&zs_cd, unit); - if (zsc == NULL) - continue; - (void)zsc_intr_soft(zsc); - } -#if 0 /* not yet */ - mutex_spin_exit(&tty_lock); -#endif -} - - -/* * Compute the current baud rate given a ZS channel. */ static int Index: include/z8530var.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/include/z8530var.h,v retrieving revision 1.9 diff -u -r1.9 z8530var.h --- include/z8530var.h 29 Mar 2008 19:15:35 -0000 1.9 +++ include/z8530var.h 20 Jun 2010 01:58:29 -0000 @@ -54,6 +54,7 @@ int zsc_node; /* PROM node, if any */ struct evcnt zsc_intrcnt; /* count interrupts */ struct zs_chanstate zsc_cs_store[2]; + void *zsc_sicookie; /* softint(9) cookie */ }; /* --- Izumi Tsutsui