// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/*
* Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
*/
#include <linux/ethtool.h>
#include <linux/pci.h>
#include "ena_netdev.h"
#include "ena_xdp.h"
struct ena_stats {
char name[ETH_GSTRING_LEN];
int stat_offset;
};
struct ena_hw_metrics {
char name[ETH_GSTRING_LEN];
};
#define ENA_STAT_ENA_COM_ENTRY(stat) { \
.name = #stat, \
.stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \
}
#define ENA_STAT_ENTRY(stat, stat_type) { \
.name = #stat, \
.stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \
}
#define ENA_STAT_HW_ENTRY(stat, stat_type) { \
.name = #stat, \
.stat_offset = offsetof(struct ena_admin_##stat_type, stat) / sizeof(u64) \
}
#define ENA_STAT_RX_ENTRY(stat) \
ENA_STAT_ENTRY(stat, rx)
#define ENA_STAT_TX_ENTRY(stat) \
ENA_STAT_ENTRY(stat, tx)
#define ENA_STAT_GLOBAL_ENTRY(stat) \
ENA_STAT_ENTRY(stat, dev)
#define ENA_STAT_ENI_ENTRY(stat) \
ENA_STAT_HW_ENTRY(stat, eni_stats)
#define ENA_STAT_ENA_SRD_ENTRY(stat) \
ENA_STAT_HW_ENTRY(stat, ena_srd_stats)
#define ENA_STAT_ENA_SRD_MODE_ENTRY(stat) { \
.name = #stat, \
.stat_offset = offsetof(struct ena_admin_ena_srd_info, flags) / sizeof(u64) \
}
#define ENA_METRIC_ENI_ENTRY(stat) { \
.name = #stat \
}
static const struct ena_stats ena_stats_global_strings[] = {
ENA_STAT_GLOBAL_ENTRY(tx_timeout),
ENA_STAT_GLOBAL_ENTRY(suspend),
ENA_STAT_GLOBAL_ENTRY(resume),
ENA_STAT_GLOBAL_ENTRY(wd_expired),
ENA_STAT_GLOBAL_ENTRY(interface_up),
ENA_STAT_GLOBAL_ENTRY(interface_down),
ENA_STAT_GLOBAL_ENTRY(admin_q_pause),
ENA_STAT_GLOBAL_ENTRY(reset_fail),
};
/* A partial list of hw stats. Used when admin command
* with type ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS is not supported
*/
static const struct ena_stats ena_stats_eni_strings[] = {
ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded),
ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded),
ENA_STAT_ENI_ENTRY(pps_allowance_exceeded),
ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded),
ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded),
};
static const struct ena_hw_metrics ena_hw_stats_strings[] = {
ENA_METRIC_ENI_ENTRY(bw_in_allowance_exceeded),
ENA_METRIC_ENI_ENTRY(bw_out_allowance_exceeded),
ENA_METRIC_ENI_ENTRY(pps_allowance_exceeded),
ENA_METRIC_ENI_ENTRY(conntrack_allowance_exceeded),
ENA_METRIC_ENI_ENTRY(linklocal_allowance_exceeded),
ENA_METRIC_ENI_ENTRY(conntrack_allowance_available),
};
static const struct ena_stats ena_srd_info_strings[] = {
ENA_STAT_ENA_SRD_MODE_ENTRY(ena_srd_mode),
ENA_STAT_ENA_SRD_ENTRY(ena_srd_tx_pkts),
ENA_STAT_ENA_SRD_ENTRY(ena_srd_eligible_tx_pkts),
ENA_STAT_ENA_SRD_ENTRY(ena_srd_rx_pkts),
ENA_STAT_ENA_SRD_ENTRY(ena_srd_resource_utilization)
};
static const struct ena_stats ena_stats_tx_strings[] = {
ENA_STAT_TX_ENTRY(cnt),
ENA_STAT_TX_ENTRY(bytes),
ENA_STAT_TX_ENTRY(queue_stop),
ENA_STAT_TX_ENTRY(queue_wakeup),
ENA_STAT_TX_ENTRY(dma_mapping_err),
ENA_STAT_TX_ENTRY(linearize),
ENA_STAT_TX_ENTRY(linearize_failed),
ENA_STAT_TX_ENTRY(napi_comp),
ENA_STAT_TX_ENTRY(tx_poll),
ENA_STAT_TX_ENTRY(doorbells),
ENA_STAT_TX_ENTRY(prepare_ctx_err),
ENA_STAT_TX_ENTRY(bad_req_id),
ENA_STAT_TX_ENTRY(llq_buffer_copy),
ENA_STAT_TX_ENTRY(missed_tx),
ENA_STAT_TX_ENTRY(unmask_interrupt),
};
static const struct ena_stats ena_stats_rx_strings[] = {
ENA_STAT_RX_ENTRY(cnt),
ENA_STAT_RX_ENTRY(bytes),
ENA_STAT_RX_ENTRY(rx_copybreak_pkt),
ENA_STAT_RX_ENTRY(csum_good),
ENA_STAT_RX_ENTRY(refil_partial),
ENA_STAT_RX_ENTRY(csum_bad),
ENA_STAT_RX_ENTRY(page_alloc_fail),
ENA_STAT_RX_ENTRY(skb_alloc_fail),
ENA_STAT_RX_ENTRY(dma_mapping_err),
ENA_STAT_RX_ENTRY(bad_desc_num),
ENA_STAT_RX_ENTRY(bad_req_id),
ENA_STAT_RX_ENTRY(empty_rx_ring),
ENA_STAT_RX_ENTRY(csum_unchecked),
ENA_STAT_RX_ENTRY(xdp_aborted),
ENA_STAT_RX_ENTRY(xdp_drop),
ENA_STAT_RX_ENTRY(xdp_pass),
ENA_STAT_RX_ENTRY(xdp_tx),
ENA_STAT_RX_ENTRY(xdp_invalid),
ENA_STAT_RX_ENTRY(xdp_redirect),
};
static const struct ena_stats ena_stats_ena_com_strings[] = {
ENA_STAT_ENA_COM_ENTRY(aborted_cmd),
ENA_STAT_ENA_COM_ENTRY(submitted_cmd),
ENA_STAT_ENA_COM_ENTRY(completed_cmd),
ENA_STAT_ENA_COM_ENTRY(out_of_space),
ENA_STAT_ENA_COM_ENTRY(no_completion),
};
#define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings)
#define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings)
#define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings)
#define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings)
#define ENA_STATS_ARRAY_ENI ARRAY_SIZE(ena_stats_eni_strings)
#define ENA_STATS_ARRAY_ENA_SRD ARRAY_SIZE(ena_srd_info_strings)
#define ENA_METRICS_ARRAY_ENI ARRAY_SIZE(ena_hw_stats_strings)
static void ena_safe_update_stat(u64 *src, u64 *dst,
struct u64_stats_sync *syncp)
{
unsigned int start;
do {
start = u64_stats_fetch_begin(syncp);
*(dst) = *src;
} while (u64_stats_fetch_retry(syncp, start));
}
static void ena_metrics_stats(struct ena_adapter *adapter, u64 **data)
{
struct ena_com_dev *dev = adapter->ena_dev;
const struct ena_stats *ena_stats