#include <sys/types.h>
#include <sys/queue.h>
+#include <rte_string_fns.h>
#include <rte_byteorder.h>
#include <rte_log.h>
#include <rte_debug.h>
#include <rte_ethdev.h>
#include <rte_cryptodev.h>
#include <rte_cryptodev_pmd.h>
+#include <rte_telemetry.h>
#include "rte_eventdev.h"
#include "rte_eventdev_pmd.h"
+#include "rte_eventdev_trace.h"
-struct rte_eventdev rte_event_devices[RTE_EVENT_MAX_DEVS];
+static struct rte_eventdev rte_event_devices[RTE_EVENT_MAX_DEVS];
-struct rte_eventdev *rte_eventdevs = &rte_event_devices[0];
+struct rte_eventdev *rte_eventdevs = rte_event_devices;
static struct rte_eventdev_global eventdev_globals = {
.nb_devs = 0
};
-struct rte_eventdev_global *rte_eventdev_globals = &eventdev_globals;
-
/* Event dev north bound API implementation */
uint8_t
rte_event_dev_count(void)
{
- return rte_eventdev_globals->nb_devs;
+ return eventdev_globals.nb_devs;
}
int
rte_event_dev_get_dev_id(const char *name)
{
int i;
+ uint8_t cmp;
if (!name)
return -EINVAL;
- for (i = 0; i < rte_eventdev_globals->nb_devs; i++)
- if ((strcmp(rte_event_devices[i].data->name, name)
- == 0) &&
- (rte_event_devices[i].attached ==
- RTE_EVENTDEV_ATTACHED))
+ for (i = 0; i < eventdev_globals.nb_devs; i++) {
+ cmp = (strncmp(rte_event_devices[i].data->name, name,
+ RTE_EVENTDEV_NAME_MAX_LEN) == 0) ||
+ (rte_event_devices[i].dev ? (strncmp(
+ rte_event_devices[i].dev->driver->name, name,
+ RTE_EVENTDEV_NAME_MAX_LEN) == 0) : 0);
+ if (cmp && (rte_event_devices[i].attached ==
+ RTE_EVENTDEV_ATTACHED))
return i;
+ }
return -ENODEV;
}
}
int
-rte_event_eth_rx_adapter_caps_get(uint8_t dev_id, uint8_t eth_port_id,
+rte_event_eth_rx_adapter_caps_get(uint8_t dev_id, uint16_t eth_port_id,
uint32_t *caps)
{
struct rte_eventdev *dev;
: 0;
}
-int __rte_experimental
+int
rte_event_timer_adapter_caps_get(uint8_t dev_id, uint32_t *caps)
{
struct rte_eventdev *dev;
: 0;
}
-int __rte_experimental
+int
rte_event_crypto_adapter_caps_get(uint8_t dev_id, uint8_t cdev_id,
uint32_t *caps)
{
(dev, cdev, caps) : -ENOTSUP;
}
+int
+rte_event_eth_tx_adapter_caps_get(uint8_t dev_id, uint16_t eth_port_id,
+ uint32_t *caps)
+{
+ struct rte_eventdev *dev;
+ struct rte_eth_dev *eth_dev;
+
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(eth_port_id, -EINVAL);
+
+ dev = &rte_eventdevs[dev_id];
+ eth_dev = &rte_eth_devices[eth_port_id];
+
+ if (caps == NULL)
+ return -EINVAL;
+
+ *caps = 0;
+
+ return dev->dev_ops->eth_tx_adapter_caps_get ?
+ (*dev->dev_ops->eth_tx_adapter_caps_get)(dev,
+ eth_dev,
+ caps)
+ : 0;
+}
+
static inline int
rte_event_dev_queue_config(struct rte_eventdev *dev, uint8_t nb_queues)
{
dev_id);
return -EINVAL;
}
- if (dev_conf->nb_event_queues > info.max_event_queues) {
- RTE_EDEV_LOG_ERR("%d nb_event_queues=%d > max_event_queues=%d",
- dev_id, dev_conf->nb_event_queues, info.max_event_queues);
+ if (dev_conf->nb_event_queues > info.max_event_queues +
+ info.max_single_link_event_port_queue_pairs) {
+ RTE_EDEV_LOG_ERR("%d nb_event_queues=%d > max_event_queues=%d + max_single_link_event_port_queue_pairs=%d",
+ dev_id, dev_conf->nb_event_queues,
+ info.max_event_queues,
+ info.max_single_link_event_port_queue_pairs);
+ return -EINVAL;
+ }
+ if (dev_conf->nb_event_queues -
+ dev_conf->nb_single_link_event_port_queues >
+ info.max_event_queues) {
+ RTE_EDEV_LOG_ERR("id%d nb_event_queues=%d - nb_single_link_event_port_queues=%d > max_event_queues=%d",
+ dev_id, dev_conf->nb_event_queues,
+ dev_conf->nb_single_link_event_port_queues,
+ info.max_event_queues);
+ return -EINVAL;
+ }
+ if (dev_conf->nb_single_link_event_port_queues >
+ dev_conf->nb_event_queues) {
+ RTE_EDEV_LOG_ERR("dev%d nb_single_link_event_port_queues=%d > nb_event_queues=%d",
+ dev_id,
+ dev_conf->nb_single_link_event_port_queues,
+ dev_conf->nb_event_queues);
return -EINVAL;
}
RTE_EDEV_LOG_ERR("dev%d nb_event_ports cannot be zero", dev_id);
return -EINVAL;
}
- if (dev_conf->nb_event_ports > info.max_event_ports) {
- RTE_EDEV_LOG_ERR("id%d nb_event_ports=%d > max_event_ports= %d",
- dev_id, dev_conf->nb_event_ports, info.max_event_ports);
+ if (dev_conf->nb_event_ports > info.max_event_ports +
+ info.max_single_link_event_port_queue_pairs) {
+ RTE_EDEV_LOG_ERR("id%d nb_event_ports=%d > max_event_ports=%d + max_single_link_event_port_queue_pairs=%d",
+ dev_id, dev_conf->nb_event_ports,
+ info.max_event_ports,
+ info.max_single_link_event_port_queue_pairs);
+ return -EINVAL;
+ }
+ if (dev_conf->nb_event_ports -
+ dev_conf->nb_single_link_event_port_queues
+ > info.max_event_ports) {
+ RTE_EDEV_LOG_ERR("id%d nb_event_ports=%d - nb_single_link_event_port_queues=%d > max_event_ports=%d",
+ dev_id, dev_conf->nb_event_ports,
+ dev_conf->nb_single_link_event_port_queues,
+ info.max_event_ports);
+ return -EINVAL;
+ }
+
+ if (dev_conf->nb_single_link_event_port_queues >
+ dev_conf->nb_event_ports) {
+ RTE_EDEV_LOG_ERR(
+ "dev%d nb_single_link_event_port_queues=%d > nb_event_ports=%d",
+ dev_id,
+ dev_conf->nb_single_link_event_port_queues,
+ dev_conf->nb_event_ports);
return -EINVAL;
}
}
dev->data->event_dev_cap = info.event_dev_cap;
+ rte_eventdev_trace_configure(dev_id, dev_conf, diag);
return diag;
}
}
dev->data->queues_cfg[queue_id] = *queue_conf;
+ rte_eventdev_trace_queue_setup(dev_id, queue_id, queue_conf);
return (*dev->dev_ops->queue_setup)(dev, queue_id, queue_conf);
}
return -EINVAL;
}
- if (port_conf && port_conf->disable_implicit_release &&
+ if (port_conf &&
+ (port_conf->event_port_cfg & RTE_EVENT_PORT_CFG_DISABLE_IMPL_REL) &&
!(dev->data->event_dev_cap &
RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE)) {
RTE_EDEV_LOG_ERR(
if (!diag)
diag = rte_event_port_unlink(dev_id, port_id, NULL, 0);
+ rte_eventdev_trace_port_setup(dev_id, port_id, port_conf, diag);
if (diag < 0)
return diag;
case RTE_EVENT_PORT_ATTR_NEW_EVENT_THRESHOLD:
*attr_value = dev->data->ports_cfg[port_id].new_event_threshold;
break;
+ case RTE_EVENT_PORT_ATTR_IMPLICIT_RELEASE_DISABLE:
+ {
+ uint32_t config;
+
+ config = dev->data->ports_cfg[port_id].event_port_cfg;
+ *attr_value = !!(config & RTE_EVENT_PORT_CFG_DISABLE_IMPL_REL);
+ break;
+ }
default:
return -EINVAL;
};
uint16_t *links_map;
int i, diag;
- RTE_EVENTDEV_VALID_DEVID_OR_ERRNO_RET(dev_id, -EINVAL, 0);
+ RTE_EVENTDEV_VALID_DEVID_OR_ERRNO_RET(dev_id, EINVAL, 0);
dev = &rte_eventdevs[dev_id];
if (*dev->dev_ops->port_link == NULL) {
- RTE_PMD_DEBUG_TRACE("Function not supported\n");
- rte_errno = -ENOTSUP;
+ RTE_EDEV_LOG_ERR("Function not supported\n");
+ rte_errno = ENOTSUP;
return 0;
}
if (!is_valid_port(dev, port_id)) {
RTE_EDEV_LOG_ERR("Invalid port_id=%" PRIu8, port_id);
- rte_errno = -EINVAL;
+ rte_errno = EINVAL;
return 0;
}
for (i = 0; i < nb_links; i++)
if (queues[i] >= dev->data->nb_queues) {
- rte_errno = -EINVAL;
+ rte_errno = EINVAL;
return 0;
}
for (i = 0; i < diag; i++)
links_map[queues[i]] = (uint8_t)priorities[i];
+ rte_eventdev_trace_port_link(dev_id, port_id, nb_links, diag);
return diag;
}
int i, diag, j;
uint16_t *links_map;
- RTE_EVENTDEV_VALID_DEVID_OR_ERRNO_RET(dev_id, -EINVAL, 0);
+ RTE_EVENTDEV_VALID_DEVID_OR_ERRNO_RET(dev_id, EINVAL, 0);
dev = &rte_eventdevs[dev_id];
if (*dev->dev_ops->port_unlink == NULL) {
- RTE_PMD_DEBUG_TRACE("Function not supported\n");
- rte_errno = -ENOTSUP;
+ RTE_EDEV_LOG_ERR("Function not supported");
+ rte_errno = ENOTSUP;
return 0;
}
if (!is_valid_port(dev, port_id)) {
RTE_EDEV_LOG_ERR("Invalid port_id=%" PRIu8, port_id);
- rte_errno = -EINVAL;
+ rte_errno = EINVAL;
return 0;
}
nb_unlinks = j;
for (i = 0; i < nb_unlinks; i++)
if (queues[i] >= dev->data->nb_queues) {
- rte_errno = -EINVAL;
+ rte_errno = EINVAL;
return 0;
}
for (i = 0; i < diag; i++)
links_map[queues[i]] = EVENT_QUEUE_SERVICE_PRIORITY_INVALID;
+ rte_eventdev_trace_port_unlink(dev_id, port_id, nb_unlinks, diag);
return diag;
}
+int
+rte_event_port_unlinks_in_progress(uint8_t dev_id, uint8_t port_id)
+{
+ struct rte_eventdev *dev;
+
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+ dev = &rte_eventdevs[dev_id];
+ if (!is_valid_port(dev, port_id)) {
+ RTE_EDEV_LOG_ERR("Invalid port_id=%" PRIu8, port_id);
+ return -EINVAL;
+ }
+
+ /* Return 0 if the PMD does not implement unlinks in progress.
+ * This allows PMDs which handle unlink synchronously to not implement
+ * this function at all.
+ */
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->port_unlinks_in_progress, 0);
+
+ return (*dev->dev_ops->port_unlinks_in_progress)(dev,
+ dev->data->ports[port_id]);
+}
+
int
rte_event_port_links_get(uint8_t dev_id, uint8_t port_id,
uint8_t queues[], uint8_t priorities[])
}
diag = (*dev->dev_ops->dev_start)(dev);
+ rte_eventdev_trace_start(dev_id, diag);
if (diag == 0)
dev->data->dev_started = 1;
else
dev->data->dev_started = 0;
(*dev->dev_ops->dev_stop)(dev);
+ rte_eventdev_trace_stop(dev_id);
}
int
return -EBUSY;
}
+ rte_eventdev_trace_close(dev_id);
return (*dev->dev_ops->dev_close)(dev);
}
return RTE_EVENT_MAX_DEVS;
}
+static uint16_t
+rte_event_tx_adapter_enqueue(__rte_unused void *port,
+ __rte_unused struct rte_event ev[],
+ __rte_unused uint16_t nb_events)
+{
+ rte_errno = ENOTSUP;
+ return 0;
+}
+
struct rte_eventdev *
rte_event_pmd_allocate(const char *name, int socket_id)
{
eventdev = &rte_eventdevs[dev_id];
+ eventdev->txa_enqueue = rte_event_tx_adapter_enqueue;
+ eventdev->txa_enqueue_same_dest = rte_event_tx_adapter_enqueue;
+
if (eventdev->data == NULL) {
struct rte_eventdev_data *eventdev_data = NULL;
eventdev->data = eventdev_data;
- snprintf(eventdev->data->name, RTE_EVENTDEV_NAME_MAX_LEN,
- "%s", name);
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
- eventdev->data->dev_id = dev_id;
- eventdev->data->socket_id = socket_id;
- eventdev->data->dev_started = 0;
+ strlcpy(eventdev->data->name, name,
+ RTE_EVENTDEV_NAME_MAX_LEN);
- eventdev->attached = RTE_EVENTDEV_ATTACHED;
+ eventdev->data->dev_id = dev_id;
+ eventdev->data->socket_id = socket_id;
+ eventdev->data->dev_started = 0;
+ }
+ eventdev->attached = RTE_EVENTDEV_ATTACHED;
eventdev_globals.nb_devs++;
}
eventdev->data = NULL;
return 0;
}
+
+
+static int
+handle_dev_list(const char *cmd __rte_unused,
+ const char *params __rte_unused,
+ struct rte_tel_data *d)
+{
+ uint8_t dev_id;
+ int ndev = rte_event_dev_count();
+
+ if (ndev < 1)
+ return -1;
+
+ rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
+ for (dev_id = 0; dev_id < RTE_EVENT_MAX_DEVS; dev_id++) {
+ if (rte_eventdevs[dev_id].attached ==
+ RTE_EVENTDEV_ATTACHED)
+ rte_tel_data_add_array_int(d, dev_id);
+ }
+
+ return 0;
+}
+
+static int
+handle_port_list(const char *cmd __rte_unused,
+ const char *params,
+ struct rte_tel_data *d)
+{
+ int i;
+ uint8_t dev_id;
+ struct rte_eventdev *dev;
+ char *end_param;
+
+ if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ return -1;
+
+ dev_id = strtoul(params, &end_param, 10);
+ if (*end_param != '\0')
+ RTE_EDEV_LOG_DEBUG(
+ "Extra parameters passed to eventdev telemetry command, ignoring");
+
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+ dev = &rte_eventdevs[dev_id];
+
+ rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
+ for (i = 0; i < dev->data->nb_ports; i++)
+ rte_tel_data_add_array_int(d, i);
+
+ return 0;
+}
+
+static int
+handle_queue_list(const char *cmd __rte_unused,
+ const char *params,
+ struct rte_tel_data *d)
+{
+ int i;
+ uint8_t dev_id;
+ struct rte_eventdev *dev;
+ char *end_param;
+
+ if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ return -1;
+
+ dev_id = strtoul(params, &end_param, 10);
+ if (*end_param != '\0')
+ RTE_EDEV_LOG_DEBUG(
+ "Extra parameters passed to eventdev telemetry command, ignoring");
+
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+ dev = &rte_eventdevs[dev_id];
+
+ rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
+ for (i = 0; i < dev->data->nb_queues; i++)
+ rte_tel_data_add_array_int(d, i);
+
+ return 0;
+}
+
+static int
+handle_queue_links(const char *cmd __rte_unused,
+ const char *params,
+ struct rte_tel_data *d)
+{
+ int i, ret, port_id = 0;
+ char *end_param;
+ uint8_t dev_id;
+ uint8_t queues[RTE_EVENT_MAX_QUEUES_PER_DEV];
+ uint8_t priorities[RTE_EVENT_MAX_QUEUES_PER_DEV];
+ const char *p_param;
+
+ if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ return -1;
+
+ /* Get dev ID from parameter string */
+ dev_id = strtoul(params, &end_param, 10);
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+
+ p_param = strtok(end_param, ",");
+ if (p_param == NULL || strlen(p_param) == 0 || !isdigit(*p_param))
+ return -1;
+
+ port_id = strtoul(p_param, &end_param, 10);
+ p_param = strtok(NULL, "\0");
+ if (p_param != NULL)
+ RTE_EDEV_LOG_DEBUG(
+ "Extra parameters passed to eventdev telemetry command, ignoring");
+
+ ret = rte_event_port_links_get(dev_id, port_id, queues, priorities);
+ if (ret < 0)
+ return -1;
+
+ rte_tel_data_start_dict(d);
+ for (i = 0; i < ret; i++) {
+ char qid_name[32];
+
+ snprintf(qid_name, 31, "qid_%u", queues[i]);
+ rte_tel_data_add_dict_u64(d, qid_name, priorities[i]);
+ }
+
+ return 0;
+}
+
+static int
+eventdev_build_telemetry_data(int dev_id,
+ enum rte_event_dev_xstats_mode mode,
+ int port_queue_id,
+ struct rte_tel_data *d)
+{
+ struct rte_event_dev_xstats_name *xstat_names;
+ unsigned int *ids;
+ uint64_t *values;
+ int i, ret, num_xstats;
+
+ num_xstats = rte_event_dev_xstats_names_get(dev_id,
+ mode,
+ port_queue_id,
+ NULL,
+ NULL,
+ 0);
+
+ if (num_xstats < 0)
+ return -1;
+
+ /* use one malloc for names */
+ xstat_names = malloc((sizeof(struct rte_event_dev_xstats_name))
+ * num_xstats);
+ if (xstat_names == NULL)
+ return -1;
+
+ ids = malloc((sizeof(unsigned int)) * num_xstats);
+ if (ids == NULL) {
+ free(xstat_names);
+ return -1;
+ }
+
+ values = malloc((sizeof(uint64_t)) * num_xstats);
+ if (values == NULL) {
+ free(xstat_names);
+ free(ids);
+ return -1;
+ }
+
+ ret = rte_event_dev_xstats_names_get(dev_id, mode, port_queue_id,
+ xstat_names, ids, num_xstats);
+ if (ret < 0 || ret > num_xstats) {
+ free(xstat_names);
+ free(ids);
+ free(values);
+ return -1;
+ }
+
+ ret = rte_event_dev_xstats_get(dev_id, mode, port_queue_id,
+ ids, values, num_xstats);
+ if (ret < 0 || ret > num_xstats) {
+ free(xstat_names);
+ free(ids);
+ free(values);
+ return -1;
+ }
+
+ rte_tel_data_start_dict(d);
+ for (i = 0; i < num_xstats; i++)
+ rte_tel_data_add_dict_u64(d, xstat_names[i].name,
+ values[i]);
+
+ free(xstat_names);
+ free(ids);
+ free(values);
+ return 0;
+}
+
+static int
+handle_dev_xstats(const char *cmd __rte_unused,
+ const char *params,
+ struct rte_tel_data *d)
+{
+ int dev_id;
+ enum rte_event_dev_xstats_mode mode;
+ char *end_param;
+
+ if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ return -1;
+
+ /* Get dev ID from parameter string */
+ dev_id = strtoul(params, &end_param, 10);
+ if (*end_param != '\0')
+ RTE_EDEV_LOG_DEBUG(
+ "Extra parameters passed to eventdev telemetry command, ignoring");
+
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+
+ mode = RTE_EVENT_DEV_XSTATS_DEVICE;
+ return eventdev_build_telemetry_data(dev_id, mode, 0, d);
+}
+
+static int
+handle_port_xstats(const char *cmd __rte_unused,
+ const char *params,
+ struct rte_tel_data *d)
+{
+ int dev_id;
+ int port_queue_id = 0;
+ enum rte_event_dev_xstats_mode mode;
+ char *end_param;
+ const char *p_param;
+
+ if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ return -1;
+
+ /* Get dev ID from parameter string */
+ dev_id = strtoul(params, &end_param, 10);
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+
+ p_param = strtok(end_param, ",");
+ mode = RTE_EVENT_DEV_XSTATS_PORT;
+
+ if (p_param == NULL || strlen(p_param) == 0 || !isdigit(*p_param))
+ return -1;
+
+ port_queue_id = strtoul(p_param, &end_param, 10);
+
+ p_param = strtok(NULL, "\0");
+ if (p_param != NULL)
+ RTE_EDEV_LOG_DEBUG(
+ "Extra parameters passed to eventdev telemetry command, ignoring");
+
+ return eventdev_build_telemetry_data(dev_id, mode, port_queue_id, d);
+}
+
+static int
+handle_queue_xstats(const char *cmd __rte_unused,
+ const char *params,
+ struct rte_tel_data *d)
+{
+ int dev_id;
+ int port_queue_id = 0;
+ enum rte_event_dev_xstats_mode mode;
+ char *end_param;
+ const char *p_param;
+
+ if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ return -1;
+
+ /* Get dev ID from parameter string */
+ dev_id = strtoul(params, &end_param, 10);
+ RTE_EVENTDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
+
+ p_param = strtok(end_param, ",");
+ mode = RTE_EVENT_DEV_XSTATS_QUEUE;
+
+ if (p_param == NULL || strlen(p_param) == 0 || !isdigit(*p_param))
+ return -1;
+
+ port_queue_id = strtoul(p_param, &end_param, 10);
+
+ p_param = strtok(NULL, "\0");
+ if (p_param != NULL)
+ RTE_EDEV_LOG_DEBUG(
+ "Extra parameters passed to eventdev telemetry command, ignoring");
+
+ return eventdev_build_telemetry_data(dev_id, mode, port_queue_id, d);
+}
+
+RTE_INIT(eventdev_init_telemetry)
+{
+ rte_telemetry_register_cmd("/eventdev/dev_list", handle_dev_list,
+ "Returns list of available eventdevs. Takes no parameters");
+ rte_telemetry_register_cmd("/eventdev/port_list", handle_port_list,
+ "Returns list of available ports. Parameter: DevID");
+ rte_telemetry_register_cmd("/eventdev/queue_list", handle_queue_list,
+ "Returns list of available queues. Parameter: DevID");
+
+ rte_telemetry_register_cmd("/eventdev/dev_xstats", handle_dev_xstats,
+ "Returns stats for an eventdev. Parameter: DevID");
+ rte_telemetry_register_cmd("/eventdev/port_xstats", handle_port_xstats,
+ "Returns stats for an eventdev port. Params: DevID,PortID");
+ rte_telemetry_register_cmd("/eventdev/queue_xstats",
+ handle_queue_xstats,
+ "Returns stats for an eventdev queue. Params: DevID,QueueID");
+ rte_telemetry_register_cmd("/eventdev/queue_links", handle_queue_links,
+ "Returns links for an eventdev port. Params: DevID,QueueID");
+}