[v3,04/19] net/ixgbe/base: resolve infinite recursion on PCIe link down
diff mbox series

Message ID 20200709080046.65879-5-guinanx.sun@intel.com
State Accepted
Delegated to: Qi Zhang
Headers show
Series
  • update ixgbe base code
Related show

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch warning coding style issues

Commit Message

Guinan Sun July 9, 2020, 8 a.m. UTC
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
inifinite 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>
---
 drivers/net/ixgbe/base/ixgbe_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Patch
diff mbox series

diff --git a/drivers/net/ixgbe/base/ixgbe_common.c b/drivers/net/ixgbe/base/ixgbe_common.c
index fec6241f5..2d848a02b 100644
--- a/drivers/net/ixgbe/base/ixgbe_common.c
+++ b/drivers/net/ixgbe/base/ixgbe_common.c
@@ -3777,11 +3777,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);