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:
parent
505d893184
commit
dbe9aeaa21
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user