summaryrefslogtreecommitdiffstats
path: root/sys/dev/ciss
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2008-08-29 01:23:16 +0000
committerscottl <scottl@FreeBSD.org>2008-08-29 01:23:16 +0000
commitdbe9aeaa2113719ca2069c9a21d8ffdd792e8d54 (patch)
tree282e1a7723d584ef3cbcf1b8e5dab0c0b0af6f95 /sys/dev/ciss
parent505d89318458cc104a4efc0e50e2f1f20f20fdd6 (diff)
downloadFreeBSD-src-dbe9aeaa2113719ca2069c9a21d8ffdd792e8d54.zip
FreeBSD-src-dbe9aeaa2113719ca2069c9a21d8ffdd792e8d54.tar.gz
Work again to fix the interrupt masking problems. We now recognize
that there are 3 different interrupt enable bits, 2 for different families of cards, and 1 for when MSI is used. Also apply a big hammer backstop for cards that aren't recognized. This should fix all of the interrupt issues at boot.
Diffstat (limited to 'sys/dev/ciss')
-rw-r--r--sys/dev/ciss/ciss.c54
-rw-r--r--sys/dev/ciss/cissreg.h23
2 files changed, 40 insertions, 37 deletions
diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c
index 9073e7b..559dacd 100644
--- a/sys/dev/ciss/ciss.c
+++ b/sys/dev/ciss/ciss.c
@@ -367,7 +367,7 @@ static int
ciss_attach(device_t dev)
{
struct ciss_softc *sc;
- int i, error;
+ int error;
debug_called(1);
@@ -415,26 +415,6 @@ ciss_attach(device_t dev)
sc->ciss_dev = dev;
/*
- * Work out adapter type.
- */
- i = ciss_lookup(dev);
- if (i < 0) {
- ciss_printf(sc, "unknown adapter type\n");
- error = ENXIO;
- goto out;
- }
- if (ciss_vendor_data[i].flags & CISS_BOARD_SA5) {
- sc->ciss_interrupt_mask = CISS_TL_SIMPLE_INTR_OPQ_SA5;
- } else if (ciss_vendor_data[i].flags & CISS_BOARD_SA5B) {
- sc->ciss_interrupt_mask = CISS_TL_SIMPLE_INTR_OPQ_SA5B;
- } else {
- /* really an error on our part */
- ciss_printf(sc, "unable to determine hardware type\n");
- error = ENXIO;
- goto out;
- }
-
- /*
* Do PCI-specific init.
*/
if ((error = ciss_init_pci(sc)) != 0)
@@ -579,12 +559,34 @@ ciss_init_pci(struct ciss_softc *sc)
{
uintptr_t cbase, csize, cofs;
uint32_t method, supported_methods;
- int error;
+ int error, sqmask, i;
void *intr;
debug_called(1);
/*
+ * Work out adapter type.
+ */
+ i = ciss_lookup(sc->ciss_dev);
+ if (i < 0) {
+ ciss_printf(sc, "unknown adapter type\n");
+ return (ENXIO);
+ }
+
+ if (ciss_vendor_data[i].flags & CISS_BOARD_SA5) {
+ sqmask = CISS_TL_SIMPLE_INTR_OPQ_SA5;
+ } else if (ciss_vendor_data[i].flags & CISS_BOARD_SA5B) {
+ sqmask = CISS_TL_SIMPLE_INTR_OPQ_SA5B;
+ } else {
+ /*
+ * XXX Big hammer, masks/unmasks all possible interrupts. This should
+ * work on all hardware variants. Need to add code to handle the
+ * "controller crashed" interupt bit that this unmasks.
+ */
+ sqmask = ~0;
+ }
+
+ /*
* Allocate register window first (we need this to find the config
* struct).
*/
@@ -729,10 +731,13 @@ setup:
sc->ciss_irq_rid[0] = 0;
if (method == CISS_TRANSPORT_METHOD_PERF) {
ciss_printf(sc, "PERFORMANT Transport\n");
- if ((ciss_force_interrupt != 1) && (ciss_setup_msix(sc) == 0))
+ if ((ciss_force_interrupt != 1) && (ciss_setup_msix(sc) == 0)) {
intr = ciss_perf_msi_intr;
- else
+ sc->ciss_interrupt_mask = CISS_TL_PERF_INTR_MSI;
+ } else {
intr = ciss_perf_intr;
+ sc->ciss_interrupt_mask = CISS_TL_PERF_INTR_OPQ;
+ }
} else {
ciss_printf(sc, "SIMPLE Transport\n");
/* MSIX doesn't seem to work in SIMPLE mode, only enable if it forced */
@@ -741,6 +746,7 @@ setup:
ciss_setup_msix(sc);
sc->ciss_perf = NULL;
intr = ciss_intr;
+ sc->ciss_interrupt_mask = sqmask;
}
/*
diff --git a/sys/dev/ciss/cissreg.h b/sys/dev/ciss/cissreg.h
index 982df2f..196307b 100644
--- a/sys/dev/ciss/cissreg.h
+++ b/sys/dev/ciss/cissreg.h
@@ -728,6 +728,9 @@ struct ciss_bmic_flush_cache {
#define CISS_TL_SIMPLE_POST_CMD(sc, phys) CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IPQ, phys)
#define CISS_TL_SIMPLE_FETCH_CMD(sc) CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_OPQ)
+#define CISS_TL_PERF_INTR_OPQ (CISS_TL_SIMPLE_INTR_OPQ_SA5 | CISS_TL_SIMPLE_INTR_OPQ_SA5B)
+#define CISS_TL_PERF_INTR_MSI 0x01
+
#define CISS_TL_PERF_POST_CMD(sc, cr) CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IPQ, CISS_FIND_COMMANDPHYS(cr) | (cr)->cr_sg_tag)
#define CISS_TL_PERF_FLUSH_INT(sc) CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_OSR)
#define CISS_TL_PERF_CLEAR_INT(sc) CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_ODC, CISS_TL_SIMPLE_ODC_CLEAR)
@@ -735,18 +738,12 @@ struct ciss_bmic_flush_cache {
#define CISS_MSI_COUNT 4
-/*
- * XXX Here we effectively trust the BIOS to set the IMR correctly. But if
- * we don't trust it, will we get into trouble with wrongly assuming what it
- * should be?
- */
-#define CISS_TL_SIMPLE_DISABLE_INTERRUPTS(sc) \
- do { \
- (sc)->ciss_interrupt_mask = \
- CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IMR); \
- CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IMR, ~0); \
- } while (0)
-#define CISS_TL_SIMPLE_ENABLE_INTERRUPTS(sc) \
- CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IMR, (sc)->ciss_interrupt_mask)
+#define CISS_TL_SIMPLE_DISABLE_INTERRUPTS(sc) \
+ CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IMR, \
+ CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IMR) | (sc)->ciss_interrupt_mask)
+#define CISS_TL_SIMPLE_ENABLE_INTERRUPTS(sc) \
+ CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IMR, \
+ CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IMR) & ~(sc)->ciss_interrupt_mask)
+
#endif /* _KERNEL */
OpenPOWER on IntegriCloud