diff options
Diffstat (limited to 'drivers/net/ethernet/intel')
35 files changed, 343 insertions, 175 deletions
| diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index 88faf05e23ba..0b1e890dd583 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -899,6 +899,8 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)  	} else {  		data &= ~IGP02E1000_PM_D0_LPLU;  		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); +		if (ret_val) +			return ret_val;  		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used  		 * during Dx states where the power conservation is most  		 * important.  During driver activity we should enable diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h index 69a2329ea463..db79c4e6413e 100644 --- a/drivers/net/ethernet/intel/e1000e/hw.h +++ b/drivers/net/ethernet/intel/e1000e/hw.h @@ -1,8 +1,8 @@  /* SPDX-License-Identifier: GPL-2.0 */  /* Copyright(c) 1999 - 2018 Intel Corporation. */ -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ +#ifndef _E1000E_HW_H_ +#define _E1000E_HW_H_  #include "regs.h"  #include "defines.h" @@ -714,4 +714,4 @@ struct e1000_hw {  #include "80003es2lan.h"  #include "ich8lan.h" -#endif +#endif /* _E1000E_HW_H_ */ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index e9b82c209c2d..a0948002ddf8 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5974,15 +5974,19 @@ static void e1000_reset_task(struct work_struct *work)  	struct e1000_adapter *adapter;  	adapter = container_of(work, struct e1000_adapter, reset_task); +	rtnl_lock();  	/* don't run the task if already down */ -	if (test_bit(__E1000_DOWN, &adapter->state)) +	if (test_bit(__E1000_DOWN, &adapter->state)) { +		rtnl_unlock();  		return; +	}  	if (!(adapter->flags & FLAG_RESTART_NOW)) {  		e1000e_dump(adapter);  		e_err("Reset adapter unexpectedly\n");  	}  	e1000e_reinit_locked(adapter); +	rtnl_unlock();  }  /** diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index cd53981fa5e0..15f93b355099 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -142,6 +142,7 @@ enum i40e_state_t {  	__I40E_VIRTCHNL_OP_PENDING,  	__I40E_RECOVERY_MODE,  	__I40E_VF_RESETS_DISABLED,	/* disable resets during i40e_remove */ +	__I40E_VFS_RELEASING,  	/* This must be last as it determines the size of the BITMAP */  	__I40E_STATE_SIZE__,  }; diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index d7c13ca9be7d..d627b59ad446 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -578,6 +578,9 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n,  	case RING_TYPE_XDP:  		ring = kmemdup(vsi->xdp_rings[ring_id], sizeof(*ring), GFP_KERNEL);  		break; +	default: +		ring = NULL; +		break;  	}  	if (!ring)  		return; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index c70dec65a572..0e92668012e3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -232,6 +232,8 @@ static void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[],  	I40E_STAT(struct i40e_vsi, _name, _stat)  #define I40E_VEB_STAT(_name, _stat) \  	I40E_STAT(struct i40e_veb, _name, _stat) +#define I40E_VEB_TC_STAT(_name, _stat) \ +	I40E_STAT(struct i40e_cp_veb_tc_stats, _name, _stat)  #define I40E_PFC_STAT(_name, _stat) \  	I40E_STAT(struct i40e_pfc_stats, _name, _stat)  #define I40E_QUEUE_STAT(_name, _stat) \ @@ -266,11 +268,18 @@ static const struct i40e_stats i40e_gstrings_veb_stats[] = {  	I40E_VEB_STAT("veb.rx_unknown_protocol", stats.rx_unknown_protocol),  }; +struct i40e_cp_veb_tc_stats { +	u64 tc_rx_packets; +	u64 tc_rx_bytes; +	u64 tc_tx_packets; +	u64 tc_tx_bytes; +}; +  static const struct i40e_stats i40e_gstrings_veb_tc_stats[] = { -	I40E_VEB_STAT("veb.tc_%u_tx_packets", tc_stats.tc_tx_packets), -	I40E_VEB_STAT("veb.tc_%u_tx_bytes", tc_stats.tc_tx_bytes), -	I40E_VEB_STAT("veb.tc_%u_rx_packets", tc_stats.tc_rx_packets), -	I40E_VEB_STAT("veb.tc_%u_rx_bytes", tc_stats.tc_rx_bytes), +	I40E_VEB_TC_STAT("veb.tc_%u_tx_packets", tc_tx_packets), +	I40E_VEB_TC_STAT("veb.tc_%u_tx_bytes", tc_tx_bytes), +	I40E_VEB_TC_STAT("veb.tc_%u_rx_packets", tc_rx_packets), +	I40E_VEB_TC_STAT("veb.tc_%u_rx_bytes", tc_rx_bytes),  };  static const struct i40e_stats i40e_gstrings_misc_stats[] = { @@ -1101,6 +1110,7 @@ static int i40e_get_link_ksettings(struct net_device *netdev,  	/* Set flow control settings */  	ethtool_link_ksettings_add_link_mode(ks, supported, Pause); +	ethtool_link_ksettings_add_link_mode(ks, supported, Asym_Pause);  	switch (hw->fc.requested_mode) {  	case I40E_FC_FULL: @@ -2217,6 +2227,29 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)  }  /** + * i40e_get_veb_tc_stats - copy VEB TC statistics to formatted structure + * @tc: the TC statistics in VEB structure (veb->tc_stats) + * @i: the index of traffic class in (veb->tc_stats) structure to copy + * + * Copy VEB TC statistics from structure of arrays (veb->tc_stats) to + * one dimensional structure i40e_cp_veb_tc_stats. + * Produce formatted i40e_cp_veb_tc_stats structure of the VEB TC + * statistics for the given TC. + **/ +static struct i40e_cp_veb_tc_stats +i40e_get_veb_tc_stats(struct i40e_veb_tc_stats *tc, unsigned int i) +{ +	struct i40e_cp_veb_tc_stats veb_tc = { +		.tc_rx_packets = tc->tc_rx_packets[i], +		.tc_rx_bytes = tc->tc_rx_bytes[i], +		.tc_tx_packets = tc->tc_tx_packets[i], +		.tc_tx_bytes = tc->tc_tx_bytes[i], +	}; + +	return veb_tc; +} + +/**   * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure   * @pf: the PF device structure   * @i: the priority value to copy @@ -2300,8 +2333,16 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,  			       i40e_gstrings_veb_stats);  	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) -		i40e_add_ethtool_stats(&data, veb_stats ? veb : NULL, -				       i40e_gstrings_veb_tc_stats); +		if (veb_stats) { +			struct i40e_cp_veb_tc_stats veb_tc = +				i40e_get_veb_tc_stats(&veb->tc_stats, i); + +			i40e_add_ethtool_stats(&data, &veb_tc, +					       i40e_gstrings_veb_tc_stats); +		} else { +			i40e_add_ethtool_stats(&data, NULL, +					       i40e_gstrings_veb_tc_stats); +		}  	i40e_add_ethtool_stats(&data, pf, i40e_gstrings_stats); @@ -5439,7 +5480,7 @@ static int i40e_get_module_eeprom(struct net_device *netdev,  		status = i40e_aq_get_phy_register(hw,  				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, -				true, addr, offset, &value, NULL); +				addr, true, offset, &value, NULL);  		if (status)  			return -EIO;  		data[i] = value; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 353deae139f9..30ad7c08d0fb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2560,8 +2560,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)  				 i40e_stat_str(hw, aq_ret),  				 i40e_aq_str(hw, hw->aq.asq_last_status));  		} else { -			dev_info(&pf->pdev->dev, "%s is %s allmulti mode.\n", -				 vsi->netdev->name, +			dev_info(&pf->pdev->dev, "%s allmulti mode.\n",  				 cur_multipromisc ? "entering" : "leaving");  		}  	} @@ -3259,6 +3258,17 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)  }  /** + * i40e_rx_offset - Return expected offset into page to access data + * @rx_ring: Ring we are requesting offset of + * + * Returns the offset value for ring into the data buffer. + */ +static unsigned int i40e_rx_offset(struct i40e_ring *rx_ring) +{ +	return ring_uses_build_skb(rx_ring) ? I40E_SKB_PAD : 0; +} + +/**   * i40e_configure_rx_ring - Configure a receive ring context   * @ring: The Rx ring to configure   * @@ -3369,6 +3379,8 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)  	else  		set_ring_build_skb_enabled(ring); +	ring->rx_offset = i40e_rx_offset(ring); +  	/* cache tail for quicker writes, and clear the reg before use */  	ring->tail = hw->hw_addr + I40E_QRX_TAIL(pf_q);  	writel(0, ring->tail); @@ -6725,9 +6737,9 @@ out:  			set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state);  			set_bit(__I40E_CLIENT_L2_CHANGE, pf->state);  		} -	/* registers are set, lets apply */ -	if (pf->hw_features & I40E_HW_USE_SET_LLDP_MIB) -		ret = i40e_hw_set_dcb_config(pf, new_cfg); +		/* registers are set, lets apply */ +		if (pf->hw_features & I40E_HW_USE_SET_LLDP_MIB) +			ret = i40e_hw_set_dcb_config(pf, new_cfg);  	}  err: @@ -10560,12 +10572,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)  		goto end_core_reset;  	} -	if (!lock_acquired) -		rtnl_lock(); -	ret = i40e_setup_pf_switch(pf, reinit); -	if (ret) -		goto end_unlock; -  #ifdef CONFIG_I40E_DCB  	/* Enable FW to write a default DCB config on link-up  	 * unless I40E_FLAG_TC_MQPRIO was enabled or DCB @@ -10580,7 +10586,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)  			i40e_aq_set_dcb_parameters(hw, false, NULL);  			dev_warn(&pf->pdev->dev,  				 "DCB is not supported for X710-T*L 2.5/5G speeds\n"); -				 pf->flags &= ~I40E_FLAG_DCB_CAPABLE; +			pf->flags &= ~I40E_FLAG_DCB_CAPABLE;  		} else {  			i40e_aq_set_dcb_parameters(hw, true, NULL);  			ret = i40e_init_pf_dcb(pf); @@ -10594,6 +10600,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)  	}  #endif /* CONFIG_I40E_DCB */ +	if (!lock_acquired) +		rtnl_lock(); +	ret = i40e_setup_pf_switch(pf, reinit); +	if (ret) +		goto end_unlock;  	/* The driver only wants link up/down and module qualification  	 * reports from firmware.  Note the negative logic. @@ -15127,12 +15138,16 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)  	 * in order to register the netdev  	 */  	v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN); -	if (v_idx < 0) +	if (v_idx < 0) { +		err = v_idx;  		goto err_switch_setup; +	}  	pf->lan_vsi = v_idx;  	vsi = pf->vsi[v_idx]; -	if (!vsi) +	if (!vsi) { +		err = -EFAULT;  		goto err_switch_setup; +	}  	vsi->alloc_queue_pairs = 1;  	err = i40e_config_netdev(vsi);  	if (err) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 627794b31e33..06b4271219b1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1570,17 +1570,6 @@ void i40e_free_rx_resources(struct i40e_ring *rx_ring)  }  /** - * i40e_rx_offset - Return expected offset into page to access data - * @rx_ring: Ring we are requesting offset of - * - * Returns the offset value for ring into the data buffer. - */ -static unsigned int i40e_rx_offset(struct i40e_ring *rx_ring) -{ -	return ring_uses_build_skb(rx_ring) ? I40E_SKB_PAD : 0; -} - -/**   * i40e_setup_rx_descriptors - Allocate Rx descriptors   * @rx_ring: Rx descriptor ring (for a specific queue) to setup   * @@ -1608,7 +1597,6 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring)  	rx_ring->next_to_alloc = 0;  	rx_ring->next_to_clean = 0;  	rx_ring->next_to_use = 0; -	rx_ring->rx_offset = i40e_rx_offset(rx_ring);  	/* XDP RX-queue info only needed for RX rings exposed to XDP */  	if (rx_ring->vsi->type == I40E_VSI_MAIN) { @@ -2307,8 +2295,7 @@ int i40e_xmit_xdp_tx_ring(struct xdp_buff *xdp, struct i40e_ring *xdp_ring)   * @rx_ring: Rx ring being processed   * @xdp: XDP buffer containing the frame   **/ -static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring, -				    struct xdp_buff *xdp) +static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp)  {  	int err, result = I40E_XDP_PASS;  	struct i40e_ring *xdp_ring; @@ -2347,7 +2334,7 @@ static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring,  	}  xdp_out:  	rcu_read_unlock(); -	return ERR_PTR(-result); +	return result;  }  /** @@ -2460,6 +2447,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  	unsigned int xdp_xmit = 0;  	bool failure = false;  	struct xdp_buff xdp; +	int xdp_res = 0;  #if (PAGE_SIZE < 8192)  	frame_sz = i40e_rx_frame_truesize(rx_ring, 0); @@ -2525,12 +2513,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)  			/* At larger PAGE_SIZE, frame_sz depend on len size */  			xdp.frame_sz = i40e_rx_frame_truesize(rx_ring, size);  #endif -			skb = i40e_run_xdp(rx_ring, &xdp); +			xdp_res = i40e_run_xdp(rx_ring, &xdp);  		} -		if (IS_ERR(skb)) { -			unsigned int xdp_res = -PTR_ERR(skb); - +		if (xdp_res) {  			if (xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR)) {  				xdp_xmit |= xdp_res;  				i40e_rx_buffer_flip(rx_ring, rx_buffer, size); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 1b6ec9be155a..5d301a466f5c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -137,6 +137,7 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)   **/  static inline void i40e_vc_disable_vf(struct i40e_vf *vf)  { +	struct i40e_pf *pf = vf->pf;  	int i;  	i40e_vc_notify_vf_reset(vf); @@ -147,6 +148,11 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf)  	 * ensure a reset.  	 */  	for (i = 0; i < 20; i++) { +		/* If PF is in VFs releasing state reset VF is impossible, +		 * so leave it. +		 */ +		if (test_bit(__I40E_VFS_RELEASING, pf->state)) +			return;  		if (i40e_reset_vf(vf, false))  			return;  		usleep_range(10000, 20000); @@ -1574,6 +1580,8 @@ void i40e_free_vfs(struct i40e_pf *pf)  	if (!pf->vf)  		return; + +	set_bit(__I40E_VFS_RELEASING, pf->state);  	while (test_and_set_bit(__I40E_VF_DISABLE, pf->state))  		usleep_range(1000, 2000); @@ -1631,6 +1639,7 @@ void i40e_free_vfs(struct i40e_pf *pf)  		}  	}  	clear_bit(__I40E_VF_DISABLE, pf->state); +	clear_bit(__I40E_VFS_RELEASING, pf->state);  }  #ifdef CONFIG_PCI_IOV diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index fc32c5019b0f..12ca84113587 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -471,7 +471,7 @@ static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget)  	nb_pkts = xsk_tx_peek_release_desc_batch(xdp_ring->xsk_pool, descs, budget);  	if (!nb_pkts) -		return false; +		return true;  	if (xdp_ring->next_to_use + nb_pkts >= xdp_ring->count) {  		nb_processed = xdp_ring->count - xdp_ring->next_to_use; @@ -488,7 +488,7 @@ static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget)  	i40e_update_tx_stats(xdp_ring, nb_pkts, total_bytes); -	return true; +	return nb_pkts < budget;  }  /** diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 0a867d64d467..dc5b3c06d1e0 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -1776,7 +1776,8 @@ static int iavf_init_get_resources(struct iavf_adapter *adapter)  		goto err_alloc;  	} -	if (iavf_process_config(adapter)) +	err = iavf_process_config(adapter); +	if (err)  		goto err_alloc;  	adapter->current_op = VIRTCHNL_OP_UNKNOWN; diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 357706444dd5..17101c45cbcd 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -196,7 +196,6 @@ enum ice_state {  	__ICE_NEEDS_RESTART,  	__ICE_PREPARED_FOR_RESET,	/* set by driver when prepared */  	__ICE_RESET_OICR_RECV,		/* set by driver after rcv reset OICR */ -	__ICE_DCBNL_DEVRESET,		/* set by dcbnl devreset */  	__ICE_PFR_REQ,			/* set by driver and peers */  	__ICE_CORER_REQ,		/* set by driver and peers */  	__ICE_GLOBR_REQ,		/* set by driver and peers */ @@ -624,7 +623,7 @@ int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset);  void ice_print_link_msg(struct ice_vsi *vsi, bool isup);  const char *ice_stat_str(enum ice_status stat_err);  const char *ice_aq_str(enum ice_aq_err aq_err); -bool ice_is_wol_supported(struct ice_pf *pf); +bool ice_is_wol_supported(struct ice_hw *hw);  int  ice_fdir_write_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input, bool add,  		    bool is_tun); @@ -642,6 +641,7 @@ int ice_fdir_create_dflt_rules(struct ice_pf *pf);  int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout,  			  struct ice_rq_event_info *event);  int ice_open(struct net_device *netdev); +int ice_open_internal(struct net_device *netdev);  int ice_stop(struct net_device *netdev);  void ice_service_task_schedule(struct ice_pf *pf); diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c index 3124a3bf519a..1148d768f8ed 100644 --- a/drivers/net/ethernet/intel/ice/ice_base.c +++ b/drivers/net/ethernet/intel/ice/ice_base.c @@ -275,6 +275,22 @@ ice_setup_tx_ctx(struct ice_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf_q)  }  /** + * ice_rx_offset - Return expected offset into page to access data + * @rx_ring: Ring we are requesting offset of + * + * Returns the offset value for ring into the data buffer. + */ +static unsigned int ice_rx_offset(struct ice_ring *rx_ring) +{ +	if (ice_ring_uses_build_skb(rx_ring)) +		return ICE_SKB_PAD; +	else if (ice_is_xdp_ena_vsi(rx_ring->vsi)) +		return XDP_PACKET_HEADROOM; + +	return 0; +} + +/**   * ice_setup_rx_ctx - Configure a receive ring context   * @ring: The Rx ring to configure   * @@ -413,11 +429,15 @@ int ice_setup_rx_ctx(struct ice_ring *ring)  	else  		ice_set_ring_build_skb_ena(ring); +	ring->rx_offset = ice_rx_offset(ring); +  	/* init queue specific tail register */  	ring->tail = hw->hw_addr + QRX_TAIL(pf_q);  	writel(0, ring->tail);  	if (ring->xsk_pool) { +		bool ok; +  		if (!xsk_buff_can_alloc(ring->xsk_pool, num_bufs)) {  			dev_warn(dev, "XSK buffer pool does not provide enough addresses to fill %d buffers on Rx ring %d\n",  				 num_bufs, ring->q_index); @@ -426,8 +446,8 @@ int ice_setup_rx_ctx(struct ice_ring *ring)  			return 0;  		} -		err = ice_alloc_rx_bufs_zc(ring, num_bufs); -		if (err) +		ok = ice_alloc_rx_bufs_zc(ring, num_bufs); +		if (!ok)  			dev_info(dev, "Failed to allocate some buffers on XSK buffer pool enabled Rx ring %d (pf_q %d)\n",  				 ring->q_index, pf_q);  		return 0; diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 3d9475e222cd..a20edf1538a0 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -717,8 +717,8 @@ static enum ice_status ice_cfg_fw_log(struct ice_hw *hw, bool enable)  			if (!data) {  				data = devm_kcalloc(ice_hw_to_dev(hw), -						    sizeof(*data),  						    ICE_AQC_FW_LOG_ID_MAX, +						    sizeof(*data),  						    GFP_KERNEL);  				if (!data)  					return ICE_ERR_NO_MEMORY; diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h b/drivers/net/ethernet/intel/ice/ice_controlq.h index faaa08e8171b..68866f4f0eb0 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.h +++ b/drivers/net/ethernet/intel/ice/ice_controlq.h @@ -31,8 +31,8 @@ enum ice_ctl_q {  	ICE_CTL_Q_MAILBOX,  }; -/* Control Queue timeout settings - max delay 250ms */ -#define ICE_CTL_Q_SQ_CMD_TIMEOUT	2500  /* Count 2500 times */ +/* Control Queue timeout settings - max delay 1s */ +#define ICE_CTL_Q_SQ_CMD_TIMEOUT	10000 /* Count 10000 times */  #define ICE_CTL_Q_SQ_CMD_USEC		100   /* Check every 100usec */  #define ICE_CTL_Q_ADMIN_INIT_TIMEOUT	10    /* Count 10 times */  #define ICE_CTL_Q_ADMIN_INIT_MSEC	100   /* Check every 100msec */ diff --git a/drivers/net/ethernet/intel/ice/ice_dcb.c b/drivers/net/ethernet/intel/ice/ice_dcb.c index e42727941ef5..211ac6f907ad 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb.c @@ -738,22 +738,27 @@ ice_aq_get_cee_dcb_cfg(struct ice_hw *hw,  /**   * ice_cee_to_dcb_cfg   * @cee_cfg: pointer to CEE configuration struct - * @dcbcfg: DCB configuration struct + * @pi: port information structure   *   * Convert CEE configuration from firmware to DCB configuration   */  static void  ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, -		   struct ice_dcbx_cfg *dcbcfg) +		   struct ice_port_info *pi)  {  	u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status);  	u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift; +	u8 i, j, err, sync, oper, app_index, ice_app_sel_type;  	u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); -	u8 i, err, sync, oper, app_index, ice_app_sel_type;  	u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift; +	struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg;  	u16 ice_app_prot_id_type; -	/* CEE PG data to ETS config */ +	dcbcfg = &pi->qos_cfg.local_dcbx_cfg; +	dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE; +	dcbcfg->tlv_status = tlv_status; + +	/* CEE PG data */  	dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc;  	/* Note that the FW creates the oper_prio_tc nibbles reversed @@ -780,10 +785,16 @@ ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg,  		}  	} -	/* CEE PFC data to ETS config */ +	/* CEE PFC data */  	dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en;  	dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS; +	/* CEE APP TLV data */ +	if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) +		cmp_dcbcfg = &pi->qos_cfg.desired_dcbx_cfg; +	else +		cmp_dcbcfg = &pi->qos_cfg.remote_dcbx_cfg; +  	app_index = 0;  	for (i = 0; i < 3; i++) {  		if (i == 0) { @@ -802,6 +813,18 @@ ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg,  			ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S;  			ice_app_sel_type = ICE_APP_SEL_TCPIP;  			ice_app_prot_id_type = ICE_APP_PROT_ID_ISCSI; + +			for (j = 0; j < cmp_dcbcfg->numapps; j++) { +				u16 prot_id = cmp_dcbcfg->app[j].prot_id; +				u8 sel = cmp_dcbcfg->app[j].selector; + +				if  (sel == ICE_APP_SEL_TCPIP && +				     (prot_id == ICE_APP_PROT_ID_ISCSI || +				      prot_id == ICE_APP_PROT_ID_ISCSI_860)) { +					ice_app_prot_id_type = prot_id; +					break; +				} +			}  		} else {  			/* FIP APP */  			ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M; @@ -892,11 +915,8 @@ enum ice_status ice_get_dcb_cfg(struct ice_port_info *pi)  	ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL);  	if (!ret) {  		/* CEE mode */ -		dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; -		dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_CEE; -		dcbx_cfg->tlv_status = le32_to_cpu(cee_cfg.tlv_status); -		ice_cee_to_dcb_cfg(&cee_cfg, dcbx_cfg);  		ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE); +		ice_cee_to_dcb_cfg(&cee_cfg, pi);  	} else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) {  		/* CEE mode not enabled try querying IEEE data */  		dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c index 468a63f7eff9..4180f1f35fb8 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c @@ -18,12 +18,10 @@ static void ice_dcbnl_devreset(struct net_device *netdev)  	while (ice_is_reset_in_progress(pf->state))  		usleep_range(1000, 2000); -	set_bit(__ICE_DCBNL_DEVRESET, pf->state);  	dev_close(netdev);  	netdev_state_change(netdev);  	dev_open(netdev, NULL);  	netdev_state_change(netdev); -	clear_bit(__ICE_DCBNL_DEVRESET, pf->state);  }  /** diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 2dcfa685b763..32ba71a16165 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -3472,7 +3472,7 @@ static void ice_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)  		netdev_warn(netdev, "Wake on LAN is not supported on this interface!\n");  	/* Get WoL settings based on the HW capability */ -	if (ice_is_wol_supported(pf)) { +	if (ice_is_wol_supported(&pf->hw)) {  		wol->supported = WAKE_MAGIC;  		wol->wolopts = pf->wol_ena ? WAKE_MAGIC : 0;  	} else { @@ -3492,7 +3492,7 @@ static int ice_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)  	struct ice_vsi *vsi = np->vsi;  	struct ice_pf *pf = vsi->back; -	if (vsi->type != ICE_VSI_PF || !ice_is_wol_supported(pf)) +	if (vsi->type != ICE_VSI_PF || !ice_is_wol_supported(&pf->hw))  		return -EOPNOTSUPP;  	/* only magic packet is supported */ diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 8d4e2ad4328d..d13c7fc8fb0a 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2620,7 +2620,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked)  			if (!locked)  				rtnl_lock(); -			err = ice_open(vsi->netdev); +			err = ice_open_internal(vsi->netdev);  			if (!locked)  				rtnl_unlock(); @@ -2649,7 +2649,7 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)  			if (!locked)  				rtnl_lock(); -			ice_stop(vsi->netdev); +			ice_vsi_close(vsi);  			if (!locked)  				rtnl_unlock(); @@ -3078,7 +3078,6 @@ err_vsi:  bool ice_is_reset_in_progress(unsigned long *state)  {  	return test_bit(__ICE_RESET_OICR_RECV, state) || -	       test_bit(__ICE_DCBNL_DEVRESET, state) ||  	       test_bit(__ICE_PFR_REQ, state) ||  	       test_bit(__ICE_CORER_REQ, state) ||  	       test_bit(__ICE_GLOBR_REQ, state); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 2c23c8f468a5..d821c687f239 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3537,15 +3537,14 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)  }  /** - * ice_is_wol_supported - get NVM state of WoL - * @pf: board private structure + * ice_is_wol_supported - check if WoL is supported + * @hw: pointer to hardware info   *   * Check if WoL is supported based on the HW configuration.   * Returns true if NVM supports and enables WoL for this port, false otherwise   */ -bool ice_is_wol_supported(struct ice_pf *pf) +bool ice_is_wol_supported(struct ice_hw *hw)  { -	struct ice_hw *hw = &pf->hw;  	u16 wol_ctrl;  	/* A bit set to 1 in the NVM Software Reserved Word 2 (WoL control @@ -3554,7 +3553,7 @@ bool ice_is_wol_supported(struct ice_pf *pf)  	if (ice_read_sr_word(hw, ICE_SR_NVM_WOL_CFG, &wol_ctrl))  		return false; -	return !(BIT(hw->pf_id) & wol_ctrl); +	return !(BIT(hw->port_info->lport) & wol_ctrl);  }  /** @@ -4192,28 +4191,25 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)  		goto err_send_version_unroll;  	} +	/* not a fatal error if this fails */  	err = ice_init_nvm_phy_type(pf->hw.port_info); -	if (err) { +	if (err)  		dev_err(dev, "ice_init_nvm_phy_type failed: %d\n", err); -		goto err_send_version_unroll; -	} +	/* not a fatal error if this fails */  	err = ice_update_link_info(pf->hw.port_info); -	if (err) { +	if (err)  		dev_err(dev, "ice_update_link_info failed: %d\n", err); -		goto err_send_version_unroll; -	}  	ice_init_link_dflt_override(pf->hw.port_info);  	/* if media available, initialize PHY settings */  	if (pf->hw.port_info->phy.link_info.link_info &  	    ICE_AQ_MEDIA_AVAILABLE) { +		/* not a fatal error if this fails */  		err = ice_init_phy_user_cfg(pf->hw.port_info); -		if (err) { +		if (err)  			dev_err(dev, "ice_init_phy_user_cfg failed: %d\n", err); -			goto err_send_version_unroll; -		}  		if (!test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags)) {  			struct ice_vsi *vsi = ice_get_main_vsi(pf); @@ -4568,6 +4564,7 @@ static int __maybe_unused ice_suspend(struct device *dev)  			continue;  		ice_vsi_free_q_vectors(pf->vsi[v]);  	} +	ice_free_cpu_rx_rmap(ice_get_main_vsi(pf));  	ice_clear_interrupt_scheme(pf);  	pci_save_state(pdev); @@ -6637,6 +6634,28 @@ static void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue)  int ice_open(struct net_device *netdev)  {  	struct ice_netdev_priv *np = netdev_priv(netdev); +	struct ice_pf *pf = np->vsi->back; + +	if (ice_is_reset_in_progress(pf->state)) { +		netdev_err(netdev, "can't open net device while reset is in progress"); +		return -EBUSY; +	} + +	return ice_open_internal(netdev); +} + +/** + * ice_open_internal - Called when a network interface becomes active + * @netdev: network interface device structure + * + * Internal ice_open implementation. Should not be used directly except for ice_open and reset + * handling routine + * + * Returns 0 on success, negative value on failure + */ +int ice_open_internal(struct net_device *netdev) +{ +	struct ice_netdev_priv *np = netdev_priv(netdev);  	struct ice_vsi *vsi = np->vsi;  	struct ice_pf *pf = vsi->back;  	struct ice_port_info *pi; @@ -6715,6 +6734,12 @@ int ice_stop(struct net_device *netdev)  {  	struct ice_netdev_priv *np = netdev_priv(netdev);  	struct ice_vsi *vsi = np->vsi; +	struct ice_pf *pf = vsi->back; + +	if (ice_is_reset_in_progress(pf->state)) { +		netdev_err(netdev, "can't stop net device while reset is in progress"); +		return -EBUSY; +	}  	ice_vsi_close(vsi); diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 67c965a3f5d2..834cbd3f7b31 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -1238,6 +1238,9 @@ ice_add_update_vsi_list(struct ice_hw *hw,  			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,  						vsi_list_id); +		if (!m_entry->vsi_list_info) +			return ICE_ERR_NO_MEMORY; +  		/* If this entry was large action then the large action needs  		 * to be updated to point to FWD to VSI list  		 */ @@ -2220,6 +2223,7 @@ ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)  	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&  		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||  		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && +		 fm_entry->vsi_list_info &&  		 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));  } @@ -2292,14 +2296,12 @@ ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,  		return ICE_ERR_PARAM;  	list_for_each_entry(fm_entry, lkup_list_head, list_entry) { -		struct ice_fltr_info *fi; - -		fi = &fm_entry->fltr_info; -		if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle)) +		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))  			continue;  		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, -							vsi_list_head, fi); +							vsi_list_head, +							&fm_entry->fltr_info);  		if (status)  			return status;  	} @@ -2622,7 +2624,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,  					  &remove_list_head);  	mutex_unlock(rule_lock);  	if (status) -		return; +		goto free_fltr_list;  	switch (lkup) {  	case ICE_SW_LKUP_MAC: @@ -2645,6 +2647,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,  		break;  	} +free_fltr_list:  	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {  		list_del(&fm_entry->list_entry);  		devm_kfree(ice_hw_to_dev(hw), fm_entry); diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index b7dc25da1202..b91dcfd12727 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -444,22 +444,6 @@ void ice_free_rx_ring(struct ice_ring *rx_ring)  }  /** - * ice_rx_offset - Return expected offset into page to access data - * @rx_ring: Ring we are requesting offset of - * - * Returns the offset value for ring into the data buffer. - */ -static unsigned int ice_rx_offset(struct ice_ring *rx_ring) -{ -	if (ice_ring_uses_build_skb(rx_ring)) -		return ICE_SKB_PAD; -	else if (ice_is_xdp_ena_vsi(rx_ring->vsi)) -		return XDP_PACKET_HEADROOM; - -	return 0; -} - -/**   * ice_setup_rx_ring - Allocate the Rx descriptors   * @rx_ring: the Rx ring to set up   * @@ -493,7 +477,6 @@ int ice_setup_rx_ring(struct ice_ring *rx_ring)  	rx_ring->next_to_use = 0;  	rx_ring->next_to_clean = 0; -	rx_ring->rx_offset = ice_rx_offset(rx_ring);  	if (ice_is_xdp_ena_vsi(rx_ring->vsi))  		WRITE_ONCE(rx_ring->xdp_prog, rx_ring->vsi->xdp_prog); diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index a6cb0c35748c..266036b7a49a 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -535,6 +535,7 @@ struct ice_dcb_app_priority_table {  #define ICE_TLV_STATUS_ERR	0x4  #define ICE_APP_PROT_ID_FCOE	0x8906  #define ICE_APP_PROT_ID_ISCSI	0x0cbc +#define ICE_APP_PROT_ID_ISCSI_860 0x035c  #define ICE_APP_PROT_ID_FIP	0x8914  #define ICE_APP_SEL_ETHTYPE	0x1  #define ICE_APP_SEL_TCPIP	0x2 diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 83f3c9574ed1..9f94d9159acd 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -358,18 +358,18 @@ xsk_pool_if_up:   * This function allocates a number of Rx buffers from the fill ring   * or the internal recycle mechanism and places them on the Rx ring.   * - * Returns false if all allocations were successful, true if any fail. + * Returns true if all allocations were successful, false if any fail.   */  bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)  {  	union ice_32b_rx_flex_desc *rx_desc;  	u16 ntu = rx_ring->next_to_use;  	struct ice_rx_buf *rx_buf; -	bool ret = false; +	bool ok = true;  	dma_addr_t dma;  	if (!count) -		return false; +		return true;  	rx_desc = ICE_RX_DESC(rx_ring, ntu);  	rx_buf = &rx_ring->rx_buf[ntu]; @@ -377,7 +377,7 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)  	do {  		rx_buf->xdp = xsk_buff_alloc(rx_ring->xsk_pool);  		if (!rx_buf->xdp) { -			ret = true; +			ok = false;  			break;  		} @@ -402,7 +402,7 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)  		ice_release_rx_desc(rx_ring, ntu);  	} -	return ret; +	return ok;  }  /** diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h index 5d87957b2627..44111f65afc7 100644 --- a/drivers/net/ethernet/intel/igb/e1000_hw.h +++ b/drivers/net/ethernet/intel/igb/e1000_hw.h @@ -1,8 +1,8 @@  /* SPDX-License-Identifier: GPL-2.0 */  /* Copyright(c) 2007 - 2018 Intel Corporation. */ -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ +#ifndef _E1000_IGB_HW_H_ +#define _E1000_IGB_HW_H_  #include <linux/types.h>  #include <linux/delay.h> @@ -551,4 +551,4 @@ s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);  void igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);  void igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value); -#endif /* _E1000_HW_H_ */ +#endif /* _E1000_IGB_HW_H_ */ diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index aaa954aae574..7bda8c5edea5 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -748,8 +748,8 @@ void igb_ptp_suspend(struct igb_adapter *adapter);  void igb_ptp_rx_hang(struct igb_adapter *adapter);  void igb_ptp_tx_hang(struct igb_adapter *adapter);  void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb); -void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, -			 struct sk_buff *skb); +int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, +			struct sk_buff *skb);  int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);  int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);  void igb_set_flag_queue_pairs(struct igb_adapter *, const u32); diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 878b31d534ec..a45cd2b416c8 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -8214,7 +8214,8 @@ static void igb_reuse_rx_page(struct igb_ring *rx_ring,  	new_buff->pagecnt_bias	= old_buff->pagecnt_bias;  } -static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer) +static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer, +				  int rx_buf_pgcnt)  {  	unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;  	struct page *page = rx_buffer->page; @@ -8225,7 +8226,7 @@ static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer)  #if (PAGE_SIZE < 8192)  	/* if we are only owner of page we can reuse it */ -	if (unlikely((page_ref_count(page) - pagecnt_bias) > 1)) +	if (unlikely((rx_buf_pgcnt - pagecnt_bias) > 1))  		return false;  #else  #define IGB_LAST_OFFSET \ @@ -8301,9 +8302,10 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,  		return NULL;  	if (unlikely(igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))) { -		igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb); -		xdp->data += IGB_TS_HDR_LEN; -		size -= IGB_TS_HDR_LEN; +		if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb)) { +			xdp->data += IGB_TS_HDR_LEN; +			size -= IGB_TS_HDR_LEN; +		}  	}  	/* Determine available headroom for copy */ @@ -8364,8 +8366,8 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,  	/* pull timestamp out of packet data */  	if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { -		igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb); -		__skb_pull(skb, IGB_TS_HDR_LEN); +		if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb)) +			__skb_pull(skb, IGB_TS_HDR_LEN);  	}  	/* update buffer offset */ @@ -8614,11 +8616,17 @@ static unsigned int igb_rx_offset(struct igb_ring *rx_ring)  }  static struct igb_rx_buffer *igb_get_rx_buffer(struct igb_ring *rx_ring, -					       const unsigned int size) +					       const unsigned int size, int *rx_buf_pgcnt)  {  	struct igb_rx_buffer *rx_buffer;  	rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; +	*rx_buf_pgcnt = +#if (PAGE_SIZE < 8192) +		page_count(rx_buffer->page); +#else +		0; +#endif  	prefetchw(rx_buffer->page);  	/* we are reusing so sync this buffer for CPU use */ @@ -8634,9 +8642,9 @@ static struct igb_rx_buffer *igb_get_rx_buffer(struct igb_ring *rx_ring,  }  static void igb_put_rx_buffer(struct igb_ring *rx_ring, -			      struct igb_rx_buffer *rx_buffer) +			      struct igb_rx_buffer *rx_buffer, int rx_buf_pgcnt)  { -	if (igb_can_reuse_rx_page(rx_buffer)) { +	if (igb_can_reuse_rx_page(rx_buffer, rx_buf_pgcnt)) {  		/* hand second half of page back to the ring */  		igb_reuse_rx_page(rx_ring, rx_buffer);  	} else { @@ -8664,6 +8672,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)  	unsigned int xdp_xmit = 0;  	struct xdp_buff xdp;  	u32 frame_sz = 0; +	int rx_buf_pgcnt;  	/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */  #if (PAGE_SIZE < 8192) @@ -8693,7 +8702,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)  		 */  		dma_rmb(); -		rx_buffer = igb_get_rx_buffer(rx_ring, size); +		rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt);  		/* retrieve a buffer from the ring */  		if (!skb) { @@ -8736,7 +8745,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)  			break;  		} -		igb_put_rx_buffer(rx_ring, rx_buffer); +		igb_put_rx_buffer(rx_ring, rx_buffer, rx_buf_pgcnt);  		cleaned_count++;  		/* fetch next buffer in frame if non-eop */ diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 7cc5428c3b3d..86a576201f5f 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -856,6 +856,9 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)  	dev_kfree_skb_any(skb);  } +#define IGB_RET_PTP_DISABLED 1 +#define IGB_RET_PTP_INVALID 2 +  /**   * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp   * @q_vector: Pointer to interrupt specific structure @@ -864,19 +867,29 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)   *   * This function is meant to retrieve a timestamp from the first buffer of an   * incoming frame.  The value is stored in little endian format starting on - * byte 8. + * byte 8 + * + * Returns: 0 if success, nonzero if failure   **/ -void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, -			 struct sk_buff *skb) +int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, +			struct sk_buff *skb)  { -	__le64 *regval = (__le64 *)va;  	struct igb_adapter *adapter = q_vector->adapter; +	__le64 *regval = (__le64 *)va;  	int adjust = 0; +	if (!(adapter->ptp_flags & IGB_PTP_ENABLED)) +		return IGB_RET_PTP_DISABLED; +  	/* The timestamp is recorded in little endian format.  	 * DWORD: 0        1        2        3  	 * Field: Reserved Reserved SYSTIML  SYSTIMH  	 */ + +	/* check reserved dwords are zero, be/le doesn't matter for zero */ +	if (regval[0]) +		return IGB_RET_PTP_INVALID; +  	igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb),  				   le64_to_cpu(regval[1])); @@ -896,6 +909,8 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,  	}  	skb_hwtstamps(skb)->hwtstamp =  		ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); + +	return 0;  }  /** @@ -906,13 +921,15 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,   * This function is meant to retrieve a timestamp from the internal registers   * of the adapter and store it in the skb.   **/ -void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, -			 struct sk_buff *skb) +void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb)  {  	struct igb_adapter *adapter = q_vector->adapter;  	struct e1000_hw *hw = &adapter->hw; -	u64 regval;  	int adjust = 0; +	u64 regval; + +	if (!(adapter->ptp_flags & IGB_PTP_ENABLED)) +		return;  	/* If this bit is set, then the RX registers contain the time stamp. No  	 * other packet will be time stamped until we read these registers, so diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 5d2809dfd06a..1b08a7dc7bc4 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -547,7 +547,7 @@ void igc_ptp_init(struct igc_adapter *adapter);  void igc_ptp_reset(struct igc_adapter *adapter);  void igc_ptp_suspend(struct igc_adapter *adapter);  void igc_ptp_stop(struct igc_adapter *adapter); -void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, void *va, +void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,  			 struct sk_buff *skb);  int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);  int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index 824a6c454bca..8722294ab90c 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1711,6 +1711,9 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,  						     Autoneg);  	} +	/* Set pause flow control settings */ +	ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); +  	switch (hw->fc.requested_mode) {  	case igc_fc_full:  		ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); @@ -1725,9 +1728,7 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,  						     Asym_Pause);  		break;  	default: -		ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); -		ethtool_link_ksettings_add_link_mode(cmd, advertising, -						     Asym_Pause); +		break;  	}  	status = pm_runtime_suspended(&adapter->pdev->dev) ? diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 7ac9597ddb84..4d989ebc9713 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -3831,10 +3831,19 @@ static void igc_reset_task(struct work_struct *work)  	adapter = container_of(work, struct igc_adapter, reset_task); +	rtnl_lock(); +	/* If we're already down or resetting, just bail */ +	if (test_bit(__IGC_DOWN, &adapter->state) || +	    test_bit(__IGC_RESETTING, &adapter->state)) { +		rtnl_unlock(); +		return; +	} +  	igc_rings_dump(adapter);  	igc_regs_dump(adapter);  	netdev_err(adapter->netdev, "Reset adapter\n");  	igc_reinit_locked(adapter); +	rtnl_unlock();  }  /** diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c index ac0b9c85da7c..545f4d0e67cf 100644 --- a/drivers/net/ethernet/intel/igc/igc_ptp.c +++ b/drivers/net/ethernet/intel/igc/igc_ptp.c @@ -152,46 +152,54 @@ static void igc_ptp_systim_to_hwtstamp(struct igc_adapter *adapter,  }  /** - * igc_ptp_rx_pktstamp - retrieve Rx per packet timestamp + * igc_ptp_rx_pktstamp - Retrieve timestamp from Rx packet buffer   * @q_vector: Pointer to interrupt specific structure   * @va: Pointer to address containing Rx buffer   * @skb: Buffer containing timestamp and packet   * - * This function is meant to retrieve the first timestamp from the - * first buffer of an incoming frame. The value is stored in little - * endian format starting on byte 0. There's a second timestamp - * starting on byte 8. - **/ -void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, void *va, + * This function retrieves the timestamp saved in the beginning of packet + * buffer. While two timestamps are available, one in timer0 reference and the + * other in timer1 reference, this function considers only the timestamp in + * timer0 reference. + */ +void igc_ptp_rx_pktstamp(struct igc_q_vector *q_vector, __le32 *va,  			 struct sk_buff *skb)  {  	struct igc_adapter *adapter = q_vector->adapter; -	__le64 *regval = (__le64 *)va; -	int adjust = 0; - -	/* The timestamp is recorded in little endian format. -	 * DWORD: | 0          | 1           | 2          | 3 -	 * Field: | Timer0 Low | Timer0 High | Timer1 Low | Timer1 High +	u64 regval; +	int adjust; + +	/* Timestamps are saved in little endian at the beginning of the packet +	 * buffer following the layout: +	 * +	 * DWORD: | 0              | 1              | 2              | 3              | +	 * Field: | Timer1 SYSTIML | Timer1 SYSTIMH | Timer0 SYSTIML | Timer0 SYSTIMH | +	 * +	 * SYSTIML holds the nanoseconds part while SYSTIMH holds the seconds +	 * part of the timestamp.  	 */ -	igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), -				   le64_to_cpu(regval[0])); - -	/* adjust timestamp for the RX latency based on link speed */ -	if (adapter->hw.mac.type == igc_i225) { -		switch (adapter->link_speed) { -		case SPEED_10: -			adjust = IGC_I225_RX_LATENCY_10; -			break; -		case SPEED_100: -			adjust = IGC_I225_RX_LATENCY_100; -			break; -		case SPEED_1000: -			adjust = IGC_I225_RX_LATENCY_1000; -			break; -		case SPEED_2500: -			adjust = IGC_I225_RX_LATENCY_2500; -			break; -		} +	regval = le32_to_cpu(va[2]); +	regval |= (u64)le32_to_cpu(va[3]) << 32; +	igc_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval); + +	/* Adjust timestamp for the RX latency based on link speed */ +	switch (adapter->link_speed) { +	case SPEED_10: +		adjust = IGC_I225_RX_LATENCY_10; +		break; +	case SPEED_100: +		adjust = IGC_I225_RX_LATENCY_100; +		break; +	case SPEED_1000: +		adjust = IGC_I225_RX_LATENCY_1000; +		break; +	case SPEED_2500: +		adjust = IGC_I225_RX_LATENCY_2500; +		break; +	default: +		adjust = 0; +		netdev_warn_once(adapter->netdev, "Imprecise timestamp\n"); +		break;  	}  	skb_hwtstamps(skb)->hwtstamp =  		ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c index eca73526ac86..54d47265a7ac 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c @@ -575,6 +575,11 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)  		return -EINVAL;  	} +	if (xs->props.mode != XFRM_MODE_TRANSPORT) { +		netdev_err(dev, "Unsupported mode for ipsec offload\n"); +		return -EINVAL; +	} +  	if (ixgbe_ipsec_check_mgmt_ip(xs)) {  		netdev_err(dev, "IPsec IP addr clash with mgmt filters\n");  		return -EINVAL; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index fae84202d870..03d9aad516d4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4118,6 +4118,8 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,  #endif  	} +	ring->rx_offset = ixgbe_rx_offset(ring); +  	if (ring->xsk_pool && hw->mac.type != ixgbe_mac_82599EB) {  		u32 xsk_buf_len = xsk_pool_get_rx_frame_size(ring->xsk_pool); @@ -6578,7 +6580,6 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,  	rx_ring->next_to_clean = 0;  	rx_ring->next_to_use = 0; -	rx_ring->rx_offset = ixgbe_rx_offset(rx_ring);  	/* XDP RX-queue info */  	if (xdp_rxq_info_reg(&rx_ring->xdp_rxq, adapter->netdev, @@ -9565,8 +9566,10 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,  	ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask);  	err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter,  						    input->sw_idx, queue); -	if (!err) -		ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx); +	if (err) +		goto err_out_w_lock; + +	ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);  	spin_unlock(&adapter->fdir_perfect_lock);  	if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.c b/drivers/net/ethernet/intel/ixgbevf/ipsec.c index 5170dd9d8705..caaea2c920a6 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c +++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c @@ -272,6 +272,11 @@ static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs)  		return -EINVAL;  	} +	if (xs->props.mode != XFRM_MODE_TRANSPORT) { +		netdev_err(dev, "Unsupported mode for ipsec offload\n"); +		return -EINVAL; +	} +  	if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {  		struct rx_sa rsa; |