Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd0ecc9a authored by Ben Hutchings's avatar Ben Hutchings
Browse files

sfc: Delegate MAC/NIC statistic description to efx_nic_type



Various hardware statistics that are available for Siena are
unavailable or meaningless for Falcon.  Huntington adds further to the
NIC-type-specific statistics, as it has different MAC blocks from
Falcon/Siena.

All NIC types still provide most statistics by DMA, and use
little-endian byte order.

Therefore:
1. Add some general utility functions for reporting hardware statistics,
   efx_nic_describe_stats() and efx_nic_update_stats().
2. Add an efx_nic_type::describe_stats operation to get the number and
   names of statistics, implemented using efx_nic_describe_stats()
3. Change efx_nic_type::update_stats to store the core statistics
   (struct rtnl_link_stats64) or full statistics (array of u64) in a
   caller-provided buffer.  Use efx_nic_update_stats() to aid in the
   implementation.
4. Rename struct efx_ethtool_stat to struct efx_sw_stat_desc and
   EFX_ETHTOOL_NUM_STATS to EFX_ETHTOOL_SW_STAT_COUNT.
5. Remove efx_nic::mac_stats and struct efx_mac_stats.

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent b681e57c
Loading
Loading
Loading
Loading
+1 −26
Original line number Diff line number Diff line
@@ -1920,34 +1920,9 @@ static struct rtnl_link_stats64 *efx_net_stats(struct net_device *net_dev,
					       struct rtnl_link_stats64 *stats)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	struct efx_mac_stats *mac_stats = &efx->mac_stats;

	spin_lock_bh(&efx->stats_lock);

	efx->type->update_stats(efx);

	stats->rx_packets = mac_stats->rx_packets;
	stats->tx_packets = mac_stats->tx_packets;
	stats->rx_bytes = mac_stats->rx_bytes;
	stats->tx_bytes = mac_stats->tx_bytes;
	stats->rx_dropped = efx->n_rx_nodesc_drop_cnt;
	stats->multicast = mac_stats->rx_multicast;
	stats->collisions = mac_stats->tx_collision;
	stats->rx_length_errors = (mac_stats->rx_gtjumbo +
				   mac_stats->rx_length_error);
	stats->rx_crc_errors = mac_stats->rx_bad;
	stats->rx_frame_errors = mac_stats->rx_align_error;
	stats->rx_fifo_errors = mac_stats->rx_overflow;
	stats->rx_missed_errors = mac_stats->rx_missed;
	stats->tx_window_errors = mac_stats->tx_late_collision;

	stats->rx_errors = (stats->rx_length_errors +
			    stats->rx_crc_errors +
			    stats->rx_frame_errors +
			    mac_stats->rx_symbol_error);
	stats->tx_errors = (stats->tx_window_errors +
			    mac_stats->tx_bad);

	efx->type->update_stats(efx, NULL, stats);
	spin_unlock_bh(&efx->stats_lock);

	return stats;
+19 −98
Original line number Diff line number Diff line
@@ -19,10 +19,9 @@
#include "filter.h"
#include "nic.h"

