diff options
author | 2020-11-09 15:09:09 +0000 | |
---|---|---|
committer | 2020-11-09 15:09:09 +0000 | |
commit | 783972a23f27e10a4f821a4e936c80cd2b214c89 (patch) | |
tree | 96107f35d1b7e7437783ced0171b30deedc324f4 | |
parent | speed up the dependency check pass significantly: (diff) | |
download | wireguard-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.c | 28 |
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); } |