i40e: ensure reset occurs when disabling VF

It is possible although rare that we may not reset when
i40e_vc_disable_vf() is called. This can lead to some weird
circumstances with some values not being properly set. Modify
i40e_reset_vf() to return a code indicating whether it reset or not.

Now, i40e_vc_disable_vf() can wait until a reset actually occurs. If it
fails to free up within a reasonable time frame we'll display a warning
message.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Jacob Keller 2017-08-22 06:57:49 -04:00 committed by Jeff Kirsher
parent f18d20218a
commit d43d60e5eb
2 changed files with 35 additions and 11 deletions

View File

@ -156,12 +156,28 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
* i40e_vc_disable_vf
* @vf: pointer to the VF info
*
* Disable the VF through a SW reset
* Disable the VF through a SW reset.
**/
static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
{
int i;
i40e_vc_notify_vf_reset(vf);
i40e_reset_vf(vf, false);
/* We want to ensure that an actual reset occurs initiated after this
* function was called. However, we do not want to wait forever, so
* we'll give a reasonable time and print a message if we failed to
* ensure a reset.
*/
for (i = 0; i < 20; i++) {
if (i40e_reset_vf(vf, false))
return;
usleep_range(10000, 20000);
}
dev_warn(&vf->pf->pdev->dev,
"Failed to initiate reset for VF %d after 200 milliseconds\n",
vf->vf_id);
}
/**
@ -1051,9 +1067,9 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
* @vf: pointer to the VF structure
* @flr: VFLR was issued or not
*
* reset the VF
* Returns true if the VF is reset, false otherwise.
**/
void i40e_reset_vf(struct i40e_vf *vf, bool flr)
bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
{
struct i40e_pf *pf = vf->pf;
struct i40e_hw *hw = &pf->hw;
@ -1061,9 +1077,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
u32 reg;
int i;
/* If VFs have been disabled, there is no need to reset */
/* If the VFs have been disabled, this means something else is
* resetting the VF, so we shouldn't continue.
*/
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
return;
return false;
i40e_trigger_vf_reset(vf, flr);
@ -1100,6 +1118,8 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
i40e_flush(hw);
clear_bit(__I40E_VF_DISABLE, pf->state);
return true;
}
/**
@ -1111,8 +1131,10 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
* VF, then do all the waiting in one chunk, and finally finish restoring each
* VF after the wait. This is useful during PF routines which need to reset
* all VFs, as otherwise it must perform these resets in a serialized fashion.
*
* Returns true if any VFs were reset, and false otherwise.
**/
void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
{
struct i40e_hw *hw = &pf->hw;
struct i40e_vf *vf;
@ -1121,11 +1143,11 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
/* If we don't have any VFs, then there is nothing to reset */
if (!pf->num_alloc_vfs)
return;
return false;
/* If VFs have been disabled, there is no need to reset */
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
return;
return false;
/* Begin reset on all VFs at once */
for (v = 0; v < pf->num_alloc_vfs; v++)
@ -1200,6 +1222,8 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
i40e_flush(hw);
clear_bit(__I40E_VF_DISABLE, pf->state);
return true;
}
/**

View File

@ -122,8 +122,8 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
u32 v_retval, u8 *msg, u16 msglen);
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
void i40e_reset_vf(struct i40e_vf *vf, bool flr);
void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
bool i40e_reset_vf(struct i40e_vf *vf, bool flr);
bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
/* VF configuration related iplink handlers */