diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-06 20:08:48 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-05-06 20:08:48 +0000 |
commit | 737eb819e7c02bbee85545db8e0e2fb75d342052 (patch) | |
tree | 8fe79192febab46a370bc3b89f96d193653e6fc8 | |
parent | c52e153b4f274e8abfebe4cd275cacce3aee3f2f (diff) |
Workaround a bridge deadlock, as advised by comments found in the linux sn1
code.
-rw-r--r-- | sys/arch/sgi/include/mnode.h | 6 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbridge.c | 30 | ||||
-rw-r--r-- | sys/arch/sgi/xbow/xbridgereg.h | 5 |
3 files changed, 35 insertions, 6 deletions
diff --git a/sys/arch/sgi/include/mnode.h b/sys/arch/sgi/include/mnode.h index b5bd754b161..0cf495b37a0 100644 --- a/sys/arch/sgi/include/mnode.h +++ b/sys/arch/sgi/include/mnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mnode.h,v 1.2 2009/05/02 21:26:00 miod Exp $ */ +/* $OpenBSD: mnode.h,v 1.3 2009/05/06 20:08:44 miod Exp $ */ /* * Copyright (c) 2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -363,8 +363,8 @@ typedef struct klttydev_s { #define IP27_LHUB_S(r, d) *(IP27_LHUB_ADDR(r)) = (d) #define IP27_RHUB_L(n, r) *(IP27_RHUB_ADDR((n), (r)) #define IP27_RHUB_S(n, r, d) *(IP27_RHUB_ADDR((n), (r)) = (d) -#define IP27_RHUB_PI_L(n, s, r) *(IP27_RHUB_PI_ADDR((n), (s), (r)) -#define IP27_RHUB_PI_S(n, s, r, d) *(IP27_RHUB_PI_ADDR((n), (s), (r)) = (d) +#define IP27_RHUB_PI_L(n, s, r) *(IP27_RHUB_PI_ADDR((n), (s), (r))) +#define IP27_RHUB_PI_S(n, s, r, d) *(IP27_RHUB_PI_ADDR((n), (s), (r))) = (d) /* HUB I/O registers */ diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c index 08e115d2079..3e95eab6b1d 100644 --- a/sys/arch/sgi/xbow/xbridge.c +++ b/sys/arch/sgi/xbow/xbridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xbridge.c,v 1.14 2009/05/03 19:44:28 miod Exp $ */ +/* $OpenBSD: xbridge.c,v 1.15 2009/05/06 20:08:47 miod Exp $ */ /* * Copyright (c) 2008, 2009 Miodrag Vallat. @@ -33,12 +33,14 @@ #include <machine/bus.h> #include <machine/cpu.h> #include <machine/intr.h> +#include <machine/mnode.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> #include <mips64/archtype.h> +#include <sgi/xbow/hub.h> #include <sgi/xbow/xbow.h> #include <sgi/xbow/xbowdevs.h> @@ -495,7 +497,8 @@ xbridge_conf_write(void *cookie, pcitag_t tag, int offset, pcireg_t data) struct xbridge_intr { struct xbridge_softc *xi_bridge; - int xi_intrsrc; + int xi_intrsrc; /* interrupt source on interrupt widget */ + int xi_intrbit; /* interrupt source on BRIDGE */ int (*xi_func)(void *); void *xi_arg; @@ -588,6 +591,7 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level, xi->xi_bridge = sc; xi->xi_intrsrc = intrsrc; + xi->xi_intrbit = intrbit; xi->xi_func = func; xi->xi_arg = arg; xi->xi_level = level; @@ -648,6 +652,7 @@ xbridge_intr_handler(void *v) { struct xbridge_intr *xi = v; struct xbridge_softc *sc = xi->xi_bridge; + uint16_t nasid = 0; /* XXX */ int rc; if (xi == NULL) { @@ -659,6 +664,27 @@ xbridge_intr_handler(void *v) if ((rc = (*xi->xi_func)(xi->xi_arg)) != 0) xi->xi_count.ec_count++; + /* + * There is a known BRIDGE race in which, if two interrupts + * on two different pins occur within 60nS of each other, + * further interrupts on the first pin do not cause an interrupt + * to be sent. + * + * The workaround against this is to check if our interrupt source + * is still active (i.e. another interrupt is pending), in which + * case we force an interrupt anyway. + * + * The XBridge even has a nice facility to do this, where we do not + * even have to check if our interrupt is pending. + */ + + if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE)) { + bus_space_write_4(sc->sc_iot, sc->sc_regh, + BRIDGE_INT_FORCE_PIN(xi->xi_intrbit), 1); + } else { + IP27_RHUB_PI_S(nasid, 0, HUB_IR_CHANGE, xi->xi_intrsrc); + } + return rc; } diff --git a/sys/arch/sgi/xbow/xbridgereg.h b/sys/arch/sgi/xbow/xbridgereg.h index 8b9e2718778..e0a176cce03 100644 --- a/sys/arch/sgi/xbow/xbridgereg.h +++ b/sys/arch/sgi/xbow/xbridgereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xbridgereg.h,v 1.3 2009/05/03 19:44:28 miod Exp $ */ +/* $OpenBSD: xbridgereg.h,v 1.4 2009/05/06 20:08:47 miod Exp $ */ /* * Copyright (c) 2008 Miodrag Vallat. @@ -66,6 +66,9 @@ #define BRIDGE_INT_DEV 0x00000124 #define BRIDGE_INT_HOST_ERR 0x0000012c #define BRIDGE_INT_ADDR(d) (0x00000134 + 8 * (d)) +/* the following two are XBridge-only */ +#define BRIDGE_INT_FORCE_ALWAYS(d) (0x00000184 + 8 * (d)) +#define BRIDGE_INT_FORCE_PIN(d) (0x000001c4 + 8 * (d)) /* * PCI Resource Mapping control |