summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2020-11-09 15:09:09 +0000
committerbluhm <bluhm@openbsd.org>2020-11-09 15:09:09 +0000
commit783972a23f27e10a4f821a4e936c80cd2b214c89 (patch)
tree96107f35d1b7e7437783ced0171b30deedc324f4
parentspeed up the dependency check pass significantly: (diff)
downloadwireguard-openbsd-783972a23f27e10a4f821a4e936c80cd2b214c89.tar.xz
wireguard-openbsd-783972a23f27e10a4f821a4e936c80cd2b214c89.zip
There seems to be a silicon errata for 82598 ix(4) chips. When the
link state changes and an interrupt is fired for that, the MSI-X interrupt mask bits of the queues are cleared. During init while the queues are enabled by the driver, the hardware disabled them in the background. Then receiving packets did not work. In MSI-X mode, use the FreeBSD logic to read the cause from EICS register. from Christiano Haesbaert; tested with 82599 and X540T and OK jmatthew@
-rw-r--r--sys/dev/pci/if_ix.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c
index b246348231c..7980b9a86df 100644
--- a/sys/dev/pci/if_ix.c
+++ b/sys/dev/pci/if_ix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ix.c,v 1.173 2020/10/27 23:32:02 bluhm Exp $ */
+/* $OpenBSD: if_ix.c,v 1.174 2020/11/09 15:09:09 bluhm Exp $ */
/******************************************************************************
@@ -1061,7 +1061,6 @@ ixgbe_legacy_intr(void *arg)
rv = ixgbe_intr(sc);
if (rv == 0) {
- ixgbe_enable_queues(sc);
return (0);
}
@@ -1082,14 +1081,27 @@ ixgbe_intr(struct ix_softc *sc)
struct ixgbe_hw *hw = &sc->hw;
uint32_t reg_eicr, mod_mask, msf_mask;
- reg_eicr = IXGBE_READ_REG(&sc->hw, IXGBE_EICR);
- if (reg_eicr == 0) {
- ixgbe_enable_intr(sc);
- return (0);
+ if (sc->sc_intrmap) {
+ /* Pause other interrupts */
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_OTHER);
+ /* First get the cause */
+ reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
+ /* Be sure the queue bits are not cleared */
+ reg_eicr &= ~IXGBE_EICR_RTX_QUEUE;
+ /* Clear interrupt with write */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
+ } else {
+ reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+ if (reg_eicr == 0) {
+ ixgbe_enable_intr(sc);
+ ixgbe_enable_queues(sc);
+ return (0);
+ }
}
/* Link status change */
if (reg_eicr & IXGBE_EICR_LSC) {
+ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC);
KERNEL_LOCK();
ixgbe_update_link_status(sc);
KERNEL_UNLOCK();
@@ -1144,7 +1156,7 @@ ixgbe_intr(struct ix_softc *sc)
(reg_eicr & IXGBE_EICR_GPI_SDP1)) {
printf("%s: CRITICAL: FAN FAILURE!! "
"REPLACE IMMEDIATELY!!\n", ifp->if_xname);
- IXGBE_WRITE_REG(&sc->hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
}
/* External PHY interrupt */
@@ -1157,6 +1169,8 @@ ixgbe_intr(struct ix_softc *sc)
KERNEL_UNLOCK();
}
+ IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC);
+
return (1);
}