diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_common.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_dcb.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ddp.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 7 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 73 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_main.c | 82 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_nvm.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ptp.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_txrx.c | 41 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 117 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_xsk.c | 17 | 
14 files changed, 234 insertions, 126 deletions
| diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index cd53981fa5e0..9067cd3ce243 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -66,6 +66,8 @@  #define I40E_FDIR_RING_COUNT		32  #define I40E_MAX_AQ_BUF_SIZE		4096  #define I40E_AQ_LEN			256 +#define I40E_MIN_ARQ_LEN		1 +#define I40E_MIN_ASQ_LEN		2  #define I40E_AQ_WORK_LIMIT		66 /* max number of VFs + a little */  #define I40E_MAX_USER_PRIORITY		8  #define I40E_DEFAULT_TRAFFIC_CLASS	BIT(0) @@ -142,6 +144,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_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index ec19e18305ec..41b813fe07a5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2332,7 +2332,7 @@ i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,  }  /** - * i40e_get_vsi_params - get VSI configuration info + * i40e_aq_get_vsi_params - get VSI configuration info   * @hw: pointer to the hw struct   * @vsi_ctx: pointer to a vsi context struct   * @cmd_details: pointer to command details structure or NULL @@ -2586,7 +2586,7 @@ i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up)  }  /** - * i40e_updatelink_status - update status of the HW network link + * i40e_update_link_info - update status of the HW network link   * @hw: pointer to the hw struct   **/  noinline_for_stack i40e_status i40e_update_link_info(struct i40e_hw *hw) @@ -5059,7 +5059,7 @@ u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num)  }  /** - * i40e_blink_phy_led + * i40e_blink_phy_link_led   * @hw: pointer to the HW structure   * @time: time how long led will blinks in secs   * @interval: gap between LED on and off in msecs diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 243b0d2b7b72..673f341f4c0c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -234,7 +234,7 @@ static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,  }  /** - * i40e_parse_ieee_etsrec_tlv + * i40e_parse_ieee_tlv   * @tlv: IEEE 802.1Qaz TLV   * @dcbcfg: Local store to update ETS REC data   * @@ -1588,7 +1588,7 @@ void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,  }  /** - * i40e_dcb_hw_rx_ets_bw_config + * i40e_dcb_hw_rx_up2tc_config   * @hw: pointer to the hw struct   * @prio_tc: priority to tc assignment indexed by priority   * diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c index 0345132a0ef5..e32c61909b31 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c @@ -392,7 +392,7 @@ static void i40e_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,  }  /** - * i40e_dcbnl_set_pg_tc_cfg_tx - Set CEE PG Tx BW config + * i40e_dcbnl_set_pg_bwg_cfg_tx - Set CEE PG Tx BW config   * @netdev: the corresponding netdev   * @pgid: the corresponding traffic class   * @bw_pct: the BW percentage for the specified traffic class diff --git a/drivers/net/ethernet/intel/i40e/i40e_ddp.c b/drivers/net/ethernet/intel/i40e/i40e_ddp.c index 5e08f100c413..e1069ae658ad 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ddp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ddp.c @@ -77,7 +77,7 @@ static bool i40e_ddp_profiles_overlap(struct i40e_profile_info *new,  }  /** - * i40e_ddp_does_profiles_ - checks if DDP overlaps with existing one. + * i40e_ddp_does_profile_overlap - checks if DDP overlaps with existing one.   * @hw: HW data structure   * @pinfo: DDP profile information structure   * diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index d7c13ca9be7d..291e61ac3e44 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; @@ -651,7 +654,7 @@ static void i40e_dbg_dump_vsi_no_seid(struct i40e_pf *pf)  }  /** - * i40e_dbg_dump_stats - handles dump stats write into command datum + * i40e_dbg_dump_eth_stats - handles dump stats write into command datum   * @pf: the i40e_pf created in command write   * @estats: the eth stats structure to be dumped   **/ @@ -1638,7 +1641,7 @@ static const struct file_operations i40e_dbg_command_fops = {  static char i40e_dbg_netdev_ops_buf[256] = "";  /** - * i40e_dbg_netdev_ops - read for netdev_ops datum + * i40e_dbg_netdev_ops_read - read for netdev_ops datum   * @filp: the opened file   * @buffer: where to write the data for the user to read   * @count: the size of the user's buffer diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index c70dec65a572..040a01400b85 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -212,7 +212,7 @@ static void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[],  }  /** - * 40e_add_stat_strings - copy stat strings into ethtool buffer + * i40e_add_stat_strings - copy stat strings into ethtool buffer   * @p: ethtool supplied buffer   * @stats: stat definitions array   * @@ -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); @@ -2368,21 +2409,15 @@ static void i40e_get_priv_flag_strings(struct net_device *netdev, u8 *data)  	struct i40e_netdev_priv *np = netdev_priv(netdev);  	struct i40e_vsi *vsi = np->vsi;  	struct i40e_pf *pf = vsi->back; -	char *p = (char *)data;  	unsigned int i; +	u8 *p = data; -	for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) { -		snprintf(p, ETH_GSTRING_LEN, "%s", -			 i40e_gstrings_priv_flags[i].flag_string); -		p += ETH_GSTRING_LEN; -	} +	for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) +		ethtool_sprintf(&p, i40e_gstrings_priv_flags[i].flag_string);  	if (pf->hw.pf_id != 0)  		return; -	for (i = 0; i < I40E_GL_PRIV_FLAGS_STR_LEN; i++) { -		snprintf(p, ETH_GSTRING_LEN, "%s", -			 i40e_gl_gstrings_priv_flags[i].flag_string); -		p += ETH_GSTRING_LEN; -	} +	for (i = 0; i < I40E_GL_PRIV_FLAGS_STR_LEN; i++) +		ethtool_sprintf(&p, i40e_gl_gstrings_priv_flags[i].flag_string);  }  static void i40e_get_strings(struct net_device *netdev, u32 stringset, @@ -5439,7 +5474,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_lan_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c index a3da422ab05b..d6e92ecddfbd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c +++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c @@ -511,7 +511,7 @@ configure_lan_hmc_out:  }  /** - * i40e_delete_hmc_object - remove hmc objects + * i40e_delete_lan_hmc_object - remove hmc objects   * @hw: pointer to the HW structure   * @info: pointer to i40e_hmc_delete_obj_info struct   * diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 353deae139f9..c2d145a56b5e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6,6 +6,7 @@  #include <linux/pci.h>  #include <linux/bpf.h>  #include <generated/utsrelease.h> +#include <linux/crash_dump.h>  /* Local includes */  #include "i40e.h" @@ -2023,7 +2024,7 @@ static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi,  }  /** - * i40e_next_entry - Get the next non-broadcast filter from a list + * i40e_next_filter - Get the next non-broadcast filter from a list   * @next: pointer to filter in list   *   * Returns the next non-broadcast filter in the list. Required so that we @@ -2560,8 +2561,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 +3259,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 +3380,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); @@ -5191,7 +5204,7 @@ static u8 i40e_pf_get_num_tc(struct i40e_pf *pf)  }  /** - * i40e_pf_get_pf_tc_map - Get bitmap for enabled traffic classes + * i40e_pf_get_tc_map - Get bitmap for enabled traffic classes   * @pf: PF being queried   *   * Return a bitmap for enabled traffic classes for this PF. @@ -6725,9 +6738,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: @@ -7326,7 +7339,7 @@ static void i40e_vsi_set_default_tc_config(struct i40e_vsi *vsi)  	qcount = min_t(int, vsi->alloc_queue_pairs,  		       i40e_pf_get_max_q_per_tc(vsi->back));  	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { -		/* For the TC that is not enabled set the offset to to default +		/* For the TC that is not enabled set the offset to default  		 * queue and allocate one queue for the given TC.  		 */  		vsi->tc_config.tc_info[i].qoffset = 0; @@ -9454,7 +9467,7 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)  }  /** - * i40e_get_current_atr_count - Get the count of total FD ATR filters programmed + * i40e_get_current_atr_cnt - Get the count of total FD ATR filters programmed   * @pf: board private structure   **/  u32 i40e_get_current_atr_cnt(struct i40e_pf *pf) @@ -10560,12 +10573,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 +10587,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 +10601,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. @@ -10612,7 +10624,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)  	 * need to rebuild the switch model in the HW.  	 *  	 * If there were VEBs but the reconstitution failed, we'll try -	 * try to recover minimal use by getting the basic PF VSI working. +	 * to recover minimal use by getting the basic PF VSI working.  	 */  	if (vsi->uplink_seid != pf->mac_seid) {  		dev_dbg(&pf->pdev->dev, "attempting to rebuild switch\n"); @@ -11028,6 +11040,11 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)  		return -ENODATA;  	} +	if (is_kdump_kernel()) { +		vsi->num_tx_desc = I40E_MIN_NUM_DESCRIPTORS; +		vsi->num_rx_desc = I40E_MIN_NUM_DESCRIPTORS; +	} +  	return 0;  } @@ -12346,6 +12363,7 @@ static int i40e_sw_init(struct i40e_pf *pf)  {  	int err = 0;  	int size; +	u16 pow;  	/* Set default capability flags */  	pf->flags = I40E_FLAG_RX_CSUM_ENABLED | @@ -12364,6 +12382,11 @@ static int i40e_sw_init(struct i40e_pf *pf)  	pf->rss_table_size = pf->hw.func_caps.rss_table_size;  	pf->rss_size_max = min_t(int, pf->rss_size_max,  				 pf->hw.func_caps.num_tx_qp); + +	/* find the next higher power-of-2 of num cpus */ +	pow = roundup_pow_of_two(num_online_cpus()); +	pf->rss_size_max = min_t(int, pf->rss_size_max, pow); +  	if (pf->hw.func_caps.rss) {  		pf->flags |= I40E_FLAG_RSS_ENABLED;  		pf->alloc_rss_size = min_t(int, pf->rss_size_max, @@ -15127,12 +15150,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) @@ -15321,8 +15348,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	i40e_check_recovery_mode(pf); -	hw->aq.num_arq_entries = I40E_AQ_LEN; -	hw->aq.num_asq_entries = I40E_AQ_LEN; +	if (is_kdump_kernel()) { +		hw->aq.num_arq_entries = I40E_MIN_ARQ_LEN; +		hw->aq.num_asq_entries = I40E_MIN_ASQ_LEN; +	} else { +		hw->aq.num_arq_entries = I40E_AQ_LEN; +		hw->aq.num_asq_entries = I40E_AQ_LEN; +	}  	hw->aq.arq_buf_size = I40E_MAX_AQ_BUF_SIZE;  	hw->aq.asq_buf_size = I40E_MAX_AQ_BUF_SIZE;  	pf->adminq_work_limit = I40E_AQ_WORK_LIMIT; @@ -15485,6 +15517,14 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (err)  		goto err_switch_setup; +	/* Reduce Tx and Rx pairs for kdump +	 * When MSI-X is enabled, it's not allowed to use more TC queue +	 * pairs than MSI-X vectors (pf->num_lan_msix) exist. Thus +	 * vsi->num_queue_pairs will be equal to pf->num_lan_msix, i.e., 1. +	 */ +	if (is_kdump_kernel()) +		pf->num_lan_msix = 1; +  	pf->udp_tunnel_nic.set_port = i40e_udp_tunnel_set_port;  	pf->udp_tunnel_nic.unset_port = i40e_udp_tunnel_unset_port;  	pf->udp_tunnel_nic.flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP; diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 7164f4ad8120..fe6dca846028 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -4,7 +4,7 @@  #include "i40e_prototype.h"  /** - * i40e_init_nvm_ops - Initialize NVM function pointers + * i40e_init_nvm - Initialize NVM function pointers   * @hw: pointer to the HW structure   *   * Setup the function pointers and the NVM info structure. Should be called diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 7a879614ca55..f1f6fc3744e9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -216,7 +216,7 @@ static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,  }  /** - * i40e_ptp_update_latch_events - Read I40E_PRTTSYN_STAT_1 and latch events + * i40e_ptp_get_rx_events - Read I40E_PRTTSYN_STAT_1 and latch events   * @pf: the PF data structure   *   * This function reads I40E_PRTTSYN_STAT_1 and updates the corresponding timers diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 627794b31e33..121cd99fdeff 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); @@ -3345,7 +3331,7 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,  }  /** - * i40e_create_tx_ctx Build the Tx context descriptor + * i40e_create_tx_ctx - Build the Tx context descriptor   * @tx_ring:  ring to create the descriptor on   * @cd_type_cmd_tso_mss: Quad Word 1   * @cd_tunneling: Quad Word 0 - bits 0-31 @@ -3847,8 +3833,8 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)   * @frames: array of XDP buffer pointers   * @flags: XDP extra info   * - * Returns number of frames successfully sent. Frames that fail are - * free'ed via XDP return API. + * Returns number of frames successfully sent. Failed frames + * will be free'ed by XDP core.   *   * For error cases, a negative errno code is returned and no-frames   * are transmitted (caller must handle freeing frames). @@ -3861,7 +3847,7 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,  	struct i40e_vsi *vsi = np->vsi;  	struct i40e_pf *pf = vsi->back;  	struct i40e_ring *xdp_ring; -	int drops = 0; +	int nxmit = 0;  	int i;  	if (test_bit(__I40E_VSI_DOWN, vsi->state)) @@ -3881,14 +3867,13 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,  		int err;  		err = i40e_xmit_xdp_ring(xdpf, xdp_ring); -		if (err != I40E_XDP_TX) { -			xdp_return_frame_rx_napi(xdpf); -			drops++; -		} +		if (err != I40E_XDP_TX) +			break; +		nxmit++;  	}  	if (unlikely(flags & XDP_XMIT_FLUSH))  		i40e_xdp_ring_update_tail(xdp_ring); -	return n - drops; +	return nxmit;  } diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 1b6ec9be155a..eff0a30790dd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -40,6 +40,66 @@ static void i40e_vc_vf_broadcast(struct i40e_pf *pf,  }  /** + * i40e_vc_link_speed2mbps + * converts i40e_aq_link_speed to integer value of Mbps + * @link_speed: the speed to convert + * + * return the speed as direct value of Mbps. + **/ +static u32 +i40e_vc_link_speed2mbps(enum i40e_aq_link_speed link_speed) +{ +	switch (link_speed) { +	case I40E_LINK_SPEED_100MB: +		return SPEED_100; +	case I40E_LINK_SPEED_1GB: +		return SPEED_1000; +	case I40E_LINK_SPEED_2_5GB: +		return SPEED_2500; +	case I40E_LINK_SPEED_5GB: +		return SPEED_5000; +	case I40E_LINK_SPEED_10GB: +		return SPEED_10000; +	case I40E_LINK_SPEED_20GB: +		return SPEED_20000; +	case I40E_LINK_SPEED_25GB: +		return SPEED_25000; +	case I40E_LINK_SPEED_40GB: +		return SPEED_40000; +	case I40E_LINK_SPEED_UNKNOWN: +		return SPEED_UNKNOWN; +	} +	return SPEED_UNKNOWN; +} + +/** + * i40e_set_vf_link_state + * @vf: pointer to the VF structure + * @pfe: pointer to PF event structure + * @ls: pointer to link status structure + * + * set a link state on a single vf + **/ +static void i40e_set_vf_link_state(struct i40e_vf *vf, +				   struct virtchnl_pf_event *pfe, struct i40e_link_status *ls) +{ +	u8 link_status = ls->link_info & I40E_AQ_LINK_UP; + +	if (vf->link_forced) +		link_status = vf->link_up; + +	if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) { +		pfe->event_data.link_event_adv.link_speed = link_status ? +			i40e_vc_link_speed2mbps(ls->link_speed) : 0; +		pfe->event_data.link_event_adv.link_status = link_status; +	} else { +		pfe->event_data.link_event.link_speed = link_status ? +			i40e_virtchnl_link_speed(ls->link_speed) : 0; +		pfe->event_data.link_event.link_status = link_status; +	} +} + +/**   * i40e_vc_notify_vf_link_state   * @vf: pointer to the VF structure   * @@ -55,16 +115,9 @@ static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf)  	pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;  	pfe.severity = PF_EVENT_SEVERITY_INFO; -	if (vf->link_forced) { -		pfe.event_data.link_event.link_status = vf->link_up; -		pfe.event_data.link_event.link_speed = -			(vf->link_up ? i40e_virtchnl_link_speed(ls->link_speed) : 0); -	} else { -		pfe.event_data.link_event.link_status = -			ls->link_info & I40E_AQ_LINK_UP; -		pfe.event_data.link_event.link_speed = -			i40e_virtchnl_link_speed(ls->link_speed); -	} + +	i40e_set_vf_link_state(vf, &pfe, ls); +  	i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT,  			       0, (u8 *)&pfe, sizeof(pfe), NULL);  } @@ -137,6 +190,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 +201,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 +1633,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 +1692,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 @@ -1940,6 +2002,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)  				  VIRTCHNL_VF_OFFLOAD_VLAN;  	vfres->vf_cap_flags = VIRTCHNL_VF_OFFLOAD_L2; +	vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED;  	vsi = pf->vsi[vf->lan_vsi_idx];  	if (!vsi->info.pvid)  		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_VLAN; @@ -3687,26 +3750,8 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg)  	}  	/* get link speed in MB to validate rate limit */ -	switch (ls->link_speed) { -	case VIRTCHNL_LINK_SPEED_100MB: -		speed = SPEED_100; -		break; -	case VIRTCHNL_LINK_SPEED_1GB: -		speed = SPEED_1000; -		break; -	case VIRTCHNL_LINK_SPEED_10GB: -		speed = SPEED_10000; -		break; -	case VIRTCHNL_LINK_SPEED_20GB: -		speed = SPEED_20000; -		break; -	case VIRTCHNL_LINK_SPEED_25GB: -		speed = SPEED_25000; -		break; -	case VIRTCHNL_LINK_SPEED_40GB: -		speed = SPEED_40000; -		break; -	default: +	speed = i40e_vc_link_speed2mbps(ls->link_speed); +	if (speed == SPEED_UNKNOWN) {  		dev_err(&pf->pdev->dev,  			"Cannot detect link speed\n");  		aq_ret = I40E_ERR_PARAM; @@ -4455,23 +4500,17 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)  	switch (link) {  	case IFLA_VF_LINK_STATE_AUTO:  		vf->link_forced = false; -		pfe.event_data.link_event.link_status = -			pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP; -		pfe.event_data.link_event.link_speed = -			(enum virtchnl_link_speed) -			pf->hw.phy.link_info.link_speed; +		i40e_set_vf_link_state(vf, &pfe, ls);  		break;  	case IFLA_VF_LINK_STATE_ENABLE:  		vf->link_forced = true;  		vf->link_up = true; -		pfe.event_data.link_event.link_status = true; -		pfe.event_data.link_event.link_speed = i40e_virtchnl_link_speed(ls->link_speed); +		i40e_set_vf_link_state(vf, &pfe, ls);  		break;  	case IFLA_VF_LINK_STATE_DISABLE:  		vf->link_forced = true;  		vf->link_up = false; -		pfe.event_data.link_event.link_status = false; -		pfe.event_data.link_event.link_speed = 0; +		i40e_set_vf_link_state(vf, &pfe, ls);  		break;  	default:  		ret = -EINVAL; diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index fc32c5019b0f..46d884417c63 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -160,6 +160,13 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp)  	xdp_prog = READ_ONCE(rx_ring->xdp_prog);  	act = bpf_prog_run_xdp(xdp_prog, xdp); +	if (likely(act == XDP_REDIRECT)) { +		err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); +		result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED; +		rcu_read_unlock(); +		return result; +	} +  	switch (act) {  	case XDP_PASS:  		break; @@ -167,10 +174,6 @@ static int i40e_run_xdp_zc(struct i40e_ring *rx_ring, struct xdp_buff *xdp)  		xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];  		result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);  		break; -	case XDP_REDIRECT: -		err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog); -		result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED; -		break;  	default:  		bpf_warn_invalid_xdp_action(act);  		fallthrough; @@ -471,7 +474,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 +491,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;  }  /** @@ -625,7 +628,7 @@ void i40e_xsk_clean_rx_ring(struct i40e_ring *rx_ring)  }  /** - * i40e_xsk_clean_xdp_ring - Clean the XDP Tx ring on shutdown + * i40e_xsk_clean_tx_ring - Clean the XDP Tx ring on shutdown   * @tx_ring: XDP Tx ring   **/  void i40e_xsk_clean_tx_ring(struct i40e_ring *tx_ring) | 
