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.
This commit is contained in:
parent
42db966caf
commit
995d4be272
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: zs_ap.c,v 1.25 2008/04/28 20:23:30 martin Exp $ */
|
||||
/* $NetBSD: zs_ap.c,v 1.26 2010/06/26 03:44:49 tsutsui Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||
|
@ -38,7 +38,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: zs_ap.c,v 1.25 2008/04/28 20:23:30 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: zs_ap.c,v 1.26 2010/06/26 03:44:49 tsutsui Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -213,7 +213,6 @@ zs_ap_attach(device_t parent, device_t self, void *aux)
|
|||
volatile u_int *portBctl = (void *)(apa->apa_hwbase + PORTB_OFFSET);
|
||||
volatile u_int *portActl = (void *)(apa->apa_hwbase + PORTA_OFFSET);
|
||||
volatile u_int *esccregs = (void *)(apa->apa_hwbase + ESCC_REG);
|
||||
static int didintr;
|
||||
|
||||
zsc->zsc_dev = self;
|
||||
zs_unit = device_unit(self);
|
||||
|
@ -295,20 +294,12 @@ zs_ap_attach(device_t parent, device_t self, void *aux)
|
|||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
zsc->zsc_si = softint_establish(SOFTINT_SERIAL, zssoft, zsc);
|
||||
apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
|
||||
NEWS5000_INT1_SCC,
|
||||
0, /* priority */
|
||||
zshard_ap, zsc,
|
||||
apa->apa_name, apa->apa_ctlnum);
|
||||
}
|
||||
zsc->zsc_si = softint_establish(SOFTINT_SERIAL, zssoft, zsc);
|
||||
apbus_intr_establish(1, /* interrupt level ( 0 or 1 ) */
|
||||
NEWS5000_INT1_SCC, 0, /* priority */
|
||||
zshard_ap, zsc, apa->apa_name, apa->apa_ctlnum);
|
||||
/* XXX; evcnt_attach() ? */
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: zs.c,v 1.25 2008/06/13 12:26:35 cegger Exp $ */
|
||||
/* $NetBSD: zs.c,v 1.26 2010/06/26 03:44:49 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.25 2008/06/13 12:26:35 cegger Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: zs.c,v 1.26 2010/06/26 03:44:49 tsutsui Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
|
@ -80,50 +80,23 @@ zs_print(void *aux, const char *name)
|
|||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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->zsc_si);
|
||||
}
|
||||
rval = zsc_intr_hard(zsc);
|
||||
if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq)
|
||||
softint_schedule(zsc->zsc_si);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar scheme as for zshard (look at all of them)
|
||||
*/
|
||||
void
|
||||
zssoft(void *arg)
|
||||
{
|
||||
struct zsc_softc *zsc;
|
||||
int s, unit;
|
||||
|
||||
/* Make sure we call the tty layer at spltty. */
|
||||
s = spltty();
|
||||
for (unit = 0; unit < zsc_cd.cd_ndevs; unit++) {
|
||||
zsc = device_lookup_private(&zsc_cd, unit);
|
||||
if (zsc == NULL)
|
||||
continue;
|
||||
(void)zsc_intr_soft(zsc);
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the current baud rate given a ZS channel.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: zs_hb.c,v 1.25 2008/04/28 20:23:30 martin Exp $ */
|
||||
/* $NetBSD: zs_hb.c,v 1.26 2010/06/26 03:44:49 tsutsui Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996 The NetBSD Foundation, Inc.
|
||||
|
@ -38,7 +38,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: zs_hb.c,v 1.25 2008/04/28 20:23:30 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: zs_hb.c,v 1.26 2010/06/26 03:44:49 tsutsui Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -196,7 +196,6 @@ zs_hb_attach(device_t parent, device_t self, void *aux)
|
|||
volatile struct zschan *zc;
|
||||
struct zs_chanstate *cs;
|
||||
int s, zs_unit, channel, intlevel;
|
||||
static int didintr;
|
||||
|
||||
zsc->zsc_dev = self;
|
||||
zs_unit = device_unit(self);
|
||||
|
@ -284,13 +283,9 @@ zs_hb_attach(device_t parent, device_t self, void *aux)
|
|||
* to the interrupt handlers aren't used. Note, we only do this
|
||||
* once since both SCCs interrupt at the same level and vector.
|
||||
*/
|
||||
if (!didintr) {
|
||||
didintr = 1;
|
||||
|
||||
zsc->zsc_si = softint_establish(SOFTINT_SERIAL, zssoft, zsc);
|
||||
hb_intr_establish(intlevel, INTST1_SCC, IPL_SERIAL,
|
||||
zshard_hb, NULL);
|
||||
}
|
||||
zsc->zsc_si = softint_establish(SOFTINT_SERIAL,
|
||||
(void (*)(void *))zsc_intr_soft, zsc);
|
||||
hb_intr_establish(intlevel, INTST1_SCC, IPL_SERIAL, zshard_hb, zsc);
|
||||
/* XXX; evcnt_attach() ? */
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue