Hi,
here are some small improvements for iwm's interrupt handler.
- Hardware errors (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) should
be checked in both cases (ict and non-ict).
- r1 and r2 should be uint32, they are read with bus_space_read_4()
- (Slightly) better explanation for hardware bug mitigation
ok?
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c
index 34877135003..518595c601e 100644
--- a/sys/dev/pci/if_iwm.c
+++ b/sys/dev/pci/if_iwm.c
@@ -8589,8 +8589,9 @@ iwm_intr(void *arg)
{
struct iwm_softc *sc = arg;
int handled = 0;
- int r1, r2, rv = 0;
+ int rv = 0;
int isperiodic = 0;
+ uint32_t r1, r2;
IWM_WRITE(sc, IWM_CSR_INT_MASK, 0);
@@ -8617,19 +8618,24 @@ iwm_intr(void *arg)
if (r1 == 0xffffffff)
r1 = 0;
- /* i am not expected to understand this */
+ /*
+ * Workaround for hardware bug where bits are falsely cleared
+ * when using interrupt coalescing. Bit 15 should be set if
+ * bits 18 and 19 are set.
+ */
if (r1 & 0xc0000)
r1 |= 0x8000;
+
r1 = (0xff & r1) | ((0xff00 & r1) << 16);
} else {
r1 = IWM_READ(sc, IWM_CSR_INT);
- if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
- goto out;
r2 = IWM_READ(sc, IWM_CSR_FH_INT_STATUS);
}
if (r1 == 0 && r2 == 0) {
goto out_ena;
}
+ if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
+ goto out;
IWM_WRITE(sc, IWM_CSR_INT, r1 | ~sc->sc_intmask);