From dbe9aeaa2113719ca2069c9a21d8ffdd792e8d54 Mon Sep 17 00:00:00 2001 From: scottl Date: Fri, 29 Aug 2008 01:23:16 +0000 Subject: 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. --- sys/dev/ciss/ciss.c | 54 ++++++++++++++++++++++++++++---------------------- sys/dev/ciss/cissreg.h | 23 ++++++++++----------- 2 files changed, 40 insertions(+), 37 deletions(-) (limited to 'sys') 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 */ -- cgit v1.1