Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d43d60e5 authored by Jacob Keller's avatar Jacob Keller Committed by Jeff Kirsher
Browse files

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: default avatarJacob Keller <jacob.e.keller@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent f18d2021
Loading
Loading
Loading
Loading
+33 −9
Original line number Original line Diff line number Diff line
@@ -156,12 +156,28 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
 * i40e_vc_disable_vf
 * i40e_vc_disable_vf
 * @vf: pointer to the VF info
 * @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)
static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
{
{
	int i;

	i40e_vc_notify_vf_reset(vf);
	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
 * @vf: pointer to the VF structure
 * @flr: VFLR was issued or not
 * @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_pf *pf = vf->pf;
	struct i40e_hw *hw = &pf->hw;
	struct i40e_hw *hw = &pf->hw;
@@ -1061,9 +1077,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
	u32 reg;
	u32 reg;
	int i;
	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))
	if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
		return;
		return false;


	i40e_trigger_vf_reset(vf, flr);
	i40e_trigger_vf_reset(vf, flr);


@@ -1100,6 +1118,8 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)


	i40e_flush(hw);
	i40e_flush(hw);
	clear_bit(__I40E_VF_DISABLE, pf->state);
	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, 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
 * 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.
 * 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_hw *hw = &pf->hw;
	struct i40e_vf *vf;
	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 we don't have any VFs, then there is nothing to reset */
	if (!pf->num_alloc_vfs)
	if (!pf->num_alloc_vfs)
		return;
		return false;


	/* If VFs have been disabled, there is no need to reset */
	/* If VFs have been disabled, there is no need to reset */
	if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
	if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
		return;
		return false;


	/* Begin reset on all VFs at once */
	/* Begin reset on all VFs at once */
	for (v = 0; v < pf->num_alloc_vfs; v++)
	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);
	i40e_flush(hw);
	clear_bit(__I40E_VF_DISABLE, pf->state);
	clear_bit(__I40E_VF_DISABLE, pf->state);

	return true;
}
}


/**
/**
+2 −2
Original line number Original line Diff line number Diff line
@@ -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,
int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
			   u32 v_retval, u8 *msg, u16 msglen);
			   u32 v_retval, u8 *msg, u16 msglen);
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
void i40e_reset_vf(struct i40e_vf *vf, bool flr);
bool i40e_reset_vf(struct i40e_vf *vf, bool flr);
void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);


/* VF configuration related iplink handlers */
/* VF configuration related iplink handlers */