Skip to content

Commit 3ba9bcb

Browse files
mawilli1Jeff Kirsher
authored andcommitted
i40e: add locking around VF reset
During VF deallocation, we need to lock out the VF reset code. However, we cannot depend on simply masking the interrupt, as this does not lock out the service task, which can still call the reset routine. Instead, leave the interrupt enabled, but add locking around the VF disable and reset routines. For the disable code, we wait to get the lock, as the reset code will take a finite amount of time to run. For the reset code, we just return if we fail to get the lock. Since we know that the VFs are being disabled, we don't need to handle the reset. This fixes a panic when disabling SR-IOV. Change-ID: Iea0a6cdef35c331f48c6d5b2f8e6f0e86322e7d8 Signed-off-by: Mitch Williams <[email protected]> Tested-by: Jim Young <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 0757489 commit 3ba9bcb

File tree

2 files changed

+8
-6
lines changed

2 files changed

+8
-6
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ enum i40e_state_t {
148148
__I40E_FD_FLUSH_REQUESTED,
149149
__I40E_RESET_FAILED,
150150
__I40E_PORT_TX_SUSPENDED,
151+
__I40E_VF_DISABLE,
151152
};
152153

153154
enum i40e_interrupt_policy {

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,9 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
647647
int i;
648648
u32 reg;
649649

650+
if (test_and_set_bit(__I40E_VF_DISABLE, &pf->state))
651+
return;
652+
650653
/* warn the VF */
651654
clear_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
652655

@@ -706,6 +709,7 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
706709
/* tell the VF the reset is done */
707710
wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
708711
i40e_flush(hw);
712+
clear_bit(__I40E_VF_DISABLE, &pf->state);
709713
}
710714

711715
/**
@@ -790,6 +794,8 @@ void i40e_free_vfs(struct i40e_pf *pf)
790794

791795
if (!pf->vf)
792796
return;
797+
while (test_and_set_bit(__I40E_VF_DISABLE, &pf->state))
798+
usleep_range(1000, 2000);
793799

794800
/* Disable IOV before freeing resources. This lets any VF drivers
795801
* running in the host get themselves cleaned up before we yank
@@ -800,9 +806,6 @@ void i40e_free_vfs(struct i40e_pf *pf)
800806

801807
msleep(20); /* let any messages in transit get finished up */
802808

803-
/* Disable interrupt 0 so we don't try to handle the VFLR. */
804-
i40e_irq_dynamic_disable_icr0(pf);
805-
806809
/* free up vf resources */
807810
tmp = pf->num_alloc_vfs;
808811
pf->num_alloc_vfs = 0;
@@ -834,9 +837,7 @@ void i40e_free_vfs(struct i40e_pf *pf)
834837
dev_warn(&pf->pdev->dev,
835838
"unable to disable SR-IOV because VFs are assigned.\n");
836839
}
837-
838-
/* Re-enable interrupt 0. */
839-
i40e_irq_dynamic_enable_icr0(pf);
840+
clear_bit(__I40E_VF_DISABLE, &pf->state);
840841
}
841842

842843
#ifdef CONFIG_PCI_IOV

0 commit comments

Comments
 (0)