diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2020-12-15 10:48:07 +0100 | 
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2020-12-15 10:48:07 +0100 | 
| commit | 3c41e57a1e168d879e923c5583adeae47eec9f64 (patch) | |
| tree | e6272012c4b766189be2821316a3d23d115f5195 /drivers/net/ethernet/intel | |
| parent | d14ce74f1fb376ccbbc0b05ded477ada51253729 (diff) | |
| parent | 2f5fbc4305d07725bfebaedb09e57271315691ef (diff) | |
Merge tag 'irqchip-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates for 5.11 from Marc Zyngier:
  - Preliminary support for managed interrupts on platform devices
  - Correctly identify allocation of MSIs proxyied by another device
  - Remove the fasteoi IPI flow which has been proved useless
  - Generalise the Ocelot support to new SoCs
  - Improve GICv4.1 vcpu entry, matching the corresponding KVM optimisation
  - Work around spurious interrupts on Qualcomm PDC
  - Random fixes and cleanups
Link: https://lore.kernel.org/r/20201212135626.1479884-1-maz@kernel.org
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 | 52 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_xsk.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 14 | 
5 files changed, 64 insertions, 27 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 c96e2f2d4cba..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; @@ -2713,6 +2717,10 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg)  				spin_unlock_bh(&vsi->mac_filter_hash_lock);  				goto error_param;  			} +			if (is_valid_ether_addr(al->list[i].addr) && +			    is_zero_ether_addr(vf->default_lan_addr.addr)) +				ether_addr_copy(vf->default_lan_addr.addr, +						al->list[i].addr);  		}  	}  	spin_unlock_bh(&vsi->mac_filter_hash_lock); @@ -2740,6 +2748,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)  {  	struct virtchnl_ether_addr_list *al =  	    (struct virtchnl_ether_addr_list *)msg; +	bool was_unimac_deleted = false;  	struct i40e_pf *pf = vf->pf;  	struct i40e_vsi *vsi = NULL;  	i40e_status ret = 0; @@ -2759,6 +2768,8 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)  			ret = I40E_ERR_INVALID_MAC_ADDR;  			goto error_param;  		} +		if (ether_addr_equal(al->list[i].addr, vf->default_lan_addr.addr)) +			was_unimac_deleted = true;  	}  	vsi = pf->vsi[vf->lan_vsi_idx]; @@ -2779,10 +2790,25 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)  		dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters, error %d\n",  			vf->vf_id, ret); +	if (vf->trusted && was_unimac_deleted) { +		struct i40e_mac_filter *f; +		struct hlist_node *h; +		u8 *macaddr = NULL; +		int bkt; + +		/* set last unicast mac address as default */ +		spin_lock_bh(&vsi->mac_filter_hash_lock); +		hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) { +			if (is_valid_ether_addr(f->macaddr)) +				macaddr = f->macaddr; +		} +		if (macaddr) +			ether_addr_copy(vf->default_lan_addr.addr, macaddr); +		spin_unlock_bh(&vsi->mac_filter_hash_lock); +	}  error_param:  	/* send the response to the VF */ -	return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR, -				       ret); +	return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR, ret);  }  /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 6acede0acdca..567fd67e900e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -281,8 +281,8 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)  	unsigned int total_rx_bytes = 0, total_rx_packets = 0;  	u16 cleaned_count = I40E_DESC_UNUSED(rx_ring);  	unsigned int xdp_res, xdp_xmit = 0; +	bool failure = false;  	struct sk_buff *skb; -	bool failure;  	while (likely(total_rx_packets < (unsigned int)budget)) {  		union i40e_rx_desc *rx_desc; diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 9112dff075cf..b673ac1199bb 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -3891,21 +3891,23 @@ static int igc_change_mtu(struct net_device *netdev, int new_mtu)  }  /** - * igc_get_stats - Get System Network Statistics + * igc_get_stats64 - Get System Network Statistics   * @netdev: network interface device structure + * @stats: rtnl_link_stats64 pointer   *   * Returns the address of the device statistics structure.   * The statistics are updated here and also from the timer callback.   */ -static struct net_device_stats *igc_get_stats(struct net_device *netdev) +static void igc_get_stats64(struct net_device *netdev, +			    struct rtnl_link_stats64 *stats)  {  	struct igc_adapter *adapter = netdev_priv(netdev); +	spin_lock(&adapter->stats64_lock);  	if (!test_bit(__IGC_RESETTING, &adapter->state))  		igc_update_stats(adapter); - -	/* only return the current stats */ -	return &netdev->stats; +	memcpy(stats, &adapter->stats64, sizeof(*stats)); +	spin_unlock(&adapter->stats64_lock);  }  static netdev_features_t igc_fix_features(struct net_device *netdev, @@ -4855,7 +4857,7 @@ static const struct net_device_ops igc_netdev_ops = {  	.ndo_set_rx_mode	= igc_set_rx_mode,  	.ndo_set_mac_address	= igc_set_mac,  	.ndo_change_mtu		= igc_change_mtu, -	.ndo_get_stats		= igc_get_stats, +	.ndo_get_stats64	= igc_get_stats64,  	.ndo_fix_features	= igc_fix_features,  	.ndo_set_features	= igc_set_features,  	.ndo_features_check	= igc_features_check, | 
