Commit f838a633 authored by Dawid Lukwinski's avatar Dawid Lukwinski Committed by Jakub Kicinski

i40e: Fix erroneous adapter reinitialization during recovery process

Fix an issue when driver incorrectly detects state
of recovery process and erroneously reinitializes interrupts,
which results in a kernel error and call trace message.

The issue was caused by a combination of two factors:
1. Assuming the EMP reset issued after completing
firmware recovery means the whole recovery process is complete.
2. Erroneous reinitialization of interrupt vector after detecting
the above mentioned EMP reset.

Fixes (1) by changing how recovery state change is detected
and (2) by adjusting the conditional expression to ensure using proper
interrupt reinitialization method, depending on the situation.

Fixes: 4ff0ee1a ("i40e: Introduce recovery mode support")
Signed-off-by: default avatarDawid Lukwinski <dawid.lukwinski@intel.com>
Signed-off-by: default avatarJan Sokolowski <jan.sokolowski@intel.com>
Tested-by: default avatarKonrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Link: https://lore.kernel.org/r/20220715214542.2968762-1-anthony.l.nguyen@intel.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 3696c952
...@@ -10650,7 +10650,7 @@ static int i40e_reset(struct i40e_pf *pf) ...@@ -10650,7 +10650,7 @@ static int i40e_reset(struct i40e_pf *pf)
**/ **/
static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
{ {
int old_recovery_mode_bit = test_bit(__I40E_RECOVERY_MODE, pf->state); const bool is_recovery_mode_reported = i40e_check_recovery_mode(pf);
struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
struct i40e_hw *hw = &pf->hw; struct i40e_hw *hw = &pf->hw;
i40e_status ret; i40e_status ret;
...@@ -10658,13 +10658,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) ...@@ -10658,13 +10658,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
int v; int v;
if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) && if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
i40e_check_recovery_mode(pf)) { is_recovery_mode_reported)
i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev); i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev);
}
if (test_bit(__I40E_DOWN, pf->state) && if (test_bit(__I40E_DOWN, pf->state) &&
!test_bit(__I40E_RECOVERY_MODE, pf->state) && !test_bit(__I40E_RECOVERY_MODE, pf->state))
!old_recovery_mode_bit)
goto clear_recovery; goto clear_recovery;
dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n"); dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
...@@ -10691,13 +10689,12 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) ...@@ -10691,13 +10689,12 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
* accordingly with regard to resources initialization * accordingly with regard to resources initialization
* and deinitialization * and deinitialization
*/ */
if (test_bit(__I40E_RECOVERY_MODE, pf->state) || if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
old_recovery_mode_bit) {
if (i40e_get_capabilities(pf, if (i40e_get_capabilities(pf,
i40e_aqc_opc_list_func_capabilities)) i40e_aqc_opc_list_func_capabilities))
goto end_unlock; goto end_unlock;
if (test_bit(__I40E_RECOVERY_MODE, pf->state)) { if (is_recovery_mode_reported) {
/* we're staying in recovery mode so we'll reinitialize /* we're staying in recovery mode so we'll reinitialize
* misc vector here * misc vector here
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment