summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-10-26 18:37:14 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-10-26 18:37:14 +0000
commit9f76936f4c7eadaade5b745d0f58663ec6bd3335 (patch)
tree9a9123a9a4e4f0456bebe5ac08a335adffc7096a
parentf756ec3c6b3d2cbefc3fc6c431706443bf69cf8f (diff)
Make pci_intr_string() on xbridge return both the xbridge irq and the crossbow
irq we route it to; this makes clear that devices connected to different xbridges but using the same xbridge irq are actually not shared at all; and this also helps figure out which device cause spurious interrupts.
-rw-r--r--sys/arch/sgi/xbow/xbridge.c70
1 files changed, 42 insertions, 28 deletions
diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c
index b7c3d652214..c86a51491f1 100644
--- a/sys/arch/sgi/xbow/xbridge.c
+++ b/sys/arch/sgi/xbow/xbridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xbridge.c,v 1.57 2009/10/26 18:13:34 miod Exp $ */
+/* $OpenBSD: xbridge.c,v 1.58 2009/10/26 18:37:13 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -125,6 +125,7 @@ struct xbpci_softc {
struct machine_bus_dma_tag *xb_dmat;
struct xbridge_intr *xb_intr[BRIDGE_NINTRS];
+ char xb_intrstr[BRIDGE_NINTRS][sizeof("irq #, xbow irq ###")];
/*
* Device information.
@@ -890,10 +891,13 @@ xbridge_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
const char *
xbridge_intr_string(void *cookie, pci_intr_handle_t ih)
{
- static char str[16];
+ struct xbpci_softc *xb = (struct xbpci_softc *)cookie;
+ int intrbit = XBRIDGE_INTR_BIT(ih);
- snprintf(str, sizeof(str), "irq %d", XBRIDGE_INTR_BIT(ih));
- return(str);
+ if (xb->xb_intrstr[intrbit][0] == '\0')
+ snprintf(xb->xb_intrstr[intrbit],
+ sizeof xb->xb_intrstr[intrbit], "irq %d", ih);
+ return xb->xb_intrstr[intrbit];
}
void *
@@ -930,6 +934,9 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level,
xi->xi_intrsrc = intrsrc;
xb->xb_intr[intrbit] = xi;
+ snprintf(xb->xb_intrstr[intrbit],
+ sizeof xb->xb_intrstr[intrbit],
+ "irq %d, xbow irq %d", intrbit, intrsrc);
} else
intrsrc = xi->xi_intrsrc;
@@ -962,7 +969,7 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level,
xih->xih_arg = arg;
xih->xih_level = level;
xih->xih_device = device;
- evcount_attach(&xih->xih_count, name, &xi->xi_intrbit, &evcount_intr);
+ evcount_attach(&xih->xih_count, name, &xi->xi_intrsrc, &evcount_intr);
LIST_INSERT_HEAD(&xi->xi_handlers, xih, xih_nxt);
if (new) {
@@ -1044,10 +1051,10 @@ xbridge_intr_handler(void *v)
struct xbridge_intr *xi = (struct xbridge_intr *)v;
struct xbpci_softc *xb = xi->xi_bus;
struct xbridge_intrhandler *xih;
- int rc = 0;
- int spurious;
- uint32_t isr;
+ int rc;
+ uint64_t isr;
+ /* XXX shouldn't happen, and assumes interrupt is not shared */
if (LIST_EMPTY(&xi->xi_handlers)) {
printf("%s: spurious irq %d\n", DEVNAME(xb), xi->xi_intrbit);
return 0;
@@ -1060,31 +1067,38 @@ xbridge_intr_handler(void *v)
xbridge_read_reg(xb, BRIDGE_DEVICE_WBFLUSH(xih->xih_device));
isr = xbridge_read_reg(xb, BRIDGE_ISR);
- if ((isr & (1 << xi->xi_intrbit)) == 0) {
- spurious = 1;
+ if ((isr & (1L << xi->xi_intrbit)) == 0) {
+ /*
+ * May be a result of the lost interrupt workaround (see
+ * near the end of this function); don't complain in that
+ * case.
+ */
+ rc = -1;
#ifdef DEBUG
printf("%s: irq %d but not pending in ISR %08x\n",
DEVNAME(xb), xi->xi_intrbit, isr);
#endif
- } else
- spurious = 0;
-
- LIST_FOREACH(xih, &xi->xi_handlers, xih_nxt) {
- splraise(xih->xih_level);
- if ((*xih->xih_func)(xih->xih_arg) != 0) {
- xih->xih_count.ec_count++;
- rc = 1;
+ } else {
+ rc = 0;
+ LIST_FOREACH(xih, &xi->xi_handlers, xih_nxt) {
+ splraise(xih->xih_level);
+ if ((*xih->xih_func)(xih->xih_arg) != 0) {
+ xih->xih_count.ec_count++;
+ rc = 1;
+ }
+ /*
+ * No need to lower spl here, as our caller will
+ * lower spl upon our return.
+ * However that splraise() is necessary so that
+ * interrupt handler code calling splx() will not
+ * cause our interrupt source to be unmasked.
+ */
}
- /*
- * No need to lower spl here, as our caller will lower
- * spl upon our return.
- * However that splraise() is necessary so that interrupt
- * handler code calling splx() will not cause our interrupt
- * source to be unmasked.
- */
+ /* XXX assumes interrupt is not shared */
+ if (rc == 0)
+ printf("%s: spurious irq %d\n",
+ DEVNAME(xb), xi->xi_intrbit);
}
- if (rc == 0 && spurious == 0)
- printf("%s: spurious irq %d\n", DEVNAME(xb), xi->xi_intrbit);
/*
* There is a known BRIDGE race in which, if two interrupts
@@ -1107,7 +1121,7 @@ xbridge_intr_handler(void *v)
xbow_intr_set(xi->xi_intrsrc);
}
- return 1;
+ return rc;
}
/*