struct efx_ethtool_stat {
struct efx_sw_stat_desc {
	const char *name;
	enum {
		EFX_ETHTOOL_STAT_SOURCE_mac_stats,
		EFX_ETHTOOL_STAT_SOURCE_nic,
		EFX_ETHTOOL_STAT_SOURCE_channel,
		EFX_ETHTOOL_STAT_SOURCE_tx_queue
@@ -31,7 +30,7 @@ struct efx_ethtool_stat {
	u64(*get_stat) (void *field); /* Reader function */
};

/* Initialiser for a struct #efx_ethtool_stat with type-checking */
/* Initialiser for a struct efx_sw_stat_desc with type-checking */
#define EFX_ETHTOOL_STAT(stat_name, source_name, field, field_type, \
				get_stat_function) {			\
	.name = #stat_name,						\
@@ -48,24 +47,11 @@ static u64 efx_get_uint_stat(void *field)
	return *(unsigned int *)field;
}

static u64 efx_get_u64_stat(void *field)
{
	return *(u64 *) field;
}

static u64 efx_get_atomic_stat(void *field)
{
	return atomic_read((atomic_t *) field);
}

#define EFX_ETHTOOL_U64_MAC_STAT(field)				\
	EFX_ETHTOOL_STAT(field, mac_stats, field,		\
			  u64, efx_get_u64_stat)

#define EFX_ETHTOOL_UINT_NIC_STAT(name)				\
	EFX_ETHTOOL_STAT(name, nic, n_##name,			\
			 unsigned int, efx_get_uint_stat)

#define EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(field)		\
	EFX_ETHTOOL_STAT(field, nic, field,			\
			 atomic_t, efx_get_atomic_stat)
@@ -78,72 +64,11 @@ static u64 efx_get_atomic_stat(void *field)
	EFX_ETHTOOL_STAT(tx_##field, tx_queue, field,		\
			 unsigned int, efx_get_uint_stat)

static const struct efx_ethtool_stat efx_ethtool_stats[] = {
	EFX_ETHTOOL_U64_MAC_STAT(tx_bytes),
	EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes),
	EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes),
	EFX_ETHTOOL_U64_MAC_STAT(tx_packets),
	EFX_ETHTOOL_U64_MAC_STAT(tx_bad),
	EFX_ETHTOOL_U64_MAC_STAT(tx_pause),
	EFX_ETHTOOL_U64_MAC_STAT(tx_control),
	EFX_ETHTOOL_U64_MAC_STAT(tx_unicast),
	EFX_ETHTOOL_U64_MAC_STAT(tx_multicast),
	EFX_ETHTOOL_U64_MAC_STAT(tx_broadcast),
	EFX_ETHTOOL_U64_MAC_STAT(tx_lt64),
	EFX_ETHTOOL_U64_MAC_STAT(tx_64),
	EFX_ETHTOOL_U64_MAC_STAT(tx_65_to_127),
	EFX_ETHTOOL_U64_MAC_STAT(tx_128_to_255),
	EFX_ETHTOOL_U64_MAC_STAT(tx_256_to_511),
	EFX_ETHTOOL_U64_MAC_STAT(tx_512_to_1023),
	EFX_ETHTOOL_U64_MAC_STAT(tx_1024_to_15xx),
	EFX_ETHTOOL_U64_MAC_STAT(tx_15xx_to_jumbo),
	EFX_ETHTOOL_U64_MAC_STAT(tx_gtjumbo),
	EFX_ETHTOOL_U64_MAC_STAT(tx_collision),
	EFX_ETHTOOL_U64_MAC_STAT(tx_single_collision),
	EFX_ETHTOOL_U64_MAC_STAT(tx_multiple_collision),
	EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_collision),
	EFX_ETHTOOL_U64_MAC_STAT(tx_deferred),
	EFX_ETHTOOL_U64_MAC_STAT(tx_late_collision),
	EFX_ETHTOOL_U64_MAC_STAT(tx_excessive_deferred),
	EFX_ETHTOOL_U64_MAC_STAT(tx_non_tcpudp),
	EFX_ETHTOOL_U64_MAC_STAT(tx_mac_src_error),
	EFX_ETHTOOL_U64_MAC_STAT(tx_ip_src_error),
