summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2014-12-04 21:52:09 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2014-12-04 21:52:09 +0000
commit3baf87af36c6d272c2f3d8464bf6e247b285df6a (patch)
tree6f70a9bf80733177698e2c1c126b47d16acd2f71
parentadb711544da2e97d8437751a2e2156bce7d5f006 (diff)
Move the PIC revision 1 interrupt workaround from xbridge_pci_intr_handler()
to a dedicated wrapper function, and register either xbridge_pci_intr_handler() or the wrapper as the interrupt handler, depending upon which chip we run on. Saves the cost of the workaround on non-affected chips, which are a large majority.
-rw-r--r--sys/arch/sgi/xbow/xbridge.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c
index 7e386d77e1f..bce52b1f7f5 100644
--- a/sys/arch/sgi/xbow/xbridge.c
+++ b/sys/arch/sgi/xbow/xbridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xbridge.c,v 1.92 2014/09/30 06:51:58 jmatthew Exp $ */
+/* $OpenBSD: xbridge.c,v 1.93 2014/12/04 21:52:08 miod Exp $ */
/*
* Copyright (c) 2008, 2009, 2011 Miodrag Vallat.
@@ -133,6 +133,7 @@ struct xbpci_softc {
char xb_intrstr[BRIDGE_NINTRS][sizeof("irq #, xbow irq ###")];
int xb_err_intrsrc;
+ int (*xb_pci_intr_handler)(void *);
uint64_t xb_ier; /* copy of BRIDGE_IER value */
@@ -214,6 +215,7 @@ int xbridge_get_widget(void *);
int xbridge_get_dl(void *, pcitag_t, struct sgi_device_location *);
int xbridge_pci_intr_handler(void *);
+int xbridge_picv1_pci_intr_handler(void *);
int xbridge_err_intr_handler(void *);
uint8_t xbridge_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
@@ -515,6 +517,15 @@ xbpci_attach(struct device *parent, struct device *self, void *aux)
}
/*
+ * Revision 1 of PIC requires a wrapper around
+ * xbridge_pci_intr_handler().
+ */
+ if (ISSET(xb->xb_flags, XF_PIC) && xb->xb_revision <= 1)
+ xb->xb_pci_intr_handler = xbridge_picv1_pci_intr_handler;
+ else
+ xb->xb_pci_intr_handler = xbridge_pci_intr_handler;
+
+ /*
* Map Bridge registers.
*/
@@ -1113,7 +1124,7 @@ xbridge_intr_establish(void *cookie, pci_intr_handle_t ih, int level,
* XXX at IPL_BIO, in case the interrupt will be shared
* XXX between devices of different levels.
*/
- if (xbow_intr_establish(xbridge_pci_intr_handler, xi, intrsrc,
+ if (xbow_intr_establish(xb->xb_pci_intr_handler, xi, intrsrc,
IPL_BIO, NULL, NULL)) {
printf("%s: unable to register interrupt handler\n",
DEVNAME(xb));
@@ -1230,18 +1241,6 @@ xbridge_pci_intr_handler(void *v)
int rc;
uint64_t isr;
- /*
- * Revision 1 of PIC is supposed to need the interrupt enable bit
- * to be toggled to prevent loss of interrupt.
- */
- if (ISSET(xb->xb_flags, XF_PIC) && xb->xb_revision <= 1) {
- xbridge_write_reg(xb, BRIDGE_IER,
- xb->xb_ier & ~(1L << xi->xi_intrbit));
- (void)xbridge_read_reg(xb, WIDGET_TFLUSH);
- xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier);
- (void)xbridge_read_reg(xb, WIDGET_TFLUSH);
- }
-
/* 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);
@@ -1323,6 +1322,24 @@ xbridge_pci_intr_handler(void *v)
return rc;
}
+int
+xbridge_picv1_pci_intr_handler(void *v)
+{
+ struct xbridge_intr *xi = (struct xbridge_intr *)v;
+ struct xbpci_softc *xb = xi->xi_bus;
+
+ /*
+ * Revision 1 of PIC is supposed to need the interrupt enable bit
+ * to be toggled to prevent loss of interrupt.
+ */
+ xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier & ~(1L << xi->xi_intrbit));
+ (void)xbridge_read_reg(xb, WIDGET_TFLUSH);
+ xbridge_write_reg(xb, BRIDGE_IER, xb->xb_ier);
+ (void)xbridge_read_reg(xb, WIDGET_TFLUSH);
+
+ return xbridge_pci_intr_handler(v);
+}
+
/*
********************* chip register access.
*/