1*41dd9a6bSDavid Young.. SPDX-License-Identifier: BSD-3-Clause 2*41dd9a6bSDavid Young Copyright (c) 2023 Marvell. 3*41dd9a6bSDavid Young 4*41dd9a6bSDavid YoungEvent DMA Adapter Library 5*41dd9a6bSDavid Young========================= 6*41dd9a6bSDavid Young 7*41dd9a6bSDavid YoungDPDK :doc:`eventdev library <eventdev>` provides event driven programming model 8*41dd9a6bSDavid Youngwith features to schedule events. 9*41dd9a6bSDavid Young:doc:`../dmadev` provides an interface to DMA poll mode drivers 10*41dd9a6bSDavid Youngthat support DMA operations. 11*41dd9a6bSDavid YoungEvent DMA adapter is intended to bridge between the event device and the DMA device. 12*41dd9a6bSDavid Young 13*41dd9a6bSDavid YoungPacket flow from DMA device to the event device can be accomplished 14*41dd9a6bSDavid Youngusing software and hardware based transfer mechanisms. 15*41dd9a6bSDavid YoungThe adapter queries an eventdev PMD to determine which mechanism to be used. 16*41dd9a6bSDavid YoungThe adapter uses an EAL service core function for software-based packet transfer 17*41dd9a6bSDavid Youngand uses the eventdev PMD functions to configure hardware-based packet transfer 18*41dd9a6bSDavid Youngbetween DMA device and the event device. 19*41dd9a6bSDavid YoungDMA adapter uses a new event type called ``RTE_EVENT_TYPE_DMADEV`` 20*41dd9a6bSDavid Youngto indicate the source of event. 21*41dd9a6bSDavid Young 22*41dd9a6bSDavid YoungApplication can choose to submit a DMA operation directly to a DMA device 23*41dd9a6bSDavid Youngor send it to a DMA adapter via eventdev 24*41dd9a6bSDavid Youngbased on ``RTE_EVENT_DMA_ADAPTER_CAP_INTERNAL_PORT_OP_FWD`` capability. 25*41dd9a6bSDavid YoungThe first mode is known as the event new (``RTE_EVENT_DMA_ADAPTER_OP_NEW``) mode 26*41dd9a6bSDavid Youngand the second as the event forward (``RTE_EVENT_DMA_ADAPTER_OP_FORWARD``) mode. 27*41dd9a6bSDavid YoungChoice of mode can be specified while creating the adapter. 28*41dd9a6bSDavid YoungIn the former mode, it is the application's responsibility to enable ingress packet ordering. 29*41dd9a6bSDavid YoungIn the latter mode, it is the adapter's responsibility to enable ingress packet ordering. 30*41dd9a6bSDavid Young 31*41dd9a6bSDavid Young 32*41dd9a6bSDavid YoungAdapter Modes 33*41dd9a6bSDavid Young------------- 34*41dd9a6bSDavid Young 35*41dd9a6bSDavid YoungRTE_EVENT_DMA_ADAPTER_OP_NEW mode 36*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37*41dd9a6bSDavid Young 38*41dd9a6bSDavid YoungIn the ``RTE_EVENT_DMA_ADAPTER_OP_NEW`` mode, 39*41dd9a6bSDavid Youngapplication submits DMA operations directly to an DMA device. 40*41dd9a6bSDavid YoungThe adapter then dequeues DMA completions from the DMA device 41*41dd9a6bSDavid Youngand enqueues them as events to the event device. 42*41dd9a6bSDavid YoungThis mode does not ensure ingress ordering 43*41dd9a6bSDavid Youngas the application directly enqueues to the dmadev without going through DMA/atomic stage. 44*41dd9a6bSDavid YoungIn this mode, events dequeued from the adapter are treated as new events. 45*41dd9a6bSDavid YoungThe application has to specify event information (response information) 46*41dd9a6bSDavid Youngwhich is needed to enqueue an event after the DMA operation is completed. 47*41dd9a6bSDavid Young 48*41dd9a6bSDavid Young.. _figure_event_dma_adapter_op_new: 49*41dd9a6bSDavid Young 50*41dd9a6bSDavid Young.. figure:: ../img/event_dma_adapter_op_new.* 51*41dd9a6bSDavid Young 52*41dd9a6bSDavid Young Working model of ``RTE_EVENT_DMA_ADAPTER_OP_NEW`` mode 53*41dd9a6bSDavid Young 54*41dd9a6bSDavid Young 55*41dd9a6bSDavid YoungRTE_EVENT_DMA_ADAPTER_OP_FORWARD mode 56*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 57*41dd9a6bSDavid Young 58*41dd9a6bSDavid YoungIn the ``RTE_EVENT_DMA_ADAPTER_OP_FORWARD`` mode, 59*41dd9a6bSDavid Youngif the event PMD and DMA PMD supports internal event port 60*41dd9a6bSDavid Young(``RTE_EVENT_DMA_ADAPTER_CAP_INTERNAL_PORT_OP_FWD``), 61*41dd9a6bSDavid Youngthe application should use ``rte_event_dma_adapter_enqueue()`` API 62*41dd9a6bSDavid Youngto enqueue DMA operations as events to DMA adapter. 63*41dd9a6bSDavid YoungIf not, application retrieves DMA adapter's event port 64*41dd9a6bSDavid Youngusing ``rte_event_dma_adapter_event_port_get()`` API, 65*41dd9a6bSDavid Younglinks its event queue to this port 66*41dd9a6bSDavid Youngand starts enqueuing DMA operations as events to eventdev 67*41dd9a6bSDavid Youngusing ``rte_event_enqueue_burst()``. 68*41dd9a6bSDavid YoungThe adapter then dequeues the events 69*41dd9a6bSDavid Youngand submits the DMA operations to the dmadev. 70*41dd9a6bSDavid YoungAfter the DMA operation is complete, 71*41dd9a6bSDavid Youngthe adapter enqueues events to the event device. 72*41dd9a6bSDavid Young 73*41dd9a6bSDavid YoungApplications can use this mode when ingress packet ordering is needed. 74*41dd9a6bSDavid YoungIn this mode, events dequeued from the adapter will be treated as forwarded events. 75*41dd9a6bSDavid YoungApplication has to specify event information (response information) 76*41dd9a6bSDavid Youngneeded to enqueue the event after the DMA operation has completed. 77*41dd9a6bSDavid Young 78*41dd9a6bSDavid Young.. _figure_event_dma_adapter_op_forward: 79*41dd9a6bSDavid Young 80*41dd9a6bSDavid Young.. figure:: ../img/event_dma_adapter_op_forward.* 81*41dd9a6bSDavid Young 82*41dd9a6bSDavid Young Working model of ``RTE_EVENT_DMA_ADAPTER_OP_FORWARD`` mode 83*41dd9a6bSDavid Young 84*41dd9a6bSDavid Young 85*41dd9a6bSDavid YoungAPI Overview 86*41dd9a6bSDavid Young------------ 87*41dd9a6bSDavid Young 88*41dd9a6bSDavid YoungThis section has a brief introduction to the event DMA adapter APIs. 89*41dd9a6bSDavid YoungThe application is expected to create an adapter 90*41dd9a6bSDavid Youngwhich is associated with a single eventdev, 91*41dd9a6bSDavid Youngthen add dmadev and vchan to the adapter instance. 92*41dd9a6bSDavid Young 93*41dd9a6bSDavid Young 94*41dd9a6bSDavid YoungCreate an adapter instance 95*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~ 96*41dd9a6bSDavid Young 97*41dd9a6bSDavid YoungAn adapter instance is created using ``rte_event_dma_adapter_create()``. 98*41dd9a6bSDavid YoungThis function is called with event device 99*41dd9a6bSDavid Youngto be associated with the adapter and port configuration 100*41dd9a6bSDavid Youngfor the adapter to setup an event port (if the adapter needs to use a service function). 101*41dd9a6bSDavid Young 102*41dd9a6bSDavid YoungAdapter can be started in ``RTE_EVENT_DMA_ADAPTER_OP_NEW`` 103*41dd9a6bSDavid Youngor ``RTE_EVENT_DMA_ADAPTER_OP_FORWARD`` mode. 104*41dd9a6bSDavid Young 105*41dd9a6bSDavid Young.. code-block:: c 106*41dd9a6bSDavid Young 107*41dd9a6bSDavid Young enum rte_event_dma_adapter_mode mode; 108*41dd9a6bSDavid Young struct rte_event_dev_info dev_info; 109*41dd9a6bSDavid Young struct rte_event_port_conf conf; 110*41dd9a6bSDavid Young uint8_t evdev_id; 111*41dd9a6bSDavid Young uint8_t dma_id; 112*41dd9a6bSDavid Young int ret; 113*41dd9a6bSDavid Young 114*41dd9a6bSDavid Young ret = rte_event_dev_info_get(dma_id, &dev_info); 115*41dd9a6bSDavid Young 116*41dd9a6bSDavid Young conf.new_event_threshold = dev_info.max_num_events; 117*41dd9a6bSDavid Young conf.dequeue_depth = dev_info.max_event_port_dequeue_depth; 118*41dd9a6bSDavid Young conf.enqueue_depth = dev_info.max_event_port_enqueue_depth; 119*41dd9a6bSDavid Young mode = RTE_EVENT_DMA_ADAPTER_OP_FORWARD; 120*41dd9a6bSDavid Young ret = rte_event_dma_adapter_create(dma_id, evdev_id, &conf, mode); 121*41dd9a6bSDavid Young 122*41dd9a6bSDavid Young 123*41dd9a6bSDavid Young``rte_event_dma_adapter_create_ext()`` function can be used by the application 124*41dd9a6bSDavid Youngto have a finer control on eventdev port allocation and setup. 125*41dd9a6bSDavid YoungThe ``rte_event_dma_adapter_create_ext()`` function is passed a callback function. 126*41dd9a6bSDavid YoungThe callback function is invoked if the adapter creates a service function 127*41dd9a6bSDavid Youngand uses an event port for it. 128*41dd9a6bSDavid YoungThe callback is expected to fill the ``struct rte_event_dma_adapter_conf`` passed to it. 129*41dd9a6bSDavid Young 130*41dd9a6bSDavid YoungIn the ``RTE_EVENT_DMA_ADAPTER_OP_FORWARD`` mode, 131*41dd9a6bSDavid Youngif the event PMD and DMA PMD supports internal event port 132*41dd9a6bSDavid Young(``RTE_EVENT_DMA_ADAPTER_CAP_INTERNAL_PORT_OP_FWD``), 133*41dd9a6bSDavid Youngevents with DMA operations should be enqueued to the DMA adapter 134*41dd9a6bSDavid Youngusing ``rte_event_dma_adapter_enqueue()`` API. 135*41dd9a6bSDavid YoungIf not, the event port created by the adapter can be retrieved 136*41dd9a6bSDavid Youngusing ``rte_event_dma_adapter_event_port_get()`` API. 137*41dd9a6bSDavid YoungAn application can use this event port to link with an event queue, 138*41dd9a6bSDavid Youngon which it enqueues events towards the DMA adapter using ``rte_event_enqueue_burst()``. 139*41dd9a6bSDavid Young 140*41dd9a6bSDavid Young.. code-block:: c 141*41dd9a6bSDavid Young 142*41dd9a6bSDavid Young uint8_t dma_adpt_id, evdev_id, dma_dev_id, dma_ev_port_id, app_qid; 143*41dd9a6bSDavid Young struct rte_event ev; 144*41dd9a6bSDavid Young uint32_t cap; 145*41dd9a6bSDavid Young int ret; 146*41dd9a6bSDavid Young 147*41dd9a6bSDavid Young /* Fill in event info and update event_ptr with rte_event_dma_adapter_op */ 148*41dd9a6bSDavid Young memset(&ev, 0, sizeof(ev)); 149*41dd9a6bSDavid Young . 150*41dd9a6bSDavid Young . 151*41dd9a6bSDavid Young ev.event_ptr = op; 152*41dd9a6bSDavid Young 153*41dd9a6bSDavid Young ret = rte_event_dma_adapter_caps_get(evdev_id, dma_dev_id, &cap); 154*41dd9a6bSDavid Young if (cap & RTE_EVENT_DMA_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) { 155*41dd9a6bSDavid Young ret = rte_event_dma_adapter_enqueue(evdev_id, app_ev_port_id, ev, nb_events); 156*41dd9a6bSDavid Young } else { 157*41dd9a6bSDavid Young ret = rte_event_dma_adapter_event_port_get(dma_adpt_id, &dma_ev_port_id); 158*41dd9a6bSDavid Young ret = rte_event_queue_setup(evdev_id, app_qid, NULL); 159*41dd9a6bSDavid Young ret = rte_event_port_link(evdev_id, dma_ev_port_id, &app_qid, NULL, 1); 160*41dd9a6bSDavid Young ev.queue_id = app_qid; 161*41dd9a6bSDavid Young ret = rte_event_enqueue_burst(evdev_id, app_ev_port_id, ev, nb_events); 162*41dd9a6bSDavid Young } 163*41dd9a6bSDavid Young 164*41dd9a6bSDavid Young 165*41dd9a6bSDavid YoungEvent device configuration for service based adapter 166*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 167*41dd9a6bSDavid Young 168*41dd9a6bSDavid YoungWhen ``rte_event_dma_adapter_create()`` is used for creating adapter instance, 169*41dd9a6bSDavid Young``rte_event_dev_config::nb_event_ports`` is automatically incremented, 170*41dd9a6bSDavid Youngand event device is reconfigured with additional event port during service initialization. 171*41dd9a6bSDavid YoungThis event device reconfigure logic also 172*41dd9a6bSDavid Youngincrements the ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter 173*41dd9a6bSDavid Youngif the adapter event port config is of type ``RTE_EVENT_PORT_CFG_SINGLE_LINK``. 174*41dd9a6bSDavid Young 175*41dd9a6bSDavid YoungApplications using this mode of adapter creation need not configure the event device 176*41dd9a6bSDavid Youngwith ``rte_event_dev_config::nb_event_ports`` and 177*41dd9a6bSDavid Young``rte_event_dev_config::nb_single_link_event_port_queues`` parameters 178*41dd9a6bSDavid Youngrequired for DMA adapter when the adapter is created using the above-mentioned API. 179*41dd9a6bSDavid Young 180*41dd9a6bSDavid Young 181*41dd9a6bSDavid YoungQuerying adapter capabilities 182*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 183*41dd9a6bSDavid Young 184*41dd9a6bSDavid YoungThe ``rte_event_dma_adapter_caps_get()`` function allows the application 185*41dd9a6bSDavid Youngto query the adapter capabilities for an eventdev and dmadev combination. 186*41dd9a6bSDavid YoungThis API provides whether dmadev and eventdev are connected using internal HW port or not. 187*41dd9a6bSDavid Young 188*41dd9a6bSDavid Young.. code-block:: c 189*41dd9a6bSDavid Young 190*41dd9a6bSDavid Young rte_event_dma_adapter_caps_get(dev_id, dma_dev_id, &cap); 191*41dd9a6bSDavid Young 192*41dd9a6bSDavid Young 193*41dd9a6bSDavid YoungAdding vchan to the adapter instance 194*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 195*41dd9a6bSDavid Young 196*41dd9a6bSDavid Youngdmadev device ID and vchan are configured using dmadev APIs. 197*41dd9a6bSDavid YoungFor more information, see :doc:`dmadev <../dmadev>`. 198*41dd9a6bSDavid Young 199*41dd9a6bSDavid Young.. code-block:: c 200*41dd9a6bSDavid Young 201*41dd9a6bSDavid Young struct rte_dma_vchan_conf vchan_conf; 202*41dd9a6bSDavid Young struct rte_dma_conf dev_conf; 203*41dd9a6bSDavid Young uint8_t dev_id = 0; 204*41dd9a6bSDavid Young uint16_t vchan = 0; 205*41dd9a6bSDavid Young 206*41dd9a6bSDavid Young rte_dma_configure(dev_id, &dev_conf); 207*41dd9a6bSDavid Young rte_dma_vchan_setup(dev_id, vchan, &vchan_conf); 208*41dd9a6bSDavid Young 209*41dd9a6bSDavid YoungThese dmadev ID and vchan are added to the instance 210*41dd9a6bSDavid Youngusing the ``rte_event_dma_adapter_vchan_add()`` API. 211*41dd9a6bSDavid YoungThe same is removed using ``rte_event_dma_adapter_vchan_del()`` API. 212*41dd9a6bSDavid YoungIf hardware supports ``RTE_EVENT_DMA_ADAPTER_CAP_INTERNAL_PORT_VCHAN_EV_BIND`` capability, 213*41dd9a6bSDavid Youngevent information must be passed to the add API. 214*41dd9a6bSDavid Young 215*41dd9a6bSDavid Young.. code-block:: c 216*41dd9a6bSDavid Young 217*41dd9a6bSDavid Young uint32_t cap; 218*41dd9a6bSDavid Young int ret; 219*41dd9a6bSDavid Young 220*41dd9a6bSDavid Young ret = rte_event_dma_adapter_caps_get(evdev_id, dma_dev_id, &cap); 221*41dd9a6bSDavid Young if (cap & RTE_EVENT_DMA_ADAPTER_CAP_INTERNAL_PORT_VCHAN_EV_BIND) { 222*41dd9a6bSDavid Young struct rte_event event; 223*41dd9a6bSDavid Young 224*41dd9a6bSDavid Young rte_event_dma_adapter_vchan_add(id, dma_dev_id, vchan, &conf); 225*41dd9a6bSDavid Young } else 226*41dd9a6bSDavid Young rte_event_dma_adapter_vchan_add(id, dma_dev_id, vchan, NULL); 227*41dd9a6bSDavid Young 228*41dd9a6bSDavid Young 229*41dd9a6bSDavid YoungConfiguring service function 230*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 231*41dd9a6bSDavid Young 232*41dd9a6bSDavid YoungIf the adapter uses a service function, the application is required 233*41dd9a6bSDavid Youngto assign a service core to the service function as show below. 234*41dd9a6bSDavid Young 235*41dd9a6bSDavid Young.. code-block:: c 236*41dd9a6bSDavid Young 237*41dd9a6bSDavid Young uint32_t service_id; 238*41dd9a6bSDavid Young 239*41dd9a6bSDavid Young if (rte_event_dma_adapter_service_id_get(dma_id, &service_id) == 0) 240*41dd9a6bSDavid Young rte_service_map_lcore_set(service_id, CORE_ID); 241*41dd9a6bSDavid Young 242*41dd9a6bSDavid Young 243*41dd9a6bSDavid YoungSet event response information 244*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 245*41dd9a6bSDavid Young 246*41dd9a6bSDavid YoungIn the ``RTE_EVENT_DMA_ADAPTER_OP_FORWARD`` / ``RTE_EVENT_DMA_ADAPTER_OP_NEW`` mode, 247*41dd9a6bSDavid Youngthe application specifies the dmadev ID and vchan ID in ``struct rte_event_dma_adapter_op`` 248*41dd9a6bSDavid Youngand the event information (response information) 249*41dd9a6bSDavid Youngneeded to enqueue an event after the DMA operation has completed. 250*41dd9a6bSDavid YoungThe response information is specified in ``struct rte_event`` 251*41dd9a6bSDavid Youngand appended to the ``struct rte_event_dma_adapter_op``. 252*41dd9a6bSDavid Young 253*41dd9a6bSDavid Young 254*41dd9a6bSDavid YoungStart the adapter instance 255*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~ 256*41dd9a6bSDavid Young 257*41dd9a6bSDavid YoungThe application calls ``rte_event_dma_adapter_start()`` to start the adapter. 258*41dd9a6bSDavid YoungThis function calls the start callbacks of the eventdev PMDs 259*41dd9a6bSDavid Youngfor hardware-based eventdev-dmadev connections 260*41dd9a6bSDavid Youngand ``rte_service_run_state_set()`` to enable the service function if one exists. 261*41dd9a6bSDavid Young 262*41dd9a6bSDavid Young.. code-block:: c 263*41dd9a6bSDavid Young 264*41dd9a6bSDavid Young rte_event_dma_adapter_start(id); 265*41dd9a6bSDavid Young 266*41dd9a6bSDavid Young.. note:: 267*41dd9a6bSDavid Young 268*41dd9a6bSDavid Young The eventdev to which the event_dma_adapter is connected should be started 269*41dd9a6bSDavid Young before calling ``rte_event_dma_adapter_start()``. 270*41dd9a6bSDavid Young 271*41dd9a6bSDavid Young 272*41dd9a6bSDavid YoungGet adapter statistics 273*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~ 274*41dd9a6bSDavid Young 275*41dd9a6bSDavid YoungThe ``rte_event_dma_adapter_stats_get()`` function reports counters 276*41dd9a6bSDavid Youngdefined in ``struct rte_event_dma_adapter_stats``. 277*41dd9a6bSDavid YoungThe received packet and enqueued event counts are a sum of the counts 278*41dd9a6bSDavid Youngfrom the eventdev PMD callbacks if the callback is supported, 279*41dd9a6bSDavid Youngand the counts maintained by the service function, if one exists. 280*41dd9a6bSDavid Young 281*41dd9a6bSDavid Young 282*41dd9a6bSDavid YoungSet/Get adapter runtime configuration parameters 283*41dd9a6bSDavid Young~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 284*41dd9a6bSDavid Young 285*41dd9a6bSDavid YoungThe runtime configuration parameters of adapter can be set/get using 286*41dd9a6bSDavid Young``rte_event_dma_adapter_runtime_params_set()`` and 287*41dd9a6bSDavid Young``rte_event_dma_adapter_runtime_params_get()`` respectively. 288*41dd9a6bSDavid YoungThe parameters that can be set/get are defined in 289*41dd9a6bSDavid Young``struct rte_event_dma_adapter_runtime_params``. 290