Skip to content

Commit d43d60e

Browse files
jacob-kellerJeff Kirsher
authored andcommitted
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 <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent f18d202 commit d43d60e

File tree

2 files changed

+35
-11
lines changed

2 files changed

+35
-11
lines changed

drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,28 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
156156
* i40e_vc_disable_vf
157157
* @vf: pointer to the VF info
158158
*
159-
* Disable the VF through a SW reset
159+
* Disable the VF through a SW reset.
160160
**/
161161
static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
162162
{
163+
int i;
164+
163165
i40e_vc_notify_vf_reset(vf);
164-
i40e_reset_vf(vf, false);
166+
167+
/* We want to ensure that an actual reset occurs initiated after this
168+
* function was called. However, we do not want to wait forever, so
169+
* we'll give a reasonable time and print a message if we failed to
170+
* ensure a reset.
171+
*/
172+
for (i = 0; i < 20; i++) {
173+
if (i40e_reset_vf(vf, false))
174+
return;
175+
usleep_range(10000, 20000);
176+
}
177+
178+
dev_warn(&vf->pf->pdev->dev,
179+
"Failed to initiate reset for VF %d after 200 milliseconds\n",
180+
vf->vf_id);
165181
}
166182

167183
/**
@@ -1051,19 +1067,21 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
10511067
* @vf: pointer to the VF structure
10521068
* @flr: VFLR was issued or not
10531069
*
1054-
* reset the VF
1070+
* Returns true if the VF is reset, false otherwise.
10551071
**/
1056-
void i40e_reset_vf(struct i40e_vf *vf, bool flr)
1072+
bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
10571073
{
10581074
struct i40e_pf *pf = vf->pf;
10591075
struct i40e_hw *hw = &pf->hw;
10601076
bool rsd = false;
10611077
u32 reg;
10621078
int i;
10631079

1064-
/* If VFs have been disabled, there is no need to reset */
1080+
/* If the VFs have been disabled, this means something else is
1081+
* resetting the VF, so we shouldn't continue.
1082+
*/
10651083
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
1066-
return;
1084+
return false;
10671085

10681086
i40e_trigger_vf_reset(vf, flr);
10691087

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

11011119
i40e_flush(hw);
11021120
clear_bit(__I40E_VF_DISABLE, pf->state);
1121+
1122+
return true;
11031123
}
11041124

11051125
/**
@@ -1111,8 +1131,10 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
11111131
* VF, then do all the waiting in one chunk, and finally finish restoring each
11121132
* VF after the wait. This is useful during PF routines which need to reset
11131133
* all VFs, as otherwise it must perform these resets in a serialized fashion.
1134+
*
1135+
* Returns true if any VFs were reset, and false otherwise.
11141136
**/
1115-
void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
1137+
bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
11161138
{
11171139
struct i40e_hw *hw = &pf->hw;
11181140
struct i40e_vf *vf;
@@ -1121,11 +1143,11 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
11211143

11221144
/* If we don't have any VFs, then there is nothing to reset */
11231145
if (!pf->num_alloc_vfs)
1124-
return;
1146+
return false;
11251147

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

11301152
/* Begin reset on all VFs at once */
11311153
for (v = 0; v < pf->num_alloc_vfs; v++)
@@ -1200,6 +1222,8 @@ void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
12001222

12011223
i40e_flush(hw);
12021224
clear_bit(__I40E_VF_DISABLE, pf->state);
1225+
1226+
return true;
12031227
}
12041228

12051229
/**

drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
122122
int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
123123
u32 v_retval, u8 *msg, u16 msglen);
124124
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
125-
void i40e_reset_vf(struct i40e_vf *vf, bool flr);
126-
void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
125+
bool i40e_reset_vf(struct i40e_vf *vf, bool flr);
126+
bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
127127
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
128128

129129
/* VF configuration related iplink handlers */

0 commit comments

Comments
 (0)