eventdev: introduce specialized enqueue forward op variant
[dpdk.git] / lib / librte_eventdev / rte_eventdev.h
index b2bc471..29d707f 100644 (file)
  * operation. Instead, Event drivers export Poll-Mode enqueue and dequeue
  * functions to applications.
  *
- * An event driven based application has following typical workflow on fastpath:
- * \code{.c}
- *     while (1) {
- *
- *             rte_event_schedule(dev_id);
- *
- *             rte_event_dequeue(...);
- *
- *             (event processing)
- *
- *             rte_event_enqueue(...);
- *     }
- * \endcode
- *
  * The events are injected to event device through *enqueue* operation by
  * event producers in the system. The typical event producers are ethdev
  * subsystem for generating packet events, CPU(SW) for generating events based
  * indicates the device is centralized and thus needs a dedicated scheduling
  * thread that repeatedly calls rte_event_schedule().
  *
+ * An event driven worker thread has following typical workflow on fastpath:
+ * \code{.c}
+ *     while (1) {
+ *             rte_event_dequeue_burst(...);
+ *             (event processing)
+ *             rte_event_enqueue_burst(...);
+ *     }
+ * \endcode
+ *
  */
 
 #ifdef __cplusplus
@@ -244,8 +239,10 @@ extern "C" {
 #endif
 
 #include <rte_common.h>
-#include <rte_pci.h>
-#include <rte_mbuf.h>
+#include <rte_memory.h>
+#include <rte_errno.h>
+
+struct rte_mbuf; /* we just use mbuf pointers; no need to include rte_mbuf.h */
 
 /* Event device capability bitmap flags */
 #define RTE_EVENT_DEV_CAP_QUEUE_QOS           (1ULL << 0)
@@ -270,6 +267,21 @@ extern "C" {
  *
  * @see rte_event_schedule(), rte_event_dequeue_burst()
  */
+#define RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES     (1ULL << 3)
+/**< Event device is capable of enqueuing events of any type to any queue.
+ * If this capability is not set, the queue only supports events of the
+ *  *RTE_EVENT_QUEUE_CFG_* type that it was created with.
+ *
+ * @see RTE_EVENT_QUEUE_CFG_* values
+ */
+#define RTE_EVENT_DEV_CAP_BURST_MODE          (1ULL << 4)
+/**< Event device is capable of operating in burst mode for enqueue(forward,
+ * release) and dequeue operation. If this capability is not set, application
+ * still uses the rte_event_dequeue_burst() and rte_event_enqueue_burst() but
+ * PMD accepts only one event at a time.
+ *
+ * @see rte_event_dequeue_burst() rte_event_enqueue_burst()
+ */
 
 /* Event device priority levels */
 #define RTE_EVENT_DEV_PRIORITY_HIGHEST   0
@@ -329,7 +341,7 @@ rte_event_dev_socket_id(uint8_t dev_id);
  */
 struct rte_event_dev_info {
        const char *driver_name;        /**< Event driver name */
-       struct rte_pci_device *pci_dev; /**< PCI information */
+       struct rte_device *dev; /**< Device information */
        uint32_t min_dequeue_timeout_ns;
        /**< Minimum supported global dequeue timeout(ns) by this device */
        uint32_t max_dequeue_timeout_ns;
@@ -400,14 +412,16 @@ struct rte_event_dev_config {
         * This value should be in the range of *min_dequeue_timeout_ns* and
         * *max_dequeue_timeout_ns* which previously provided in
         * rte_event_dev_info_get()
+        * The value 0 is allowed, in which case, default dequeue timeout used.
         * @see RTE_EVENT_DEV_CFG_PER_DEQUEUE_TIMEOUT
         */
        int32_t nb_events_limit;
-       /**< Applies to *closed system* event dev only. This field indicates a
-        * limit to ethdev-like devices to limit the number of events injected
-        * into the system to not overwhelm core-to-core events.
-        * This value cannot exceed the *max_num_events* which previously
-        * provided in rte_event_dev_info_get()
+       /**< In a *closed system* this field is the limit on maximum number of
+        * events that can be inflight in the eventdev at a given time. The
+        * limit is required to ensure that the finite space in a closed system
+        * is not overwhelmed. The value cannot exceed the *max_num_events*
+        * as provided by rte_event_dev_info_get().
+        * This value should be set to -1 for *open system*.
         */
        uint8_t nb_event_queues;
        /**< Number of event queues to configure on this device.
@@ -424,18 +438,20 @@ struct rte_event_dev_config {
         * This value cannot exceed the *max_event_queue_flows* which previously
         * provided in rte_event_dev_info_get()
         */
-       uint8_t nb_event_port_dequeue_depth;
+       uint32_t nb_event_port_dequeue_depth;
        /**< Maximum number of events can be dequeued at a time from an
         * event port by this device.
         * This value cannot exceed the *max_event_port_dequeue_depth*
-        * which previously provided in rte_event_dev_info_get()
+        * which previously provided in rte_event_dev_info_get().
+        * Ignored when device is not RTE_EVENT_DEV_CAP_BURST_MODE capable.
         * @see rte_event_port_setup()
         */
        uint32_t nb_event_port_enqueue_depth;
        /**< Maximum number of events can be enqueued at a time from an
         * event port by this device.
         * This value cannot exceed the *max_event_port_enqueue_depth*
-        * which previously provided in rte_event_dev_info_get()
+        * which previously provided in rte_event_dev_info_get().
+        * Ignored when device is not RTE_EVENT_DEV_CAP_BURST_MODE capable.
         * @see rte_event_port_setup()
         */
        uint32_t event_dev_cfg;
@@ -469,12 +485,6 @@ rte_event_dev_configure(uint8_t dev_id,
 /* Event queue specific APIs */
 
 /* Event queue configuration bitmap flags */
-#define RTE_EVENT_QUEUE_CFG_DEFAULT            (0)
-/**< Default value of *event_queue_cfg* when rte_event_queue_setup() invoked
- * with queue_conf == NULL
- *
- * @see rte_event_queue_setup()
- */
 #define RTE_EVENT_QUEUE_CFG_TYPE_MASK          (3ULL << 0)
 /**< Mask for event queue schedule type configuration request */
 #define RTE_EVENT_QUEUE_CFG_ALL_TYPES          (0ULL << 0)
@@ -517,9 +527,11 @@ rte_event_dev_configure(uint8_t dev_id,
 struct rte_event_queue_conf {
        uint32_t nb_atomic_flows;
        /**< The maximum number of active flows this queue can track at any
-        * given time. The value must be in the range of
-        * [1 - nb_event_queue_flows)] which previously provided in
-        * rte_event_dev_info_get().
+        * given time. If the queue is configured for atomic scheduling (by
+        * applying the RTE_EVENT_QUEUE_CFG_ALL_TYPES or
+        * RTE_EVENT_QUEUE_CFG_ATOMIC_ONLY flags to event_queue_cfg), then the
+        * value must be in the range of [1, nb_event_queue_flows], which was
+        * previously provided in rte_event_dev_configure().
         */
        uint32_t nb_atomic_order_sequences;
        /**< The maximum number of outstanding events waiting to be
@@ -529,8 +541,11 @@ struct rte_event_queue_conf {
         * scheduler cannot schedule the events from this queue and invalid
         * event will be returned from dequeue until one or more entries are
         * freed up/released.
-        * The value must be in the range of [1 - nb_event_queue_flows)]
-        * which previously supplied to rte_event_dev_configure().
+        * If the queue is configured for ordered scheduling (by applying the
+        * RTE_EVENT_QUEUE_CFG_ALL_TYPES or RTE_EVENT_QUEUE_CFG_ORDERED_ONLY
+        * flags to event_queue_cfg), then the value must be in the range of
+        * [1, nb_event_queue_flows], which was previously supplied to
+        * rte_event_dev_configure().
         */
        uint32_t event_queue_cfg; /**< Queue cfg flags(EVENT_QUEUE_CFG_) */
        uint8_t priority;
@@ -632,17 +647,20 @@ struct rte_event_port_conf {
         * can have a lower threshold so as not to overwhelm the device,
         * while ports used for worker pools can have a higher threshold.
         * This value cannot exceed the *nb_events_limit*
-        * which previously supplied to rte_event_dev_configure()
+        * which was previously supplied to rte_event_dev_configure().
+        * This should be set to '-1' for *open system*.
         */
-       uint8_t dequeue_depth;
+       uint16_t dequeue_depth;
        /**< Configure number of bulk dequeues for this event port.
         * This value cannot exceed the *nb_event_port_dequeue_depth*
-        * which previously supplied to rte_event_dev_configure()
+        * which previously supplied to rte_event_dev_configure().
+        * Ignored when device is not RTE_EVENT_DEV_CAP_BURST_MODE capable.
         */
-       uint8_t enqueue_depth;
+       uint16_t enqueue_depth;
        /**< Configure number of bulk enqueues for this event port.
         * This value cannot exceed the *nb_event_port_enqueue_depth*
-        * which previously supplied to rte_event_dev_configure()
+        * which previously supplied to rte_event_dev_configure().
+        * Ignored when device is not RTE_EVENT_DEV_CAP_BURST_MODE capable.
         */
 };
 
@@ -752,7 +770,8 @@ rte_event_port_count(uint8_t dev_id);
  *   Event device identifier
  * @return
  *   - 0: Success, device started.
- *   - <0: Error code of the driver device start function.
+ *   - -ESTALE : Not all ports of the device are configured
+ *   - -ENOLINK: Not all queues are linked, which could lead to deadlock.
  */
 int
 rte_event_dev_start(uint8_t dev_id);
@@ -899,9 +918,9 @@ rte_event_dev_close(uint8_t dev_id);
  * The generic *rte_event* structure to hold the event attributes
  * for dequeue and enqueue operation
  */
+RTE_STD_C11
 struct rte_event {
        /** WORD0 */
-       RTE_STD_C11
        union {
                uint64_t event;
                /** Event attributes for dequeue or enqueue operation */
@@ -961,7 +980,6 @@ struct rte_event {
                };
        };
        /** WORD1 */
-       RTE_STD_C11
        union {
                uint64_t u64;
                /**< Opaque 64-bit value */
@@ -972,6 +990,106 @@ struct rte_event {
        };
 };
 
+
+struct rte_eventdev_driver;
+struct rte_eventdev_ops;
+struct rte_eventdev;
+
+typedef void (*event_schedule_t)(struct rte_eventdev *dev);
+/**< @internal Schedule one or more events in the event dev. */
+
+typedef uint16_t (*event_enqueue_t)(void *port, const struct rte_event *ev);
+/**< @internal Enqueue event on port of a device */
+
+typedef uint16_t (*event_enqueue_burst_t)(void *port,
+                       const struct rte_event ev[], uint16_t nb_events);
+/**< @internal Enqueue burst of events on port of a device */
+
+typedef uint16_t (*event_dequeue_t)(void *port, struct rte_event *ev,
+               uint64_t timeout_ticks);
+/**< @internal Dequeue event from port of a device */
+
+typedef uint16_t (*event_dequeue_burst_t)(void *port, struct rte_event ev[],
+               uint16_t nb_events, uint64_t timeout_ticks);
+/**< @internal Dequeue burst of events from port of a device */
+
+#define RTE_EVENTDEV_NAME_MAX_LEN      (64)
+/**< @internal Max length of name of event PMD */
+
+/**
+ * @internal
+ * The data part, with no function pointers, associated with each device.
+ *
+ * This structure is safe to place in shared memory to be common among
+ * different processes in a multi-process configuration.
+ */
+struct rte_eventdev_data {
+       int socket_id;
+       /**< Socket ID where memory is allocated */
+       uint8_t dev_id;
+       /**< Device ID for this instance */
+       uint8_t nb_queues;
+       /**< Number of event queues. */
+       uint8_t nb_ports;
+       /**< Number of event ports. */
+       void **ports;
+       /**< Array of pointers to ports. */
+       uint8_t *ports_dequeue_depth;
+       /**< Array of port dequeue depth. */
+       uint8_t *ports_enqueue_depth;
+       /**< Array of port enqueue depth. */
+       uint8_t *queues_prio;
+       /**< Array of queue priority. */
+       uint16_t *links_map;
+       /**< Memory to store queues to port connections. */
+       void *dev_private;
+       /**< PMD-specific private data */
+       uint32_t event_dev_cap;
+       /**< Event device capabilities(RTE_EVENT_DEV_CAP_)*/
+       struct rte_event_dev_config dev_conf;
+       /**< Configuration applied to device. */
+
+       RTE_STD_C11
+       uint8_t dev_started : 1;
+       /**< Device state: STARTED(1)/STOPPED(0) */
+
+       char name[RTE_EVENTDEV_NAME_MAX_LEN];
+       /**< Unique identifier name */
+} __rte_cache_aligned;
+
+/** @internal The data structure associated with each event device. */
+struct rte_eventdev {
+       event_schedule_t schedule;
+       /**< Pointer to PMD schedule function. */
+       event_enqueue_t enqueue;
+       /**< Pointer to PMD enqueue function. */
+       event_enqueue_burst_t enqueue_burst;
+       /**< Pointer to PMD enqueue burst function. */
+       event_enqueue_burst_t enqueue_new_burst;
+       /**< Pointer to PMD enqueue burst function(op new variant) */
+       event_enqueue_burst_t enqueue_forward_burst;
+       /**< Pointer to PMD enqueue burst function(op forward variant) */
+       event_dequeue_t dequeue;
+       /**< Pointer to PMD dequeue function. */
+       event_dequeue_burst_t dequeue_burst;
+       /**< Pointer to PMD dequeue burst function. */
+
+       struct rte_eventdev_data *data;
+       /**< Pointer to device data */
+       const struct rte_eventdev_ops *dev_ops;
+       /**< Functions exported by PMD */
+       struct rte_device *dev;
+       /**< Device info. supplied by probing */
+
+       RTE_STD_C11
+       uint8_t attached : 1;
+       /**< Flag indicating the device is attached */
+} __rte_cache_aligned;
+
+extern struct rte_eventdev *rte_eventdevs;
+/** @internal The pool of rte_eventdev structures. */
+
+
 /**
  * Schedule one or more events in the event dev.
  *
@@ -981,8 +1099,41 @@ struct rte_event {
  * @param dev_id
  *   The identifier of the device.
  */
-void
-rte_event_schedule(uint8_t dev_id);
+static inline void
+rte_event_schedule(uint8_t dev_id)
+{
+       struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+       if (*dev->schedule)
+               (*dev->schedule)(dev);
+}
+
+static __rte_always_inline uint16_t
+__rte_event_enqueue_burst(uint8_t dev_id, uint8_t port_id,
+                       const struct rte_event ev[], uint16_t nb_events,
+                       const event_enqueue_burst_t fn)
+{
+       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+
+#ifdef RTE_LIBRTE_EVENTDEV_DEBUG
+       if (dev_id >= RTE_EVENT_MAX_DEVS || !rte_eventdevs[dev_id].attached) {
+               rte_errno = -EINVAL;
+               return 0;
+       }
+
+       if (port_id >= dev->data->nb_ports) {
+               rte_errno = -EINVAL;
+               return 0;
+       }
+#endif
+       /*
+        * Allow zero cost non burst mode routine invocation if application
+        * requests nb_events as const one
+        */
+       if (nb_events == 1)
+               return (*dev->enqueue)(dev->data->ports[port_id], ev);
+       else
+               return fn(dev->data->ports[port_id], ev, nb_events);
+}
 
 /**
  * Enqueue a burst of events objects or an event object supplied in *rte_event*
@@ -1012,14 +1163,124 @@ rte_event_schedule(uint8_t dev_id);
  *   The number of event objects actually enqueued on the event device. The
  *   return value can be less than the value of the *nb_events* parameter when
  *   the event devices queue is full or if invalid parameters are specified in a
- *   *rte_event*. If return value is less than *nb_events*, the remaining events
- *   at the end of ev[] are not consumed,and the caller has to take care of them
- *
+ *   *rte_event*. If the return value is less than *nb_events*, the remaining
+ *   events at the end of ev[] are not consumed and the caller has to take care
+ *   of them, and rte_errno is set accordingly. Possible errno values include:
+ *   - -EINVAL  The port ID is invalid, device ID is invalid, an event's queue
+ *              ID is invalid, or an event's sched type doesn't match the
+ *              capabilities of the destination queue.
+ *   - -ENOSPC  The event port was backpressured and unable to enqueue
+ *              one or more events. This error code is only applicable to
+ *              closed systems.
  * @see rte_event_port_enqueue_depth()
  */
-uint16_t
+static inline uint16_t
 rte_event_enqueue_burst(uint8_t dev_id, uint8_t port_id,
-                       const struct rte_event ev[], uint16_t nb_events);
+                       const struct rte_event ev[], uint16_t nb_events)
+{
+       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+
+       return __rte_event_enqueue_burst(dev_id, port_id, ev, nb_events,
+                       dev->enqueue_burst);
+}
+
+/**
+ * Enqueue a burst of events objects of operation type *RTE_EVENT_OP_NEW* on
+ * an event device designated by its *dev_id* through the event port specified
+ * by *port_id*.
+ *
+ * Provides the same functionality as rte_event_enqueue_burst(), expect that
+ * application can use this API when the all objects in the burst contains
+ * the enqueue operation of the type *RTE_EVENT_OP_NEW*. This specialized
+ * function can provide the additional hint to the PMD and optimize if possible.
+ *
+ * The rte_event_enqueue_new_burst() result is undefined if the enqueue burst
+ * has event object of operation type != RTE_EVENT_OP_NEW.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param port_id
+ *   The identifier of the event port.
+ * @param ev
+ *   Points to an array of *nb_events* objects of type *rte_event* structure
+ *   which contain the event object enqueue operations to be processed.
+ * @param nb_events
+ *   The number of event objects to enqueue, typically number of
+ *   rte_event_port_enqueue_depth() available for this port.
+ *
+ * @return
+ *   The number of event objects actually enqueued on the event device. The
+ *   return value can be less than the value of the *nb_events* parameter when
+ *   the event devices queue is full or if invalid parameters are specified in a
+ *   *rte_event*. If the return value is less than *nb_events*, the remaining
+ *   events at the end of ev[] are not consumed and the caller has to take care
+ *   of them, and rte_errno is set accordingly. Possible errno values include:
+ *   - -EINVAL  The port ID is invalid, device ID is invalid, an event's queue
+ *              ID is invalid, or an event's sched type doesn't match the
+ *              capabilities of the destination queue.
+ *   - -ENOSPC  The event port was backpressured and unable to enqueue
+ *              one or more events. This error code is only applicable to
+ *              closed systems.
+ * @see rte_event_port_enqueue_depth() rte_event_enqueue_burst()
+ */
+static inline uint16_t
+rte_event_enqueue_new_burst(uint8_t dev_id, uint8_t port_id,
+                       const struct rte_event ev[], uint16_t nb_events)
+{
+       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+
+       return __rte_event_enqueue_burst(dev_id, port_id, ev, nb_events,
+                       dev->enqueue_new_burst);
+}
+
+/**
+ * Enqueue a burst of events objects of operation type *RTE_EVENT_OP_FORWARD*
+ * on an event device designated by its *dev_id* through the event port
+ * specified by *port_id*.
+ *
+ * Provides the same functionality as rte_event_enqueue_burst(), expect that
+ * application can use this API when the all objects in the burst contains
+ * the enqueue operation of the type *RTE_EVENT_OP_FORWARD*. This specialized
+ * function can provide the additional hint to the PMD and optimize if possible.
+ *
+ * The rte_event_enqueue_new_burst() result is undefined if the enqueue burst
+ * has event object of operation type != RTE_EVENT_OP_FORWARD.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param port_id
+ *   The identifier of the event port.
+ * @param ev
+ *   Points to an array of *nb_events* objects of type *rte_event* structure
+ *   which contain the event object enqueue operations to be processed.
+ * @param nb_events
+ *   The number of event objects to enqueue, typically number of
+ *   rte_event_port_enqueue_depth() available for this port.
+ *
+ * @return
+ *   The number of event objects actually enqueued on the event device. The
+ *   return value can be less than the value of the *nb_events* parameter when
+ *   the event devices queue is full or if invalid parameters are specified in a
+ *   *rte_event*. If the return value is less than *nb_events*, the remaining
+ *   events at the end of ev[] are not consumed and the caller has to take care
+ *   of them, and rte_errno is set accordingly. Possible errno values include:
+ *   - -EINVAL  The port ID is invalid, device ID is invalid, an event's queue
+ *              ID is invalid, or an event's sched type doesn't match the
+ *              capabilities of the destination queue.
+ *   - -ENOSPC  The event port was backpressured and unable to enqueue
+ *              one or more events. This error code is only applicable to
+ *              closed systems.
+ * @see rte_event_port_enqueue_depth() rte_event_enqueue_burst()
+ */
+static inline uint16_t
+rte_event_enqueue_forward_burst(uint8_t dev_id, uint8_t port_id,
+                       const struct rte_event ev[], uint16_t nb_events)
+{
+       const struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+
+       return __rte_event_enqueue_burst(dev_id, port_id, ev, nb_events,
+                       dev->enqueue_forward_burst);
+}
 
 /**
  * Converts nanoseconds to *timeout_ticks* value for rte_event_dequeue_burst()
@@ -1038,7 +1299,9 @@ rte_event_enqueue_burst(uint8_t dev_id, uint8_t port_id,
  *
  * @return
  *  - 0 on success.
- *  - <0 on failure.
+ *  - -ENOTSUP if the device doesn't support timeouts
+ *  - -EINVAL if *dev_id* is invalid or *timeout_ticks* is NULL
+ *  - other values < 0 on failure.
  *
  * @see rte_event_dequeue_burst(), RTE_EVENT_DEV_CFG_PER_DEQUEUE_TIMEOUT
  * @see rte_event_dev_configure()
@@ -1098,7 +1361,7 @@ rte_event_dequeue_timeout_ticks(uint8_t dev_id, uint64_t ns,
  *   - 0 no-wait, returns immediately if there is no event.
  *   - >0 wait for the event, if the device is configured with
  *   RTE_EVENT_DEV_CFG_PER_DEQUEUE_TIMEOUT then this function will wait until
- *   the event available or *timeout_ticks* time.
+ *   at least one event is available or *timeout_ticks* time.
  *   if the device is not configured with RTE_EVENT_DEV_CFG_PER_DEQUEUE_TIMEOUT
  *   then this function will wait until the event available or
  *   *dequeue_timeout_ns* ns which was previously supplied to
@@ -1111,9 +1374,36 @@ rte_event_dequeue_timeout_ticks(uint8_t dev_id, uint64_t ns,
  *
  * @see rte_event_port_dequeue_depth()
  */
-uint16_t
+static inline uint16_t
 rte_event_dequeue_burst(uint8_t dev_id, uint8_t port_id, struct rte_event ev[],
-                       uint16_t nb_events, uint64_t timeout_ticks);
+                       uint16_t nb_events, uint64_t timeout_ticks)
+{
+       struct rte_eventdev *dev = &rte_eventdevs[dev_id];
+
+#ifdef RTE_LIBRTE_EVENTDEV_DEBUG
+       if (dev_id >= RTE_EVENT_MAX_DEVS || !rte_eventdevs[dev_id].attached) {
+               rte_errno = -EINVAL;
+               return 0;
+       }
+
+       if (port_id >= dev->data->nb_ports) {
+               rte_errno = -EINVAL;
+               return 0;
+       }
+#endif
+
+       /*
+        * Allow zero cost non burst mode routine invocation if application
+        * requests nb_events as const one
+        */
+       if (nb_events == 1)
+               return (*dev->dequeue)(
+                       dev->data->ports[port_id], ev, timeout_ticks);
+       else
+               return (*dev->dequeue_burst)(
+                       dev->data->ports[port_id], ev, nb_events,
+                               timeout_ticks);
+}
 
 /**
  * Link multiple source event queues supplied in *queues* to the destination
@@ -1158,7 +1448,8 @@ rte_event_dequeue_burst(uint8_t dev_id, uint8_t port_id, struct rte_event ev[],
  *   with RTE_EVENT_DEV_PRIORITY_NORMAL servicing priority
  *
  * @param nb_links
- *   The number of links to establish
+ *   The number of links to establish. This parameter is ignored if queues is
+ *   NULL.
  *
  * @return
  * The number of links actually established. The return value can be less than
@@ -1203,7 +1494,8 @@ rte_event_port_link(uint8_t dev_id, uint8_t port_id,
  *   event queue(s) from the event port *port_id*.
  *
  * @param nb_unlinks
- *   The number of unlinks to establish
+ *   The number of unlinks to establish. This parameter is ignored if queues is
+ *   NULL.
  *
  * @return
  * The number of unlinks actually established. The return value can be less
@@ -1268,6 +1560,148 @@ rte_event_port_links_get(uint8_t dev_id, uint8_t port_id,
 int
 rte_event_dev_dump(uint8_t dev_id, FILE *f);
 
+/** Maximum name length for extended statistics counters */
+#define RTE_EVENT_DEV_XSTATS_NAME_SIZE 64
+
+/**
+ * Selects the component of the eventdev to retrieve statistics from.
+ */
+enum rte_event_dev_xstats_mode {
+       RTE_EVENT_DEV_XSTATS_DEVICE,
+       RTE_EVENT_DEV_XSTATS_PORT,
+       RTE_EVENT_DEV_XSTATS_QUEUE,
+};
+
+/**
+ * A name-key lookup element for extended statistics.
+ *
+ * This structure is used to map between names and ID numbers
+ * for extended ethdev statistics.
+ */
+struct rte_event_dev_xstats_name {
+       char name[RTE_EVENT_DEV_XSTATS_NAME_SIZE];
+};
+
+/**
+ * Retrieve names of extended statistics of an event device.
+ *
+ * @param dev_id
+ *   The identifier of the event device.
+ * @param mode
+ *   The mode of statistics to retrieve. Choices include the device statistics,
+ *   port statistics or queue statistics.
+ * @param queue_port_id
+ *   Used to specify the port or queue number in queue or port mode, and is
+ *   ignored in device mode.
+ * @param[out] xstats_names
+ *   Block of memory to insert names into. Must be at least size in capacity.
+ *   If set to NULL, function returns required capacity.
+ * @param[out] ids
+ *   Block of memory to insert ids into. Must be at least size in capacity.
+ *   If set to NULL, function returns required capacity. The id values returned
+ *   can be passed to *rte_event_dev_xstats_get* to select statistics.
+ * @param size
+ *   Capacity of xstats_names (number of names).
+ * @return
+ *   - positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ *   - negative value on error:
+ *        -ENODEV for invalid *dev_id*
+ *        -EINVAL for invalid mode, queue port or id parameters
+ *        -ENOTSUP if the device doesn't support this function.
+ */
+int
+rte_event_dev_xstats_names_get(uint8_t dev_id,
+                              enum rte_event_dev_xstats_mode mode,
+                              uint8_t queue_port_id,
+                              struct rte_event_dev_xstats_name *xstats_names,
+                              unsigned int *ids,
+                              unsigned int size);
+
+/**
+ * Retrieve extended statistics of an event device.
+ *
+ * @param dev_id
+ *   The identifier of the device.
+ * @param mode
+ *  The mode of statistics to retrieve. Choices include the device statistics,
+ *  port statistics or queue statistics.
+ * @param queue_port_id
+ *   Used to specify the port or queue number in queue or port mode, and is
+ *   ignored in device mode.
+ * @param ids
+ *   The id numbers of the stats to get. The ids can be got from the stat
+ *   position in the stat list from rte_event_dev_get_xstats_names(), or
+ *   by using rte_eventdev_get_xstats_by_name()
+ * @param[out] values
+ *   The values for each stats request by ID.
+ * @param n
+ *   The number of stats requested
+ * @return
+ *   - positive value: number of stat entries filled into the values array
+ *   - negative value on error:
+ *        -ENODEV for invalid *dev_id*
+ *        -EINVAL for invalid mode, queue port or id parameters
+ *        -ENOTSUP if the device doesn't support this function.
+ */
+int
+rte_event_dev_xstats_get(uint8_t dev_id,
+                        enum rte_event_dev_xstats_mode mode,
+                        uint8_t queue_port_id,
+                        const unsigned int ids[],
+                        uint64_t values[], unsigned int n);
+
+/**
+ * Retrieve the value of a single stat by requesting it by name.
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param name
+ *   The stat name to retrieve
+ * @param[out] id
+ *   If non-NULL, the numerical id of the stat will be returned, so that further
+ *   requests for the stat can be got using rte_eventdev_xstats_get, which will
+ *   be faster as it doesn't need to scan a list of names for the stat.
+ *   If the stat cannot be found, the id returned will be (unsigned)-1.
+ * @return
+ *   - positive value or zero: the stat value
+ *   - negative value: -EINVAL if stat not found, -ENOTSUP if not supported.
+ */
+uint64_t
+rte_event_dev_xstats_by_name_get(uint8_t dev_id, const char *name,
+                                unsigned int *id);
+
+/**
+ * Reset the values of the xstats of the selected component in the device.
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param mode
+ *   The mode of the statistics to reset. Choose from device, queue or port.
+ * @param queue_port_id
+ *   The queue or port to reset. 0 and positive values select ports and queues,
+ *   while -1 indicates all ports or queues.
+ * @param ids
+ *   Selects specific statistics to be reset. When NULL, all statistics selected
+ *   by *mode* will be reset. If non-NULL, must point to array of at least
+ *   *nb_ids* size.
+ * @param nb_ids
+ *   The number of ids available from the *ids* array. Ignored when ids is NULL.
+ * @return
+ *   - zero: successfully reset the statistics to zero
+ *   - negative value: -EINVAL invalid parameters, -ENOTSUP if not supported.
+ */
+int
+rte_event_dev_xstats_reset(uint8_t dev_id,
+                          enum rte_event_dev_xstats_mode mode,
+                          int16_t queue_port_id,
+                          const uint32_t ids[],
+                          uint32_t nb_ids);
+
 #ifdef __cplusplus
 }
 #endif