Module Name: src Committed By: tsutsui Date: Sat Jun 26 01:48:57 UTC 2010
Modified Files: src/sys/arch/sun3/dev: zs.c Log Message: Pull a similar fix from sparc/dev/zs.c rev 1.119: Establish interrupt handlers with proper softc per each zs device rather than sharing them among all zs devices and searching softc in handlers, to avoid possible recursive lock. To generate a diff of this commit: cvs rdiff -u -r1.84 -r1.85 src/sys/arch/sun3/dev/zs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/sun3/dev/zs.c diff -u src/sys/arch/sun3/dev/zs.c:1.84 src/sys/arch/sun3/dev/zs.c:1.85 --- src/sys/arch/sun3/dev/zs.c:1.84 Fri Jun 13 13:11:42 2008 +++ src/sys/arch/sun3/dev/zs.c Sat Jun 26 01:48:57 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: zs.c,v 1.84 2008/06/13 13:11:42 cegger Exp $ */ +/* $NetBSD: zs.c,v 1.85 2010/06/26 01:48:57 tsutsui Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.84 2008/06/13 13:11:42 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.85 2010/06/26 01:48:57 tsutsui Exp $"); #include "opt_kgdb.h" @@ -260,7 +260,6 @@ volatile struct zschan *zc; struct zs_chanstate *cs; int s, zs_unit, channel; - static int didintr; zsc->zsc_dev = self; zs_unit = device_unit(self); @@ -331,14 +330,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; - isr_add_autovect(zshard, NULL, ca->ca_intpri); - } + isr_add_autovect(zshard, zsc, ca->ca_intpri); zsc->zs_si = softint_establish(SOFTINT_SERIAL, (void (*)(void *))zsc_intr_soft, zsc); /* XXX; evcnt_attach() ? */ @@ -382,25 +376,18 @@ /* * Our ZS chips all share a common, autovectored interrupt, - * so we have to look at all of them on each interrupt. + * but we establish zshard handler per each ZS chip + * to avoid holding unnecessary locks in interrupt context. */ static int zshard(void *arg) { - struct zsc_softc *zsc; - int unit, rval, softreq; + struct zsc_softc *zsc = arg; + int rval; - rval = 0; - for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) { - zsc = device_lookup_private(&zsc_cd, unit); - if (zsc == NULL) - continue; - rval |= zsc_intr_hard(zsc); - softreq = zsc->zsc_cs[0]->cs_softreq; - softreq |= zsc->zsc_cs[1]->cs_softreq; - if (softreq) - softint_schedule(zsc->zs_si); - } + rval = zsc_intr_hard(zsc); + if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq) + softint_schedule(zsc->zs_si); return (rval); }