numam-dpdk/drivers/event/dsw/dsw_xstats.c
Pavan Nikhilesh 1bdfe4d76e eventdev: increase xstats ID width to 64 bits
Increase xstats ID width from 32 to 64 bits. This also
fixes the xstats ID datatype discrepancy between reset and
rest of the xstats family.

Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
Reviewed-by: Mattias Rönnblom <mattias.ronnblom@ericsson.com>
Acked-by: Jerin Jacob <jerinj@marvell.com>
2022-10-21 11:42:08 +02:00

377 lines
9.3 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2018-2019 Ericsson AB
*/
#include "dsw_evdev.h"
#include <stdbool.h>
#include <string.h>
#include <rte_debug.h>
/* The high bits in the xstats id is used to store an additional
* parameter (beyond the queue or port id already in the xstats
* interface).
*/
#define DSW_XSTATS_ID_PARAM_BITS (8)
#define DSW_XSTATS_ID_STAT_BITS \
(sizeof(uint64_t)*CHAR_BIT - DSW_XSTATS_ID_PARAM_BITS)
#define DSW_XSTATS_ID_STAT_MASK ((UINT64_C(1) << DSW_XSTATS_ID_STAT_BITS) - 1)
#define DSW_XSTATS_ID_GET_PARAM(id) \
((id)>>DSW_XSTATS_ID_STAT_BITS)
#define DSW_XSTATS_ID_GET_STAT(id) \
((id) & DSW_XSTATS_ID_STAT_MASK)
#define DSW_XSTATS_ID_CREATE(id, param_value) \
((((uint64_t)param_value) << DSW_XSTATS_ID_STAT_BITS) | id)
typedef
uint64_t (*dsw_xstats_dev_get_value_fn)(struct dsw_evdev *dsw);
struct dsw_xstat_dev {
const char *name;
dsw_xstats_dev_get_value_fn get_value_fn;
};
typedef
uint64_t (*dsw_xstats_port_get_value_fn)(struct dsw_evdev *dsw,
uint8_t port_id, uint8_t queue_id);
struct dsw_xstats_port {
const char *name_fmt;
dsw_xstats_port_get_value_fn get_value_fn;
bool per_queue;
};
static uint64_t
dsw_xstats_dev_credits_on_loan(struct dsw_evdev *dsw)
{
return __atomic_load_n(&dsw->credits_on_loan, __ATOMIC_RELAXED);
}
static struct dsw_xstat_dev dsw_dev_xstats[] = {
{ "dev_credits_on_loan", dsw_xstats_dev_credits_on_loan }
};
#define DSW_GEN_PORT_ACCESS_FN(_variable) \
static uint64_t \
dsw_xstats_port_get_ ## _variable(struct dsw_evdev *dsw, \
uint8_t port_id, \
uint8_t queue_id __rte_unused) \
{ \
return dsw->ports[port_id]._variable; \
}
DSW_GEN_PORT_ACCESS_FN(new_enqueued)
DSW_GEN_PORT_ACCESS_FN(forward_enqueued)
DSW_GEN_PORT_ACCESS_FN(release_enqueued)
static uint64_t
dsw_xstats_port_get_queue_enqueued(struct dsw_evdev *dsw, uint8_t port_id,
uint8_t queue_id)
{
return dsw->ports[port_id].queue_enqueued[queue_id];
}
DSW_GEN_PORT_ACCESS_FN(dequeued)
static uint64_t
dsw_xstats_port_get_queue_dequeued(struct dsw_evdev *dsw, uint8_t port_id,
uint8_t queue_id)
{
return dsw->ports[port_id].queue_dequeued[queue_id];
}
DSW_GEN_PORT_ACCESS_FN(emigrations)
DSW_GEN_PORT_ACCESS_FN(immigrations)
static uint64_t
dsw_xstats_port_get_migration_latency(struct dsw_evdev *dsw, uint8_t port_id,
uint8_t queue_id __rte_unused)
{
uint64_t total_latency = dsw->ports[port_id].emigration_latency;
uint64_t num_emigrations = dsw->ports[port_id].emigrations;
return num_emigrations > 0 ? total_latency / num_emigrations : 0;
}
static uint64_t
dsw_xstats_port_get_event_proc_latency(struct dsw_evdev *dsw, uint8_t port_id,
uint8_t queue_id __rte_unused)
{
uint64_t total_busy_cycles =
dsw->ports[port_id].total_busy_cycles;
uint64_t dequeued =
dsw->ports[port_id].dequeued;
return dequeued > 0 ? total_busy_cycles / dequeued : 0;
}
static uint64_t
dsw_xstats_port_get_busy_cycles(struct dsw_evdev *dsw, uint8_t port_id,
uint8_t queue_id __rte_unused)
{
return dsw->ports[port_id].total_busy_cycles;
}
DSW_GEN_PORT_ACCESS_FN(inflight_credits)
DSW_GEN_PORT_ACCESS_FN(pending_releases)
static uint64_t
dsw_xstats_port_get_load(struct dsw_evdev *dsw, uint8_t port_id,
uint8_t queue_id __rte_unused)
{
int16_t load;
load = __atomic_load_n(&dsw->ports[port_id].load, __ATOMIC_RELAXED);
return DSW_LOAD_TO_PERCENT(load);
}
DSW_GEN_PORT_ACCESS_FN(last_bg)
static struct dsw_xstats_port dsw_port_xstats[] = {
{ "port_%u_new_enqueued", dsw_xstats_port_get_new_enqueued,
false },
{ "port_%u_forward_enqueued", dsw_xstats_port_get_forward_enqueued,
false },
{ "port_%u_release_enqueued", dsw_xstats_port_get_release_enqueued,
false },
{ "port_%u_queue_%u_enqueued", dsw_xstats_port_get_queue_enqueued,
true },
{ "port_%u_dequeued", dsw_xstats_port_get_dequeued,
false },
{ "port_%u_queue_%u_dequeued", dsw_xstats_port_get_queue_dequeued,
true },
{ "port_%u_emigrations", dsw_xstats_port_get_emigrations,
false },
{ "port_%u_migration_latency", dsw_xstats_port_get_migration_latency,
false },
{ "port_%u_immigrations", dsw_xstats_port_get_immigrations,
false },
{ "port_%u_event_proc_latency", dsw_xstats_port_get_event_proc_latency,
false },
{ "port_%u_busy_cycles", dsw_xstats_port_get_busy_cycles,
false },
{ "port_%u_inflight_credits", dsw_xstats_port_get_inflight_credits,
false },
{ "port_%u_pending_releases", dsw_xstats_port_get_pending_releases,
false },
{ "port_%u_load", dsw_xstats_port_get_load,
false },
{ "port_%u_last_bg", dsw_xstats_port_get_last_bg,
false }
};
typedef
void (*dsw_xstats_foreach_fn)(const char *xstats_name,
enum rte_event_dev_xstats_mode mode,
uint8_t queue_port_id, uint64_t xstats_id,
void *data);
static void
dsw_xstats_dev_foreach(dsw_xstats_foreach_fn fn, void *fn_data)
{
unsigned int i;
for (i = 0; i < RTE_DIM(dsw_dev_xstats); i++)
fn(dsw_dev_xstats[i].name, RTE_EVENT_DEV_XSTATS_DEVICE, 0,
i, fn_data);
}
static void
dsw_xstats_port_foreach(struct dsw_evdev *dsw, uint8_t port_id,
dsw_xstats_foreach_fn fn, void *fn_data)
{
uint8_t queue_id;
unsigned int stat_idx;
for (stat_idx = 0, queue_id = 0;
stat_idx < RTE_DIM(dsw_port_xstats);) {
struct dsw_xstats_port *xstat = &dsw_port_xstats[stat_idx];
char xstats_name[RTE_EVENT_DEV_XSTATS_NAME_SIZE];
uint64_t xstats_id;
if (xstat->per_queue) {
xstats_id = DSW_XSTATS_ID_CREATE(stat_idx, queue_id);
snprintf(xstats_name, sizeof(xstats_name),
dsw_port_xstats[stat_idx].name_fmt, port_id,
queue_id);
queue_id++;
} else {
xstats_id = stat_idx;
snprintf(xstats_name, sizeof(xstats_name),
dsw_port_xstats[stat_idx].name_fmt, port_id);
}
fn(xstats_name, RTE_EVENT_DEV_XSTATS_PORT, port_id,
xstats_id, fn_data);
if (!(xstat->per_queue && queue_id < dsw->num_queues)) {
stat_idx++;
queue_id = 0;
}
}
}
struct store_ctx {
struct rte_event_dev_xstats_name *names;
uint64_t *ids;
unsigned int count;
unsigned int capacity;
};
static void
dsw_xstats_store_stat(const char *xstats_name,
enum rte_event_dev_xstats_mode mode,
uint8_t queue_port_id, uint64_t xstats_id,
void *data)
{
struct store_ctx *ctx = data;
RTE_SET_USED(mode);
RTE_SET_USED(queue_port_id);
if (ctx->count < ctx->capacity) {
strcpy(ctx->names[ctx->count].name, xstats_name);
ctx->ids[ctx->count] = xstats_id;
}
ctx->count++;
}
int
dsw_xstats_get_names(const struct rte_eventdev *dev,
enum rte_event_dev_xstats_mode mode,
uint8_t queue_port_id,
struct rte_event_dev_xstats_name *xstats_names,
uint64_t *ids, unsigned int capacity)
{
struct dsw_evdev *dsw = dsw_pmd_priv(dev);
struct store_ctx ctx = {
.names = xstats_names,
.ids = ids,
.capacity = capacity
};
switch (mode) {
case RTE_EVENT_DEV_XSTATS_DEVICE:
dsw_xstats_dev_foreach(dsw_xstats_store_stat, &ctx);
return ctx.count;
case RTE_EVENT_DEV_XSTATS_PORT:
dsw_xstats_port_foreach(dsw, queue_port_id,
dsw_xstats_store_stat, &ctx);
return ctx.count;
case RTE_EVENT_DEV_XSTATS_QUEUE:
return 0;
default:
RTE_ASSERT(false);
return -1;
}
}
static int
dsw_xstats_dev_get(const struct rte_eventdev *dev,
const uint64_t ids[], uint64_t values[], unsigned int n)
{
struct dsw_evdev *dsw = dsw_pmd_priv(dev);
unsigned int i;
for (i = 0; i < n; i++) {
uint64_t id = ids[i];
struct dsw_xstat_dev *xstat = &dsw_dev_xstats[id];
values[i] = xstat->get_value_fn(dsw);
}
return n;
}
static int
dsw_xstats_port_get(const struct rte_eventdev *dev, uint8_t port_id,
const uint64_t ids[], uint64_t values[], unsigned int n)
{
struct dsw_evdev *dsw = dsw_pmd_priv(dev);
unsigned int i;
for (i = 0; i < n; i++) {
uint64_t id = ids[i];
unsigned int stat_idx = DSW_XSTATS_ID_GET_STAT(id);
struct dsw_xstats_port *xstat = &dsw_port_xstats[stat_idx];
uint8_t queue_id = 0;
if (xstat->per_queue)
queue_id = DSW_XSTATS_ID_GET_PARAM(id);
values[i] = xstat->get_value_fn(dsw, port_id, queue_id);
}
return n;
}
int
dsw_xstats_get(const struct rte_eventdev *dev,
enum rte_event_dev_xstats_mode mode, uint8_t queue_port_id,
const uint64_t ids[], uint64_t values[], unsigned int n)
{
switch (mode) {
case RTE_EVENT_DEV_XSTATS_DEVICE:
return dsw_xstats_dev_get(dev, ids, values, n);
case RTE_EVENT_DEV_XSTATS_PORT:
return dsw_xstats_port_get(dev, queue_port_id, ids, values, n);
case RTE_EVENT_DEV_XSTATS_QUEUE:
return 0;
default:
RTE_ASSERT(false);
return -1;
}
return 0;
}
struct find_ctx {
const struct rte_eventdev *dev;
const char *name;
uint64_t *id;
uint64_t value;
};
static void
dsw_xstats_find_stat(const char *xstats_name,
enum rte_event_dev_xstats_mode mode,
uint8_t queue_port_id, uint64_t xstats_id,
void *data)
{
struct find_ctx *ctx = data;
if (strcmp(ctx->name, xstats_name) == 0) {
if (ctx->id != NULL)
*ctx->id = xstats_id;
dsw_xstats_get(ctx->dev, mode, queue_port_id, &xstats_id,
&ctx->value, 1);
}
}
uint64_t
dsw_xstats_get_by_name(const struct rte_eventdev *dev, const char *name,
uint64_t *id)
{
struct dsw_evdev *dsw = dsw_pmd_priv(dev);
uint16_t port_id;
struct find_ctx ctx = {
.dev = dev,
.name = name,
.id = id,
.value = -EINVAL
};
dsw_xstats_dev_foreach(dsw_xstats_find_stat, &ctx);
for (port_id = 0; port_id < dsw->num_ports; port_id++)
dsw_xstats_port_foreach(dsw, port_id, dsw_xstats_find_stat,
&ctx);
return ctx.value;
}