aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuinan Sun <guinanx.sun@intel.com>2020-07-09 08:00:31 +0000
committerKevin Bowling <kbowling@FreeBSD.org>2021-09-14 00:36:41 +0000
commitd357a27643af01bd39056ffc77a745568dbf5035 (patch)
tree517bedd8713efc06597e59286624890f4785ae94
parentdf57aa230c7fe67c5c72217d8e19ed5aef72d626 (diff)
downloadsrc-d357a27643af01bd39056ffc77a745568dbf5035.tar.gz
src-d357a27643af01bd39056ffc77a745568dbf5035.zip
ixgbe: fix infinite recursion on PCIe link down
In some corner cases the functions ixgbe_clear_rar_generic and ixgbe_clear_vmdq_generic may call one another leading to infinite recursion. When ixgbe_clear_vmdq_generic is called with IXGBE_CLEAR_VMDQ_ALL flag, it's going to clear MPSAR registers, and proceed to call ixgbe_clear_rar_generic, which in turn will clear the RAR registers, and recursively call back ixgbe_clear_vmdq_generic. Normally, the latter would detect that MPSAR registers have already been cleared and terminate the recursion. However, when PCIe link is down, and before the driver has had the opportunity to shut itself down, all register reads return 0xFFFFFFFF, and all register writes fail silently. In such case, because ixgbe_clear_vmdq_generic blindly assumes that clearing MPSAR registers succeeded, it's going to always call ixgbe_clear_rar_generic, which in turn will always call back ixgbe_clear_vmdq_generic, creating infinite recursion. This patch re-reads MPSAR register values after they had been cleared. In case of PCIe link failure, the values read will be non-zero, which will terminate the recursion. On the other hand, under normal circumstances the value read from MPSAR registers is going to be equal to the value previously written, so this patch is expected not to cause any regressions. Signed-off-by: Robert Konklewski <robertx.konklewski@intel.com> Signed-off-by: Guinan Sun <guinanx.sun@intel.com> Reviewed-by: Wei Zhao <wei.zhao1@intel.com> Approved by: imp Obtained from: DPDK (2d04b9e856125197ec8e967471426d56ab7efcf0) MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D31621 (cherry picked from commit 8270b7174c48417a4d5f3effa4a4f4588205e687)
-rw-r--r--sys/dev/ixgbe/ixgbe_common.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c
index d7da9f81fbf8..92db7c14da45 100644
--- a/sys/dev/ixgbe/ixgbe_common.c
+++ b/sys/dev/ixgbe/ixgbe_common.c
@@ -3813,11 +3813,11 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
if (mpsar_lo) {
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
- mpsar_lo = 0;
+ mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
}
if (mpsar_hi) {
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
- mpsar_hi = 0;
+ mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
}
} else if (vmdq < 32) {
mpsar_lo &= ~(1 << vmdq);