diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_ethtool.c')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 542 | 
1 files changed, 297 insertions, 245 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index b974482ff630..6947a2a571cb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1,29 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 -/******************************************************************************* - * - * Intel Ethernet Controller XL710 Family Linux Driver - * Copyright(c) 2013 - 2016 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program.  If not, see <http://www.gnu.org/licenses/>. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - ******************************************************************************/ +/* Copyright(c) 2013 - 2018 Intel Corporation. */  /* ethtool support for i40e */ @@ -43,13 +19,13 @@ struct i40e_stats {  }  #define I40E_NETDEV_STAT(_net_stat) \ -		I40E_STAT(struct rtnl_link_stats64, #_net_stat, _net_stat) +	I40E_STAT(struct rtnl_link_stats64, #_net_stat, _net_stat)  #define I40E_PF_STAT(_name, _stat) \ -		I40E_STAT(struct i40e_pf, _name, _stat) +	I40E_STAT(struct i40e_pf, _name, _stat)  #define I40E_VSI_STAT(_name, _stat) \ -		I40E_STAT(struct i40e_vsi, _name, _stat) +	I40E_STAT(struct i40e_vsi, _name, _stat)  #define I40E_VEB_STAT(_name, _stat) \ -		I40E_STAT(struct i40e_veb, _name, _stat) +	I40E_STAT(struct i40e_veb, _name, _stat)  static const struct i40e_stats i40e_gstrings_net_stats[] = {  	I40E_NETDEV_STAT(rx_packets), @@ -66,18 +42,18 @@ static const struct i40e_stats i40e_gstrings_net_stats[] = {  };  static const struct i40e_stats i40e_gstrings_veb_stats[] = { -	I40E_VEB_STAT("rx_bytes", stats.rx_bytes), -	I40E_VEB_STAT("tx_bytes", stats.tx_bytes), -	I40E_VEB_STAT("rx_unicast", stats.rx_unicast), -	I40E_VEB_STAT("tx_unicast", stats.tx_unicast), -	I40E_VEB_STAT("rx_multicast", stats.rx_multicast), -	I40E_VEB_STAT("tx_multicast", stats.tx_multicast), -	I40E_VEB_STAT("rx_broadcast", stats.rx_broadcast), -	I40E_VEB_STAT("tx_broadcast", stats.tx_broadcast), -	I40E_VEB_STAT("rx_discards", stats.rx_discards), -	I40E_VEB_STAT("tx_discards", stats.tx_discards), -	I40E_VEB_STAT("tx_errors", stats.tx_errors), -	I40E_VEB_STAT("rx_unknown_protocol", stats.rx_unknown_protocol), +	I40E_VEB_STAT("veb.rx_bytes", stats.rx_bytes), +	I40E_VEB_STAT("veb.tx_bytes", stats.tx_bytes), +	I40E_VEB_STAT("veb.rx_unicast", stats.rx_unicast), +	I40E_VEB_STAT("veb.tx_unicast", stats.tx_unicast), +	I40E_VEB_STAT("veb.rx_multicast", stats.rx_multicast), +	I40E_VEB_STAT("veb.tx_multicast", stats.tx_multicast), +	I40E_VEB_STAT("veb.rx_broadcast", stats.rx_broadcast), +	I40E_VEB_STAT("veb.tx_broadcast", stats.tx_broadcast), +	I40E_VEB_STAT("veb.rx_discards", stats.rx_discards), +	I40E_VEB_STAT("veb.tx_discards", stats.tx_discards), +	I40E_VEB_STAT("veb.tx_errors", stats.tx_errors), +	I40E_VEB_STAT("veb.rx_unknown_protocol", stats.rx_unknown_protocol),  };  static const struct i40e_stats i40e_gstrings_misc_stats[] = { @@ -90,6 +66,7 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {  	I40E_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol),  	I40E_VSI_STAT("tx_linearize", tx_linearize),  	I40E_VSI_STAT("tx_force_wb", tx_force_wb), +	I40E_VSI_STAT("tx_busy", tx_busy),  	I40E_VSI_STAT("rx_alloc_fail", rx_buf_failed),  	I40E_VSI_STAT("rx_pg_alloc_fail", rx_page_failed),  }; @@ -105,76 +82,77 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = {   * is queried on the base PF netdev, not on the VMDq or FCoE netdev.   */  static const struct i40e_stats i40e_gstrings_stats[] = { -	I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes), -	I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes), -	I40E_PF_STAT("rx_unicast", stats.eth.rx_unicast), -	I40E_PF_STAT("tx_unicast", stats.eth.tx_unicast), -	I40E_PF_STAT("rx_multicast", stats.eth.rx_multicast), -	I40E_PF_STAT("tx_multicast", stats.eth.tx_multicast), -	I40E_PF_STAT("rx_broadcast", stats.eth.rx_broadcast), -	I40E_PF_STAT("tx_broadcast", stats.eth.tx_broadcast), -	I40E_PF_STAT("tx_errors", stats.eth.tx_errors), -	I40E_PF_STAT("rx_dropped", stats.eth.rx_discards), -	I40E_PF_STAT("tx_dropped_link_down", stats.tx_dropped_link_down), -	I40E_PF_STAT("rx_crc_errors", stats.crc_errors), -	I40E_PF_STAT("illegal_bytes", stats.illegal_bytes), -	I40E_PF_STAT("mac_local_faults", stats.mac_local_faults), -	I40E_PF_STAT("mac_remote_faults", stats.mac_remote_faults), -	I40E_PF_STAT("tx_timeout", tx_timeout_count), -	I40E_PF_STAT("rx_csum_bad", hw_csum_rx_error), -	I40E_PF_STAT("rx_length_errors", stats.rx_length_errors), -	I40E_PF_STAT("link_xon_rx", stats.link_xon_rx), -	I40E_PF_STAT("link_xoff_rx", stats.link_xoff_rx), -	I40E_PF_STAT("link_xon_tx", stats.link_xon_tx), -	I40E_PF_STAT("link_xoff_tx", stats.link_xoff_tx), -	I40E_PF_STAT("priority_xon_rx", stats.priority_xon_rx), -	I40E_PF_STAT("priority_xoff_rx", stats.priority_xoff_rx), -	I40E_PF_STAT("priority_xon_tx", stats.priority_xon_tx), -	I40E_PF_STAT("priority_xoff_tx", stats.priority_xoff_tx), -	I40E_PF_STAT("rx_size_64", stats.rx_size_64), -	I40E_PF_STAT("rx_size_127", stats.rx_size_127), -	I40E_PF_STAT("rx_size_255", stats.rx_size_255), -	I40E_PF_STAT("rx_size_511", stats.rx_size_511), -	I40E_PF_STAT("rx_size_1023", stats.rx_size_1023), -	I40E_PF_STAT("rx_size_1522", stats.rx_size_1522), -	I40E_PF_STAT("rx_size_big", stats.rx_size_big), -	I40E_PF_STAT("tx_size_64", stats.tx_size_64), -	I40E_PF_STAT("tx_size_127", stats.tx_size_127), -	I40E_PF_STAT("tx_size_255", stats.tx_size_255), -	I40E_PF_STAT("tx_size_511", stats.tx_size_511), -	I40E_PF_STAT("tx_size_1023", stats.tx_size_1023), -	I40E_PF_STAT("tx_size_1522", stats.tx_size_1522), -	I40E_PF_STAT("tx_size_big", stats.tx_size_big), -	I40E_PF_STAT("rx_undersize", stats.rx_undersize), -	I40E_PF_STAT("rx_fragments", stats.rx_fragments), -	I40E_PF_STAT("rx_oversize", stats.rx_oversize), -	I40E_PF_STAT("rx_jabber", stats.rx_jabber), -	I40E_PF_STAT("VF_admin_queue_requests", vf_aq_requests), -	I40E_PF_STAT("arq_overflows", arq_overflows), -	I40E_PF_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), -	I40E_PF_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped), -	I40E_PF_STAT("fdir_flush_cnt", fd_flush_cnt), -	I40E_PF_STAT("fdir_atr_match", stats.fd_atr_match), -	I40E_PF_STAT("fdir_atr_tunnel_match", stats.fd_atr_tunnel_match), -	I40E_PF_STAT("fdir_atr_status", stats.fd_atr_status), -	I40E_PF_STAT("fdir_sb_match", stats.fd_sb_match), -	I40E_PF_STAT("fdir_sb_status", stats.fd_sb_status), +	I40E_PF_STAT("port.rx_bytes", stats.eth.rx_bytes), +	I40E_PF_STAT("port.tx_bytes", stats.eth.tx_bytes), +	I40E_PF_STAT("port.rx_unicast", stats.eth.rx_unicast), +	I40E_PF_STAT("port.tx_unicast", stats.eth.tx_unicast), +	I40E_PF_STAT("port.rx_multicast", stats.eth.rx_multicast), +	I40E_PF_STAT("port.tx_multicast", stats.eth.tx_multicast), +	I40E_PF_STAT("port.rx_broadcast", stats.eth.rx_broadcast), +	I40E_PF_STAT("port.tx_broadcast", stats.eth.tx_broadcast), +	I40E_PF_STAT("port.tx_errors", stats.eth.tx_errors), +	I40E_PF_STAT("port.rx_dropped", stats.eth.rx_discards), +	I40E_PF_STAT("port.tx_dropped_link_down", stats.tx_dropped_link_down), +	I40E_PF_STAT("port.rx_crc_errors", stats.crc_errors), +	I40E_PF_STAT("port.illegal_bytes", stats.illegal_bytes), +	I40E_PF_STAT("port.mac_local_faults", stats.mac_local_faults), +	I40E_PF_STAT("port.mac_remote_faults", stats.mac_remote_faults), +	I40E_PF_STAT("port.tx_timeout", tx_timeout_count), +	I40E_PF_STAT("port.rx_csum_bad", hw_csum_rx_error), +	I40E_PF_STAT("port.rx_length_errors", stats.rx_length_errors), +	I40E_PF_STAT("port.link_xon_rx", stats.link_xon_rx), +	I40E_PF_STAT("port.link_xoff_rx", stats.link_xoff_rx), +	I40E_PF_STAT("port.link_xon_tx", stats.link_xon_tx), +	I40E_PF_STAT("port.link_xoff_tx", stats.link_xoff_tx), +	I40E_PF_STAT("port.rx_size_64", stats.rx_size_64), +	I40E_PF_STAT("port.rx_size_127", stats.rx_size_127), +	I40E_PF_STAT("port.rx_size_255", stats.rx_size_255), +	I40E_PF_STAT("port.rx_size_511", stats.rx_size_511), +	I40E_PF_STAT("port.rx_size_1023", stats.rx_size_1023), +	I40E_PF_STAT("port.rx_size_1522", stats.rx_size_1522), +	I40E_PF_STAT("port.rx_size_big", stats.rx_size_big), +	I40E_PF_STAT("port.tx_size_64", stats.tx_size_64), +	I40E_PF_STAT("port.tx_size_127", stats.tx_size_127), +	I40E_PF_STAT("port.tx_size_255", stats.tx_size_255), +	I40E_PF_STAT("port.tx_size_511", stats.tx_size_511), +	I40E_PF_STAT("port.tx_size_1023", stats.tx_size_1023), +	I40E_PF_STAT("port.tx_size_1522", stats.tx_size_1522), +	I40E_PF_STAT("port.tx_size_big", stats.tx_size_big), +	I40E_PF_STAT("port.rx_undersize", stats.rx_undersize), +	I40E_PF_STAT("port.rx_fragments", stats.rx_fragments), +	I40E_PF_STAT("port.rx_oversize", stats.rx_oversize), +	I40E_PF_STAT("port.rx_jabber", stats.rx_jabber), +	I40E_PF_STAT("port.VF_admin_queue_requests", vf_aq_requests), +	I40E_PF_STAT("port.arq_overflows", arq_overflows), +	I40E_PF_STAT("port.tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), +	I40E_PF_STAT("port.rx_hwtstamp_cleared", rx_hwtstamp_cleared), +	I40E_PF_STAT("port.tx_hwtstamp_skipped", tx_hwtstamp_skipped), +	I40E_PF_STAT("port.fdir_flush_cnt", fd_flush_cnt), +	I40E_PF_STAT("port.fdir_atr_match", stats.fd_atr_match), +	I40E_PF_STAT("port.fdir_atr_tunnel_match", stats.fd_atr_tunnel_match), +	I40E_PF_STAT("port.fdir_atr_status", stats.fd_atr_status), +	I40E_PF_STAT("port.fdir_sb_match", stats.fd_sb_match), +	I40E_PF_STAT("port.fdir_sb_status", stats.fd_sb_status),  	/* LPI stats */ -	I40E_PF_STAT("tx_lpi_status", stats.tx_lpi_status), -	I40E_PF_STAT("rx_lpi_status", stats.rx_lpi_status), -	I40E_PF_STAT("tx_lpi_count", stats.tx_lpi_count), -	I40E_PF_STAT("rx_lpi_count", stats.rx_lpi_count), +	I40E_PF_STAT("port.tx_lpi_status", stats.tx_lpi_status), +	I40E_PF_STAT("port.rx_lpi_status", stats.rx_lpi_status), +	I40E_PF_STAT("port.tx_lpi_count", stats.tx_lpi_count), +	I40E_PF_STAT("port.rx_lpi_count", stats.rx_lpi_count),  }; -#define I40E_QUEUE_STATS_LEN(n) \ -	(((struct i40e_netdev_priv *)netdev_priv((n)))->vsi->num_queue_pairs \ +/* We use num_tx_queues here as a proxy for the maximum number of queues + * available because we always allocate queues symmetrically. + */ +#define I40E_MAX_NUM_QUEUES(n) ((n)->num_tx_queues) +#define I40E_QUEUE_STATS_LEN(n)                                              \ +	   (I40E_MAX_NUM_QUEUES(n)                                           \  	    * 2 /* Tx and Rx together */                                     \  	    * (sizeof(struct i40e_queue_stats) / sizeof(u64)))  #define I40E_GLOBAL_STATS_LEN	ARRAY_SIZE(i40e_gstrings_stats) -#define I40E_NETDEV_STATS_LEN   ARRAY_SIZE(i40e_gstrings_net_stats) +#define I40E_NETDEV_STATS_LEN	ARRAY_SIZE(i40e_gstrings_net_stats)  #define I40E_MISC_STATS_LEN	ARRAY_SIZE(i40e_gstrings_misc_stats) -#define I40E_VSI_STATS_LEN(n)   (I40E_NETDEV_STATS_LEN + \ +#define I40E_VSI_STATS_LEN(n)	(I40E_NETDEV_STATS_LEN + \  				 I40E_MISC_STATS_LEN + \  				 I40E_QUEUE_STATS_LEN((n)))  #define I40E_PFC_STATS_LEN ( \ @@ -977,7 +955,9 @@ static int i40e_set_link_ksettings(struct net_device *netdev,  	    ethtool_link_ksettings_test_link_mode(ks, advertising,  						  10000baseCR_Full) ||  	    ethtool_link_ksettings_test_link_mode(ks, advertising, -						  10000baseSR_Full)) +						  10000baseSR_Full) || +	    ethtool_link_ksettings_test_link_mode(ks, advertising, +						  10000baseLR_Full))  		config.link_speed |= I40E_LINK_SPEED_10GB;  	if (ethtool_link_ksettings_test_link_mode(ks, advertising,  						  20000baseKR2_Full)) @@ -1079,6 +1059,9 @@ static int i40e_nway_reset(struct net_device *netdev)  /**   * i40e_get_pauseparam -  Get Flow Control status + * @netdev: netdevice structure + * @pause: buffer to return pause parameters + *   * Return tx/rx-pause status   **/  static void i40e_get_pauseparam(struct net_device *netdev, @@ -1677,6 +1660,32 @@ done:  	return err;  } +/** + * i40e_get_stats_count - return the stats count for a device + * @netdev: the netdev to return the count for + * + * Returns the total number of statistics for this netdev. Note that even + * though this is a function, it is required that the count for a specific + * netdev must never change. Basing the count on static values such as the + * maximum number of queues or the device type is ok. However, the API for + * obtaining stats is *not* safe against changes based on non-static + * values such as the *current* number of queues, or runtime flags. + * + * If a statistic is not always enabled, return it as part of the count + * anyways, always return its string, and report its value as zero. + **/ +static int i40e_get_stats_count(struct net_device *netdev) +{ +	struct i40e_netdev_priv *np = netdev_priv(netdev); +	struct i40e_vsi *vsi = np->vsi; +	struct i40e_pf *pf = vsi->back; + +	if (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id == 1) +		return I40E_PF_STATS_LEN(netdev) + I40E_VEB_STATS_TOTAL; +	else +		return I40E_VSI_STATS_LEN(netdev); +} +  static int i40e_get_sset_count(struct net_device *netdev, int sset)  {  	struct i40e_netdev_priv *np = netdev_priv(netdev); @@ -1687,16 +1696,7 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)  	case ETH_SS_TEST:  		return I40E_TEST_LEN;  	case ETH_SS_STATS: -		if (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id == 1) { -			int len = I40E_PF_STATS_LEN(netdev); - -			if ((pf->lan_veb != I40E_NO_VEB) && -			    (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) -				len += I40E_VEB_STATS_TOTAL; -			return len; -		} else { -			return I40E_VSI_STATS_LEN(netdev); -		} +		return i40e_get_stats_count(netdev);  	case ETH_SS_PRIV_FLAGS:  		return I40E_PRIV_FLAGS_STR_LEN +  			(pf->hw.pf_id == 0 ? I40E_GL_PRIV_FLAGS_STR_LEN : 0); @@ -1705,6 +1705,20 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset)  	}  } +/** + * i40e_get_ethtool_stats - copy stat values into supplied buffer + * @netdev: the netdev to collect stats for + * @stats: ethtool stats command structure + * @data: ethtool supplied buffer + * + * Copy the stats values for this netdev into the buffer. Expects data to be + * pre-allocated to the size returned by i40e_get_stats_count.. Note that all + * statistics must be copied in a static order, and the count must not change + * for a given netdev. See i40e_get_stats_count for more details. + * + * If a statistic is not currently valid (such as a disabled queue), this + * function reports its value as zero. + **/  static void i40e_get_ethtool_stats(struct net_device *netdev,  				   struct ethtool_stats *stats, u64 *data)  { @@ -1712,47 +1726,54 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,  	struct i40e_ring *tx_ring, *rx_ring;  	struct i40e_vsi *vsi = np->vsi;  	struct i40e_pf *pf = vsi->back; -	unsigned int j; -	int i = 0; +	unsigned int i;  	char *p;  	struct rtnl_link_stats64 *net_stats = i40e_get_vsi_stats_struct(vsi);  	unsigned int start;  	i40e_update_stats(vsi); -	for (j = 0; j < I40E_NETDEV_STATS_LEN; j++) { -		p = (char *)net_stats + i40e_gstrings_net_stats[j].stat_offset; -		data[i++] = (i40e_gstrings_net_stats[j].sizeof_stat == +	for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) { +		p = (char *)net_stats + i40e_gstrings_net_stats[i].stat_offset; +		*(data++) = (i40e_gstrings_net_stats[i].sizeof_stat ==  			sizeof(u64)) ? *(u64 *)p : *(u32 *)p;  	} -	for (j = 0; j < I40E_MISC_STATS_LEN; j++) { -		p = (char *)vsi + i40e_gstrings_misc_stats[j].stat_offset; -		data[i++] = (i40e_gstrings_misc_stats[j].sizeof_stat == +	for (i = 0; i < I40E_MISC_STATS_LEN; i++) { +		p = (char *)vsi + i40e_gstrings_misc_stats[i].stat_offset; +		*(data++) = (i40e_gstrings_misc_stats[i].sizeof_stat ==  			    sizeof(u64)) ? *(u64 *)p : *(u32 *)p;  	}  	rcu_read_lock(); -	for (j = 0; j < vsi->num_queue_pairs; j++) { -		tx_ring = READ_ONCE(vsi->tx_rings[j]); +	for (i = 0; i < I40E_MAX_NUM_QUEUES(netdev) ; i++) { +		tx_ring = READ_ONCE(vsi->tx_rings[i]); -		if (!tx_ring) +		if (!tx_ring) { +			/* Bump the stat counter to skip these stats, and make +			 * sure the memory is zero'd +			 */ +			*(data++) = 0; +			*(data++) = 0; +			*(data++) = 0; +			*(data++) = 0;  			continue; +		}  		/* process Tx ring statistics */  		do {  			start = u64_stats_fetch_begin_irq(&tx_ring->syncp); -			data[i] = tx_ring->stats.packets; -			data[i + 1] = tx_ring->stats.bytes; +			data[0] = tx_ring->stats.packets; +			data[1] = tx_ring->stats.bytes;  		} while (u64_stats_fetch_retry_irq(&tx_ring->syncp, start)); -		i += 2; +		data += 2;  		/* Rx ring is the 2nd half of the queue pair */  		rx_ring = &tx_ring[1];  		do {  			start = u64_stats_fetch_begin_irq(&rx_ring->syncp); -			data[i] = rx_ring->stats.packets; -			data[i + 1] = rx_ring->stats.bytes; +			data[0] = rx_ring->stats.packets; +			data[1] = rx_ring->stats.bytes;  		} while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start)); -		i += 2; +		data += 2;  	}  	rcu_read_unlock();  	if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) @@ -1762,38 +1783,131 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,  	    (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) {  		struct i40e_veb *veb = pf->veb[pf->lan_veb]; -		for (j = 0; j < I40E_VEB_STATS_LEN; j++) { +		for (i = 0; i < I40E_VEB_STATS_LEN; i++) {  			p = (char *)veb; -			p += i40e_gstrings_veb_stats[j].stat_offset; -			data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat == +			p += i40e_gstrings_veb_stats[i].stat_offset; +			*(data++) = (i40e_gstrings_veb_stats[i].sizeof_stat ==  				     sizeof(u64)) ? *(u64 *)p : *(u32 *)p;  		} -		for (j = 0; j < I40E_MAX_TRAFFIC_CLASS; j++) { -			data[i++] = veb->tc_stats.tc_tx_packets[j]; -			data[i++] = veb->tc_stats.tc_tx_bytes[j]; -			data[i++] = veb->tc_stats.tc_rx_packets[j]; -			data[i++] = veb->tc_stats.tc_rx_bytes[j]; +		for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { +			*(data++) = veb->tc_stats.tc_tx_packets[i]; +			*(data++) = veb->tc_stats.tc_tx_bytes[i]; +			*(data++) = veb->tc_stats.tc_rx_packets[i]; +			*(data++) = veb->tc_stats.tc_rx_bytes[i];  		} +	} else { +		data += I40E_VEB_STATS_TOTAL;  	} -	for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) { -		p = (char *)pf + i40e_gstrings_stats[j].stat_offset; -		data[i++] = (i40e_gstrings_stats[j].sizeof_stat == +	for (i = 0; i < I40E_GLOBAL_STATS_LEN; i++) { +		p = (char *)pf + i40e_gstrings_stats[i].stat_offset; +		*(data++) = (i40e_gstrings_stats[i].sizeof_stat ==  			     sizeof(u64)) ? *(u64 *)p : *(u32 *)p;  	} -	for (j = 0; j < I40E_MAX_USER_PRIORITY; j++) { -		data[i++] = pf->stats.priority_xon_tx[j]; -		data[i++] = pf->stats.priority_xoff_tx[j]; +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { +		*(data++) = pf->stats.priority_xon_tx[i]; +		*(data++) = pf->stats.priority_xoff_tx[i];  	} -	for (j = 0; j < I40E_MAX_USER_PRIORITY; j++) { -		data[i++] = pf->stats.priority_xon_rx[j]; -		data[i++] = pf->stats.priority_xoff_rx[j]; +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { +		*(data++) = pf->stats.priority_xon_rx[i]; +		*(data++) = pf->stats.priority_xoff_rx[i];  	} -	for (j = 0; j < I40E_MAX_USER_PRIORITY; j++) -		data[i++] = pf->stats.priority_xon_2_xoff[j]; +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) +		*(data++) = pf->stats.priority_xon_2_xoff[i];  } -static void i40e_get_strings(struct net_device *netdev, u32 stringset, -			     u8 *data) +/** + * i40e_get_stat_strings - copy stat strings into supplied buffer + * @netdev: the netdev to collect strings for + * @data: supplied buffer to copy strings into + * + * Copy the strings related to stats for this netdev. Expects data to be + * pre-allocated with the size reported by i40e_get_stats_count. Note that the + * strings must be copied in a static order and the total count must not + * change for a given netdev. See i40e_get_stats_count for more details. + **/ +static void i40e_get_stat_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; +	unsigned int i; +	u8 *p = data; + +	for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) { +		snprintf(data, ETH_GSTRING_LEN, "%s", +			 i40e_gstrings_net_stats[i].stat_string); +		data += ETH_GSTRING_LEN; +	} +	for (i = 0; i < I40E_MISC_STATS_LEN; i++) { +		snprintf(data, ETH_GSTRING_LEN, "%s", +			 i40e_gstrings_misc_stats[i].stat_string); +		data += ETH_GSTRING_LEN; +	} +	for (i = 0; i < I40E_MAX_NUM_QUEUES(netdev); i++) { +		snprintf(data, ETH_GSTRING_LEN, "tx-%u.tx_packets", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, "tx-%u.tx_bytes", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, "rx-%u.rx_packets", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, "rx-%u.rx_bytes", i); +		data += ETH_GSTRING_LEN; +	} +	if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) +		return; + +	for (i = 0; i < I40E_VEB_STATS_LEN; i++) { +		snprintf(data, ETH_GSTRING_LEN, "%s", +			 i40e_gstrings_veb_stats[i].stat_string); +		data += ETH_GSTRING_LEN; +	} +	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { +		snprintf(data, ETH_GSTRING_LEN, +			 "veb.tc_%u_tx_packets", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, +			 "veb.tc_%u_tx_bytes", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, +			 "veb.tc_%u_rx_packets", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, +			 "veb.tc_%u_rx_bytes", i); +		data += ETH_GSTRING_LEN; +	} + +	for (i = 0; i < I40E_GLOBAL_STATS_LEN; i++) { +		snprintf(data, ETH_GSTRING_LEN, "%s", +			 i40e_gstrings_stats[i].stat_string); +		data += ETH_GSTRING_LEN; +	} +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { +		snprintf(data, ETH_GSTRING_LEN, +			 "port.tx_priority_%u_xon", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, +			 "port.tx_priority_%u_xoff", i); +		data += ETH_GSTRING_LEN; +	} +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { +		snprintf(data, ETH_GSTRING_LEN, +			 "port.rx_priority_%u_xon", i); +		data += ETH_GSTRING_LEN; +		snprintf(data, ETH_GSTRING_LEN, +			 "port.rx_priority_%u_xoff", i); +		data += ETH_GSTRING_LEN; +	} +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { +		snprintf(data, ETH_GSTRING_LEN, +			 "port.rx_priority_%u_xon_2_xoff", i); +		data += ETH_GSTRING_LEN; +	} + +	WARN_ONCE(p - data != i40e_get_stats_count(netdev) * ETH_GSTRING_LEN, +		  "stat strings count mismatch!"); +} + +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; @@ -1801,98 +1915,33 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset,  	char *p = (char *)data;  	unsigned int i; +	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; +	} +	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; +	} +} + +static void i40e_get_strings(struct net_device *netdev, u32 stringset, +			     u8 *data) +{  	switch (stringset) {  	case ETH_SS_TEST:  		memcpy(data, i40e_gstrings_test,  		       I40E_TEST_LEN * ETH_GSTRING_LEN);  		break;  	case ETH_SS_STATS: -		for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) { -			snprintf(p, ETH_GSTRING_LEN, "%s", -				 i40e_gstrings_net_stats[i].stat_string); -			p += ETH_GSTRING_LEN; -		} -		for (i = 0; i < I40E_MISC_STATS_LEN; i++) { -			snprintf(p, ETH_GSTRING_LEN, "%s", -				 i40e_gstrings_misc_stats[i].stat_string); -			p += ETH_GSTRING_LEN; -		} -		for (i = 0; i < vsi->num_queue_pairs; i++) { -			snprintf(p, ETH_GSTRING_LEN, "tx-%d.tx_packets", i); -			p += ETH_GSTRING_LEN; -			snprintf(p, ETH_GSTRING_LEN, "tx-%d.tx_bytes", i); -			p += ETH_GSTRING_LEN; -			snprintf(p, ETH_GSTRING_LEN, "rx-%d.rx_packets", i); -			p += ETH_GSTRING_LEN; -			snprintf(p, ETH_GSTRING_LEN, "rx-%d.rx_bytes", i); -			p += ETH_GSTRING_LEN; -		} -		if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) -			return; - -		if ((pf->lan_veb != I40E_NO_VEB) && -		    (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) { -			for (i = 0; i < I40E_VEB_STATS_LEN; i++) { -				snprintf(p, ETH_GSTRING_LEN, "veb.%s", -					i40e_gstrings_veb_stats[i].stat_string); -				p += ETH_GSTRING_LEN; -			} -			for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { -				snprintf(p, ETH_GSTRING_LEN, -					 "veb.tc_%d_tx_packets", i); -				p += ETH_GSTRING_LEN; -				snprintf(p, ETH_GSTRING_LEN, -					 "veb.tc_%d_tx_bytes", i); -				p += ETH_GSTRING_LEN; -				snprintf(p, ETH_GSTRING_LEN, -					 "veb.tc_%d_rx_packets", i); -				p += ETH_GSTRING_LEN; -				snprintf(p, ETH_GSTRING_LEN, -					 "veb.tc_%d_rx_bytes", i); -				p += ETH_GSTRING_LEN; -			} -		} -		for (i = 0; i < I40E_GLOBAL_STATS_LEN; i++) { -			snprintf(p, ETH_GSTRING_LEN, "port.%s", -				 i40e_gstrings_stats[i].stat_string); -			p += ETH_GSTRING_LEN; -		} -		for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { -			snprintf(p, ETH_GSTRING_LEN, -				 "port.tx_priority_%d_xon", i); -			p += ETH_GSTRING_LEN; -			snprintf(p, ETH_GSTRING_LEN, -				 "port.tx_priority_%d_xoff", i); -			p += ETH_GSTRING_LEN; -		} -		for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { -			snprintf(p, ETH_GSTRING_LEN, -				 "port.rx_priority_%d_xon", i); -			p += ETH_GSTRING_LEN; -			snprintf(p, ETH_GSTRING_LEN, -				 "port.rx_priority_%d_xoff", i); -			p += ETH_GSTRING_LEN; -		} -		for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { -			snprintf(p, ETH_GSTRING_LEN, -				 "port.rx_priority_%d_xon_2_xoff", i); -			p += ETH_GSTRING_LEN; -		} -		/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */ +		i40e_get_stat_strings(netdev, data);  		break;  	case ETH_SS_PRIV_FLAGS: -		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; -		} -		if (pf->hw.pf_id != 0) -			break; -		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; -		} +		i40e_get_priv_flag_strings(netdev, data);  		break;  	default:  		break; @@ -2550,7 +2599,7 @@ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd)  /**   * i40e_check_mask - Check whether a mask field is set   * @mask: the full mask value - * @field; mask of the field to check + * @field: mask of the field to check   *   * If the given mask is fully set, return positive value. If the mask for the   * field is fully unset, return zero. Otherwise return a negative error code. @@ -2621,6 +2670,7 @@ static int i40e_parse_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp,  /**   * i40e_fill_rx_flow_user_data - Fill in user-defined data field   * @fsp: pointer to rx_flow specification + * @data: pointer to return userdef data   *   * Reads the userdef data structure and properly fills in the user defined   * fields of the rx_flow_spec. @@ -2799,6 +2849,7 @@ no_input_set:   * i40e_get_rxnfc - command to get RX flow classification rules   * @netdev: network interface device structure   * @cmd: ethtool rxnfc command + * @rule_locs: pointer to store rule data   *   * Returns Success if the command is supported.   **/ @@ -2840,7 +2891,7 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,  /**   * i40e_get_rss_hash_bits - Read RSS Hash bits from register   * @nfc: pointer to user request - * @i_setc bits currently set + * @i_setc: bits currently set   *   * Returns value of bits to be set per user request   **/ @@ -2885,7 +2936,7 @@ static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc)  /**   * i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash   * @pf: pointer to the physical function struct - * @cmd: ethtool rxnfc command + * @nfc: ethtool rxnfc command   *   * Returns Success if the flow input set is supported.   **/ @@ -3284,7 +3335,7 @@ static int i40e_add_flex_offset(struct list_head *flex_pit_list,   * __i40e_reprogram_flex_pit - Re-program specific FLX_PIT table   * @pf: Pointer to the PF structure   * @flex_pit_list: list of flexible src offsets in use - * #flex_pit_start: index to first entry for this section of the table + * @flex_pit_start: index to first entry for this section of the table   *   * In order to handle flexible data, the hardware uses a table of values   * called the FLX_PIT table. This table is used to indicate which sections of @@ -3398,7 +3449,7 @@ static void i40e_reprogram_flex_pit(struct i40e_pf *pf)  /**   * i40e_flow_str - Converts a flow_type into a human readable string - * @flow_type: the flow type from a flow specification + * @fsp: the flow specification   *   * Currently only flow types we support are included here, and the string   * value attempts to match what ethtool would use to configure this flow type. @@ -4103,7 +4154,7 @@ static unsigned int i40e_max_channels(struct i40e_vsi *vsi)  /**   * i40e_get_channels - Get the current channels enabled and max supported etc. - * @netdev: network interface device structure + * @dev: network interface device structure   * @ch: ethtool channels structure   *   * We don't support separate tx and rx queues as channels. The other count @@ -4112,7 +4163,7 @@ static unsigned int i40e_max_channels(struct i40e_vsi *vsi)   * q_vectors since we support a lot more queue pairs than q_vectors.   **/  static void i40e_get_channels(struct net_device *dev, -			       struct ethtool_channels *ch) +			      struct ethtool_channels *ch)  {  	struct i40e_netdev_priv *np = netdev_priv(dev);  	struct i40e_vsi *vsi = np->vsi; @@ -4131,14 +4182,14 @@ static void i40e_get_channels(struct net_device *dev,  /**   * i40e_set_channels - Set the new channels count. - * @netdev: network interface device structure + * @dev: network interface device structure   * @ch: ethtool channels structure   *   * The new channels count may not be the same as requested by the user   * since it gets rounded down to a power of 2 value.   **/  static int i40e_set_channels(struct net_device *dev, -			      struct ethtool_channels *ch) +			     struct ethtool_channels *ch)  {  	const u8 drop = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;  	struct i40e_netdev_priv *np = netdev_priv(dev); @@ -4273,6 +4324,7 @@ out:   * @netdev: network interface device structure   * @indir: indirection table   * @key: hash key + * @hfunc: hash function to use   *   * Returns -EINVAL if the table specifies an invalid queue id, otherwise   * returns 0 after programming the table.  | 
