mirror of
https://github.com/torvalds/linux.git
synced 2024-12-16 08:02:17 +00:00
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: Ben Hutchings <bhutchings@solarflare.com>
This commit is contained in:
parent
b681e57c38
commit
cd0ecc9a6d
@ -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,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;
|
||||
|
@ -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)
|
||||
#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 }
|
||||
|
||||
/* 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)
|
||||
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,
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -429,3 +429,86 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* efx_nic_describe_stats - Describe supported statistics for ethtool
|
||||
* @desc: Array of &struct efx_hw_stat_desc describing the statistics
|
||||
* @count: Length of the @desc array
|
||||
* @mask: Bitmask of which elements of @desc are enabled
|
||||
* @names: Buffer to copy names to, or %NULL. The names are copied
|
||||
* starting at intervals of %ETH_GSTRING_LEN bytes.
|
||||
*
|
||||
* Returns the number of visible statistics, i.e. the number of set
|
||||
* bits in the first @count bits of @mask for which a name is defined.
|
||||
*/
|
||||
size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
|
||||
const unsigned long *mask, u8 *names)
|
||||
{
|
||||
size_t visible = 0;
|
||||
size_t index;
|
||||
|
||||
for_each_set_bit(index, mask, count) {
|
||||
if (desc[index].name) {
|
||||
if (names) {
|
||||
strlcpy(names, desc[index].name,
|
||||
ETH_GSTRING_LEN);
|
||||
names += ETH_GSTRING_LEN;
|
||||
}
|
||||
++visible;
|
||||
}
|
||||
}
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* efx_nic_update_stats - Convert statistics DMA buffer to array of u64
|
||||
* @desc: Array of &struct efx_hw_stat_desc describing the DMA buffer
|
||||
* layout. DMA widths of 0, 16, 32 and 64 are supported; where
|
||||
* the width is specified as 0 the corresponding element of
|
||||
* @stats is not updated.
|
||||
* @count: Length of the @desc array
|
||||
* @mask: Bitmask of which elements of @desc are enabled
|
||||
* @stats: Buffer to update with the converted statistics. The length
|
||||
* of this array must be at least the number of set bits in the
|
||||
* first @count bits of @mask.
|
||||
* @dma_buf: DMA buffer containing hardware statistics
|
||||
* @accumulate: If set, the converted values will be added rather than
|
||||
* directly stored to the corresponding elements of @stats
|
||||
*/
|
||||
void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
|
||||
const unsigned long *mask,
|
||||
u64 *stats, const void *dma_buf, bool accumulate)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
for_each_set_bit(index, mask, count) {
|
||||
if (desc[index].dma_width) {
|
||||
const void *addr = dma_buf + desc[index].offset;
|
||||
u64 val;
|
||||
|
||||
switch (desc[index].dma_width) {
|
||||
case 16:
|
||||
val = le16_to_cpup((__le16 *)addr);
|
||||
break;
|
||||
case 32:
|
||||
val = le32_to_cpup((__le32 *)addr);
|
||||
break;
|
||||
case 64:
|
||||
val = le64_to_cpup((__le64 *)addr);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (accumulate)
|
||||
*stats += val;
|
||||
else
|
||||
*stats = val;
|
||||
}
|
||||
|
||||
++stats;
|
||||
}
|
||||
}
|
||||
|
@ -191,10 +191,62 @@ static inline bool falcon_spi_present(const struct falcon_spi_device *spi)
|
||||
return spi->size != 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
FALCON_STAT_tx_bytes,
|
||||
FALCON_STAT_tx_packets,
|
||||
FALCON_STAT_tx_pause,
|
||||
FALCON_STAT_tx_control,
|
||||
FALCON_STAT_tx_unicast,
|
||||
FALCON_STAT_tx_multicast,
|
||||
FALCON_STAT_tx_broadcast,
|
||||
FALCON_STAT_tx_lt64,
|
||||
FALCON_STAT_tx_64,
|
||||
FALCON_STAT_tx_65_to_127,
|
||||
FALCON_STAT_tx_128_to_255,
|
||||
FALCON_STAT_tx_256_to_511,
|
||||
FALCON_STAT_tx_512_to_1023,
|
||||
FALCON_STAT_tx_1024_to_15xx,
|
||||
FALCON_STAT_tx_15xx_to_jumbo,
|
||||
FALCON_STAT_tx_gtjumbo,
|
||||
FALCON_STAT_tx_non_tcpudp,
|
||||
FALCON_STAT_tx_mac_src_error,
|
||||
FALCON_STAT_tx_ip_src_error,
|
||||
FALCON_STAT_rx_bytes,
|
||||
FALCON_STAT_rx_good_bytes,
|
||||
FALCON_STAT_rx_bad_bytes,
|
||||
FALCON_STAT_rx_packets,
|
||||
FALCON_STAT_rx_good,
|
||||
FALCON_STAT_rx_bad,
|
||||
FALCON_STAT_rx_pause,
|
||||
FALCON_STAT_rx_control,
|
||||
FALCON_STAT_rx_unicast,
|
||||
FALCON_STAT_rx_multicast,
|
||||
FALCON_STAT_rx_broadcast,
|
||||
FALCON_STAT_rx_lt64,
|
||||
FALCON_STAT_rx_64,
|
||||
FALCON_STAT_rx_65_to_127,
|
||||
FALCON_STAT_rx_128_to_255,
|
||||
FALCON_STAT_rx_256_to_511,
|
||||
FALCON_STAT_rx_512_to_1023,
|
||||
FALCON_STAT_rx_1024_to_15xx,
|
||||
FALCON_STAT_rx_15xx_to_jumbo,
|
||||
FALCON_STAT_rx_gtjumbo,
|
||||
FALCON_STAT_rx_bad_lt64,
|
||||
FALCON_STAT_rx_bad_gtjumbo,
|
||||
FALCON_STAT_rx_overflow,
|
||||
FALCON_STAT_rx_symbol_error,
|
||||
FALCON_STAT_rx_align_error,
|
||||
FALCON_STAT_rx_length_error,
|
||||
FALCON_STAT_rx_internal_error,
|
||||
FALCON_STAT_rx_nodesc_drop_cnt,
|
||||
FALCON_STAT_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* struct falcon_nic_data - Falcon NIC state
|
||||
* @pci_dev2: Secondary function of Falcon A
|
||||
* @board: Board state and functions
|
||||
* @stats: Hardware statistics
|
||||
* @stats_disable_count: Nest count for disabling statistics fetches
|
||||
* @stats_pending: Is there a pending DMA of MAC statistics.
|
||||
* @stats_timer: A timer for regularly fetching MAC statistics.
|
||||
@ -207,6 +259,7 @@ static inline bool falcon_spi_present(const struct falcon_spi_device *spi)
|
||||
struct falcon_nic_data {
|
||||
struct pci_dev *pci_dev2;
|
||||
struct falcon_board board;
|
||||
u64 stats[FALCON_STAT_COUNT];
|
||||
unsigned int stats_disable_count;
|
||||
bool stats_pending;
|
||||
struct timer_list stats_timer;
|
||||
@ -223,12 +276,75 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
|
||||
return &data->board;
|
||||
}
|
||||
|
||||
enum {
|
||||
SIENA_STAT_tx_bytes,
|
||||
SIENA_STAT_tx_good_bytes,
|
||||
SIENA_STAT_tx_bad_bytes,
|
||||
SIENA_STAT_tx_packets,
|
||||
SIENA_STAT_tx_bad,
|
||||
SIENA_STAT_tx_pause,
|
||||
SIENA_STAT_tx_control,
|
||||
SIENA_STAT_tx_unicast,
|
||||
SIENA_STAT_tx_multicast,
|
||||
SIENA_STAT_tx_broadcast,
|
||||
SIENA_STAT_tx_lt64,
|
||||
SIENA_STAT_tx_64,
|
||||
SIENA_STAT_tx_65_to_127,
|
||||
SIENA_STAT_tx_128_to_255,
|
||||
SIENA_STAT_tx_256_to_511,
|
||||
SIENA_STAT_tx_512_to_1023,
|
||||
SIENA_STAT_tx_1024_to_15xx,
|
||||
SIENA_STAT_tx_15xx_to_jumbo,
|
||||
SIENA_STAT_tx_gtjumbo,
|
||||
SIENA_STAT_tx_collision,
|
||||
SIENA_STAT_tx_single_collision,
|
||||
SIENA_STAT_tx_multiple_collision,
|
||||
SIENA_STAT_tx_excessive_collision,
|
||||
SIENA_STAT_tx_deferred,
|
||||
SIENA_STAT_tx_late_collision,
|
||||
SIENA_STAT_tx_excessive_deferred,
|
||||
SIENA_STAT_tx_non_tcpudp,
|
||||
SIENA_STAT_tx_mac_src_error,
|
||||
SIENA_STAT_tx_ip_src_error,
|
||||
SIENA_STAT_rx_bytes,
|
||||
SIENA_STAT_rx_good_bytes,
|
||||
SIENA_STAT_rx_bad_bytes,
|
||||
SIENA_STAT_rx_packets,
|
||||
SIENA_STAT_rx_good,
|
||||
SIENA_STAT_rx_bad,
|
||||
SIENA_STAT_rx_pause,
|
||||
SIENA_STAT_rx_control,
|
||||
SIENA_STAT_rx_unicast,
|
||||
SIENA_STAT_rx_multicast,
|
||||
SIENA_STAT_rx_broadcast,
|
||||
SIENA_STAT_rx_lt64,
|
||||
SIENA_STAT_rx_64,
|
||||
SIENA_STAT_rx_65_to_127,
|
||||
SIENA_STAT_rx_128_to_255,
|
||||
SIENA_STAT_rx_256_to_511,
|
||||
SIENA_STAT_rx_512_to_1023,
|
||||
SIENA_STAT_rx_1024_to_15xx,
|
||||
SIENA_STAT_rx_15xx_to_jumbo,
|
||||
SIENA_STAT_rx_gtjumbo,
|
||||
SIENA_STAT_rx_bad_gtjumbo,
|
||||
SIENA_STAT_rx_overflow,
|
||||
SIENA_STAT_rx_false_carrier,
|
||||
SIENA_STAT_rx_symbol_error,
|
||||
SIENA_STAT_rx_align_error,
|
||||
SIENA_STAT_rx_length_error,
|
||||
SIENA_STAT_rx_internal_error,
|
||||
SIENA_STAT_rx_nodesc_drop_cnt,
|
||||
SIENA_STAT_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* struct siena_nic_data - Siena NIC state
|
||||
* @wol_filter_id: Wake-on-LAN packet filter id
|
||||
* @stats: Hardware statistics
|
||||
*/
|
||||
struct siena_nic_data {
|
||||
int wol_filter_id;
|
||||
u64 stats[SIENA_STAT_COUNT];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -533,6 +649,14 @@ extern int efx_farch_test_registers(struct efx_nic *efx,
|
||||
extern size_t efx_nic_get_regs_len(struct efx_nic *efx);
|
||||
extern void efx_nic_get_regs(struct efx_nic *efx, void *buf);
|
||||
|
||||
extern size_t
|
||||
efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
|
||||
const unsigned long *mask, u8 *names);
|
||||
extern void
|
||||
efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
|
||||
const unsigned long *mask,
|
||||
u64 *stats, const void *dma_buf, bool accumulate);
|
||||
|
||||
#define EFX_MAX_FLUSH_TIME 5000
|
||||
|
||||
extern void efx_farch_generate_event(struct efx_nic *efx, unsigned int evq,
|
||||
|
@ -380,117 +380,160 @@ static void siena_remove_nic(struct efx_nic *efx)
|
||||
efx_mcdi_fini(efx);
|
||||
}
|
||||
|
||||
#define SIENA_DMA_STAT(ext_name, mcdi_name) \
|
||||
[SIENA_STAT_ ## ext_name] = \
|
||||
{ #ext_name, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
|
||||
#define SIENA_OTHER_STAT(ext_name) \
|
||||
[SIENA_STAT_ ## ext_name] = { #ext_name, 0, 0 }
|
||||
|
||||
static const struct efx_hw_stat_desc siena_stat_desc[SIENA_STAT_COUNT] = {
|
||||
SIENA_DMA_STAT(tx_bytes, TX_BYTES),
|
||||
SIENA_OTHER_STAT(tx_good_bytes),
|
||||
SIENA_DMA_STAT(tx_bad_bytes, TX_BAD_BYTES),
|
||||
SIENA_DMA_STAT(tx_packets, TX_PKTS),
|
||||
SIENA_DMA_STAT(tx_bad, TX_BAD_FCS_PKTS),
|
||||
SIENA_DMA_STAT(tx_pause, TX_PAUSE_PKTS),
|
||||
SIENA_DMA_STAT(tx_control, TX_CONTROL_PKTS),
|
||||
SIENA_DMA_STAT(tx_unicast, TX_UNICAST_PKTS),
|
||||
SIENA_DMA_STAT(tx_multicast, TX_MULTICAST_PKTS),
|
||||
SIENA_DMA_STAT(tx_broadcast, TX_BROADCAST_PKTS),
|
||||
SIENA_DMA_STAT(tx_lt64, TX_LT64_PKTS),
|
||||
SIENA_DMA_STAT(tx_64, TX_64_PKTS),
|
||||
SIENA_DMA_STAT(tx_65_to_127, TX_65_TO_127_PKTS),
|
||||
SIENA_DMA_STAT(tx_128_to_255, TX_128_TO_255_PKTS),
|
||||
SIENA_DMA_STAT(tx_256_to_511, TX_256_TO_511_PKTS),
|
||||
SIENA_DMA_STAT(tx_512_to_1023, TX_512_TO_1023_PKTS),
|
||||
SIENA_DMA_STAT(tx_1024_to_15xx, TX_1024_TO_15XX_PKTS),
|
||||
SIENA_DMA_STAT(tx_15xx_to_jumbo, TX_15XX_TO_JUMBO_PKTS),
|
||||
SIENA_DMA_STAT(tx_gtjumbo, TX_GTJUMBO_PKTS),
|
||||
SIENA_OTHER_STAT(tx_collision),
|
||||
SIENA_DMA_STAT(tx_single_collision, TX_SINGLE_COLLISION_PKTS),
|
||||
SIENA_DMA_STAT(tx_multiple_collision, TX_MULTIPLE_COLLISION_PKTS),
|
||||
SIENA_DMA_STAT(tx_excessive_collision, TX_EXCESSIVE_COLLISION_PKTS),
|
||||
SIENA_DMA_STAT(tx_deferred, TX_DEFERRED_PKTS),
|
||||
SIENA_DMA_STAT(tx_late_collision, TX_LATE_COLLISION_PKTS),
|
||||
SIENA_DMA_STAT(tx_excessive_deferred, TX_EXCESSIVE_DEFERRED_PKTS),
|
||||
SIENA_DMA_STAT(tx_non_tcpudp, TX_NON_TCPUDP_PKTS),
|
||||
SIENA_DMA_STAT(tx_mac_src_error, TX_MAC_SRC_ERR_PKTS),
|
||||
SIENA_DMA_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS),
|
||||
SIENA_DMA_STAT(rx_bytes, RX_BYTES),
|
||||
SIENA_OTHER_STAT(rx_good_bytes),
|
||||
SIENA_DMA_STAT(rx_bad_bytes, RX_BAD_BYTES),
|
||||
SIENA_DMA_STAT(rx_packets, RX_PKTS),
|
||||
SIENA_DMA_STAT(rx_good, RX_GOOD_PKTS),
|
||||
SIENA_DMA_STAT(rx_bad, RX_BAD_FCS_PKTS),
|
||||
SIENA_DMA_STAT(rx_pause, RX_PAUSE_PKTS),
|
||||
SIENA_DMA_STAT(rx_control, RX_CONTROL_PKTS),
|
||||
SIENA_DMA_STAT(rx_unicast, RX_UNICAST_PKTS),
|
||||
SIENA_DMA_STAT(rx_multicast, RX_MULTICAST_PKTS),
|
||||
SIENA_DMA_STAT(rx_broadcast, RX_BROADCAST_PKTS),
|
||||
SIENA_DMA_STAT(rx_lt64, RX_UNDERSIZE_PKTS),
|
||||
SIENA_DMA_STAT(rx_64, RX_64_PKTS),
|
||||
SIENA_DMA_STAT(rx_65_to_127, RX_65_TO_127_PKTS),
|
||||
SIENA_DMA_STAT(rx_128_to_255, RX_128_TO_255_PKTS),
|
||||
SIENA_DMA_STAT(rx_256_to_511, RX_256_TO_511_PKTS),
|
||||
SIENA_DMA_STAT(rx_512_to_1023, RX_512_TO_1023_PKTS),
|
||||
SIENA_DMA_STAT(rx_1024_to_15xx, RX_1024_TO_15XX_PKTS),
|
||||
SIENA_DMA_STAT(rx_15xx_to_jumbo, RX_15XX_TO_JUMBO_PKTS),
|
||||
SIENA_DMA_STAT(rx_gtjumbo, RX_GTJUMBO_PKTS),
|
||||
SIENA_DMA_STAT(rx_bad_gtjumbo, RX_JABBER_PKTS),
|
||||
SIENA_DMA_STAT(rx_overflow, RX_OVERFLOW_PKTS),
|
||||
SIENA_DMA_STAT(rx_false_carrier, RX_FALSE_CARRIER_PKTS),
|
||||
SIENA_DMA_STAT(rx_symbol_error, RX_SYMBOL_ERROR_PKTS),
|
||||
SIENA_DMA_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS),
|
||||
SIENA_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS),
|
||||
SIENA_DMA_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS),
|
||||
SIENA_DMA_STAT(rx_nodesc_drop_cnt, RX_NODESC_DROPS),
|
||||
};
|
||||
static const unsigned long siena_stat_mask[] = {
|
||||
[0 ... BITS_TO_LONGS(SIENA_STAT_COUNT) - 1] = ~0UL,
|
||||
};
|
||||
|
||||
static size_t siena_describe_nic_stats(struct efx_nic *efx, u8 *names)
|
||||
{
|
||||
return efx_nic_describe_stats(siena_stat_desc, SIENA_STAT_COUNT,
|
||||
siena_stat_mask, names);
|
||||
}
|
||||
|
||||
static int siena_try_update_nic_stats(struct efx_nic *efx)
|
||||
{
|
||||
struct siena_nic_data *nic_data = efx->nic_data;
|
||||
u64 *stats = nic_data->stats;
|
||||
__le64 *dma_stats;
|
||||
struct efx_mac_stats *mac_stats;
|
||||
__le64 generation_start, generation_end;
|
||||
|
||||
mac_stats = &efx->mac_stats;
|
||||
dma_stats = efx->stats_buffer.addr;
|
||||
|
||||
generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
|
||||
if (generation_end == EFX_MC_STATS_GENERATION_INVALID)
|
||||
return 0;
|
||||
rmb();
|
||||
|
||||
#define MAC_STAT(M, D) \
|
||||
mac_stats->M = le64_to_cpu(dma_stats[MC_CMD_MAC_ ## D])
|
||||
|
||||
MAC_STAT(tx_bytes, TX_BYTES);
|
||||
MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
|
||||
efx_update_diff_stat(&mac_stats->tx_good_bytes,
|
||||
mac_stats->tx_bytes - mac_stats->tx_bad_bytes);
|
||||
MAC_STAT(tx_packets, TX_PKTS);
|
||||
MAC_STAT(tx_bad, TX_BAD_FCS_PKTS);
|
||||
MAC_STAT(tx_pause, TX_PAUSE_PKTS);
|
||||
MAC_STAT(tx_control, TX_CONTROL_PKTS);
|
||||
MAC_STAT(tx_unicast, TX_UNICAST_PKTS);
|
||||
MAC_STAT(tx_multicast, TX_MULTICAST_PKTS);
|
||||
MAC_STAT(tx_broadcast, TX_BROADCAST_PKTS);
|
||||
MAC_STAT(tx_lt64, TX_LT64_PKTS);
|
||||
MAC_STAT(tx_64, TX_64_PKTS);
|
||||
MAC_STAT(tx_65_to_127, TX_65_TO_127_PKTS);
|
||||
MAC_STAT(tx_128_to_255, TX_128_TO_255_PKTS);
|
||||
MAC_STAT(tx_256_to_511, TX_256_TO_511_PKTS);
|
||||
MAC_STAT(tx_512_to_1023, TX_512_TO_1023_PKTS);
|
||||
MAC_STAT(tx_1024_to_15xx, TX_1024_TO_15XX_PKTS);
|
||||
MAC_STAT(tx_15xx_to_jumbo, TX_15XX_TO_JUMBO_PKTS);
|
||||
MAC_STAT(tx_gtjumbo, TX_GTJUMBO_PKTS);
|
||||
mac_stats->tx_collision = 0;
|
||||
MAC_STAT(tx_single_collision, TX_SINGLE_COLLISION_PKTS);
|
||||
MAC_STAT(tx_multiple_collision, TX_MULTIPLE_COLLISION_PKTS);
|
||||
MAC_STAT(tx_excessive_collision, TX_EXCESSIVE_COLLISION_PKTS);
|
||||
MAC_STAT(tx_deferred, TX_DEFERRED_PKTS);
|
||||
MAC_STAT(tx_late_collision, TX_LATE_COLLISION_PKTS);
|
||||
mac_stats->tx_collision = (mac_stats->tx_single_collision +
|
||||
mac_stats->tx_multiple_collision +
|
||||
mac_stats->tx_excessive_collision +
|
||||
mac_stats->tx_late_collision);
|
||||
MAC_STAT(tx_excessive_deferred, TX_EXCESSIVE_DEFERRED_PKTS);
|
||||
MAC_STAT(tx_non_tcpudp, TX_NON_TCPUDP_PKTS);
|
||||
MAC_STAT(tx_mac_src_error, TX_MAC_SRC_ERR_PKTS);
|
||||
MAC_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS);
|
||||
MAC_STAT(rx_bytes, RX_BYTES);
|
||||
MAC_STAT(rx_bad_bytes, RX_BAD_BYTES);
|
||||
efx_update_diff_stat(&mac_stats->rx_good_bytes,
|
||||
mac_stats->rx_bytes - mac_stats->rx_bad_bytes);
|
||||
MAC_STAT(rx_packets, RX_PKTS);
|
||||
MAC_STAT(rx_good, RX_GOOD_PKTS);
|
||||
MAC_STAT(rx_bad, RX_BAD_FCS_PKTS);
|
||||
MAC_STAT(rx_pause, RX_PAUSE_PKTS);
|
||||
MAC_STAT(rx_control, RX_CONTROL_PKTS);
|
||||
MAC_STAT(rx_unicast, RX_UNICAST_PKTS);
|
||||
MAC_STAT(rx_multicast, RX_MULTICAST_PKTS);
|
||||
MAC_STAT(rx_broadcast, RX_BROADCAST_PKTS);
|
||||
MAC_STAT(rx_lt64, RX_UNDERSIZE_PKTS);
|
||||
MAC_STAT(rx_64, RX_64_PKTS);
|
||||
MAC_STAT(rx_65_to_127, RX_65_TO_127_PKTS);
|
||||
MAC_STAT(rx_128_to_255, RX_128_TO_255_PKTS);
|
||||
MAC_STAT(rx_256_to_511, RX_256_TO_511_PKTS);
|
||||
MAC_STAT(rx_512_to_1023, RX_512_TO_1023_PKTS);
|
||||
MAC_STAT(rx_1024_to_15xx, RX_1024_TO_15XX_PKTS);
|
||||
MAC_STAT(rx_15xx_to_jumbo, RX_15XX_TO_JUMBO_PKTS);
|
||||
MAC_STAT(rx_gtjumbo, RX_GTJUMBO_PKTS);
|
||||
mac_stats->rx_bad_lt64 = 0;
|
||||
mac_stats->rx_bad_64_to_15xx = 0;
|
||||
mac_stats->rx_bad_15xx_to_jumbo = 0;
|
||||
MAC_STAT(rx_bad_gtjumbo, RX_JABBER_PKTS);
|
||||
MAC_STAT(rx_overflow, RX_OVERFLOW_PKTS);
|
||||
mac_stats->rx_missed = 0;
|
||||
MAC_STAT(rx_false_carrier, RX_FALSE_CARRIER_PKTS);
|
||||
MAC_STAT(rx_symbol_error, RX_SYMBOL_ERROR_PKTS);
|
||||
MAC_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS);
|
||||
MAC_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS);
|
||||
MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS);
|
||||
mac_stats->rx_good_lt64 = 0;
|
||||
|
||||
efx->n_rx_nodesc_drop_cnt =
|
||||
le64_to_cpu(dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]);
|
||||
|
||||
#undef MAC_STAT
|
||||
|
||||
efx_nic_update_stats(siena_stat_desc, SIENA_STAT_COUNT, siena_stat_mask,
|
||||
stats, efx->stats_buffer.addr, false);
|
||||
rmb();
|
||||
generation_start = dma_stats[MC_CMD_MAC_GENERATION_START];
|
||||
if (generation_end != generation_start)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Update derived statistics */
|
||||
efx_update_diff_stat(&stats[SIENA_STAT_tx_good_bytes],
|
||||
stats[SIENA_STAT_tx_bytes] -
|
||||
stats[SIENA_STAT_tx_bad_bytes]);
|
||||
stats[SIENA_STAT_tx_collision] =
|
||||
stats[SIENA_STAT_tx_single_collision] +
|
||||
stats[SIENA_STAT_tx_multiple_collision] +
|
||||
stats[SIENA_STAT_tx_excessive_collision] +
|
||||
stats[SIENA_STAT_tx_late_collision];
|
||||
efx_update_diff_stat(&stats[SIENA_STAT_rx_good_bytes],
|
||||
stats[SIENA_STAT_rx_bytes] -
|
||||
stats[SIENA_STAT_rx_bad_bytes]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void siena_update_nic_stats(struct efx_nic *efx)
|
||||
static size_t siena_update_nic_stats(struct efx_nic *efx, u64 *full_stats,
|
||||
struct rtnl_link_stats64 *core_stats)
|
||||
{
|
||||
struct siena_nic_data *nic_data = efx->nic_data;
|
||||
u64 *stats = nic_data->stats;
|
||||
int retry;
|
||||
|
||||
/* If we're unlucky enough to read statistics wduring the DMA, wait
|
||||
* up to 10ms for it to finish (typically takes <500us) */
|
||||
for (retry = 0; retry < 100; ++retry) {
|
||||
if (siena_try_update_nic_stats(efx) == 0)
|
||||
return;
|
||||
break;
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
/* Use the old values instead */
|
||||
if (full_stats)
|
||||
memcpy(full_stats, stats, sizeof(u64) * SIENA_STAT_COUNT);
|
||||
|
||||
if (core_stats) {
|
||||
core_stats->rx_packets = stats[SIENA_STAT_rx_packets];
|
||||
core_stats->tx_packets = stats[SIENA_STAT_tx_packets];
|
||||
core_stats->rx_bytes = stats[SIENA_STAT_rx_bytes];
|
||||
core_stats->tx_bytes = stats[SIENA_STAT_tx_bytes];
|
||||
core_stats->rx_dropped = stats[SIENA_STAT_rx_nodesc_drop_cnt];
|
||||
core_stats->multicast = stats[SIENA_STAT_rx_multicast];
|
||||
core_stats->collisions = stats[SIENA_STAT_tx_collision];
|
||||
core_stats->rx_length_errors =
|
||||
stats[SIENA_STAT_rx_gtjumbo] +
|
||||
stats[SIENA_STAT_rx_length_error];
|
||||
core_stats->rx_crc_errors = stats[SIENA_STAT_rx_bad];
|
||||
core_stats->rx_frame_errors = stats[SIENA_STAT_rx_align_error];
|
||||
core_stats->rx_fifo_errors = stats[SIENA_STAT_rx_overflow];
|
||||
core_stats->tx_window_errors =
|
||||
stats[SIENA_STAT_tx_late_collision];
|
||||
|
||||
core_stats->rx_errors = (core_stats->rx_length_errors +
|
||||
core_stats->rx_crc_errors +
|
||||
core_stats->rx_frame_errors +
|
||||
stats[SIENA_STAT_rx_symbol_error]);
|
||||
core_stats->tx_errors = (core_stats->tx_window_errors +
|
||||
stats[SIENA_STAT_tx_bad]);
|
||||
}
|
||||
|
||||
return SIENA_STAT_COUNT;
|
||||
}
|
||||
|
||||
static int siena_mac_reconfigure(struct efx_nic *efx)
|
||||
@ -652,6 +695,7 @@ static void siena_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf,
|
||||
|
||||
static int siena_mcdi_poll_reboot(struct efx_nic *efx)
|
||||
{
|
||||
struct siena_nic_data *nic_data = efx->nic_data;
|
||||
unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx);
|
||||
efx_dword_t reg;
|
||||
u32 value;
|
||||
@ -665,6 +709,12 @@ static int siena_mcdi_poll_reboot(struct efx_nic *efx)
|
||||
EFX_ZERO_DWORD(reg);
|
||||
efx_writed(efx, ®, addr);
|
||||
|
||||
/* MAC statistics have been cleared on the NIC; clear the local
|
||||
* copies that we update with efx_update_diff_stat().
|
||||
*/
|
||||
nic_data->stats[SIENA_STAT_tx_good_bytes] = 0;
|
||||
nic_data->stats[SIENA_STAT_rx_good_bytes] = 0;
|
||||
|
||||
if (value == MC_STATUS_DWORD_ASSERT)
|
||||
return -EINTR;
|
||||
else
|
||||
@ -830,6 +880,7 @@ const struct efx_nic_type siena_a0_nic_type = {
|
||||
.fini_dmaq = efx_farch_fini_dmaq,
|
||||
.prepare_flush = siena_prepare_flush,
|
||||
.finish_flush = siena_finish_flush,
|
||||
.describe_stats = siena_describe_nic_stats,
|
||||
.update_stats = siena_update_nic_stats,
|
||||
.start_stats = efx_mcdi_mac_start_stats,
|
||||
.stop_stats = efx_mcdi_mac_stop_stats,
|
||||
|
Loading…
Reference in New Issue
Block a user