diff options
Diffstat (limited to 'drivers/net/ethernet/intel')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 22 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 | 
3 files changed, 31 insertions, 18 deletions
| diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 537300e762f0..d231a2cdd98f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -140,6 +140,7 @@ enum i40e_state_t {  	__I40E_CLIENT_RESET,  	__I40E_VIRTCHNL_OP_PENDING,  	__I40E_RECOVERY_MODE, +	__I40E_VF_RESETS_DISABLED,	/* disable resets during i40e_remove */  	/* This must be last as it determines the size of the BITMAP */  	__I40E_STATE_SIZE__,  }; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4f8a2154b93f..1337686bd099 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4010,8 +4010,16 @@ static irqreturn_t i40e_intr(int irq, void *data)  	}  	if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) { -		ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; -		set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); +		/* disable any further VFLR event notifications */ +		if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) { +			u32 reg = rd32(hw, I40E_PFINT_ICR0_ENA); + +			reg &= ~I40E_PFINT_ICR0_VFLR_MASK; +			wr32(hw, I40E_PFINT_ICR0_ENA, reg); +		} else { +			ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; +			set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); +		}  	}  	if (icr0 & I40E_PFINT_ICR0_GRST_MASK) { @@ -15311,6 +15319,11 @@ static void i40e_remove(struct pci_dev *pdev)  	while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))  		usleep_range(1000, 2000); +	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { +		set_bit(__I40E_VF_RESETS_DISABLED, pf->state); +		i40e_free_vfs(pf); +		pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; +	}  	/* no more scheduling of any task */  	set_bit(__I40E_SUSPENDED, pf->state);  	set_bit(__I40E_DOWN, pf->state); @@ -15337,11 +15350,6 @@ static void i40e_remove(struct pci_dev *pdev)  	 */  	i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false); -	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { -		i40e_free_vfs(pf); -		pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; -	} -  	i40e_fdir_teardown(pf);  	/* If there is a switch structure or any orphans, remove them. diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 4919d22d7b6b..1b5390ec3d78 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1403,7 +1403,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf)   * @vf: pointer to the VF structure   * @flr: VFLR was issued or not   * - * Returns true if the VF is reset, false otherwise. + * Returns true if the VF is in reset, resets successfully, or resets + * are disabled and false otherwise.   **/  bool i40e_reset_vf(struct i40e_vf *vf, bool flr)  { @@ -1413,11 +1414,14 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr)  	u32 reg;  	int i; +	if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) +		return true; +  	/* 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)) -		return false; +		return true;  	i40e_trigger_vf_reset(vf, flr); @@ -1581,6 +1585,15 @@ void i40e_free_vfs(struct i40e_pf *pf)  	i40e_notify_client_of_vf_enable(pf, 0); +	/* Disable IOV before freeing resources. This lets any VF drivers +	 * running in the host get themselves cleaned up before we yank +	 * the carpet out from underneath their feet. +	 */ +	if (!pci_vfs_assigned(pf->pdev)) +		pci_disable_sriov(pf->pdev); +	else +		dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); +  	/* Amortize wait time by stopping all VFs at the same time */  	for (i = 0; i < pf->num_alloc_vfs; i++) {  		if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states)) @@ -1596,15 +1609,6 @@ void i40e_free_vfs(struct i40e_pf *pf)  		i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[i].lan_vsi_idx]);  	} -	/* Disable IOV before freeing resources. This lets any VF drivers -	 * running in the host get themselves cleaned up before we yank -	 * the carpet out from underneath their feet. -	 */ -	if (!pci_vfs_assigned(pf->pdev)) -		pci_disable_sriov(pf->pdev); -	else -		dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); -  	/* free up VF resources */  	tmp = pf->num_alloc_vfs;  	pf->num_alloc_vfs = 0; |