Commit 0f344c81 authored by Karen Sornek's avatar Karen Sornek Committed by Tony Nguyen

i40e: Fix for failed to init adminq while VF reset

Fix for failed to init adminq: -53 while VF is resetting via MAC
address changing procedure.
Added sync module to avoid reading deadbeef value in reinit adminq
during software reset.
Without this patch it is possible to trigger VF reset procedure
during reinit adminq. This resulted in an incorrect reading of
value from the AQP registers and generated the -53 error.

Fixes: 5c3c48ac ("i40e: implement virtual device interface")
Signed-off-by: default avatarGrzegorz Szczurek <grzegorzx.szczurek@intel.com>
Signed-off-by: default avatarKaren Sornek <karen.sornek@intel.com>
Tested-by: default avatarKonrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 92947844
......@@ -413,6 +413,9 @@
#define I40E_VFINT_DYN_CTLN(_INTVF) (0x00024800 + ((_INTVF) * 4)) /* _i=0...511 */ /* Reset: VFR */
#define I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT 1
#define I40E_VFINT_DYN_CTLN_CLEARPBA_MASK I40E_MASK(0x1, I40E_VFINT_DYN_CTLN_CLEARPBA_SHIFT)
#define I40E_VFINT_ICR0_ADMINQ_SHIFT 30
#define I40E_VFINT_ICR0_ADMINQ_MASK I40E_MASK(0x1, I40E_VFINT_ICR0_ADMINQ_SHIFT)
#define I40E_VFINT_ICR0_ENA(_VF) (0x0002C000 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPINT_AEQCTL(_VF) (0x0002B800 + ((_VF) * 4)) /* _i=0...127 */ /* Reset: CORER */
#define I40E_VPINT_AEQCTL_MSIX_INDX_SHIFT 0
#define I40E_VPINT_AEQCTL_ITR_INDX_SHIFT 11
......
......@@ -1376,6 +1376,32 @@ static i40e_status i40e_config_vf_promiscuous_mode(struct i40e_vf *vf,
return aq_ret;
}
/**
* i40e_sync_vfr_reset
* @hw: pointer to hw struct
* @vf_id: VF identifier
*
* Before trigger hardware reset, we need to know if no other process has
* reserved the hardware for any reset operations. This check is done by
* examining the status of the RSTAT1 register used to signal the reset.
**/
static int i40e_sync_vfr_reset(struct i40e_hw *hw, int vf_id)
{
u32 reg;
int i;
for (i = 0; i < I40E_VFR_WAIT_COUNT; i++) {
reg = rd32(hw, I40E_VFINT_ICR0_ENA(vf_id)) &
I40E_VFINT_ICR0_ADMINQ_MASK;
if (reg)
return 0;
usleep_range(100, 200);
}
return -EAGAIN;
}
/**
* i40e_trigger_vf_reset
* @vf: pointer to the VF structure
......@@ -1390,9 +1416,11 @@ static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr)
struct i40e_pf *pf = vf->pf;
struct i40e_hw *hw = &pf->hw;
u32 reg, reg_idx, bit_idx;
bool vf_active;
u32 radq;
/* warn the VF */
clear_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
vf_active = test_and_clear_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states);
/* Disable VF's configuration API during reset. The flag is re-enabled
* in i40e_alloc_vf_res(), when it's safe again to access VF's VSI.
......@@ -1406,7 +1434,19 @@ static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr)
* just need to clean up, so don't hit the VFRTRIG register.
*/
if (!flr) {
/* reset VF using VPGEN_VFRTRIG reg */
/* Sync VFR reset before trigger next one */
radq = rd32(hw, I40E_VFINT_ICR0_ENA(vf->vf_id)) &
I40E_VFINT_ICR0_ADMINQ_MASK;
if (vf_active && !radq)
/* waiting for finish reset by virtual driver */
if (i40e_sync_vfr_reset(hw, vf->vf_id))
dev_info(&pf->pdev->dev,
"Reset VF %d never finished\n",
vf->vf_id);
/* Reset VF using VPGEN_VFRTRIG reg. It is also setting
* in progress state in rstat1 register.
*/
reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
reg |= I40E_VPGEN_VFRTRIG_VFSWR_MASK;
wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
......
......@@ -19,6 +19,7 @@
#define I40E_MAX_VF_PROMISC_FLAGS 3
#define I40E_VF_STATE_WAIT_COUNT 20
#define I40E_VFR_WAIT_COUNT 100
/* Various queue ctrls */
enum i40e_queue_ctrl {
......
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