Merge branch 'ena-driver-metrics-changes'
David Arinzon says: ==================== ENA driver metrics changes This patchset contains an introduction of new metrics available to ENA users. ==================== Link: https://patch.msgid.link/20240909084704.13856-1-darinzon@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -230,6 +230,11 @@ per-queue stats) from the device.
|
||||
|
||||
In addition the driver logs the stats to syslog upon device reset.
|
||||
|
||||
On supported instance types, the statistics will also include the
|
||||
ENA Express data (fields prefixed with `ena_srd`). For a complete
|
||||
documentation of ENA Express data refer to
|
||||
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ena-express.html#ena-express-monitor
|
||||
|
||||
MTU
|
||||
===
|
||||
|
||||
|
||||
@@ -7,6 +7,21 @@
|
||||
|
||||
#define ENA_ADMIN_RSS_KEY_PARTS 10
|
||||
|
||||
#define ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK 0x3F
|
||||
#define ENA_ADMIN_CUSTOMER_METRICS_MIN_SUPPORT_MASK 0x1F
|
||||
|
||||
/* customer metrics - in correlation with
|
||||
* ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK
|
||||
*/
|
||||
enum ena_admin_customer_metrics_id {
|
||||
ENA_ADMIN_BW_IN_ALLOWANCE_EXCEEDED = 0,
|
||||
ENA_ADMIN_BW_OUT_ALLOWANCE_EXCEEDED = 1,
|
||||
ENA_ADMIN_PPS_ALLOWANCE_EXCEEDED = 2,
|
||||
ENA_ADMIN_CONNTRACK_ALLOWANCE_EXCEEDED = 3,
|
||||
ENA_ADMIN_LINKLOCAL_ALLOWANCE_EXCEEDED = 4,
|
||||
ENA_ADMIN_CONNTRACK_ALLOWANCE_AVAILABLE = 5,
|
||||
};
|
||||
|
||||
enum ena_admin_aq_opcode {
|
||||
ENA_ADMIN_CREATE_SQ = 1,
|
||||
ENA_ADMIN_DESTROY_SQ = 2,
|
||||
@@ -51,6 +66,9 @@ enum ena_admin_aq_feature_id {
|
||||
/* device capabilities */
|
||||
enum ena_admin_aq_caps_id {
|
||||
ENA_ADMIN_ENI_STATS = 0,
|
||||
/* ENA SRD customer metrics */
|
||||
ENA_ADMIN_ENA_SRD_INFO = 1,
|
||||
ENA_ADMIN_CUSTOMER_METRICS = 2,
|
||||
};
|
||||
|
||||
enum ena_admin_placement_policy_type {
|
||||
@@ -99,6 +117,9 @@ enum ena_admin_get_stats_type {
|
||||
ENA_ADMIN_GET_STATS_TYPE_EXTENDED = 1,
|
||||
/* extra HW stats for specific network interface */
|
||||
ENA_ADMIN_GET_STATS_TYPE_ENI = 2,
|
||||
/* extra HW stats for ENA SRD */
|
||||
ENA_ADMIN_GET_STATS_TYPE_ENA_SRD = 3,
|
||||
ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS = 4,
|
||||
};
|
||||
|
||||
enum ena_admin_get_stats_scope {
|
||||
@@ -106,6 +127,16 @@ enum ena_admin_get_stats_scope {
|
||||
ENA_ADMIN_ETH_TRAFFIC = 1,
|
||||
};
|
||||
|
||||
/* ENA SRD configuration for ENI */
|
||||
enum ena_admin_ena_srd_flags {
|
||||
/* Feature enabled */
|
||||
ENA_ADMIN_ENA_SRD_ENABLED = BIT(0),
|
||||
/* UDP support enabled */
|
||||
ENA_ADMIN_ENA_SRD_UDP_ENABLED = BIT(1),
|
||||
/* Bypass Rx UDP ordering */
|
||||
ENA_ADMIN_ENA_SRD_UDP_ORDERING_BYPASS_ENABLED = BIT(2),
|
||||
};
|
||||
|
||||
struct ena_admin_aq_common_desc {
|
||||
/* 11:0 : command_id
|
||||
* 15:12 : reserved12
|
||||
@@ -363,6 +394,9 @@ struct ena_admin_aq_get_stats_cmd {
|
||||
* stats of other device
|
||||
*/
|
||||
u16 device_id;
|
||||
|
||||
/* a bitmap representing the requested metric values */
|
||||
u64 requested_metrics;
|
||||
};
|
||||
|
||||
/* Basic Statistics Command. */
|
||||
@@ -419,6 +453,40 @@ struct ena_admin_eni_stats {
|
||||
u64 linklocal_allowance_exceeded;
|
||||
};
|
||||
|
||||
struct ena_admin_ena_srd_stats {
|
||||
/* Number of packets transmitted over ENA SRD */
|
||||
u64 ena_srd_tx_pkts;
|
||||
|
||||
/* Number of packets transmitted or could have been
|
||||
* transmitted over ENA SRD
|
||||
*/
|
||||
u64 ena_srd_eligible_tx_pkts;
|
||||
|
||||
/* Number of packets received over ENA SRD */
|
||||
u64 ena_srd_rx_pkts;
|
||||
|
||||
/* Percentage of the ENA SRD resources that is in use */
|
||||
u64 ena_srd_resource_utilization;
|
||||
};
|
||||
|
||||
/* ENA SRD Statistics Command */
|
||||
struct ena_admin_ena_srd_info {
|
||||
/* ENA SRD configuration bitmap. See ena_admin_ena_srd_flags for
|
||||
* details
|
||||
*/
|
||||
u64 flags;
|
||||
|
||||
struct ena_admin_ena_srd_stats ena_srd_stats;
|
||||
};
|
||||
|
||||
/* Customer Metrics Command. */
|
||||
struct ena_admin_customer_metrics {
|
||||
/* A bitmap representing the reported customer metrics according to
|
||||
* the order they are reported
|
||||
*/
|
||||
u64 reported_metrics;
|
||||
};
|
||||
|
||||
struct ena_admin_acq_get_stats_resp {
|
||||
struct ena_admin_acq_common_desc acq_common_desc;
|
||||
|
||||
@@ -428,6 +496,10 @@ struct ena_admin_acq_get_stats_resp {
|
||||
struct ena_admin_basic_stats basic_stats;
|
||||
|
||||
struct ena_admin_eni_stats eni_stats;
|
||||
|
||||
struct ena_admin_ena_srd_info ena_srd_info;
|
||||
|
||||
struct ena_admin_customer_metrics customer_metrics;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
@@ -1881,6 +1881,56 @@ int ena_com_get_link_params(struct ena_com_dev *ena_dev,
|
||||
return ena_com_get_feature(ena_dev, resp, ENA_ADMIN_LINK_CONFIG, 0);
|
||||
}
|
||||
|
||||
static int ena_get_dev_stats(struct ena_com_dev *ena_dev,
|
||||
struct ena_com_stats_ctx *ctx,
|
||||
enum ena_admin_get_stats_type type)
|
||||
{
|
||||
struct ena_admin_acq_get_stats_resp *get_resp = &ctx->get_resp;
|
||||
struct ena_admin_aq_get_stats_cmd *get_cmd = &ctx->get_cmd;
|
||||
struct ena_com_admin_queue *admin_queue;
|
||||
int ret;
|
||||
|
||||
admin_queue = &ena_dev->admin_queue;
|
||||
|
||||
get_cmd->aq_common_descriptor.opcode = ENA_ADMIN_GET_STATS;
|
||||
get_cmd->aq_common_descriptor.flags = 0;
|
||||
get_cmd->type = type;
|
||||
|
||||
ret = ena_com_execute_admin_command(admin_queue,
|
||||
(struct ena_admin_aq_entry *)get_cmd,
|
||||
sizeof(*get_cmd),
|
||||
(struct ena_admin_acq_entry *)get_resp,
|
||||
sizeof(*get_resp));
|
||||
|
||||
if (unlikely(ret))
|
||||
netdev_err(ena_dev->net_device, "Failed to get stats. error: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ena_com_set_supported_customer_metrics(struct ena_com_dev *ena_dev)
|
||||
{
|
||||
struct ena_customer_metrics *customer_metrics;
|
||||
struct ena_com_stats_ctx ctx;
|
||||
int ret;
|
||||
|
||||
customer_metrics = &ena_dev->customer_metrics;
|
||||
if (!ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) {
|
||||
customer_metrics->supported_metrics = ENA_ADMIN_CUSTOMER_METRICS_MIN_SUPPORT_MASK;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&ctx, 0x0, sizeof(ctx));
|
||||
ctx.get_cmd.requested_metrics = ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK;
|
||||
ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS);
|
||||
if (likely(ret == 0))
|
||||
customer_metrics->supported_metrics =
|
||||
ctx.get_resp.u.customer_metrics.reported_metrics;
|
||||
else
|
||||
netdev_err(ena_dev->net_device,
|
||||
"Failed to query customer metrics support. error: %d\n", ret);
|
||||
}
|
||||
|
||||
int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
|
||||
struct ena_com_dev_get_features_ctx *get_feat_ctx)
|
||||
{
|
||||
@@ -1960,6 +2010,8 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
|
||||
else
|
||||
return rc;
|
||||
|
||||
ena_com_set_supported_customer_metrics(ena_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2104,33 +2156,6 @@ int ena_com_dev_reset(struct ena_com_dev *ena_dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ena_get_dev_stats(struct ena_com_dev *ena_dev,
|
||||
struct ena_com_stats_ctx *ctx,
|
||||
enum ena_admin_get_stats_type type)
|
||||
{
|
||||
struct ena_admin_aq_get_stats_cmd *get_cmd = &ctx->get_cmd;
|
||||
struct ena_admin_acq_get_stats_resp *get_resp = &ctx->get_resp;
|
||||
struct ena_com_admin_queue *admin_queue;
|
||||
int ret;
|
||||
|
||||
admin_queue = &ena_dev->admin_queue;
|
||||
|
||||
get_cmd->aq_common_descriptor.opcode = ENA_ADMIN_GET_STATS;
|
||||
get_cmd->aq_common_descriptor.flags = 0;
|
||||
get_cmd->type = type;
|
||||
|
||||
ret = ena_com_execute_admin_command(admin_queue,
|
||||
(struct ena_admin_aq_entry *)get_cmd,
|
||||
sizeof(*get_cmd),
|
||||
(struct ena_admin_acq_entry *)get_resp,
|
||||
sizeof(*get_resp));
|
||||
|
||||
if (unlikely(ret))
|
||||
netdev_err(ena_dev->net_device, "Failed to get stats. error: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ena_com_get_eni_stats(struct ena_com_dev *ena_dev,
|
||||
struct ena_admin_eni_stats *stats)
|
||||
{
|
||||
@@ -2152,6 +2177,27 @@ int ena_com_get_eni_stats(struct ena_com_dev *ena_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ena_com_get_ena_srd_info(struct ena_com_dev *ena_dev,
|
||||
struct ena_admin_ena_srd_info *info)
|
||||
{
|
||||
struct ena_com_stats_ctx ctx;
|
||||
int ret;
|
||||
|
||||
if (!ena_com_get_cap(ena_dev, ENA_ADMIN_ENA_SRD_INFO)) {
|
||||
netdev_err(ena_dev->net_device, "Capability %d isn't supported\n",
|
||||
ENA_ADMIN_ENA_SRD_INFO);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
memset(&ctx, 0x0, sizeof(ctx));
|
||||
ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_ENA_SRD);
|
||||
if (likely(ret == 0))
|
||||
memcpy(info, &ctx.get_resp.u.ena_srd_info,
|
||||
sizeof(ctx.get_resp.u.ena_srd_info));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
|
||||
struct ena_admin_basic_stats *stats)
|
||||
{
|
||||
@@ -2167,6 +2213,50 @@ int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ena_com_get_customer_metrics(struct ena_com_dev *ena_dev, char *buffer, u32 len)
|
||||
{
|
||||
struct ena_admin_aq_get_stats_cmd *get_cmd;
|
||||
struct ena_com_stats_ctx ctx;
|
||||
int ret;
|
||||
|
||||
if (unlikely(len > ena_dev->customer_metrics.buffer_len)) {
|
||||
netdev_err(ena_dev->net_device,
|
||||
"Invalid buffer size %u. The given buffer is too big.\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ena_com_get_cap(ena_dev, ENA_ADMIN_CUSTOMER_METRICS)) {
|
||||
netdev_err(ena_dev->net_device, "Capability %d not supported.\n",
|
||||
ENA_ADMIN_CUSTOMER_METRICS);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!ena_dev->customer_metrics.supported_metrics) {
|
||||
netdev_err(ena_dev->net_device, "No supported customer metrics.\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
get_cmd = &ctx.get_cmd;
|
||||
memset(&ctx, 0x0, sizeof(ctx));
|
||||
ret = ena_com_mem_addr_set(ena_dev,
|
||||
&get_cmd->u.control_buffer.address,
|
||||
ena_dev->customer_metrics.buffer_dma_addr);
|
||||
if (unlikely(ret)) {
|
||||
netdev_err(ena_dev->net_device, "Memory address set failed.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
get_cmd->u.control_buffer.length = ena_dev->customer_metrics.buffer_len;
|
||||
get_cmd->requested_metrics = ena_dev->customer_metrics.supported_metrics;
|
||||
ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_CUSTOMER_METRICS);
|
||||
if (likely(ret == 0))
|
||||
memcpy(buffer, ena_dev->customer_metrics.buffer_virt_addr, len);
|
||||
else
|
||||
netdev_err(ena_dev->net_device, "Failed to get customer metrics. error: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ena_com_set_dev_mtu(struct ena_com_dev *ena_dev, u32 mtu)
|
||||
{
|
||||
struct ena_com_admin_queue *admin_queue;
|
||||
@@ -2706,6 +2796,24 @@ int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ena_com_allocate_customer_metrics_buffer(struct ena_com_dev *ena_dev)
|
||||
{
|
||||
struct ena_customer_metrics *customer_metrics = &ena_dev->customer_metrics;
|
||||
|
||||
customer_metrics->buffer_len = ENA_CUSTOMER_METRICS_BUFFER_SIZE;
|
||||
customer_metrics->buffer_virt_addr = NULL;
|
||||
|
||||
customer_metrics->buffer_virt_addr =
|
||||
dma_alloc_coherent(ena_dev->dmadev, customer_metrics->buffer_len,
|
||||
&customer_metrics->buffer_dma_addr, GFP_KERNEL);
|
||||
if (!customer_metrics->buffer_virt_addr) {
|
||||
customer_metrics->buffer_len = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ena_com_delete_host_info(struct ena_com_dev *ena_dev)
|
||||
{
|
||||
struct ena_host_attribute *host_attr = &ena_dev->host_attr;
|
||||
@@ -2728,6 +2836,19 @@ void ena_com_delete_debug_area(struct ena_com_dev *ena_dev)
|
||||
}
|
||||
}
|
||||
|
||||
void ena_com_delete_customer_metrics_buffer(struct ena_com_dev *ena_dev)
|
||||
{
|
||||
struct ena_customer_metrics *customer_metrics = &ena_dev->customer_metrics;
|
||||
|
||||
if (customer_metrics->buffer_virt_addr) {
|
||||
dma_free_coherent(ena_dev->dmadev, customer_metrics->buffer_len,
|
||||
customer_metrics->buffer_virt_addr,
|
||||
customer_metrics->buffer_dma_addr);
|
||||
customer_metrics->buffer_virt_addr = NULL;
|
||||
customer_metrics->buffer_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ena_com_set_host_attributes(struct ena_com_dev *ena_dev)
|
||||
{
|
||||
struct ena_host_attribute *host_attr = &ena_dev->host_attr;
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
#define ADMIN_CQ_SIZE(depth) ((depth) * sizeof(struct ena_admin_acq_entry))
|
||||
#define ADMIN_AENQ_SIZE(depth) ((depth) * sizeof(struct ena_admin_aenq_entry))
|
||||
|
||||
#define ENA_CUSTOMER_METRICS_BUFFER_SIZE 512
|
||||
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/* ENA adaptive interrupt moderation settings */
|
||||
@@ -278,6 +280,16 @@ struct ena_rss {
|
||||
|
||||
};
|
||||
|
||||
struct ena_customer_metrics {
|
||||
/* in correlation with ENA_ADMIN_CUSTOMER_METRICS_SUPPORT_MASK
|
||||
* and ena_admin_customer_metrics_id
|
||||
*/
|
||||
u64 supported_metrics;
|
||||
dma_addr_t buffer_dma_addr;
|
||||
void *buffer_virt_addr;
|
||||
u32 buffer_len;
|
||||
};
|
||||
|
||||
struct ena_host_attribute {
|
||||
/* Debug area */
|
||||
u8 *debug_area_virt_addr;
|
||||
@@ -327,6 +339,8 @@ struct ena_com_dev {
|
||||
struct ena_intr_moder_entry *intr_moder_tbl;
|
||||
|
||||
struct ena_com_llq_info llq_info;
|
||||
|
||||
struct ena_customer_metrics customer_metrics;
|
||||
};
|
||||
|
||||
struct ena_com_dev_get_features_ctx {
|
||||
@@ -595,6 +609,24 @@ int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
|
||||
int ena_com_get_eni_stats(struct ena_com_dev *ena_dev,
|
||||
struct ena_admin_eni_stats *stats);
|
||||
|
||||
/* ena_com_get_ena_srd_info - Get ENA SRD network interface statistics
|
||||
* @ena_dev: ENA communication layer struct
|
||||
* @info: ena srd stats and flags
|
||||
*
|
||||
* @return: 0 on Success and negative value otherwise.
|
||||
*/
|
||||
int ena_com_get_ena_srd_info(struct ena_com_dev *ena_dev,
|
||||
struct ena_admin_ena_srd_info *info);
|
||||
|
||||
/* ena_com_get_customer_metrics - Get customer metrics for network interface
|
||||
* @ena_dev: ENA communication layer struct
|
||||
* @buffer: buffer for returned customer metrics
|
||||
* @len: size of the buffer
|
||||
*
|
||||
* @return: 0 on Success and negative value otherwise.
|
||||
*/
|
||||
int ena_com_get_customer_metrics(struct ena_com_dev *ena_dev, char *buffer, u32 len);
|
||||
|
||||
/* ena_com_set_dev_mtu - Configure the device mtu.
|
||||
* @ena_dev: ENA communication layer struct
|
||||
* @mtu: mtu value
|
||||
@@ -805,6 +837,13 @@ int ena_com_allocate_host_info(struct ena_com_dev *ena_dev);
|
||||
int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev,
|
||||
u32 debug_area_size);
|
||||
|
||||
/* ena_com_allocate_customer_metrics_buffer - Allocate customer metrics resources.
|
||||
* @ena_dev: ENA communication layer struct
|
||||
*
|
||||
* @return: 0 on Success and negative value otherwise.
|
||||
*/
|
||||
int ena_com_allocate_customer_metrics_buffer(struct ena_com_dev *ena_dev);
|
||||
|
||||
/* ena_com_delete_debug_area - Free the debug area resources.
|
||||
* @ena_dev: ENA communication layer struct
|
||||
*
|
||||
@@ -819,6 +858,13 @@ void ena_com_delete_debug_area(struct ena_com_dev *ena_dev);
|
||||
*/
|
||||
void ena_com_delete_host_info(struct ena_com_dev *ena_dev);
|
||||
|
||||
/* ena_com_delete_customer_metrics_buffer - Free the customer metrics resources.
|
||||
* @ena_dev: ENA communication layer struct
|
||||
*
|
||||
* Free the allocated customer metrics area.
|
||||
*/
|
||||
void ena_com_delete_customer_metrics_buffer(struct ena_com_dev *ena_dev);
|
||||
|
||||
/* ena_com_set_host_attributes - Update the device with the host
|
||||
* attributes (debug area and host info) base address.
|
||||
* @ena_dev: ENA communication layer struct
|
||||
@@ -975,6 +1021,28 @@ static inline bool ena_com_get_cap(struct ena_com_dev *ena_dev,
|
||||
return !!(ena_dev->capabilities & BIT(cap_id));
|
||||
}
|
||||
|
||||
/* ena_com_get_customer_metric_support - query whether device supports a given customer metric.
|
||||
* @ena_dev: ENA communication layer struct
|
||||
* @metric_id: enum value representing the customer metric
|
||||
*
|
||||
* @return - true if customer metric is supported or false otherwise
|
||||
*/
|
||||
static inline bool ena_com_get_customer_metric_support(struct ena_com_dev *ena_dev,
|
||||
enum ena_admin_customer_metrics_id metric_id)
|
||||
{
|
||||
return !!(ena_dev->customer_metrics.supported_metrics & BIT(metric_id));
|
||||
}
|
||||
|
||||
/* ena_com_get_customer_metric_count - return the number of supported customer metrics.
|
||||
* @ena_dev: ENA communication layer struct
|
||||
*
|
||||
* @return - the number of supported customer metrics
|
||||
*/
|
||||
static inline int ena_com_get_customer_metric_count(struct ena_com_dev *ena_dev)
|
||||
{
|
||||
return hweight64(ena_dev->customer_metrics.supported_metrics);
|
||||
}
|
||||
|
||||
/* ena_com_update_intr_reg - Prepare interrupt register
|
||||
* @intr_reg: interrupt register to update.
|
||||
* @rx_delay_interval: Rx interval in usecs
|
||||
|
||||
@@ -14,6 +14,10 @@ struct ena_stats {
|
||||
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) \
|
||||
@@ -41,6 +45,18 @@ struct ena_stats {
|
||||
#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),
|
||||
@@ -52,6 +68,9 @@ static const struct ena_stats ena_stats_global_strings[] = {
|
||||
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),
|
||||
@@ -60,6 +79,23 @@ static const struct ena_stats ena_stats_eni_strings[] = {
|
||||
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),
|
||||
@@ -112,7 +148,9 @@ static const struct ena_stats ena_stats_ena_com_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(adapter) ARRAY_SIZE(ena_stats_eni_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)
|
||||
@@ -125,6 +163,57 @@ static void ena_safe_update_stat(u64 *src, u64 *dst,
|
||||
} 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;
|
||||
u64 *ptr;
|
||||
int i;
|
||||
|
||||
if (ena_com_get_cap(dev, ENA_ADMIN_CUSTOMER_METRICS)) {
|
||||
u32 supported_metrics_count;
|
||||
int len;
|
||||
|
||||
supported_metrics_count = ena_com_get_customer_metric_count(dev);
|
||||
len = supported_metrics_count * sizeof(u64);
|
||||
|
||||
/* Fill the data buffer, and advance its pointer */
|
||||
ena_com_get_customer_metrics(dev, (char *)(*data), len);
|
||||
(*data) += supported_metrics_count;
|
||||
|
||||
} else if (ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS)) {
|
||||
ena_com_get_eni_stats(dev, &adapter->eni_stats);
|
||||
/* Updating regardless of rc - once we told ethtool how many stats we have
|
||||
* it will print that much stats. We can't leave holes in the stats
|
||||
*/
|
||||
for (i = 0; i < ENA_STATS_ARRAY_ENI; i++) {
|
||||
ena_stats = &ena_stats_eni_strings[i];
|
||||
|
||||
ptr = (u64 *)&adapter->eni_stats +
|
||||
ena_stats->stat_offset;
|
||||
|
||||
ena_safe_update_stat(ptr, (*data)++, &adapter->syncp);
|
||||
}
|
||||
}
|
||||
|
||||
if (ena_com_get_cap(dev, ENA_ADMIN_ENA_SRD_INFO)) {
|
||||
ena_com_get_ena_srd_info(dev, &adapter->ena_srd_info);
|
||||
/* Get ENA SRD mode */
|
||||
ptr = (u64 *)&adapter->ena_srd_info;
|
||||
ena_safe_update_stat(ptr, (*data)++, &adapter->syncp);
|
||||
for (i = 1; i < ENA_STATS_ARRAY_ENA_SRD; i++) {
|
||||
ena_stats = &ena_srd_info_strings[i];
|
||||
/* Wrapped within an outer struct - need to accommodate an
|
||||
* additional offset of the ENA SRD mode that was already processed
|
||||
*/
|
||||
ptr = (u64 *)&adapter->ena_srd_info +
|
||||
ena_stats->stat_offset + 1;
|
||||
|
||||
ena_safe_update_stat(ptr, (*data)++, &adapter->syncp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ena_queue_stats(struct ena_adapter *adapter, u64 **data)
|
||||
{
|
||||
const struct ena_stats *ena_stats;
|
||||
@@ -179,7 +268,7 @@ static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data)
|
||||
|
||||
static void ena_get_stats(struct ena_adapter *adapter,
|
||||
u64 *data,
|
||||
bool eni_stats_needed)
|
||||
bool hw_stats_needed)
|
||||
{
|
||||
const struct ena_stats *ena_stats;
|
||||
u64 *ptr;
|
||||
@@ -193,17 +282,8 @@ static void ena_get_stats(struct ena_adapter *adapter,
|
||||
ena_safe_update_stat(ptr, data++, &adapter->syncp);
|
||||
}
|
||||
|
||||
if (eni_stats_needed) {
|
||||
ena_update_hw_stats(adapter);
|
||||
for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
|
||||
ena_stats = &ena_stats_eni_strings[i];
|
||||
|
||||
ptr = (u64 *)&adapter->eni_stats +
|
||||
ena_stats->stat_offset;
|
||||
|
||||
ena_safe_update_stat(ptr, data++, &adapter->syncp);
|
||||
}
|
||||
}
|
||||
if (hw_stats_needed)
|
||||
ena_metrics_stats(adapter, &data);
|
||||
|
||||
ena_queue_stats(adapter, &data);
|
||||
ena_dev_admin_queue_stats(adapter, &data);
|
||||
@@ -214,9 +294,8 @@ static void ena_get_ethtool_stats(struct net_device *netdev,
|
||||
u64 *data)
|
||||
{
|
||||
struct ena_adapter *adapter = netdev_priv(netdev);
|
||||
struct ena_com_dev *dev = adapter->ena_dev;
|
||||
|
||||
ena_get_stats(adapter, data, ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS));
|
||||
ena_get_stats(adapter, data, true);
|
||||
}
|
||||
|
||||
static int ena_get_sw_stats_count(struct ena_adapter *adapter)
|
||||
@@ -228,9 +307,17 @@ static int ena_get_sw_stats_count(struct ena_adapter *adapter)
|
||||
|
||||
static int ena_get_hw_stats_count(struct ena_adapter *adapter)
|
||||
{
|
||||
bool supported = ena_com_get_cap(adapter->ena_dev, ENA_ADMIN_ENI_STATS);
|
||||
struct ena_com_dev *dev = adapter->ena_dev;
|
||||
int count;
|
||||
|
||||
return ENA_STATS_ARRAY_ENI(adapter) * supported;
|
||||
count = ENA_STATS_ARRAY_ENA_SRD * ena_com_get_cap(dev, ENA_ADMIN_ENA_SRD_INFO);
|
||||
|
||||
if (ena_com_get_cap(dev, ENA_ADMIN_CUSTOMER_METRICS))
|
||||
count += ena_com_get_customer_metric_count(dev);
|
||||
else if (ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS))
|
||||
count += ENA_STATS_ARRAY_ENI;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int ena_get_sset_count(struct net_device *netdev, int sset)
|
||||
@@ -246,6 +333,35 @@ int ena_get_sset_count(struct net_device *netdev, int sset)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void ena_metrics_stats_strings(struct ena_adapter *adapter, u8 **data)
|
||||
{
|
||||
struct ena_com_dev *dev = adapter->ena_dev;
|
||||
const struct ena_hw_metrics *ena_metrics;
|
||||
const struct ena_stats *ena_stats;
|
||||
int i;
|
||||
|
||||
if (ena_com_get_cap(dev, ENA_ADMIN_CUSTOMER_METRICS)) {
|
||||
for (i = 0; i < ENA_METRICS_ARRAY_ENI; i++) {
|
||||
if (ena_com_get_customer_metric_support(dev, i)) {
|
||||
ena_metrics = &ena_hw_stats_strings[i];
|
||||
ethtool_puts(data, ena_metrics->name);
|
||||
}
|
||||
}
|
||||
} else if (ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS)) {
|
||||
for (i = 0; i < ENA_STATS_ARRAY_ENI; i++) {
|
||||
ena_stats = &ena_stats_eni_strings[i];
|
||||
ethtool_puts(data, ena_stats->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (ena_com_get_cap(dev, ENA_ADMIN_ENA_SRD_INFO)) {
|
||||
for (i = 0; i < ENA_STATS_ARRAY_ENA_SRD; i++) {
|
||||
ena_stats = &ena_srd_info_strings[i];
|
||||
ethtool_puts(data, ena_stats->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ena_queue_strings(struct ena_adapter *adapter, u8 **data)
|
||||
{
|
||||
const struct ena_stats *ena_stats;
|
||||
@@ -291,7 +407,7 @@ static void ena_com_dev_strings(u8 **data)
|
||||
|
||||
static void ena_get_strings(struct ena_adapter *adapter,
|
||||
u8 *data,
|
||||
bool eni_stats_needed)
|
||||
bool hw_stats_needed)
|
||||
{
|
||||
const struct ena_stats *ena_stats;
|
||||
int i;
|
||||
@@ -301,12 +417,8 @@ static void ena_get_strings(struct ena_adapter *adapter,
|
||||
ethtool_puts(&data, ena_stats->name);
|
||||
}
|
||||
|
||||
if (eni_stats_needed) {
|
||||
for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
|
||||
ena_stats = &ena_stats_eni_strings[i];
|
||||
ethtool_puts(&data, ena_stats->name);
|
||||
}
|
||||
}
|
||||
if (hw_stats_needed)
|
||||
ena_metrics_stats_strings(adapter, &data);
|
||||
|
||||
ena_queue_strings(adapter, &data);
|
||||
ena_com_dev_strings(&data);
|
||||
@@ -317,11 +429,10 @@ static void ena_get_ethtool_strings(struct net_device *netdev,
|
||||
u8 *data)
|
||||
{
|
||||
struct ena_adapter *adapter = netdev_priv(netdev);
|
||||
struct ena_com_dev *dev = adapter->ena_dev;
|
||||
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
ena_get_strings(adapter, data, ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS));
|
||||
ena_get_strings(adapter, data, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2798,19 +2798,6 @@ err:
|
||||
ena_com_delete_debug_area(adapter->ena_dev);
|
||||
}
|
||||
|
||||
int ena_update_hw_stats(struct ena_adapter *adapter)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ena_com_get_eni_stats(adapter->ena_dev, &adapter->eni_stats);
|
||||
if (rc) {
|
||||
netdev_err(adapter->netdev, "Failed to get ENI stats\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ena_get_stats64(struct net_device *netdev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
@@ -3944,10 +3931,16 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
pci_set_drvdata(pdev, adapter);
|
||||
|
||||
rc = ena_com_allocate_customer_metrics_buffer(ena_dev);
|
||||
if (rc) {
|
||||
netdev_err(netdev, "ena_com_allocate_customer_metrics_buffer failed\n");
|
||||
goto err_netdev_destroy;
|
||||
}
|
||||
|
||||
rc = ena_map_llq_mem_bar(pdev, ena_dev, bars);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "ENA LLQ bar mapping failed\n");
|
||||
goto err_netdev_destroy;
|
||||
goto err_metrics_destroy;
|
||||
}
|
||||
|
||||
rc = ena_device_init(adapter, pdev, &get_feat_ctx, &wd_state);
|
||||
@@ -3955,7 +3948,7 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dev_err(&pdev->dev, "ENA device init failed\n");
|
||||
if (rc == -ETIME)
|
||||
rc = -EPROBE_DEFER;
|
||||
goto err_netdev_destroy;
|
||||
goto err_metrics_destroy;
|
||||
}
|
||||
|
||||
/* Initial TX and RX interrupt delay. Assumes 1 usec granularity.
|
||||
@@ -4076,6 +4069,8 @@ err_worker_destroy:
|
||||
err_device_destroy:
|
||||
ena_com_delete_host_info(ena_dev);
|
||||
ena_com_admin_destroy(ena_dev);
|
||||
err_metrics_destroy:
|
||||
ena_com_delete_customer_metrics_buffer(ena_dev);
|
||||
err_netdev_destroy:
|
||||
free_netdev(netdev);
|
||||
err_free_region:
|
||||
@@ -4139,6 +4134,8 @@ static void __ena_shutoff(struct pci_dev *pdev, bool shutdown)
|
||||
|
||||
ena_com_delete_host_info(ena_dev);
|
||||
|
||||
ena_com_delete_customer_metrics_buffer(ena_dev);
|
||||
|
||||
ena_release_bars(ena_dev, pdev);
|
||||
|
||||
pci_disable_device(pdev);
|
||||
|
||||
@@ -373,6 +373,7 @@ struct ena_adapter {
|
||||
struct u64_stats_sync syncp;
|
||||
struct ena_stats_dev dev_stats;
|
||||
struct ena_admin_eni_stats eni_stats;
|
||||
struct ena_admin_ena_srd_info ena_srd_info;
|
||||
|
||||
/* last queue index that was checked for uncompleted tx packets */
|
||||
u32 last_monitored_tx_qid;
|
||||
@@ -390,7 +391,6 @@ void ena_dump_stats_to_dmesg(struct ena_adapter *adapter);
|
||||
|
||||
void ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf);
|
||||
|
||||
int ena_update_hw_stats(struct ena_adapter *adapter);
|
||||
|
||||
int ena_update_queue_params(struct ena_adapter *adapter,
|
||||
u32 new_tx_size,
|
||||
|
||||
Reference in New Issue
Block a user