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.
This commit is contained in:
scottl 2008-08-29 01:23:16 +00:00
parent 505d893184
commit dbe9aeaa21
2 changed files with 40 additions and 37 deletions

View File

@ -367,7 +367,7 @@ static int
ciss_attach(device_t dev)
{
struct ciss_softc *sc;
int i, error;
int error;
debug_called(1);
@ -414,26 +414,6 @@ ciss_attach(device_t dev)
sc = device_get_softc(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.
*/
@ -579,11 +559,33 @@ 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 @@ ciss_init_pci(struct ciss_softc *sc)
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 @@ ciss_init_pci(struct ciss_softc *sc)
ciss_setup_msix(sc);
sc->ciss_perf = NULL;
intr = ciss_intr;
sc->ciss_interrupt_mask = sqmask;
}
/*

View File

@ -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 */