Thanks Jerin, this looks good. I've put a few notes/questions inline. Thanks, Gage
> -----Original Message----- > From: Jerin Jacob [mailto:jerin.jacob at caviumnetworks.com] > Sent: Tuesday, October 11, 2016 2:30 PM > To: dev at dpdk.org > Cc: thomas.monjalon at 6wind.com; Richardson, Bruce > <bruce.richardson at intel.com>; Vangati, Narender > <narender.vangati at intel.com>; hemant.agrawal at nxp.com; Eads, Gage > <gage.eads at intel.com>; Jerin Jacob <jerin.jacob at caviumnetworks.com> > Subject: [dpdk-dev] [RFC] [PATCH v2] libeventdev: event driven programming > model framework for DPDK > > Thanks to Intel and NXP folks for the positive and constructive feedback > I've received so far. Here is the updated RFC(v2). > > I've attempted to address as many comments as possible. > > This series adds rte_eventdev.h to the DPDK tree with > adequate documentation in doxygen format. > > Updates are also available online: > > Related draft header file (this patch): > https://rawgit.com/jerinjacobk/libeventdev/master/rte_eventdev.h > > PDF version(doxgen output): > https://rawgit.com/jerinjacobk/libeventdev/master/librte_eventdev_v2.pdf > > Repo: > https://github.com/jerinjacobk/libeventdev > > v1..v2 > > - Added Cavium, Intel, NXP copyrights in header file > > - Changed the concept of flow queues to flow ids. > This is avoid dictating a specific structure to hold the flows. > A s/w implementation can do atomic load balancing on multiple > flow ids more efficiently than maintaining each event in a specific flow > queue. > > - Change the scheduling group to event queue. > A scheduling group is more a stream of events, so an event queue is a better > abstraction. > > - Introduced event port concept, Instead of trying eventdev access to the > lcore, > a higher level of abstraction called event port is needed which is the > application i/f to the eventdev to dequeue and enqueue the events. > One or more event queues can be linked to single event port. > There can be more than one event port per lcore allowing multiple lightweight > threads to have their own i/f into eventdev, if the implementation supports > it. > An event port will be bound to a lcore or a lightweight thread to keep > portable application workflow. > An event port abstraction also encapsulates dequeue depth and enqueue depth > for > a scheduler implementations which can schedule multiple events at a time and > output events that can be buffered. > > - Added configuration options with event queue(nb_atomic_flows, > nb_atomic_order_sequences, single consumer etc) > and event port(dequeue_queue_depth, enqueue_queue_depth etc) to define > the > limits on the resource usage.(Useful for optimized software implementation) > > - Introduced RTE_EVENT_DEV_CAP_QUEUE_QOS and > RTE_EVENT_DEV_CAP_EVENT_QOS > schemes of priority handling > > - Added event port to event queue servicing priority. > This allows two event ports to connect to the same event queue with > different priorities. > > - Changed the workflow as schedule/dequeue/enqueue. > An implementation is free to define schedule as NOOP. > A distributed s/w scheduler can use this to schedule events; > also a centralized s/w scheduler can make this a NOOP on non-scheduler cores. > > - Removed Cavium HW specific schedule_from_group API > > - Removed Cavium HW specific ctxt_update/ctxt_wait APIs. > Introduced a more generic "event pinning" concept. i.e > If the normal workflow is a dequeue -> do work based on event type -> > enqueue, > a pin_event argument to enqueue > where the pinned event is returned through the normal dequeue) > allows application workflow to remain the same whether or not an > implementation supports it. > > - Added dequeue() burst variant > > - Added the definition of a closed/open system - where open system is memory > backed and closed system eventdev has limited capacity. > In such systems, it is also useful to denote per event port how many packets > can be active in the system. > This can serve as a threshold for ethdev like devices so they don't overwhelm > core to core events. > > - Added the option to specify maximum amount of time(in ns) application needs > wait on dequeue() > > - Removed the scheme of expressing the number of flows in log2 format > > Open item or the item needs improvement. > ---------------------------------------- > - Abstract the differences in event QoS management with different priority > schemes > available in different HW or SW implementations with portable application > workflow. > > Based on the feedback, there three different kinds of QoS support available > in > three different HW or SW implementations. > 1) Priority associated with the event queue > 2) Priority associated with each event enqueue > (Same flow can have two different priority on two separate enqueue) > 3) Priority associated with the flow(each flow has unique priority) > > In v2, The differences abstracted based on device capability > (RTE_EVENT_DEV_CAP_QUEUE_QOS for the first scheme, > RTE_EVENT_DEV_CAP_EVENT_QOS for the second and third scheme). > This scheme would call for different application workflow for > nontrivial QoS-enabled applications. > > Looking forward to getting comments from both application and driver > implementation perspective. > > /Jerin > > --- > doc/api/doxy-api-index.md | 1 + > doc/api/doxy-api.conf | 1 + > lib/librte_eventdev/rte_eventdev.h | 1204 > ++++++++++++++++++++++++++++++++++++ > 3 files changed, 1206 insertions(+) > create mode 100644 lib/librte_eventdev/rte_eventdev.h > > diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md > index 6675f96..28c1329 100644 > --- a/doc/api/doxy-api-index.md > +++ b/doc/api/doxy-api-index.md > @@ -40,6 +40,7 @@ There are many libraries, so their headers may be > grouped by topics: > [ethdev] (@ref rte_ethdev.h), > [ethctrl] (@ref rte_eth_ctrl.h), > [cryptodev] (@ref rte_cryptodev.h), > + [eventdev] (@ref rte_eventdev.h), > [devargs] (@ref rte_devargs.h), > [bond] (@ref rte_eth_bond.h), > [vhost] (@ref rte_virtio_net.h), > diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf > index 9dc7ae5..9841477 100644 > --- a/doc/api/doxy-api.conf > +++ b/doc/api/doxy-api.conf > @@ -41,6 +41,7 @@ INPUT = doc/api/doxy-api-index.md \ > lib/librte_cryptodev \ > lib/librte_distributor \ > lib/librte_ether \ > + lib/librte_eventdev \ > lib/librte_hash \ > lib/librte_ip_frag \ > lib/librte_jobstats \ > diff --git a/lib/librte_eventdev/rte_eventdev.h > b/lib/librte_eventdev/rte_eventdev.h > new file mode 100644 > index 0000000..f60e461 > --- /dev/null > +++ b/lib/librte_eventdev/rte_eventdev.h > @@ -0,0 +1,1204 @@ > +/* > + * BSD LICENSE > + * > + * Copyright 2016 Cavium. > + * Copyright 2016 Intel Corporation. > + * Copyright 2016 NXP. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Cavium nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT > NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND > FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS > OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED > AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR > TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + */ > + > +#ifndef _RTE_EVENTDEV_H_ > +#define _RTE_EVENTDEV_H_ > + > +/** > + * @file > + * > + * RTE Event Device API > + * > + * The Event Device API is composed of two parts: > + * > + * - The application-oriented Event API that includes functions to setup > + * an event device (configure it, setup its queues, ports and start it), > to > + * establish the link between queues to port and to receive events, and > so on. > + * > + * - The driver-oriented Event API that exports a function allowing > + * an event poll Mode Driver (PMD) to simultaneously register itself as > + * an event device driver. > + * > + * Event device components: > + * > + * +-----------------+ > + * | +-------------+ | > + * +-------+ | | flow 0 | | > + * |Packet | | +-------------+ | > + * |event | | +-------------+ | > + * | | | | flow 1 | |event_port_link(port0, queue0) > + * +-------+ | +-------------+ | | +--------+ > + * +-------+ | +-------------+ o-----v-----o |dequeue > +------+ > + * |Crypto | | | flow n | | | event > +------->|Core 0| > + * |work | | +-------------+ o----+ | port 0 | | > | > + * |done ev| | event queue 0 | | +--------+ > +------+ > + * +-------+ +-----------------+ | > + * +-------+ | > + * |Timer | +-----------------+ | +--------+ > + * |expiry | | +-------------+ | +------o |dequeue > +------+ > + * |event | | | flow 0 | o-----------o event > +------->|Core 1| > + * +-------+ | +-------------+ | +----o port 1 | | > | > + * Event enqueue | +-------------+ | | +--------+ > +------+ > + * o-------------> | | flow 1 | | | > + * enqueue( | +-------------+ | | > + * queue_id, | | | +--------+ > +------+ > + * flow_id, | +-------------+ | | | |dequeue > |Core 2| > + * sched_type, | | flow n | o-----------o event +------->| > | > + * event_type, | +-------------+ | | | port 2 | > +------+ > + * subev_type, | event queue 1 | | +--------+ > + * event) +-----------------+ | +--------+ > + * | | |dequeue > +------+ > + * +-------+ +-----------------+ | | event > +------->|Core n| > + * |Core | | +-------------+ o-----------o port n | | > | > + * |(SW) | | | flow 0 | | | +--------+ > +--+---+ > + * |event | | +-------------+ | | | > + * +-------+ | +-------------+ | | | > + * ^ | | flow 1 | | | | > + * | | +-------------+ o------+ | > + * | | +-------------+ | | > + * | | | flow n | | | > + * | | +-------------+ | | > + * | | event queue n | | > + * | +-----------------+ | > + * | | > + * +-----------------------------------------------------------+ > + * > + * > + * > + * Event device: A hardware or software-based event scheduler. > + * > + * Event: A unit of scheduling that encapsulates a packet or other datatype > + * like SW generated event from the core, Crypto work completion > notification, > + * Timer expiry event notification etc as well as metadata. > + * The metadata includes flow ID, scheduling type, event priority, > event_type, > + * sub_event_type etc. > + * > + * Event queue: A queue containing events that are scheduled by the event > dev. > + * An event queue contains events of different flows associated with > scheduling > + * types, such as atomic, ordered, or parallel. > + * > + * Event port: An application's interface into the event dev for enqueue and > + * dequeue operations. Each event port can be linked with one or more > + * event queues for dequeue operations. > + * > + * By default, all the functions of the Event Device API exported by a PMD > + * are lock-free functions which assume to not be invoked in parallel on > + * different logical cores to work on the same target object. For instance, > + * the dequeue function of a PMD cannot be invoked in parallel on two > logical > + * cores to operates on same event port. Of course, this function > + * can be invoked in parallel by different logical cores on different ports. > + * It is the responsibility of the upper level application to enforce this > rule. > + * > + * In all functions of the Event API, the Event device is > + * designated by an integer >= 0 named the device identifier *dev_id* > + * > + * At the Event driver level, Event devices are represented by a generic > + * data structure of type *rte_event_dev*. > + * > + * Event devices are dynamically registered during the PCI/SoC device > probing > + * phase performed at EAL initialization time. > + * When an Event device is being probed, a *rte_event_dev* structure and > + * a new device identifier are allocated for that device. Then, the > + * event_dev_init() function supplied by the Event driver matching the > probed > + * device is invoked to properly initialize the device. > + * > + * The role of the device init function consists of resetting the hardware > or > + * software event driver implementations. > + * > + * If the device init operation is successful, the correspondence between > + * the device identifier assigned to the new device and its associated > + * *rte_event_dev* structure is effectively registered. > + * Otherwise, both the *rte_event_dev* structure and the device identifier > are > + * freed. > + * > + * The functions exported by the application Event API to setup a device > + * designated by its device identifier must be invoked in the following > order: > + * - rte_event_dev_configure() > + * - rte_event_queue_setup() > + * - rte_event_port_setup() > + * - rte_event_port_link() > + * - rte_event_dev_start() > + * > + * Then, the application can invoke, in any order, the functions > + * exported by the Event API to schedule events, dequeue events, enqueue > events, > + * change event queue(s) to event port [un]link establishment and so on. > + * > + * Application may use rte_event_[queue/port]_default_conf_get() to get the > + * default configuration to set up an event queue or event port by > + * overriding few default values. > + * > + * If the application wants to change the configuration (i.e. call > + * rte_event_dev_configure(), rte_event_queue_setup(), or > + * rte_event_port_setup()), it must call rte_event_dev_stop() first to stop > the > + * device and then do the reconfiguration before calling > rte_event_dev_start() > + * again. The schedule, enqueue and dequeue functions should not be invoked > + * when the device is stopped. > + * > + * Finally, an application can close an Event device by invoking the > + * rte_event_dev_close() function. > + * > + * Each function of the application Event API invokes a specific function > + * of the PMD that controls the target device designated by its device > + * identifier. > + * > + * For this purpose, all device-specific functions of an Event driver are > + * supplied through a set of pointers contained in a generic structure of > type > + * *event_dev_ops*. > + * The address of the *event_dev_ops* structure is stored in the > *rte_event_dev* > + * structure by the device init function of the Event driver, which is > + * invoked during the PCI/SoC device probing phase, as explained earlier. > + * > + * In other words, each function of the Event API simply retrieves the > + * *rte_event_dev* structure associated with the device identifier and > + * performs an indirect invocation of the corresponding driver function > + * supplied in the *event_dev_ops* structure of the *rte_event_dev* > structure. > + * > + * For performance reasons, the address of the fast-path functions of the > + * Event driver is not contained in the *event_dev_ops* structure. > + * Instead, they are directly stored at the beginning of the *rte_event_dev* > + * structure to avoid an extra indirect memory access during their > invocation. > + * > + * RTE event device drivers do not use interrupts for enqueue or dequeue > + * 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 *schedule* operation is intended to do event scheduling, and the > + * *dequeue* operation returns the scheduled events. An implementation > + * is free to define the semantics between *schedule* and *dequeue*. For > + * example, a system based on a hardware scheduler can define its > + * rte_event_schedule() to be an NOOP, whereas a software scheduler can use > + * the *schedule* operation to schedule events. > + * > + * 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, core(SW) for generating events > based > + * on different stages of application processing, cryptodev for generating > + * crypto work completion notification etc > + * > + * The *dequeue* operation gets one or more events from the event ports. > + * The application process the events and send to downstream event queue > through > + * rte_event_enqueue() if it is an intermediate stage of event processing, > on > + * the final stage, the application may send to different subsystem like > ethdev > + * to send the packet/event on the wire using ethdev rte_eth_tx_burst() API. > + * > + */ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <rte_pci.h> > +#include <rte_dev.h> > +#include <rte_devargs.h> > +#include <rte_errno.h> > + > +/** > + * Get the total number of event devices that have been successfully > + * initialised. > + * > + * @return > + * The total number of usable event devices. > + */ > +extern uint8_t > +rte_event_dev_count(void); > + > +/** > + * Get the device identifier for the named event device. > + * > + * @param name > + * Event device name to select the event device identifier. > + * > + * @return > + * Returns event device identifier on success. > + * - <0: Failure to find named event device. > + */ > +extern uint8_t > +rte_event_dev_get_dev_id(const char *name); This return type should be int8_t, or some signed type, to support the failure case. > + > +/** > + * Return the NUMA socket to which a device is connected. > + * > + * @param dev_id > + * The identifier of the device. > + * @return > + * The NUMA socket id to which the device is connected or > + * a default of zero if the socket could not be determined. > + * - -1: dev_id value is out of range. > + */ > +extern int > +rte_event_dev_socket_id(uint8_t dev_id); > + > +/* Event device capability bitmap flags */ > +#define RTE_EVENT_DEV_CAP_QUEUE_QOS (1 << 0) > +/**< Event scheduling prioritization is based on the priority associated > with > + * each event queue. > + * > + * \see rte_event_queue_setup(), RTE_EVENT_QUEUE_PRIORITY_NORMAL > + */ > +#define RTE_EVENT_DEV_CAP_EVENT_QOS (1 << 1) > +/**< Event scheduling prioritization is based on the priority associated > with > + * each event. Priority of each event is supplied in *rte_event* structure > + * on each enqueue operation. > + * > + * \see rte_event_enqueue() > + */ > + > +/** > + * Event device information > + */ > +struct rte_event_dev_info { > + const char *driver_name; /**< Event driver name */ > + struct rte_pci_device *pci_dev; /**< PCI information */ > + uint32_t min_dequeue_wait_ns; > + /**< Minimum supported global dequeue wait delay(ns) by this device > */ > + uint32_t max_dequeue_wait_ns; > + /**< Maximum supported global dequeue wait delay(ns) by this device > */ > + uint32_t dequeue_wait_ns; > + /**< Configured global dequeue wait delay(ns) for this device */ > + uint8_t max_event_queues; > + /**< Maximum event_queues supported by this device */ > + uint32_t max_event_queue_flows; > + /**< Maximum supported flows in an event queue by this device*/ > + uint8_t max_event_queue_priority_levels; > + /**< Maximum number of event queue priority levels by this device. > + * Valid when the device has RTE_EVENT_DEV_CAP_QUEUE_QOS > capability > + */ > + uint8_t nb_event_queues; > + /**< Configured number of event queues for this device */ > + uint8_t max_event_priority_levels; > + /**< Maximum number of event priority levels by this device. > + * Valid when the device has RTE_EVENT_DEV_CAP_EVENT_QOS > capability > + */ > + uint8_t max_event_ports; > + /**< Maximum number of event ports supported by this device */ > + uint8_t nb_event_ports; > + /**< Configured number of event ports for this device */ > + uint8_t max_event_port_dequeue_queue_depth; > + /**< Maximum dequeue queue depth for any event port. > + * Implementations can schedule N events at a time to an event port. > + * A device that does not support bulk dequeue will set this as 1. > + * \see rte_event_port_setup() > + */ > + uint32_t max_event_port_enqueue_queue_depth; > + /**< Maximum enqueue queue depth for any event port. > Implementations > + * can batch N events at a time to enqueue through event port > + * \see rte_event_port_setup() > + */ > + int32_t max_num_events; > + /**< A *closed system* event dev has a limit on the number of events > it > + * can manage at a time. An *open system* event dev does not have a > + * limit and will specify this as -1. > + */ > + uint32_t event_dev_cap; > + /**< Event device capabilities(RTE_EVENT_DEV_CAP_)*/ > +}; > + > +/** > + * Retrieve the contextual information of an event device. > + * > + * @param dev_id > + * The identifier of the device. > + * > + * @param[out] dev_info > + * A pointer to a structure of type *rte_event_dev_info* to be filled > with the > + * contextual information of the device. > + * > + */ > +extern void > +rte_event_dev_info_get(uint8_t dev_id, struct rte_event_dev_info > *dev_info); I'm wondering if this return type should be int, so we can return an error if the dev_id is invalid. > + > +/* Event device configuration bitmap flags */ > +#define RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT (1 << 0) > +/**< Override the global *dequeue_wait_ns* and use per dequeue wait in ns. > + * \see rte_event_dequeue_wait_time(), rte_event_dequeue() > + */ > + > +/** Event device configuration structure */ > +struct rte_event_dev_config { > + uint32_t dequeue_wait_ns; > + /**< rte_event_dequeue() wait for *dequeue_wait_ns* ns on this > device. > + * This value should be in the range of *min_dequeue_wait_ns* and > + * *max_dequeue_wait_ns* which previously provided in > + * rte_event_dev_info_get() > + * \see RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT > + */ > + 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() > + */ > + uint8_t nb_event_queues; > + /**< Number of event queues to configure on this device. > + * This value cannot exceed the *max_event_queues* which previously > + * provided in rte_event_dev_info_get() > + */ > + uint8_t nb_event_ports; > + /**< Number of event ports to configure on this device. > + * This value cannot exceed the *max_event_ports* which previously > + * provided in rte_event_dev_info_get() > + */ > + uint32_t event_dev_cfg; > + /**< Event device config flags(RTE_EVENT_DEV_CFG_)*/ > +}; > + > +/** > + * Configure an event device. > + * > + * This function must be invoked first before any other function in the > + * API. This function can also be re-invoked when a device is in the > + * stopped state. > + * > + * The caller may use rte_event_dev_info_get() to get the capability of each > + * resources available for this event device. > + * > + * @param dev_id > + * The identifier of the device to configure. > + * @param config > + * The event device configuration structure. > + * > + * @return > + * - 0: Success, device configured. > + * - <0: Error code returned by the driver configuration function. > + */ > +extern int > +rte_event_dev_configure(uint8_t dev_id, struct rte_event_dev_config > *config); > + > + > +/* Event queue specific APIs */ > + > +#define RTE_EVENT_QUEUE_PRIORITY_HIGHEST 0 > +/**< Highest event queue priority */ > +#define RTE_EVENT_QUEUE_PRIORITY_NORMAL 128 > +/**< Normal event queue priority */ > +#define RTE_EVENT_QUEUE_PRIORITY_LOWEST 255 > +/**< Lowest event queue priority */ > + > +/* Event queue configuration bitmap flags */ > +#define RTE_EVENT_QUEUE_CFG_SINGLE_CONSUMER (1 << 0) > +/**< This event queue links only to a single event port. > + * > + * \see rte_event_port_setup(), rte_event_port_link() > + */ > + > +/** Event queue configuration structure */ > +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 - max_event_queue_flows)] which previously supplied > + * to rte_event_dev_configure(). > + */ > + uint32_t nb_atomic_order_sequences; > + /**< The maximum number of outstanding events waiting to be > (egress-) > + * reordered by this queue. In other words, the number of entries in > + * this queue?s reorder buffer.The value must be in the range of > + * [1 - max_event_queue_flows)] which previously supplied > + * to rte_event_dev_configure(). > + */ > + uint32_t event_queue_cfg; /**< Queue config > flags(EVENT_QUEUE_CFG_) */ > + uint8_t priority; > + /**< Priority for this event queue relative to other event queues. > + * The requested priority should in the range of > + * [RTE_EVENT_QUEUE_PRIORITY_HIGHEST, > RTE_EVENT_QUEUE_PRIORITY_LOWEST]. > + * The implementation shall normalize the requested priority to > + * event device supported priority value. > + * Valid when the device has RTE_EVENT_DEV_CAP_QUEUE_QOS > capability > + */ > +}; > + > +/** > + * Retrieve the default configuration information of an event queue > designated > + * by its *queue_id* from the event driver for an event device. > + * > + * This function intended to be used in conjunction with > rte_event_queue_setup() > + * where caller needs to set up the queue by overriding few default values. > + * > + * @param dev_id > + * The identifier of the device. > + * @param queue_id > + * The index of the event queue to get the configuration information. > + * The value must be in the range [0, nb_event_queues - 1] > + * previously supplied to rte_event_dev_configure(). > + * @param[out] queue_conf > + * The pointer to the default event queue configuration data. > + * > + * \see rte_event_queue_setup() > + * > + */ > +extern void > +rte_event_queue_default_conf_get(uint8_t dev_id, uint8_t queue_id, > + struct rte_event_queue_conf *queue_conf); > + > +/** > + * Allocate and set up an event queue for an event device. > + * > + * @param dev_id > + * The identifier of the device. > + * @param queue_id > + * The index of the event queue to setup. The value must be in the range > + * [0, nb_event_queues - 1] previously supplied to > rte_event_dev_configure(). > + * @param queue_conf > + * The pointer to the configuration data to be used for the event queue. > + * NULL value is allowed, in which case default configuration used. > + * > + * \see rte_event_queue_default_conf_get() > + * > + * @return > + * - 0: Success, event queue correctly set up. > + * - <0: event queue configuration failed > + */ > +extern int > +rte_event_queue_setup(uint8_t dev_id, uint8_t queue_id, > + struct rte_event_queue_conf *queue_conf); > + > +/** > + * Get the number of event queues on a specific event device > + * > + * @param dev_id > + * Event device identifier. > + * @return > + * - The number of configured event queues > + */ > +extern uint16_t > +rte_event_queue_count(uint8_t dev_id); > + > +/** > + * Get the priority of the event queue on a specific event device > + * > + * @param dev_id > + * Event device identifier. > + * @param queue_id > + * Event queue identifier. > + * @return > + * - If the device has RTE_EVENT_DEV_CAP_QUEUE_QOS capability then the > + * configured priority of the event queue in > + * [RTE_EVENT_QUEUE_PRIORITY_HIGHEST, > RTE_EVENT_QUEUE_PRIORITY_LOWEST] range > + * else the value one > + */ > +extern uint8_t > +rte_event_queue_priority(uint8_t dev_id, uint8_t queue_id); > + > +/* Event port specific APIs */ > + > +/** Event port configuration structure */ > +struct rte_event_port_conf { > + int32_t new_event_threshold; > + /**< A backpressure threshold for new event enqueues on this port. > + * Use for *closed system* event dev where event capacity is limited, > + * and cannot exceed the capacity of the event dev. > + * Configuring ports with different thresholds can make higher priority > + * traffic less likely to be backpressured. > + * For example, a port used to inject NIC Rx packets into the event dev > + * can have a lower threshold so as not to overwhelm the device, > + * while ports used for worker pools can have a higher threshold. > + */ > + uint8_t dequeue_queue_depth; > + /**< Configure number of bulk dequeues for this event port. > + * This value cannot exceed the > *max_event_port_dequeue_queue_depth* > + * which previously supplied to rte_event_dev_configure() > + */ > + uint8_t enqueue_queue_depth; > + /**< Configure number of bulk enqueues for this event port. > + * This value cannot exceed the > *max_event_port_enqueue_queue_depth* > + * which previously supplied to rte_event_dev_configure() > + */ > +}; > + > +/** > + * Retrieve the default configuration information of an event port > designated > + * by its *port_id* from the event driver for an event device. > + * > + * This function intended to be used in conjunction with > rte_event_port_setup() > + * where caller needs to set up the port by overriding few default values. > + * > + * @param dev_id > + * The identifier of the device. > + * @param port_id > + * The index of the event port to get the configuration information. > + * The value must be in the range [0, nb_event_ports - 1] > + * previously supplied to rte_event_dev_configure(). > + * @param[out] port_conf > + * The pointer to the default event port configuration data > + * > + * \see rte_event_port_setup() > + * > + */ > +extern void > +rte_event_port_default_conf_get(uint8_t dev_id, uint8_t port_id, > + struct rte_event_port_conf *port_conf); > + > +/** > + * Allocate and set up an event port for an event device. > + * > + * @param dev_id > + * The identifier of the device. > + * @param port_id > + * The index of the event port to setup. The value must be in the range > + * [0, nb_event_ports - 1] previously supplied to > rte_event_dev_configure(). > + * @param port_conf > + * The pointer to the configuration data to be used for the queue. > + * NULL value is allowed, in which case default configuration used. > + * > + * \see rte_event_port_default_conf_get() > + * > + * @return > + * - 0: Success, event port correctly set up. > + * - <0: Port configuration failed > + * - (-EDQUOT) Quota exceeded(Application tried to link the queue > configured > + * with RTE_EVENT_QUEUE_CFG_SINGLE_CONSUMER to more than one > event ports) > + */ > +extern int > +rte_event_port_setup(uint8_t dev_id, uint8_t port_id, > + struct rte_event_port_conf *port_conf); > + > +/** > + * Get the number of dequeue queue depth configured for event port > designated > + * by its *port_id* on a specific event device > + * > + * @param dev_id > + * Event device identifier. > + * @param port_id > + * Event port identifier. > + * @return > + * - The number of configured dequeue queue depth > + * > + * \see rte_event_dequeue_burst() > + */ > +extern uint8_t > +rte_event_port_dequeue_depth(uint8_t dev_id, uint8_t port_id); > + > +/** > + * Get the number of enqueue queue depth configured for event port > designated > + * by its *port_id* on a specific event device > + * > + * @param dev_id > + * Event device identifier. > + * @param port_id > + * Event port identifier. > + * @return > + * - The number of configured enqueue queue depth > + * > + * \see rte_event_enqueue_burst() > + */ > +extern uint8_t > +rte_event_port_enqueue_depth(uint8_t dev_id, uint8_t port_id); > + > +/** > + * Get the number of ports on a specific event device > + * > + * @param dev_id > + * Event device identifier. > + * @return > + * - The number of configured ports > + */ > +extern uint8_t > +rte_event_port_count(uint8_t dev_id); > + > +/** > + * Start an event device. > + * > + * The device start step is the last one and consists of setting the event > + * queues to start accepting the events and schedules to event ports. > + * > + * On success, all basic functions exported by the API (event enqueue, > + * event dequeue and so on) can be invoked. > + * > + * @param dev_id > + * Event device identifier > + * @return > + * - 0: Success, device started. > + * - <0: Error code of the driver device start function. > + */ > +extern int > +rte_event_dev_start(uint8_t dev_id); > + > +/** > + * Stop an event device. The device can be restarted with a call to > + * rte_event_dev_start() > + * > + * @param dev_id > + * Event device identifier. > + */ > +extern void > +rte_event_dev_stop(uint8_t dev_id); > + > +/** > + * Close an event device. The device cannot be restarted! > + * > + * @param dev_id > + * Event device identifier > + * > + * @return > + * - 0 on successfully closing device > + * - <0 on failure to close device > + */ > +extern int > +rte_event_dev_close(uint8_t dev_id); > + > +/* Scheduler type definitions */ > +#define RTE_SCHED_TYPE_ORDERED 0 > +/**< Ordered scheduling > + * > + * Events from an ordered flow of an event queue can be scheduled to > multiple > + * ports for concurrent processing while maintaining the original event > order. > + * This scheme enables the user to achieve high single flow throughput by > + * avoiding SW synchronization for ordering between ports which bound to > cores. > + * > + * The source flow ordering from an event queue is maintained when events > are > + * enqueued to their destination queue within the same ordered flow context. > + * An event port holds the context until application call > rte_event_dequeue() > + * from the same port, which implicitly releases the context. > + * User may allow the scheduler to release the context earlier than that > + * by calling rte_event_release() > + * > + * Events from the source queue appear in their original order when dequeued > + * from a destination queue. > + * Event ordering is based on the received event(s), but also other > + * (newly allocated or stored) events are ordered when enqueued within the > same > + * ordered context. Events not enqueued (e.g. released or stored) within the > + * context are considered missing from reordering and are skipped at this > time > + * (but can be ordered again within another context). > + * > + * \see rte_event_dequeue(), rte_event_release() > + */ > + > +#define RTE_SCHED_TYPE_ATOMIC 1 > +/**< Atomic scheduling > + * > + * Events from an atomic flow of an event queue can be scheduled only to a > + * single port at a time. The port is guaranteed to have exclusive (atomic) > + * access to the associated flow context, which enables the user to avoid SW > + * synchronization. Atomic flows also help to maintain event ordering > + * since only one port at a time can process events from a flow of an > + * event queue. > + * > + * The atomic queue synchronization context is dedicated to the port until > + * application call rte_event_dequeue() from the same port, which implicitly > + * releases the context. User may allow the scheduler to release the context > + * earlier than that by calling rte_event_release() > + * > + * \see rte_event_dequeue(), rte_event_release() > + */ > + > +#define RTE_SCHED_TYPE_PARALLEL 2 > +/**< Parallel scheduling > + * > + * The scheduler performs priority scheduling, load balancing, etc. > functions > + * but does not provide additional event synchronization or ordering. > + * It is free to schedule events from a single parallel flow of an event > queue > + * to multiple events ports for concurrent processing. > + * The application is responsible for flow context synchronization and > + * event ordering (SW synchronization). > + */ > + > +/* Event types to classify the event source */ > +#define RTE_EVENT_TYPE_ETHDEV 0x0 > +/**< The event generated from ethdev subsystem */ > +#define RTE_EVENT_TYPE_CRYPTODEV 0x1 > +/**< The event generated from crypodev subsystem */ > +#define RTE_EVENT_TYPE_TIMERDEV 0x2 > +/**< The event generated from timerdev subsystem */ > +#define RTE_EVENT_TYPE_CORE 0x3 > +/**< The event generated from core. > + * Application may use *sub_event_type* to further classify the event > + */ > +#define RTE_EVENT_TYPE_MAX 0x10 > +/**< Maximum number of event types */ > + > +/* Event priority */ > +#define RTE_EVENT_PRIORITY_HIGHEST 0 > +/**< Highest event priority */ > +#define RTE_EVENT_PRIORITY_NORMAL 128 > +/**< Normal event priority */ > +#define RTE_EVENT_PRIORITY_LOWEST 255 > +/**< Lowest event priority */ > + > +/** > + * The generic *rte_event* structure to hold the event attributes > + * for dequeue and enqueue operation > + */ > +struct rte_event { > + /** WORD0 */ > + RTE_STD_C11 > + union { > + uint64_t u64; > + /** Event attributes for dequeue or enqueue operation */ > + struct { > + uint32_t flow_id:24; > + /**< Targeted flow identifier for the enqueue and > + * dequeue operation. > + * The value must be in the range of > + * [1 - max_event_queue_flows)] which > + * previously supplied to rte_event_dev_configure(). > + */ > + uint32_t queue_id:8; > + /**< Targeted event queue identifier for the enqueue > or > + * dequeue operation. > + * The value must be in the range of > + * [0, nb_event_queues - 1] which previously supplied > to > + * rte_event_dev_configure(). > + */ > + uint8_t sched_type; > + /**< Scheduler synchronization type > (RTE_SCHED_TYPE_) > + * associated with flow id on a given event queue > + * for the enqueue and dequeue operation. > + */ > + uint8_t event_type; > + /**< Event type to classify the event source. */ > + uint8_t sub_event_type; > + /**< Sub-event types based on the event source. > + * \see RTE_EVENT_TYPE_CORE > + */ > + uint8_t priority; > + /**< Event priority relative to other events in the > + * event queue. The requested priority should in the > + * range of [RTE_EVENT_PRIORITY_HIGHEST, > + * RTE_EVENT_PRIORITY_LOWEST]. > + * The implementation shall normalize the requested > + * priority to supported priority value. > + * Valid when the device has > RTE_EVENT_DEV_CAP_EVENT_QOS > + * capability. > + */ > + }; > + }; > + /** WORD1 */ > + RTE_STD_C11 > + union { > + uintptr_t event; > + /**< Opaque event pointer */ > + struct rte_mbuf *mbuf; > + /**< mbuf pointer if dequeued event is associated with mbuf > */ > + }; > +}; > + > +/** > + * Schedule one or more events in the event dev. > + * > + * An event dev implementation may define this is a NOOP, for instance if > + * the event dev performs its scheduling in hardware. > + * > + * @param dev_id > + * The identifier of the device. > + */ > +extern void > +rte_event_schedule(uint8_t dev_id); One idea: Have the function return the number of scheduled packets (or 0 for implementations that do scheduling in hardware). This could be a helpful diagnostic for the software scheduler. > + > +/** > + * Enqueue the event object supplied in the *rte_event* structure on an > + * event device designated by its *dev_id* through the event port specified > by > + * *port_id*. The event object specifies the event queue on which this > + * event will be enqueued. > + * > + * @param dev_id > + * Event device identifier. > + * @param port_id > + * The identifier of the event port. > + * @param ev > + * Pointer to struct rte_event > + * @param pin_event > + * Hint to the scheduler that the event can be pinned to the same port for > + * the next scheduling stage. For implementations that support it, this > + * allows the same core to process the next stage in the pipeline for a > given > + * event, taking advantage of cache locality. The pinned event will be > + * received through rte_event_dequeue(). This is a hint and the event is > + * not guaranteed to be pinned to the port. This hint is valid only when > the > + * event is dequeued with rte_event_dequeue() followed by > rte_event_enqueue(). > + * > + * @return > + * - 0 on success > + * - <0 on failure. Failure can occur if the event port's output queue is > + * backpressured, for instance. > + */ > +extern int > +rte_event_enqueue(uint8_t dev_id, uint8_t port_id, struct rte_event *ev, > + bool pin_event); > + > +/** > + * Enqueue a burst of events objects supplied in *rte_event* structure on an > + * event device designated by its *dev_id* through the event port specified > by > + * *port_id*. Each event object specifies the event queue on which it > + * will be enqueued. > + * > + * The rte_event_enqueue_burst() function is invoked to enqueue > + * multiple event objects. > + * It is the burst variant of rte_event_enqueue() function. > + * > + * The *num* parameter is the number of event objects to enqueue which are > + * supplied in the *ev* array of *rte_event* structure. > + * > + * The rte_event_enqueue_burst() function returns the number of > + * events objects it actually enqueued. A return value equal to *num* means > + * that all event objects have been enqueued. > + * > + * @param dev_id > + * The identifier of the device. > + * @param port_id > + * The identifier of the event port. > + * @param ev > + * An array of *num* pointers to *rte_event* structure > + * which contain the event object enqueue operations to be processed. > + * @param num > + * The number of event objects to enqueue, typically number of > + * rte_event_port_enqueue_depth() available for this port. > + * @param pin_event > + * Hint to the scheduler that the event can be pinned to the same port for > + * the next scheduling stage. For implementations that support it, this > + * allows the same core to process the next stage in the pipeline for a > given > + * event, taking advantage of cache locality. The pinned event will be > + * received through rte_event_dequeue(). This is a hint and the event is > + * not guaranteed to be pinned to the port. This hint is valid only when > the > + * event is dequeued with rte_event_dequeue() followed by > rte_event_enqueue(). > + * > + * @return > + * The number of event objects actually enqueued on the event device. The > + * return value can be less than the value of the *num* parameter when the > + * event devices queue is full or if invalid parameters are specified in a > + * *rte_event*. If return value is less than *num*, the remaining events > at > + * the end of ev[] are not consumed, and the caller has to take care of > them. > + * > + * \see rte_event_enqueue(), rte_event_port_enqueue_depth() > + */ > +extern int > +rte_event_enqueue_burst(uint8_t dev_id, uint8_t port_id, > + struct rte_event ev[], int num, bool pin_event); > + > +/** > + * Converts nanoseconds to *wait* value for rte_event_dequeue() > + * > + * If the device is configured with > RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT flag then > + * application can use this function to convert wait value in nanoseconds to > + * implementations specific wait value supplied in rte_event_dequeue() > + * > + * @param dev_id > + * The identifier of the device. > + * @param ns > + * Wait time in nanosecond > + * > + * @return > + * Value for the *wait* parameter in rte_event_dequeue() function > + * > + * \see rte_event_dequeue(), RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT > + * \see rte_event_dev_configure() > + * > + */ > +extern uint64_t > +rte_event_dequeue_wait_time(uint8_t dev_id, uint64_t ns); > + > +/** > + * Dequeue an event from the event port specified by *port_id* on the > + * event device designated by its *dev_id*. > + * > + * rte_event_dequeue() does not dictate the specifics of scheduling > algorithm > as > + * each eventdev driver may have different criteria to schedule an event. > + * However, in general, from an application perspective scheduler may use > the > + * following scheme to dispatch an event to the port. > + * > + * 1) Selection of event queue based on > + * a) The list of event queues are linked to the event port. > + * b) If the device has RTE_EVENT_DEV_CAP_QUEUE_QOS capability then > event > + * queue selection from list is based on event queue priority relative to > + * other event queue supplied as *priority* in rte_event_queue_setup() > + * c) If the device has RTE_EVENT_DEV_CAP_EVENT_QOS capability then > event > + * queue selection from the list is based on event priority supplied as > + * *priority* in rte_event_enqueue_burst() > + * 2) Selection of event > + * a) The number of flows available in selected event queue. > + * b) Schedule type method associated with the event > + * > + * On a successful dequeue, the event port holds flow id and schedule type > + * context associated with the dispatched event. The context is > automatically > + * released in the next rte_event_dequeue() invocation, or > rte_event_release() > + * can be called to release the context early. > + * > + * @param dev_id > + * The identifier of the device. > + * @param port_id > + * The identifier of the event port. > + * @param[out] ev > + * Pointer to struct rte_event. On successful event dispatch, > implementation > + * updates the event attributes. > + * @param wait > + * 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_WAIT then this function will wait > until > + * the event available or *wait* time. > + * if the device is not configured with > RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT > + * then this function will wait until the event available or > *dequeue_wait_ns* > + * ns which was previously supplied to rte_event_dev_configure() > + * > + * @return > + * When true, a valid event has been dispatched by the scheduler. > + * > + */ > +extern bool > +rte_event_dequeue(uint8_t dev_id, uint8_t port_id, > + struct rte_event *ev, uint64_t wait); > + > +/** > + * Dequeue a burst of events objects from the event port designated by its > + * *event_port_id*, on an event device designated by its *dev_id*. > + * > + * The rte_event_dequeue_burst() function is invoked to dequeue > + * multiple event objects. It is the burst variant of rte_event_dequeue() > + * function. > + * > + * The *num* parameter is the maximum number of event objects to dequeue > which > + * are returned in the *ev* array of *rte_event* structure. > + * > + * The rte_event_dequeue_burst() function returns the number of > + * events objects it actually dequeued. A return value equal to > + * *num* means that all event objects have been dequeued. > + * > + * The number of events dequeued is the number of scheduler contexts held > by > + * this port. These contexts are automatically released in the next > + * rte_event_dequeue() invocation, or rte_event_release() can be called once > + * per event to release the contexts early. > + * > + * @param dev_id > + * The identifier of the device. > + * @param port_id > + * The identifier of the event port. > + * @param[out] ev > + * An array of *num* pointers to *rte_event* structure which is populated > + * with the dequeued event objects. > + * @param num > + * The maximum number of event objects to dequeue, typically number of > + * rte_event_port_dequeue_depth() available for this port. > + * @param wait > + * 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_WAIT then this function will wait > until the > + * event available or *wait* time. > + * if the device is not configured with > RTE_EVENT_DEV_CFG_PER_DEQUEUE_WAIT > + * then this function will wait until the event available or > *dequeue_wait_ns* > + * ns which was previously supplied to rte_event_dev_configure() > + * > + * @return > + * The number of event objects actually dequeued from the port. The return > + * value can be less than the value of the *num* parameter when the > + * event port's queue is not full. > + * > + * \see rte_event_dequeue(), rte_event_port_dequeue_depth() > + */ > +extern int > +rte_event_dequeue_burst(uint8_t dev_id, uint8_t port_id, > + struct rte_event *ev, int num, uint64_t wait); > + > +/** > + * Release the current flow context associated with a schedule type which > + * dequeued from a given event queue though the event port designated by > + * its *port_id* > + * > + * If current flow's scheduler type method is *RTE_SCHED_TYPE_ATOMIC* > + * then this function hints the scheduler that the user has completed > critical > + * section processing in the current atomic context. > + * The scheduler is now allowed to schedule events from the same flow from > + * an event queue to another port. However, the context may be still held > + * until the next rte_event_dequeue() or rte_event_dequeue_burst() call, > this > + * call allows but does not force the scheduler to release the context > early. > + * > + * Early atomic context release may increase parallelism and thus system > + * performance, but the user needs to design carefully the split into > critical > + * vs non-critical sections. > + * > + * If current flow's scheduler type method is *RTE_SCHED_TYPE_ORDERED* > + * then this function hints the scheduler that the user has done all that > need > + * to maintain event order in the current ordered context. > + * The scheduler is allowed to release the ordered context of this port and > + * avoid reordering any following enqueues. > + * > + * Early ordered context release may increase parallelism and thus system > + * performance. > + * > + * If current flow's scheduler type method is *RTE_SCHED_TYPE_PARALLEL* > + * or no scheduling context is held then this function may be an NOOP, > + * depending on the implementation. > + * > + * If multiple events are dequeued with rte_event_dequeue_burst(), > + * rte_event_release() will release each flow context associated with a > + * schedule type of an event though *index*, it denotes the order in > + * which it was dequeued with rte_event_dequeue_burst() > + * > + * @param dev_id > + * The identifier of the device. > + * @param port_id > + * The identifier of the event port. > + * @param index > + * The index of the event that dequeued with rte_event_dequeue_burst() > + * which needs to release. The value zero used if the event dequeued with > + * rte_event_dequeue() > + * > + * \see rte_event_dequeue(), rte_event_dequeue_burst() > + */ > +extern void > +rte_event_release(uint8_t dev_id, uint8_t port_id, uint8_t index); > + > +#define RTE_EVENT_QUEUE_SERVICE_PRIORITY_HIGHEST 0 > +/**< Highest event queue servicing priority */ > +#define RTE_EVENT_QUEUE_SERVICE_PRIORITY_NORMAL 128 > +/**< Normal event queue servicing priority */ > +#define RTE_EVENT_QUEUE_SERVICE_PRIORITY_LOWEST 255 > +/**< Lowest event queue servicing priority */ > + > +/** Structure to hold the queue to port link establishment attributes */ > +struct rte_event_queue_link { > + uint8_t queue_id; > + /**< Event queue identifier to select the source queue to link */ > + uint8_t priority; > + /**< The priority of the event queue for this event port. > + * The priority defines the event port's servicing priority for > + * event queue, which may be ignored by an implementation. > + * The requested priority should in the range of > + * [RTE_EVENT_QUEUE_SERVICE_PRIORITY_HIGHEST, > + * RTE_EVENT_QUEUE_SERVICE_PRIORITY_LOWEST]. > + * The implementation shall normalize the requested priority to > + * implementation supported priority value. > + */ > +}; > + > +/** > + * Link multiple source event queues supplied in *rte_event_queue_link* > + * structure as *queue_id* to the destination event port designated by its > + * *port_id* on the event device designated by its *dev_id*. > + * > + * The link establishment shall enable the event port *port_id* from > + * receiving events from the specified event queue *queue_id* > + * > + * An event queue may link to one or more event ports. > + * The number of links can be established from an event queue to event port > is > + * implementation defined. > + * > + * Event queue(s) to event port link establishment can be changed at runtime > + * without re-configuring the device to support scaling and to reduce the > + * latency of critical work by establishing the link with more event ports > + * at runtime. > + * > + * @param dev_id > + * The identifier of the device. > + * > + * @param port_id > + * Event port identifier to select the destination port to link. > + * > + * @param link > + * An array of *num* pointers to *rte_event_queue_link* structure > + * which contain the event queue to event port link establishment > attributes. > + * NULL value is allowed, in which case this function links all the > configured > + * event queues *nb_event_queues* which previously supplied to > + * rte_event_dev_configure() to the event port *port_id* with normal > servicing > + * priority(RTE_EVENT_QUEUE_SERVICE_PRIORITY_NORMAL). > + * > + * @param num > + * The number of links to establish > + * > + * @return > + * The number of links actually established on the event device. The return > + * value can be less than the value of the *num* parameter when the > + * implementation has the limitation on specific queue to port link > + * establishment or if invalid parameters are specified > + * in a *rte_event_queue_link*. > + * If the return value is less than *num*, the remaining links at the end of > + * link[] are not established, and the caller has to take care of them. > + * If return value is less than *num* then implementation shall update the > + * rte_errno accordingly, Possible rte_errno values are > + * (-EDQUOT) Quota exceeded(Application tried to link the queue configured > with > + * RTE_EVENT_QUEUE_CFG_SINGLE_CONSUMER to more than one event > ports) > + * (-EINVAL) Invalid parameter > + * > + */ > +extern int > +rte_event_port_link(uint8_t dev_id, uint8_t port_id, > + struct rte_event_queue_link link[], int num); > + > +/** > + * Unlink multiple source event queues supplied in *queues* from the > destination > + * event port designated by its *port_id* on the event device designated > + * by its *dev_id*. > + * > + * The unlink establishment shall disable the event port *port_id* from > + * receiving events from the specified event queue *queue_id* > + * > + * Event queue(s) to event port unlink establishment can be changed at > runtime > + * without re-configuring the device. > + * > + * @param dev_id > + * The identifier of the device. > + * > + * @param port_id > + * Event port identifier to select the destination port to unlink. > + * > + * @param queues > + * An array of *num* event queues to be unlinked from the event port. > + * NULL value is allowed, in which case this function unlinks all the > + * event queue(s) from the event port *port_id*. > + * > + * @param num > + * The number of unlinks to establish > + * > + * @return > + * The number of unlinks actually established on the event device. The > return > + * value can be less than the value of the *num* parameter when the > + * implementation has the limitation on specific queue to port unlink > + * establishment or if invalid parameters are specified. > + * If the return value is less than *num*, the remaining queues at the end > of > + * queues[] are not established, and the caller has to take care of them. > + * If return value is less than *num* then implementation shall update the > + * rte_errno accordingly, Possible rte_errno values are > + * (-EINVAL) Invalid parameter > + * > + */ > +extern int > +rte_event_port_unlink(uint8_t dev_id, uint8_t port_id, > + uint8_t queues[], int num); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* _RTE_EVENTDEV_H_ */ > -- > 2.5.5