Skip to content

Commit 52424f9

Browse files
sylwesterdziedziuchkuba-moo
authored andcommitted
i40e: Fix VF hang when reset is triggered on another VF
When a reset was triggered on one VF with i40e_reset_vf global PF state __I40E_VF_DISABLE was set on a PF until the reset finished. If immediately after triggering reset on one VF there is a request to reset on another it will cause a hang on VF side because VF will be notified of incoming reset but the reset will never happen because of this global state, we will get such error message: [ +4.890195] iavf 0000:86:02.1: Never saw reset and VF will hang waiting for the reset to be triggered. Fix this by introducing new VF state I40E_VF_STATE_RESETTING that will be set on a VF if it is currently resetting instead of the global __I40E_VF_DISABLE PF state. Fixes: 3ba9bcb ("i40e: add locking around VF reset") Signed-off-by: Sylwester Dziedziuch <[email protected]> Signed-off-by: Mateusz Palczewski <[email protected]> Tested-by: Konrad Jankowski <[email protected]> Signed-off-by: Jacob Keller <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 54b5af5 commit 52424f9

File tree

2 files changed

+33
-11
lines changed

2 files changed

+33
-11
lines changed

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

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,10 +1536,12 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
15361536
if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state))
15371537
return true;
15381538

1539-
/* If the VFs have been disabled, this means something else is
1540-
* resetting the VF, so we shouldn't continue.
1541-
*/
1542-
if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
1539+
/* Bail out if VFs are disabled. */
1540+
if (test_bit(__I40E_VF_DISABLE, pf->state))
1541+
return true;
1542+
1543+
/* If VF is being reset already we don't need to continue. */
1544+
if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
15431545
return true;
15441546

15451547
i40e_trigger_vf_reset(vf, flr);
@@ -1576,7 +1578,7 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
15761578
i40e_cleanup_reset_vf(vf);
15771579

15781580
i40e_flush(hw);
1579-
clear_bit(__I40E_VF_DISABLE, pf->state);
1581+
clear_bit(I40E_VF_STATE_RESETTING, &vf->vf_states);
15801582

15811583
return true;
15821584
}
@@ -1609,8 +1611,12 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
16091611
return false;
16101612

16111613
/* Begin reset on all VFs at once */
1612-
for (v = 0; v < pf->num_alloc_vfs; v++)
1613-
i40e_trigger_vf_reset(&pf->vf[v], flr);
1614+
for (v = 0; v < pf->num_alloc_vfs; v++) {
1615+
vf = &pf->vf[v];
1616+
/* If VF is being reset no need to trigger reset again */
1617+
if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
1618+
i40e_trigger_vf_reset(&pf->vf[v], flr);
1619+
}
16141620

16151621
/* HW requires some time to make sure it can flush the FIFO for a VF
16161622
* when it resets it. Poll the VPGEN_VFRSTAT register for each VF in
@@ -1626,9 +1632,11 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
16261632
*/
16271633
while (v < pf->num_alloc_vfs) {
16281634
vf = &pf->vf[v];
1629-
reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
1630-
if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK))
1631-
break;
1635+
if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) {
1636+
reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
1637+
if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK))
1638+
break;
1639+
}
16321640

16331641
/* If the current VF has finished resetting, move on
16341642
* to the next VF in sequence.
@@ -1656,6 +1664,10 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
16561664
if (pf->vf[v].lan_vsi_idx == 0)
16571665
continue;
16581666

1667+
/* If VF is reset in another thread just continue */
1668+
if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
1669+
continue;
1670+
16591671
i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[v].lan_vsi_idx]);
16601672
}
16611673

@@ -1667,6 +1679,10 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
16671679
if (pf->vf[v].lan_vsi_idx == 0)
16681680
continue;
16691681

1682+
/* If VF is reset in another thread just continue */
1683+
if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
1684+
continue;
1685+
16701686
i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[v].lan_vsi_idx]);
16711687
}
16721688

@@ -1676,8 +1692,13 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
16761692
mdelay(50);
16771693

16781694
/* Finish the reset on each VF */
1679-
for (v = 0; v < pf->num_alloc_vfs; v++)
1695+
for (v = 0; v < pf->num_alloc_vfs; v++) {
1696+
/* If VF is reset in another thread just continue */
1697+
if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
1698+
continue;
1699+
16801700
i40e_cleanup_reset_vf(&pf->vf[v]);
1701+
}
16811702

16821703
i40e_flush(hw);
16831704
clear_bit(__I40E_VF_DISABLE, pf->state);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum i40e_vf_states {
3939
I40E_VF_STATE_MC_PROMISC,
4040
I40E_VF_STATE_UC_PROMISC,
4141
I40E_VF_STATE_PRE_ENABLE,
42+
I40E_VF_STATE_RESETTING
4243
};
4344

4445
/* VF capabilities */

0 commit comments

Comments
 (0)