static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
	EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts),
	EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers),
	EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets),
	EFX_ETHTOOL_UINT_TXQ_STAT(pushes),
	EFX_ETHTOOL_U64_MAC_STAT(rx_bytes),
	EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes),
	EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes),
	EFX_ETHTOOL_U64_MAC_STAT(rx_packets),
	EFX_ETHTOOL_U64_MAC_STAT(rx_good),
	EFX_ETHTOOL_U64_MAC_STAT(rx_bad),
	EFX_ETHTOOL_U64_MAC_STAT(rx_pause),
	EFX_ETHTOOL_U64_MAC_STAT(rx_control),
	EFX_ETHTOOL_U64_MAC_STAT(rx_unicast),
	EFX_ETHTOOL_U64_MAC_STAT(rx_multicast),
	EFX_ETHTOOL_U64_MAC_STAT(rx_broadcast),
	EFX_ETHTOOL_U64_MAC_STAT(rx_lt64),
	EFX_ETHTOOL_U64_MAC_STAT(rx_64),
	EFX_ETHTOOL_U64_MAC_STAT(rx_65_to_127),
	EFX_ETHTOOL_U64_MAC_STAT(rx_128_to_255),
	EFX_ETHTOOL_U64_MAC_STAT(rx_256_to_511),
	EFX_ETHTOOL_U64_MAC_STAT(rx_512_to_1023),
	EFX_ETHTOOL_U64_MAC_STAT(rx_1024_to_15xx),
	EFX_ETHTOOL_U64_MAC_STAT(rx_15xx_to_jumbo),
	EFX_ETHTOOL_U64_MAC_STAT(rx_gtjumbo),
	EFX_ETHTOOL_U64_MAC_STAT(rx_bad_lt64),
	EFX_ETHTOOL_U64_MAC_STAT(rx_bad_64_to_15xx),
	EFX_ETHTOOL_U64_MAC_STAT(rx_bad_15xx_to_jumbo),
	EFX_ETHTOOL_U64_MAC_STAT(rx_bad_gtjumbo),
	EFX_ETHTOOL_U64_MAC_STAT(rx_overflow),
	EFX_ETHTOOL_U64_MAC_STAT(rx_missed),
	EFX_ETHTOOL_U64_MAC_STAT(rx_false_carrier),
	EFX_ETHTOOL_U64_MAC_STAT(rx_symbol_error),
	EFX_ETHTOOL_U64_MAC_STAT(rx_align_error),
	EFX_ETHTOOL_U64_MAC_STAT(rx_length_error),
	EFX_ETHTOOL_U64_MAC_STAT(rx_internal_error),
	EFX_ETHTOOL_UINT_NIC_STAT(rx_nodesc_drop_cnt),
	EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
@@ -153,8 +78,7 @@ static const struct efx_ethtool_stat efx_ethtool_stats[] = {
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_nodesc_trunc),
};

/* Number of ethtool statistics */
#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats)
#define EFX_ETHTOOL_SW_STAT_COUNT ARRAY_SIZE(efx_sw_stat_desc)

#define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB

@@ -424,12 +348,14 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
static int efx_ethtool_get_sset_count(struct net_device *net_dev,
				      int string_set)
{
	struct efx_nic *efx = netdev_priv(net_dev);

	switch (string_set) {
	case ETH_SS_STATS:
		return EFX_ETHTOOL_NUM_STATS;
		return efx->type->describe_stats(efx, NULL) +
			EFX_ETHTOOL_SW_STAT_COUNT;
	case ETH_SS_TEST:
		return efx_ethtool_fill_self_tests(netdev_priv(net_dev),
						   NULL, NULL, NULL);
		return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL);
	default:
		return -EINVAL;
	}
@@ -443,9 +369,11 @@ static void efx_ethtool_get_strings(struct net_device *net_dev,

	switch (string_set) {
	case ETH_SS_STATS:
		for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++)
		strings += (efx->type->describe_stats(efx, strings) *
			    ETH_GSTRING_LEN);
		for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++)
			strlcpy(strings + i * ETH_GSTRING_LEN,
				efx_ethtool_stats[i].name, ETH_GSTRING_LEN);
				efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
		break;
	case ETH_SS_TEST:
		efx_ethtool_fill_self_tests(efx, NULL, strings, NULL);
