Commit 347b5650 authored by Eryk Rybak's avatar Eryk Rybak Committed by Tony Nguyen

i40e: Fix kernel oops when i40e driver removes VF's

Fix the reason of kernel oops when i40e driver removed VFs.
Added new __I40E_VFS_RELEASING state to signalize releasing
process by PF, that it makes possible to exit of reset VF procedure.
Without this patch, it is possible to suspend the VFs reset by
releasing VFs resources procedure. Retrying the reset after the
timeout works on the freed VF memory causing a kernel oops.

Fixes: d43d60e5 ("i40e: ensure reset occurs when disabling VF")
Signed-off-by: default avatarEryk Rybak <eryk.roch.rybak@intel.com>
Signed-off-by: default avatarGrzegorz Szczurek <grzegorzx.szczurek@intel.com>
Reviewed-by: default avatarAleksandr Loktionov <aleksandr.loktionov@intel.com>
Tested-by: default avatarKonrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 90449e98
...@@ -142,6 +142,7 @@ enum i40e_state_t { ...@@ -142,6 +142,7 @@ enum i40e_state_t {
__I40E_VIRTCHNL_OP_PENDING, __I40E_VIRTCHNL_OP_PENDING,
__I40E_RECOVERY_MODE, __I40E_RECOVERY_MODE,
__I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */ __I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */
__I40E_VFS_RELEASING,
/* This must be last as it determines the size of the BITMAP */ /* This must be last as it determines the size of the BITMAP */
__I40E_STATE_SIZE__, __I40E_STATE_SIZE__,
}; };
......
...@@ -137,6 +137,7 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf) ...@@ -137,6 +137,7 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
**/ **/
static inline void i40e_vc_disable_vf(struct i40e_vf *vf) static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
{ {
struct i40e_pf *pf = vf->pf;
int i; int i;
i40e_vc_notify_vf_reset(vf); i40e_vc_notify_vf_reset(vf);
...@@ -147,6 +148,11 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf) ...@@ -147,6 +148,11 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
* ensure a reset. * ensure a reset.
*/ */
for (i = 0; i < 20; i++) { for (i = 0; i < 20; i++) {
/* If PF is in VFs releasing state reset VF is impossible,
* so leave it.
*/
if (test_bit(__I40E_VFS_RELEASING, pf->state))
return;
if (i40e_reset_vf(vf, false)) if (i40e_reset_vf(vf, false))
return; return;
usleep_range(10000, 20000); usleep_range(10000, 20000);
...@@ -1574,6 +1580,8 @@ void i40e_free_vfs(struct i40e_pf *pf) ...@@ -1574,6 +1580,8 @@ void i40e_free_vfs(struct i40e_pf *pf)
if (!pf->vf) if (!pf->vf)
return; return;
set_bit(__I40E_VFS_RELEASING, pf->state);
while (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) while (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
usleep_range(1000, 2000); usleep_range(1000, 2000);
...@@ -1631,6 +1639,7 @@ void i40e_free_vfs(struct i40e_pf *pf) ...@@ -1631,6 +1639,7 @@ void i40e_free_vfs(struct i40e_pf *pf)
} }
} }
clear_bit(__I40E_VF_DISABLE, pf->state); clear_bit(__I40E_VF_DISABLE, pf->state);
clear_bit(__I40E_VFS_RELEASING, pf->state);
} }
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
......
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