@@ -461,27 +389,20 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
				  u64 *data)
{
	struct efx_nic *efx = netdev_priv(net_dev);
	struct efx_mac_stats *mac_stats = &efx->mac_stats;
	const struct efx_ethtool_stat *stat;
	const struct efx_sw_stat_desc *stat;
	struct efx_channel *channel;
	struct efx_tx_queue *tx_queue;
	int i;

	EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS);

	spin_lock_bh(&efx->stats_lock);

	/* Update MAC and NIC statistics */
	efx->type->update_stats(efx);
	/* Get NIC statistics */
	data += efx->type->update_stats(efx, data, NULL);

	/* Fill detailed statistics buffer */
	for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) {
		stat = &efx_ethtool_stats[i];
	/* Get software statistics */
	for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++) {
		stat = &efx_sw_stat_desc[i];
		switch (stat->source) {
		case EFX_ETHTOOL_STAT_SOURCE_mac_stats:
			data[i] = stat->get_stat((void *)mac_stats +
						 stat->offset);
			break;
		case EFX_ETHTOOL_STAT_SOURCE_nic:
			data[i] = stat->get_stat((void *)efx + stat->offset);
			break;
+119 −93
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@

/**************************************************************************
 *
 * MAC stats DMA format
 * NIC stats
 *
 **************************************************************************
 */
@@ -134,27 +134,67 @@
#define FALCON_XMAC_STATS_DMA_FLAG(efx)				\
	(*(u32 *)((efx)->stats_buffer.addr + XgDmaDone_offset))

#define FALCON_STAT_OFFSET(falcon_stat) EFX_VAL(falcon_stat, offset)
#define FALCON_STAT_WIDTH(falcon_stat) EFX_VAL(falcon_stat, WIDTH)

/* Retrieve statistic from statistics block */
#define FALCON_STAT(efx, falcon_stat, efx_stat) do {		\
	if (FALCON_STAT_WIDTH(falcon_stat) == 16)		\
		(efx)->mac_stats.efx_stat += le16_to_cpu(	\
			*((__force __le16 *)				\
			  (efx->stats_buffer.addr +		\
			   FALCON_STAT_OFFSET(falcon_stat))));	\
	else if (FALCON_STAT_WIDTH(falcon_stat) == 32)		\
		(efx)->mac_stats.efx_stat += le32_to_cpu(	\
			*((__force __le32 *)				\
			  (efx->stats_buffer.addr +		\
			   FALCON_STAT_OFFSET(falcon_stat))));	\
	else							\
		(efx)->mac_stats.efx_stat += le64_to_cpu(	\
			*((__force __le64 *)				\
			  (efx->stats_buffer.addr +		\
			   FALCON_STAT_OFFSET(falcon_stat))));	\
	} while (0)
#define FALCON_DMA_STAT(ext_name, hw_name)				\
	[FALCON_STAT_ ## ext_name] =					\
	{ #ext_name,							\
	  /* 48-bit stats are zero-padded to 64 on DMA */		\
	  hw_name ## _ ## WIDTH == 48 ? 64 : hw_name ## _ ## WIDTH,	\
	  hw_name ## _ ## offset }
#define FALCON_OTHER_STAT(ext_name)					\
	[FALCON_STAT_ ## ext_name] = { #ext_name, 0, 0 }

static const struct efx_hw_stat_desc falcon_stat_desc[FALCON_STAT_COUNT] = {
	FALCON_DMA_STAT(tx_bytes, XgTxOctets),
	FALCON_DMA_STAT(tx_packets, XgTxPkts),
	FALCON_DMA_STAT(tx_pause, XgTxPausePkts),
	FALCON_DMA_STAT(tx_control, XgTxControlPkts),
	FALCON_DMA_STAT(tx_unicast, XgTxUnicastPkts),
	FALCON_DMA_STAT(tx_multicast, XgTxMulticastPkts),
	FALCON_DMA_STAT(tx_broadcast, XgTxBroadcastPkts),
	FALCON_DMA_STAT(tx_lt64, XgTxUndersizePkts),
	FALCON_DMA_STAT(tx_64, XgTxPkts64Octets),
	FALCON_DMA_STAT(tx_65_to_127, XgTxPkts65to127Octets),
	FALCON_DMA_STAT(tx_128_to_255, XgTxPkts128to255Octets),
	FALCON_DMA_STAT(tx_256_to_511, XgTxPkts256to511Octets),
	FALCON_DMA_STAT(tx_512_to_1023, XgTxPkts512to1023Octets),
	FALCON_DMA_STAT(tx_1024_to_15xx, XgTxPkts1024to15xxOctets),
	FALCON_DMA_STAT(tx_15xx_to_jumbo, XgTxPkts1519toMaxOctets),
	FALCON_DMA_STAT(tx_gtjumbo, XgTxOversizePkts),
	FALCON_DMA_STAT(tx_non_tcpudp, XgTxNonTcpUdpPkt),
	FALCON_DMA_STAT(tx_mac_src_error, XgTxMacSrcErrPkt),
	FALCON_DMA_STAT(tx_ip_src_error, XgTxIpSrcErrPkt),
	FALCON_DMA_STAT(rx_bytes, XgRxOctets),
	FALCON_DMA_STAT(rx_good_bytes, XgRxOctetsOK),
	FALCON_OTHER_STAT(rx_bad_bytes),
	FALCON_DMA_STAT(rx_packets, XgRxPkts),
	FALCON_DMA_STAT(rx_good, XgRxPktsOK),
	FALCON_DMA_STAT(rx_bad, XgRxFCSerrorPkts),
	FALCON_DMA_STAT(rx_pause, XgRxPausePkts),
	FALCON_DMA_STAT(rx_control, XgRxControlPkts),
	FALCON_DMA_STAT(rx_unicast, XgRxUnicastPkts),
	FALCON_DMA_STAT(rx_multicast, XgRxMulticastPkts),
	FALCON_DMA_STAT(rx_broadcast, XgRxBroadcastPkts),
	FALCON_DMA_STAT(rx_lt64, XgRxUndersizePkts),
	FALCON_DMA_STAT(rx_64, XgRxPkts64Octets),
	FALCON_DMA_STAT(rx_65_to_127, XgRxPkts65to127Octets),
	FALCON_DMA_STAT(rx_128_to_255, XgRxPkts128to255Octets),
	FALCON_DMA_STAT(rx_256_to_511, XgRxPkts256to511Octets),
	FALCON_DMA_STAT(rx_512_to_1023, XgRxPkts512to1023Octets),
	FALCON_DMA_STAT(rx_1024_to_15xx, XgRxPkts1024to15xxOctets),
	FALCON_DMA_STAT(rx_15xx_to_jumbo, XgRxPkts15xxtoMaxOctets),
	FALCON_DMA_STAT(rx_gtjumbo, XgRxOversizePkts),
	FALCON_DMA_STAT(rx_bad_lt64, XgRxUndersizeFCSerrorPkts),
	FALCON_DMA_STAT(rx_bad_gtjumbo, XgRxJabberPkts),
	FALCON_DMA_STAT(rx_overflow, XgRxDropEvents),
	FALCON_DMA_STAT(rx_symbol_error, XgRxSymbolError),
	FALCON_DMA_STAT(rx_align_error, XgRxAlignError),
	FALCON_DMA_STAT(rx_length_error, XgRxLengthError),
	FALCON_DMA_STAT(rx_internal_error, XgRxInternalMACError),
	FALCON_OTHER_STAT(rx_nodesc_drop_cnt),
};
static const unsigned long falcon_stat_mask[] = {
	[0 ... BITS_TO_LONGS(FALCON_STAT_COUNT) - 1] = ~0UL,
};

/**************************************************************************
 *
@@ -1159,66 +1199,6 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx)
	return 0;
}

static void falcon_update_stats_xmac(struct efx_nic *efx)
{
	struct efx_mac_stats *mac_stats = &efx->mac_stats;

	/* Update MAC stats from DMAed values */
	FALCON_STAT(efx, XgRxOctets, rx_bytes);
	FALCON_STAT(efx, XgRxOctetsOK, rx_good_bytes);
	FALCON_STAT(efx, XgRxPkts, rx_packets);
	FALCON_STAT(efx, XgRxPktsOK, rx_good);
	FALCON_STAT(efx, XgRxBroadcastPkts, rx_broadcast);
	FALCON_STAT(efx, XgRxMulticastPkts, rx_multicast);
	FALCON_STAT(efx, XgRxUnicastPkts, rx_unicast);
	FALCON_STAT(efx, XgRxUndersizePkts, rx_lt64);
	FALCON_STAT(efx, XgRxOversizePkts, rx_gtjumbo);
	FALCON_STAT(efx, XgRxJabberPkts, rx_bad_gtjumbo);
	FALCON_STAT(efx, XgRxUndersizeFCSerrorPkts, rx_bad_lt64);
	FALCON_STAT(efx, XgRxDropEvents, rx_overflow);
	FALCON_STAT(efx, XgRxFCSerrorPkts, rx_bad);
	FALCON_STAT(efx, XgRxAlignError, rx_align_error);
	FALCON_STAT(efx, XgRxSymbolError, rx_symbol_error);
	FALCON_STAT(efx, XgRxInternalMACError, rx_internal_error);
	FALCON_STAT(efx, XgRxControlPkts, rx_control);
	FALCON_STAT(efx, XgRxPausePkts, rx_pause);
	FALCON_STAT(efx, XgRxPkts64Octets, rx_64);
	FALCON_STAT(efx, XgRxPkts65to127Octets, rx_65_to_127);
	FALCON_STAT(efx, XgRxPkts128to255Octets, rx_128_to_255);
	FALCON_STAT(efx, XgRxPkts256to511Octets, rx_256_to_511);
	FALCON_STAT(efx, XgRxPkts512to1023Octets, rx_512_to_1023);
	FALCON_STAT(efx, XgRxPkts1024to15xxOctets, rx_1024_to_15xx);
	FALCON_STAT(efx, XgRxPkts15xxtoMaxOctets, rx_15xx_to_jumbo);
	FALCON_STAT(efx, XgRxLengthError, rx_length_error);
	FALCON_STAT(efx, XgTxPkts, tx_packets);
	FALCON_STAT(efx, XgTxOctets, tx_bytes);
	FALCON_STAT(efx, XgTxMulticastPkts, tx_multicast);
	FALCON_STAT(efx, XgTxBroadcastPkts, tx_broadcast);
	FALCON_STAT(efx, XgTxUnicastPkts, tx_unicast);
	FALCON_STAT(efx, XgTxControlPkts, tx_control);
	FALCON_STAT(efx, XgTxPausePkts, tx_pause);
	FALCON_STAT(efx, XgTxPkts64Octets, tx_64);
	FALCON_STAT(efx, XgTxPkts65to127Octets, tx_65_to_127);
	FALCON_STAT(efx, XgTxPkts128to255Octets, tx_128_to_255);
	FALCON_STAT(efx, XgTxPkts256to511Octets, tx_256_to_511);
	FALCON_STAT(efx, XgTxPkts512to1023Octets, tx_512_to_1023);
	FALCON_STAT(efx, XgTxPkts1024to15xxOctets, tx_1024_to_15xx);
	FALCON_STAT(efx, XgTxPkts1519toMaxOctets, tx_15xx_to_jumbo);
	FALCON_STAT(efx, XgTxUndersizePkts, tx_lt64);
	FALCON_STAT(efx, XgTxOversizePkts, tx_gtjumbo);
	FALCON_STAT(efx, XgTxNonTcpUdpPkt, tx_non_tcpudp);
	FALCON_STAT(efx, XgTxMacSrcErrPkt, tx_mac_src_error);
	FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error);

	/* Update derived statistics */
	efx_update_diff_stat(&mac_stats->tx_good_bytes,
			     mac_stats->tx_bytes - mac_stats->tx_bad_bytes -
			     mac_stats->tx_control * 64);
	efx_update_diff_stat(&mac_stats->rx_bad_bytes,
			     mac_stats->rx_bytes - mac_stats->rx_good_bytes -
			     mac_stats->rx_control * 64);
}

static void falcon_poll_xmac(struct efx_nic *efx)
{
	struct falcon_nic_data *nic_data = efx->nic_data;
@@ -1422,7 +1402,9 @@ static void falcon_stats_complete(struct efx_nic *efx)
	nic_data->stats_pending = false;
	if (FALCON_XMAC_STATS_DMA_FLAG(efx)) {
		rmb(); /* read the done flag before the stats */
		falcon_update_stats_xmac(efx);
		efx_nic_update_stats(falcon_stat_desc, FALCON_STAT_COUNT,
				     falcon_stat_mask, nic_data->stats,
				     efx->stats_buffer.addr, true);
	} else {
		netif_err(efx, hw, efx->net_dev,
			  "timed out waiting for statistics\n");
@@ -2538,23 +2520,65 @@ static void falcon_remove_nic(struct efx_nic *efx)
	efx->nic_data = NULL;
}

static void falcon_update_nic_stats(struct efx_nic *efx)
static size_t falcon_describe_nic_stats(struct efx_nic *efx, u8 *names)
{
	return efx_nic_describe_stats(falcon_stat_desc, FALCON_STAT_COUNT,
				      falcon_stat_mask, names);
}

static size_t falcon_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
				      struct rtnl_link_stats64 *core_stats)
{
	struct falcon_nic_data *nic_data = efx->nic_data;
	u64 *stats = nic_data->stats;
	efx_oword_t cnt;

	if (nic_data->stats_disable_count)
		return;

	if (!nic_data->stats_disable_count) {
		efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP);
	efx->n_rx_nodesc_drop_cnt +=
		stats[FALCON_STAT_rx_nodesc_drop_cnt] +=
			EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT);

	if (nic_data->stats_pending && FALCON_XMAC_STATS_DMA_FLAG(efx)) {
		if (nic_data->stats_pending &&
		    FALCON_XMAC_STATS_DMA_FLAG(efx)) {
			nic_data->stats_pending = false;
			rmb(); /* read the done flag before the stats */
		falcon_update_stats_xmac(efx);
			efx_nic_update_stats(
				falcon_stat_desc, FALCON_STAT_COUNT,
				falcon_stat_mask,
				stats, efx->stats_buffer.addr, true);
		}

		/* Update derived statistic */
		efx_update_diff_stat(&stats[FALCON_STAT_rx_bad_bytes],
				     stats[FALCON_STAT_rx_bytes] -
				     stats[FALCON_STAT_rx_good_bytes] -
				     stats[FALCON_STAT_rx_control] * 64);
	}

	if (full_stats)
		memcpy(full_stats, stats, sizeof(u64) * FALCON_STAT_COUNT);

	if (core_stats) {
		core_stats->rx_packets = stats[FALCON_STAT_rx_packets];
		core_stats->tx_packets = stats[FALCON_STAT_tx_packets];
		core_stats->rx_bytes = stats[FALCON_STAT_rx_bytes];
		core_stats->tx_bytes = stats[FALCON_STAT_tx_bytes];
		core_stats->rx_dropped = stats[FALCON_STAT_rx_nodesc_drop_cnt];
		core_stats->multicast = stats[FALCON_STAT_rx_multicast];
		core_stats->rx_length_errors =
			stats[FALCON_STAT_rx_gtjumbo] +
			stats[FALCON_STAT_rx_length_error];
		core_stats->rx_crc_errors = stats[FALCON_STAT_rx_bad];
		core_stats->rx_frame_errors = stats[FALCON_STAT_rx_align_error];
		core_stats->rx_fifo_errors = stats[FALCON_STAT_rx_overflow];

		core_stats->rx_errors = (core_stats->rx_length_errors +
					 core_stats->rx_crc_errors +
					 core_stats->rx_frame_errors +
					 stats[FALCON_STAT_rx_symbol_error]);
	}

	return FALCON_STAT_COUNT;
}

void falcon_start_nic_stats(struct efx_nic *efx)
@@ -2643,6 +2667,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
	.fini_dmaq = efx_farch_fini_dmaq,
	.prepare_flush = falcon_prepare_flush,
	.finish_flush = efx_port_dummy_op_void,
	.describe_stats = falcon_describe_nic_stats,
	.update_stats = falcon_update_nic_stats,
	.start_stats = falcon_start_nic_stats,
	.stop_stats = falcon_stop_nic_stats,
@@ -2735,6 +2760,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
	.fini_dmaq = efx_farch_fini_dmaq,
	.prepare_flush = falcon_prepare_flush,
	.finish_flush = efx_port_dummy_op_void,
	.describe_stats = falcon_describe_nic_stats,
	.update_stats = falcon_update_nic_stats,
	.start_stats = falcon_start_nic_stats,
	.stop_stats = falcon_stop_nic_stats,
+1 −12
Original line number Diff line number Diff line
@@ -236,21 +236,10 @@ static int efx_mcdi_poll(struct efx_nic *efx)
 */
int efx_mcdi_poll_reboot(struct efx_nic *efx)
{
	int rc;

	if (!efx->mcdi)
		return 0;

	rc = efx->type->mcdi_poll_reboot(efx);
	if (!rc)
		return 0;

	/* MAC statistics have been cleared on the NIC; clear our copy
	 * so that efx_update_diff_stat() can continue to work.
	 */
	memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));

	return rc;
	return efx->type->mcdi_poll_reboot(efx);
}

static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
+18 −78
Original line number Diff line number Diff line
@@ -595,75 +595,17 @@ static inline bool efx_phy_mode_disabled(enum efx_phy_mode mode)
	return !!(mode & ~PHY_MODE_TX_DISABLED);
}

/*
 * Efx extended statistics
 *
 * Not all statistics are provided by all supported MACs.  The purpose
 * is this structure is to contain the raw statistics provided by each
 * MAC.
/**
 * struct efx_hw_stat_desc - Description of a hardware statistic
 * @name: Name of the statistic as visible through ethtool, or %NULL if
 *	it should not be exposed
 * @dma_width: Width in bits (0 for non-DMA statistics)
 * @offset: Offset within stats (ignored for non-DMA statistics)
 */
struct efx_mac_stats {
	u64 tx_bytes;
	u64 tx_good_bytes;
	u64 tx_bad_bytes;
	u64 tx_packets;
	u64 tx_bad;
	u64 tx_pause;
	u64 tx_control;
	u64 tx_unicast;
	u64 tx_multicast;
	u64 tx_broadcast;
	u64 tx_lt64;
	u64 tx_64;
	u64 tx_65_to_127;
	u64 tx_128_to_255;
	u64 tx_256_to_511;
	u64 tx_512_to_1023;
	u64 tx_1024_to_15xx;
	u64 tx_15xx_to_jumbo;
	u64 tx_gtjumbo;
	u64 tx_collision;
	u64 tx_single_collision;
	u64 tx_multiple_collision;
	u64 tx_excessive_collision;
	u64 tx_deferred;
	u64 tx_late_collision;
	u64 tx_excessive_deferred;
	u64 tx_non_tcpudp;
	u64 tx_mac_src_error;
	u64 tx_ip_src_error;
	u64 rx_bytes;
	u64 rx_good_bytes;
	u64 rx_bad_bytes;
	u64 rx_packets;
	u64 rx_good;
	u64 rx_bad;
	u64 rx_pause;
	u64 rx_control;
	u64 rx_unicast;
	u64 rx_multicast;
	u64 rx_broadcast;
	u64 rx_lt64;
	u64 rx_64;
	u64 rx_65_to_127;
	u64 rx_128_to_255;
	u64 rx_256_to_511;
	u64 rx_512_to_1023;
	u64 rx_1024_to_15xx;
	u64 rx_15xx_to_jumbo;
	u64 rx_gtjumbo;
	u64 rx_bad_lt64;
	u64 rx_bad_64_to_15xx;
	u64 rx_bad_15xx_to_jumbo;
	u64 rx_bad_gtjumbo;
	u64 rx_overflow;
	u64 rx_missed;
	u64 rx_false_carrier;
	u64 rx_symbol_error;
	u64 rx_align_error;
	u64 rx_length_error;
	u64 rx_internal_error;
	u64 rx_good_lt64;
struct efx_hw_stat_desc {
	const char *name;
	u16 dma_width;
	u16 offset;
};

/* Number of bits used in a multicast filter hash address */
@@ -795,12 +737,8 @@ struct vfdi_status;
 * @last_irq_cpu: Last CPU to handle a possible test interrupt.  This
 *	field is used by efx_test_interrupts() to verify that an
 *	interrupt has occurred.
 * @n_rx_nodesc_drop_cnt: RX no descriptor drop count
 * @mac_stats: MAC statistics. These include all statistics the MACs
 *	can provide.  Generic code converts these into a standard
 *	&struct net_device_stats.
 * @stats_lock: Statistics update lock. Serialises statistics fetches
 *	and access to @mac_stats.
 * @stats_lock: Statistics update lock. Must be held when calling
 *	efx_nic_type::{update,start,stop}_stats.
 *
 * This is stored in the private area of the &struct net_device.
 */
@@ -939,8 +877,6 @@ struct efx_nic {
	struct delayed_work monitor_work ____cacheline_aligned_in_smp;
	spinlock_t biu_lock;
	int last_irq_cpu;
	unsigned n_rx_nodesc_drop_cnt;
	struct efx_mac_stats mac_stats;
	spinlock_t stats_lock;
};

@@ -984,7 +920,9 @@ struct efx_mtd_partition {
 *	(for Falcon architecture)
 * @finish_flush: Clean up after flushing the DMA queues (for Falcon
 *	architecture)
 * @update_stats: Update statistics not provided by event handling
 * @describe_stats: Describe statistics for ethtool
 * @update_stats: Update statistics not provided by event handling.
 *	Either argument may be %NULL.
 * @start_stats: Start the regular fetching of statistics
 * @stop_stats: Stop the regular fetching of statistics
 * @set_id_led: Set state of identifying LED or revert to automatic function
@@ -1098,7 +1036,9 @@ struct efx_nic_type {
	int (*fini_dmaq)(struct efx_nic *efx);
	void (*prepare_flush)(struct efx_nic *efx);
	void (*finish_flush)(struct efx_nic *efx);
	void (*update_stats)(struct efx_nic *efx);
	size_t (*describe_stats)(struct efx_nic *efx, u8 *names);
	size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats,
			       struct rtnl_link_stats64 *core_stats);
	void (*start_stats)(struct efx_nic *efx);
	void (*stop_stats)(struct efx_nic *efx);
	void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode);
Loading