examples/ipsec-secgw: add event worker launch
[dpdk.git] / examples / ipsec-secgw / event_helper.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (C) 2020 Marvell International Ltd.
3  */
4 #include <rte_bitmap.h>
5 #include <rte_ethdev.h>
6 #include <rte_eventdev.h>
7 #include <rte_event_eth_rx_adapter.h>
8 #include <rte_event_eth_tx_adapter.h>
9 #include <rte_malloc.h>
10 #include <stdbool.h>
11
12 #include "event_helper.h"
13
14 static volatile bool eth_core_running;
15
16 static int
17 eh_get_enabled_cores(struct rte_bitmap *eth_core_mask)
18 {
19         int i, count = 0;
20
21         RTE_LCORE_FOREACH(i) {
22                 /* Check if this core is enabled in core mask*/
23                 if (rte_bitmap_get(eth_core_mask, i)) {
24                         /* Found enabled core */
25                         count++;
26                 }
27         }
28         return count;
29 }
30
31 static inline unsigned int
32 eh_get_next_eth_core(struct eventmode_conf *em_conf)
33 {
34         static unsigned int prev_core = -1;
35         unsigned int next_core;
36
37         /*
38          * Make sure we have at least one eth core running, else the following
39          * logic would lead to an infinite loop.
40          */
41         if (eh_get_enabled_cores(em_conf->eth_core_mask) == 0) {
42                 EH_LOG_ERR("No enabled eth core found");
43                 return RTE_MAX_LCORE;
44         }
45
46         /* Only some cores are marked as eth cores, skip others */
47         do {
48                 /* Get the next core */
49                 next_core = rte_get_next_lcore(prev_core, 0, 1);
50
51                 /* Check if we have reached max lcores */
52                 if (next_core == RTE_MAX_LCORE)
53                         return next_core;
54
55                 /* Update prev_core */
56                 prev_core = next_core;
57         } while (!(rte_bitmap_get(em_conf->eth_core_mask, next_core)));
58
59         return next_core;
60 }
61
62 static inline unsigned int
63 eh_get_next_active_core(struct eventmode_conf *em_conf, unsigned int prev_core)
64 {
65         unsigned int next_core;
66
67         /* Get next active core skipping cores reserved as eth cores */
68         do {
69                 /* Get the next core */
70                 next_core = rte_get_next_lcore(prev_core, 0, 0);
71
72                 /* Check if we have reached max lcores */
73                 if (next_core == RTE_MAX_LCORE)
74                         return next_core;
75
76                 prev_core = next_core;
77         } while (rte_bitmap_get(em_conf->eth_core_mask, next_core));
78
79         return next_core;
80 }
81
82 static struct eventdev_params *
83 eh_get_eventdev_params(struct eventmode_conf *em_conf, uint8_t eventdev_id)
84 {
85         int i;
86
87         for (i = 0; i < em_conf->nb_eventdev; i++) {
88                 if (em_conf->eventdev_config[i].eventdev_id == eventdev_id)
89                         break;
90         }
91
92         /* No match */
93         if (i == em_conf->nb_eventdev)
94                 return NULL;
95
96         return &(em_conf->eventdev_config[i]);
97 }
98 static inline bool
99 eh_dev_has_burst_mode(uint8_t dev_id)
100 {
101         struct rte_event_dev_info dev_info;
102
103         rte_event_dev_info_get(dev_id, &dev_info);
104         return (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_BURST_MODE) ?
105                         true : false;
106 }
107
108 static int
109 eh_set_default_conf_eventdev(struct eventmode_conf *em_conf)
110 {
111         int lcore_count, nb_eventdev, nb_eth_dev, ret;
112         struct eventdev_params *eventdev_config;
113         struct rte_event_dev_info dev_info;
114
115         /* Get the number of event devices */
116         nb_eventdev = rte_event_dev_count();
117         if (nb_eventdev == 0) {
118                 EH_LOG_ERR("No event devices detected");
119                 return -EINVAL;
120         }
121
122         if (nb_eventdev != 1) {
123                 EH_LOG_ERR("Event mode does not support multiple event devices. "
124                            "Please provide only one event device.");
125                 return -EINVAL;
126         }
127
128         /* Get the number of eth devs */
129         nb_eth_dev = rte_eth_dev_count_avail();
130         if (nb_eth_dev == 0) {
131                 EH_LOG_ERR("No eth devices detected");
132                 return -EINVAL;
133         }
134
135         /* Get the number of lcores */
136         lcore_count = rte_lcore_count();
137
138         /* Read event device info */
139         ret = rte_event_dev_info_get(0, &dev_info);
140         if (ret < 0) {
141                 EH_LOG_ERR("Failed to read event device info %d", ret);
142                 return ret;
143         }
144
145         /* Check if enough ports are available */
146         if (dev_info.max_event_ports < 2) {
147                 EH_LOG_ERR("Not enough event ports available");
148                 return -EINVAL;
149         }
150
151         /* Get the first event dev conf */
152         eventdev_config = &(em_conf->eventdev_config[0]);
153
154         /* Save number of queues & ports available */
155         eventdev_config->eventdev_id = 0;
156         eventdev_config->nb_eventqueue = dev_info.max_event_queues;
157         eventdev_config->nb_eventport = dev_info.max_event_ports;
158         eventdev_config->ev_queue_mode = RTE_EVENT_QUEUE_CFG_ALL_TYPES;
159
160         /* Check if there are more queues than required */
161         if (eventdev_config->nb_eventqueue > nb_eth_dev + 1) {
162                 /* One queue is reserved for Tx */
163                 eventdev_config->nb_eventqueue = nb_eth_dev + 1;
164         }
165
166         /* Check if there are more ports than required */
167         if (eventdev_config->nb_eventport > lcore_count) {
168                 /* One port per lcore is enough */
169                 eventdev_config->nb_eventport = lcore_count;
170         }
171
172         /* Update the number of event devices */
173         em_conf->nb_eventdev++;
174
175         return 0;
176 }
177
178 static int
179 eh_set_default_conf_link(struct eventmode_conf *em_conf)
180 {
181         struct eventdev_params *eventdev_config;
182         struct eh_event_link_info *link;
183         unsigned int lcore_id = -1;
184         int i, link_index;
185
186         /*
187          * Create a 1:1 mapping from event ports to cores. If the number
188          * of event ports is lesser than the cores, some cores won't
189          * execute worker. If there are more event ports, then some ports
190          * won't be used.
191          *
192          */
193
194         /*
195          * The event queue-port mapping is done according to the link. Since
196          * we are falling back to the default link config, enabling
197          * "all_ev_queue_to_ev_port" mode flag. This will map all queues
198          * to the port.
199          */
200         em_conf->ext_params.all_ev_queue_to_ev_port = 1;
201
202         /* Get first event dev conf */
203         eventdev_config = &(em_conf->eventdev_config[0]);
204
205         /* Loop through the ports */
206         for (i = 0; i < eventdev_config->nb_eventport; i++) {
207
208                 /* Get next active core id */
209                 lcore_id = eh_get_next_active_core(em_conf,
210                                 lcore_id);
211
212                 if (lcore_id == RTE_MAX_LCORE) {
213                         /* Reached max cores */
214                         return 0;
215                 }
216
217                 /* Save the current combination as one link */
218
219                 /* Get the index */
220                 link_index = em_conf->nb_link;
221
222                 /* Get the corresponding link */
223                 link = &(em_conf->link[link_index]);
224
225                 /* Save link */
226                 link->eventdev_id = eventdev_config->eventdev_id;
227                 link->event_port_id = i;
228                 link->lcore_id = lcore_id;
229
230                 /*
231                  * Don't set eventq_id as by default all queues
232                  * need to be mapped to the port, which is controlled
233                  * by the operating mode.
234                  */
235
236                 /* Update number of links */
237                 em_conf->nb_link++;
238         }
239
240         return 0;
241 }
242
243 static int
244 eh_set_default_conf_rx_adapter(struct eventmode_conf *em_conf)
245 {
246         struct rx_adapter_connection_info *conn;
247         struct eventdev_params *eventdev_config;
248         struct rx_adapter_conf *adapter;
249         bool single_ev_queue = false;
250         int eventdev_id;
251         int nb_eth_dev;
252         int adapter_id;
253         int conn_id;
254         int i;
255
256         /* Create one adapter with eth queues mapped to event queue(s) */
257
258         if (em_conf->nb_eventdev == 0) {
259                 EH_LOG_ERR("No event devs registered");
260                 return -EINVAL;
261         }
262
263         /* Get the number of eth devs */
264         nb_eth_dev = rte_eth_dev_count_avail();
265
266         /* Use the first event dev */
267         eventdev_config = &(em_conf->eventdev_config[0]);
268
269         /* Get eventdev ID */
270         eventdev_id = eventdev_config->eventdev_id;
271         adapter_id = 0;
272
273         /* Get adapter conf */
274         adapter = &(em_conf->rx_adapter[adapter_id]);
275
276         /* Set adapter conf */
277         adapter->eventdev_id = eventdev_id;
278         adapter->adapter_id = adapter_id;
279         adapter->rx_core_id = eh_get_next_eth_core(em_conf);
280
281         /*
282          * Map all queues of eth device (port) to an event queue. If there
283          * are more event queues than eth ports then create 1:1 mapping.
284          * Otherwise map all eth ports to a single event queue.
285          */
286         if (nb_eth_dev > eventdev_config->nb_eventqueue)
287                 single_ev_queue = true;
288
289         for (i = 0; i < nb_eth_dev; i++) {
290
291                 /* Use only the ports enabled */
292                 if ((em_conf->eth_portmask & (1 << i)) == 0)
293                         continue;
294
295                 /* Get the connection id */
296                 conn_id = adapter->nb_connections;
297
298                 /* Get the connection */
299                 conn = &(adapter->conn[conn_id]);
300
301                 /* Set mapping between eth ports & event queues*/
302                 conn->ethdev_id = i;
303                 conn->eventq_id = single_ev_queue ? 0 : i;
304
305                 /* Add all eth queues eth port to event queue */
306                 conn->ethdev_rx_qid = -1;
307
308                 /* Update no of connections */
309                 adapter->nb_connections++;
310
311         }
312
313         /* We have setup one adapter */
314         em_conf->nb_rx_adapter = 1;
315
316         return 0;
317 }
318
319 static int
320 eh_set_default_conf_tx_adapter(struct eventmode_conf *em_conf)
321 {
322         struct tx_adapter_connection_info *conn;
323         struct eventdev_params *eventdev_config;
324         struct tx_adapter_conf *tx_adapter;
325         int eventdev_id;
326         int adapter_id;
327         int nb_eth_dev;
328         int conn_id;
329         int i;
330
331         /*
332          * Create one Tx adapter with all eth queues mapped to event queues
333          * 1:1.
334          */
335
336         if (em_conf->nb_eventdev == 0) {
337                 EH_LOG_ERR("No event devs registered");
338                 return -EINVAL;
339         }
340
341         /* Get the number of eth devs */
342         nb_eth_dev = rte_eth_dev_count_avail();
343
344         /* Use the first event dev */
345         eventdev_config = &(em_conf->eventdev_config[0]);
346
347         /* Get eventdev ID */
348         eventdev_id = eventdev_config->eventdev_id;
349         adapter_id = 0;
350
351         /* Get adapter conf */
352         tx_adapter = &(em_conf->tx_adapter[adapter_id]);
353
354         /* Set adapter conf */
355         tx_adapter->eventdev_id = eventdev_id;
356         tx_adapter->adapter_id = adapter_id;
357
358         /* TODO: Tx core is required only when internal port is not present */
359         tx_adapter->tx_core_id = eh_get_next_eth_core(em_conf);
360
361         /*
362          * Application uses one event queue per adapter for submitting
363          * packets for Tx. Reserve the last queue available and decrement
364          * the total available event queues for this
365          */
366
367         /* Queue numbers start at 0 */
368         tx_adapter->tx_ev_queue = eventdev_config->nb_eventqueue - 1;
369
370         /*
371          * Map all Tx queues of the eth device (port) to the event device.
372          */
373
374         /* Set defaults for connections */
375
376         /*
377          * One eth device (port) is one connection. Map all Tx queues
378          * of the device to the Tx adapter.
379          */
380
381         for (i = 0; i < nb_eth_dev; i++) {
382
383                 /* Use only the ports enabled */
384                 if ((em_conf->eth_portmask & (1 << i)) == 0)
385                         continue;
386
387                 /* Get the connection id */
388                 conn_id = tx_adapter->nb_connections;
389
390                 /* Get the connection */
391                 conn = &(tx_adapter->conn[conn_id]);
392
393                 /* Add ethdev to connections */
394                 conn->ethdev_id = i;
395
396                 /* Add all eth tx queues to adapter */
397                 conn->ethdev_tx_qid = -1;
398
399                 /* Update no of connections */
400                 tx_adapter->nb_connections++;
401         }
402
403         /* We have setup one adapter */
404         em_conf->nb_tx_adapter = 1;
405         return 0;
406 }
407
408 static int
409 eh_validate_conf(struct eventmode_conf *em_conf)
410 {
411         int ret;
412
413         /*
414          * Check if event devs are specified. Else probe the event devices
415          * and initialize the config with all ports & queues available
416          */
417         if (em_conf->nb_eventdev == 0) {
418                 ret = eh_set_default_conf_eventdev(em_conf);
419                 if (ret != 0)
420                         return ret;
421         }
422
423         /*
424          * Check if links are specified. Else generate a default config for
425          * the event ports used.
426          */
427         if (em_conf->nb_link == 0) {
428                 ret = eh_set_default_conf_link(em_conf);
429                 if (ret != 0)
430                         return ret;
431         }
432
433         /*
434          * Check if rx adapters are specified. Else generate a default config
435          * with one rx adapter and all eth queues - event queue mapped.
436          */
437         if (em_conf->nb_rx_adapter == 0) {
438                 ret = eh_set_default_conf_rx_adapter(em_conf);
439                 if (ret != 0)
440                         return ret;
441         }
442
443         /*
444          * Check if tx adapters are specified. Else generate a default config
445          * with one tx adapter.
446          */
447         if (em_conf->nb_tx_adapter == 0) {
448                 ret = eh_set_default_conf_tx_adapter(em_conf);
449                 if (ret != 0)
450                         return ret;
451         }
452
453         return 0;
454 }
455
456 static int
457 eh_initialize_eventdev(struct eventmode_conf *em_conf)
458 {
459         struct rte_event_queue_conf eventq_conf = {0};
460         struct rte_event_dev_info evdev_default_conf;
461         struct rte_event_dev_config eventdev_conf;
462         struct eventdev_params *eventdev_config;
463         int nb_eventdev = em_conf->nb_eventdev;
464         struct eh_event_link_info *link;
465         uint8_t *queue = NULL;
466         uint8_t eventdev_id;
467         int nb_eventqueue;
468         uint8_t i, j;
469         int ret;
470
471         for (i = 0; i < nb_eventdev; i++) {
472
473                 /* Get eventdev config */
474                 eventdev_config = &(em_conf->eventdev_config[i]);
475
476                 /* Get event dev ID */
477                 eventdev_id = eventdev_config->eventdev_id;
478
479                 /* Get the number of queues */
480                 nb_eventqueue = eventdev_config->nb_eventqueue;
481
482                 /* Reset the default conf */
483                 memset(&evdev_default_conf, 0,
484                         sizeof(struct rte_event_dev_info));
485
486                 /* Get default conf of eventdev */
487                 ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
488                 if (ret < 0) {
489                         EH_LOG_ERR(
490                                 "Error in getting event device info[devID:%d]",
491                                 eventdev_id);
492                         return ret;
493                 }
494
495                 memset(&eventdev_conf, 0, sizeof(struct rte_event_dev_config));
496                 eventdev_conf.nb_events_limit =
497                                 evdev_default_conf.max_num_events;
498                 eventdev_conf.nb_event_queues = nb_eventqueue;
499                 eventdev_conf.nb_event_ports =
500                                 eventdev_config->nb_eventport;
501                 eventdev_conf.nb_event_queue_flows =
502                                 evdev_default_conf.max_event_queue_flows;
503                 eventdev_conf.nb_event_port_dequeue_depth =
504                                 evdev_default_conf.max_event_port_dequeue_depth;
505                 eventdev_conf.nb_event_port_enqueue_depth =
506                                 evdev_default_conf.max_event_port_enqueue_depth;
507
508                 /* Configure event device */
509                 ret = rte_event_dev_configure(eventdev_id, &eventdev_conf);
510                 if (ret < 0) {
511                         EH_LOG_ERR("Error in configuring event device");
512                         return ret;
513                 }
514
515                 /* Configure event queues */
516                 for (j = 0; j < nb_eventqueue; j++) {
517
518                         memset(&eventq_conf, 0,
519                                         sizeof(struct rte_event_queue_conf));
520
521                         /* Per event dev queues can be ATQ or SINGLE LINK */
522                         eventq_conf.event_queue_cfg =
523                                         eventdev_config->ev_queue_mode;
524                         /*
525                          * All queues need to be set with sched_type as
526                          * schedule type for the application stage. One queue
527                          * would be reserved for the final eth tx stage. This
528                          * will be an atomic queue.
529                          */
530                         if (j == nb_eventqueue-1) {
531                                 eventq_conf.schedule_type =
532                                         RTE_SCHED_TYPE_ATOMIC;
533                         } else {
534                                 eventq_conf.schedule_type =
535                                         em_conf->ext_params.sched_type;
536                         }
537
538                         /* Set max atomic flows to 1024 */
539                         eventq_conf.nb_atomic_flows = 1024;
540                         eventq_conf.nb_atomic_order_sequences = 1024;
541
542                         /* Setup the queue */
543                         ret = rte_event_queue_setup(eventdev_id, j,
544                                         &eventq_conf);
545                         if (ret < 0) {
546                                 EH_LOG_ERR("Failed to setup event queue %d",
547                                            ret);
548                                 return ret;
549                         }
550                 }
551
552                 /* Configure event ports */
553                 for (j = 0; j <  eventdev_config->nb_eventport; j++) {
554                         ret = rte_event_port_setup(eventdev_id, j, NULL);
555                         if (ret < 0) {
556                                 EH_LOG_ERR("Failed to setup event port %d",
557                                            ret);
558                                 return ret;
559                         }
560                 }
561         }
562
563         /* Make event queue - event port link */
564         for (j = 0; j <  em_conf->nb_link; j++) {
565
566                 /* Get link info */
567                 link = &(em_conf->link[j]);
568
569                 /* Get event dev ID */
570                 eventdev_id = link->eventdev_id;
571
572                 /*
573                  * If "all_ev_queue_to_ev_port" params flag is selected, all
574                  * queues need to be mapped to the port.
575                  */
576                 if (em_conf->ext_params.all_ev_queue_to_ev_port)
577                         queue = NULL;
578                 else
579                         queue = &(link->eventq_id);
580
581                 /* Link queue to port */
582                 ret = rte_event_port_link(eventdev_id, link->event_port_id,
583                                 queue, NULL, 1);
584                 if (ret < 0) {
585                         EH_LOG_ERR("Failed to link event port %d", ret);
586                         return ret;
587                 }
588         }
589
590         /* Start event devices */
591         for (i = 0; i < nb_eventdev; i++) {
592
593                 /* Get eventdev config */
594                 eventdev_config = &(em_conf->eventdev_config[i]);
595
596                 ret = rte_event_dev_start(eventdev_config->eventdev_id);
597                 if (ret < 0) {
598                         EH_LOG_ERR("Failed to start event device %d, %d",
599                                    i, ret);
600                         return ret;
601                 }
602         }
603         return 0;
604 }
605
606 static int
607 eh_rx_adapter_configure(struct eventmode_conf *em_conf,
608                 struct rx_adapter_conf *adapter)
609 {
610         struct rte_event_eth_rx_adapter_queue_conf queue_conf = {0};
611         struct rte_event_dev_info evdev_default_conf = {0};
612         struct rte_event_port_conf port_conf = {0};
613         struct rx_adapter_connection_info *conn;
614         uint8_t eventdev_id;
615         uint32_t service_id;
616         int ret;
617         int j;
618
619         /* Get event dev ID */
620         eventdev_id = adapter->eventdev_id;
621
622         /* Get default configuration of event dev */
623         ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
624         if (ret < 0) {
625                 EH_LOG_ERR("Failed to get event dev info %d", ret);
626                 return ret;
627         }
628
629         /* Setup port conf */
630         port_conf.new_event_threshold = 1200;
631         port_conf.dequeue_depth =
632                         evdev_default_conf.max_event_port_dequeue_depth;
633         port_conf.enqueue_depth =
634                         evdev_default_conf.max_event_port_enqueue_depth;
635
636         /* Create Rx adapter */
637         ret = rte_event_eth_rx_adapter_create(adapter->adapter_id,
638                         adapter->eventdev_id, &port_conf);
639         if (ret < 0) {
640                 EH_LOG_ERR("Failed to create rx adapter %d", ret);
641                 return ret;
642         }
643
644         /* Setup various connections in the adapter */
645         for (j = 0; j < adapter->nb_connections; j++) {
646                 /* Get connection */
647                 conn = &(adapter->conn[j]);
648
649                 /* Setup queue conf */
650                 queue_conf.ev.queue_id = conn->eventq_id;
651                 queue_conf.ev.sched_type = em_conf->ext_params.sched_type;
652                 queue_conf.ev.event_type = RTE_EVENT_TYPE_ETHDEV;
653
654                 /* Add queue to the adapter */
655                 ret = rte_event_eth_rx_adapter_queue_add(adapter->adapter_id,
656                                 conn->ethdev_id, conn->ethdev_rx_qid,
657                                 &queue_conf);
658                 if (ret < 0) {
659                         EH_LOG_ERR("Failed to add eth queue to rx adapter %d",
660                                    ret);
661                         return ret;
662                 }
663         }
664
665         /* Get the service ID used by rx adapter */
666         ret = rte_event_eth_rx_adapter_service_id_get(adapter->adapter_id,
667                                                       &service_id);
668         if (ret != -ESRCH && ret < 0) {
669                 EH_LOG_ERR("Failed to get service id used by rx adapter %d",
670                            ret);
671                 return ret;
672         }
673
674         rte_service_set_runstate_mapped_check(service_id, 0);
675
676         /* Start adapter */
677         ret = rte_event_eth_rx_adapter_start(adapter->adapter_id);
678         if (ret < 0) {
679                 EH_LOG_ERR("Failed to start rx adapter %d", ret);
680                 return ret;
681         }
682
683         return 0;
684 }
685
686 static int
687 eh_initialize_rx_adapter(struct eventmode_conf *em_conf)
688 {
689         struct rx_adapter_conf *adapter;
690         int i, ret;
691
692         /* Configure rx adapters */
693         for (i = 0; i < em_conf->nb_rx_adapter; i++) {
694                 adapter = &(em_conf->rx_adapter[i]);
695                 ret = eh_rx_adapter_configure(em_conf, adapter);
696                 if (ret < 0) {
697                         EH_LOG_ERR("Failed to configure rx adapter %d", ret);
698                         return ret;
699                 }
700         }
701         return 0;
702 }
703
704 static int32_t
705 eh_start_worker_eth_core(struct eventmode_conf *conf, uint32_t lcore_id)
706 {
707         uint32_t service_id[EVENT_MODE_MAX_ADAPTERS_PER_RX_CORE];
708         struct rx_adapter_conf *rx_adapter;
709         struct tx_adapter_conf *tx_adapter;
710         int service_count = 0;
711         int adapter_id;
712         int32_t ret;
713         int i;
714
715         EH_LOG_INFO("Entering eth_core processing on lcore %u", lcore_id);
716
717         /*
718          * Parse adapter config to check which of all Rx adapters need
719          * to be handled by this core.
720          */
721         for (i = 0; i < conf->nb_rx_adapter; i++) {
722                 /* Check if we have exceeded the max allowed */
723                 if (service_count > EVENT_MODE_MAX_ADAPTERS_PER_RX_CORE) {
724                         EH_LOG_ERR(
725                               "Exceeded the max allowed adapters per rx core");
726                         break;
727                 }
728
729                 rx_adapter = &(conf->rx_adapter[i]);
730                 if (rx_adapter->rx_core_id != lcore_id)
731                         continue;
732
733                 /* Adapter is handled by this core */
734                 adapter_id = rx_adapter->adapter_id;
735
736                 /* Get the service ID for the adapters */
737                 ret = rte_event_eth_rx_adapter_service_id_get(adapter_id,
738                                 &(service_id[service_count]));
739
740                 if (ret != -ESRCH && ret < 0) {
741                         EH_LOG_ERR(
742                                 "Failed to get service id used by rx adapter");
743                         return ret;
744                 }
745
746                 /* Update service count */
747                 service_count++;
748         }
749
750         /*
751          * Parse adapter config to see which of all Tx adapters need
752          * to be handled by this core.
753          */
754         for (i = 0; i < conf->nb_tx_adapter; i++) {
755                 /* Check if we have exceeded the max allowed */
756                 if (service_count > EVENT_MODE_MAX_ADAPTERS_PER_TX_CORE) {
757                         EH_LOG_ERR(
758                                 "Exceeded the max allowed adapters per tx core");
759                         break;
760                 }
761
762                 tx_adapter = &conf->tx_adapter[i];
763                 if (tx_adapter->tx_core_id != lcore_id)
764                         continue;
765
766                 /* Adapter is handled by this core */
767                 adapter_id = tx_adapter->adapter_id;
768
769                 /* Get the service ID for the adapters */
770                 ret = rte_event_eth_tx_adapter_service_id_get(adapter_id,
771                                 &(service_id[service_count]));
772
773                 if (ret != -ESRCH && ret < 0) {
774                         EH_LOG_ERR(
775                                 "Failed to get service id used by tx adapter");
776                         return ret;
777                 }
778
779                 /* Update service count */
780                 service_count++;
781         }
782
783         eth_core_running = true;
784
785         while (eth_core_running) {
786                 for (i = 0; i < service_count; i++) {
787                         /* Initiate adapter service */
788                         rte_service_run_iter_on_app_lcore(service_id[i], 0);
789                 }
790         }
791
792         return 0;
793 }
794
795 static int32_t
796 eh_stop_worker_eth_core(void)
797 {
798         if (eth_core_running) {
799                 EH_LOG_INFO("Stopping eth cores");
800                 eth_core_running = false;
801         }
802         return 0;
803 }
804
805 static struct eh_app_worker_params *
806 eh_find_worker(uint32_t lcore_id, struct eh_conf *conf,
807                 struct eh_app_worker_params *app_wrkrs, uint8_t nb_wrkr_param)
808 {
809         struct eh_app_worker_params curr_conf = { {{0} }, NULL};
810         struct eh_event_link_info *link = NULL;
811         struct eh_app_worker_params *tmp_wrkr;
812         struct eventmode_conf *em_conf;
813         uint8_t eventdev_id;
814         int i;
815
816         /* Get eventmode config */
817         em_conf = conf->mode_params;
818
819         /*
820          * Use event device from the first lcore-event link.
821          *
822          * Assumption: All lcore-event links tied to a core are using the
823          * same event device. In other words, one core would be polling on
824          * queues of a single event device only.
825          */
826
827         /* Get a link for this lcore */
828         for (i = 0; i < em_conf->nb_link; i++) {
829                 link = &(em_conf->link[i]);
830                 if (link->lcore_id == lcore_id)
831                         break;
832         }
833
834         if (link == NULL) {
835                 EH_LOG_ERR("No valid link found for lcore %d", lcore_id);
836                 return NULL;
837         }
838
839         /* Get event dev ID */
840         eventdev_id = link->eventdev_id;
841
842         /* Populate the curr_conf with the capabilities */
843
844         /* Check for burst mode */
845         if (eh_dev_has_burst_mode(eventdev_id))
846                 curr_conf.cap.burst = EH_RX_TYPE_BURST;
847         else
848                 curr_conf.cap.burst = EH_RX_TYPE_NON_BURST;
849
850         /* Parse the passed list and see if we have matching capabilities */
851
852         /* Initialize the pointer used to traverse the list */
853         tmp_wrkr = app_wrkrs;
854
855         for (i = 0; i < nb_wrkr_param; i++, tmp_wrkr++) {
856
857                 /* Skip this if capabilities are not matching */
858                 if (tmp_wrkr->cap.u64 != curr_conf.cap.u64)
859                         continue;
860
861                 /* If the checks pass, we have a match */
862                 return tmp_wrkr;
863         }
864
865         return NULL;
866 }
867
868 static int
869 eh_verify_match_worker(struct eh_app_worker_params *match_wrkr)
870 {
871         /* Verify registered worker */
872         if (match_wrkr->worker_thread == NULL) {
873                 EH_LOG_ERR("No worker registered");
874                 return 0;
875         }
876
877         /* Success */
878         return 1;
879 }
880
881 static uint8_t
882 eh_get_event_lcore_links(uint32_t lcore_id, struct eh_conf *conf,
883                 struct eh_event_link_info **links)
884 {
885         struct eh_event_link_info *link_cache;
886         struct eventmode_conf *em_conf = NULL;
887         struct eh_event_link_info *link;
888         uint8_t lcore_nb_link = 0;
889         size_t single_link_size;
890         size_t cache_size;
891         int index = 0;
892         int i;
893
894         if (conf == NULL || links == NULL) {
895                 EH_LOG_ERR("Invalid args");
896                 return -EINVAL;
897         }
898
899         /* Get eventmode conf */
900         em_conf = conf->mode_params;
901
902         if (em_conf == NULL) {
903                 EH_LOG_ERR("Invalid event mode parameters");
904                 return -EINVAL;
905         }
906
907         /* Get the number of links registered */
908         for (i = 0; i < em_conf->nb_link; i++) {
909
910                 /* Get link */
911                 link = &(em_conf->link[i]);
912
913                 /* Check if we have link intended for this lcore */
914                 if (link->lcore_id == lcore_id) {
915
916                         /* Update the number of links for this core */
917                         lcore_nb_link++;
918
919                 }
920         }
921
922         /* Compute size of one entry to be copied */
923         single_link_size = sizeof(struct eh_event_link_info);
924
925         /* Compute size of the buffer required */
926         cache_size = lcore_nb_link * sizeof(struct eh_event_link_info);
927
928         /* Compute size of the buffer required */
929         link_cache = calloc(1, cache_size);
930
931         /* Get the number of links registered */
932         for (i = 0; i < em_conf->nb_link; i++) {
933
934                 /* Get link */
935                 link = &(em_conf->link[i]);
936
937                 /* Check if we have link intended for this lcore */
938                 if (link->lcore_id == lcore_id) {
939
940                         /* Cache the link */
941                         memcpy(&link_cache[index], link, single_link_size);
942
943                         /* Update index */
944                         index++;
945                 }
946         }
947
948         /* Update the links for application to use the cached links */
949         *links = link_cache;
950
951         /* Return the number of cached links */
952         return lcore_nb_link;
953 }
954
955 static int
956 eh_tx_adapter_configure(struct eventmode_conf *em_conf,
957                 struct tx_adapter_conf *adapter)
958 {
959         struct rte_event_dev_info evdev_default_conf = {0};
960         struct rte_event_port_conf port_conf = {0};
961         struct tx_adapter_connection_info *conn;
962         struct eventdev_params *eventdev_config;
963         uint8_t tx_port_id = 0;
964         uint8_t eventdev_id;
965         uint32_t service_id;
966         int ret, j;
967
968         /* Get event dev ID */
969         eventdev_id = adapter->eventdev_id;
970
971         /* Get event device conf */
972         eventdev_config = eh_get_eventdev_params(em_conf, eventdev_id);
973
974         /* Create Tx adapter */
975
976         /* Get default configuration of event dev */
977         ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
978         if (ret < 0) {
979                 EH_LOG_ERR("Failed to get event dev info %d", ret);
980                 return ret;
981         }
982
983         /* Setup port conf */
984         port_conf.new_event_threshold =
985                         evdev_default_conf.max_num_events;
986         port_conf.dequeue_depth =
987                         evdev_default_conf.max_event_port_dequeue_depth;
988         port_conf.enqueue_depth =
989                         evdev_default_conf.max_event_port_enqueue_depth;
990
991         /* Create adapter */
992         ret = rte_event_eth_tx_adapter_create(adapter->adapter_id,
993                         adapter->eventdev_id, &port_conf);
994         if (ret < 0) {
995                 EH_LOG_ERR("Failed to create tx adapter %d", ret);
996                 return ret;
997         }
998
999         /* Setup various connections in the adapter */
1000         for (j = 0; j < adapter->nb_connections; j++) {
1001
1002                 /* Get connection */
1003                 conn = &(adapter->conn[j]);
1004
1005                 /* Add queue to the adapter */
1006                 ret = rte_event_eth_tx_adapter_queue_add(adapter->adapter_id,
1007                                 conn->ethdev_id, conn->ethdev_tx_qid);
1008                 if (ret < 0) {
1009                         EH_LOG_ERR("Failed to add eth queue to tx adapter %d",
1010                                    ret);
1011                         return ret;
1012                 }
1013         }
1014
1015         /* Setup Tx queue & port */
1016
1017         /* Get event port used by the adapter */
1018         ret = rte_event_eth_tx_adapter_event_port_get(
1019                         adapter->adapter_id, &tx_port_id);
1020         if (ret) {
1021                 EH_LOG_ERR("Failed to get tx adapter port id %d", ret);
1022                 return ret;
1023         }
1024
1025         /*
1026          * Tx event queue is reserved for Tx adapter. Unlink this queue
1027          * from all other ports
1028          *
1029          */
1030         for (j = 0; j < eventdev_config->nb_eventport; j++) {
1031                 rte_event_port_unlink(eventdev_id, j,
1032                                       &(adapter->tx_ev_queue), 1);
1033         }
1034
1035         /* Link Tx event queue to Tx port */
1036         ret = rte_event_port_link(eventdev_id, tx_port_id,
1037                         &(adapter->tx_ev_queue), NULL, 1);
1038         if (ret != 1) {
1039                 EH_LOG_ERR("Failed to link event queue to port");
1040                 return ret;
1041         }
1042
1043         /* Get the service ID used by Tx adapter */
1044         ret = rte_event_eth_tx_adapter_service_id_get(adapter->adapter_id,
1045                                                       &service_id);
1046         if (ret != -ESRCH && ret < 0) {
1047                 EH_LOG_ERR("Failed to get service id used by tx adapter %d",
1048                            ret);
1049                 return ret;
1050         }
1051
1052         rte_service_set_runstate_mapped_check(service_id, 0);
1053
1054         /* Start adapter */
1055         ret = rte_event_eth_tx_adapter_start(adapter->adapter_id);
1056         if (ret < 0) {
1057                 EH_LOG_ERR("Failed to start tx adapter %d", ret);
1058                 return ret;
1059         }
1060
1061         return 0;
1062 }
1063
1064 static int
1065 eh_initialize_tx_adapter(struct eventmode_conf *em_conf)
1066 {
1067         struct tx_adapter_conf *adapter;
1068         int i, ret;
1069
1070         /* Configure Tx adapters */
1071         for (i = 0; i < em_conf->nb_tx_adapter; i++) {
1072                 adapter = &(em_conf->tx_adapter[i]);
1073                 ret = eh_tx_adapter_configure(em_conf, adapter);
1074                 if (ret < 0) {
1075                         EH_LOG_ERR("Failed to configure tx adapter %d", ret);
1076                         return ret;
1077                 }
1078         }
1079         return 0;
1080 }
1081
1082 static void
1083 eh_display_operating_mode(struct eventmode_conf *em_conf)
1084 {
1085         char sched_types[][32] = {
1086                 "RTE_SCHED_TYPE_ORDERED",
1087                 "RTE_SCHED_TYPE_ATOMIC",
1088                 "RTE_SCHED_TYPE_PARALLEL",
1089         };
1090         EH_LOG_INFO("Operating mode:");
1091
1092         EH_LOG_INFO("\tScheduling type: \t%s",
1093                 sched_types[em_conf->ext_params.sched_type]);
1094
1095         EH_LOG_INFO("");
1096 }
1097
1098 static void
1099 eh_display_event_dev_conf(struct eventmode_conf *em_conf)
1100 {
1101         char queue_mode[][32] = {
1102                 "",
1103                 "ATQ (ALL TYPE QUEUE)",
1104                 "SINGLE LINK",
1105         };
1106         char print_buf[256] = { 0 };
1107         int i;
1108
1109         EH_LOG_INFO("Event Device Configuration:");
1110
1111         for (i = 0; i < em_conf->nb_eventdev; i++) {
1112                 sprintf(print_buf,
1113                         "\tDev ID: %-2d \tQueues: %-2d \tPorts: %-2d",
1114                         em_conf->eventdev_config[i].eventdev_id,
1115                         em_conf->eventdev_config[i].nb_eventqueue,
1116                         em_conf->eventdev_config[i].nb_eventport);
1117                 sprintf(print_buf + strlen(print_buf),
1118                         "\tQueue mode: %s",
1119                         queue_mode[em_conf->eventdev_config[i].ev_queue_mode]);
1120                 EH_LOG_INFO("%s", print_buf);
1121         }
1122         EH_LOG_INFO("");
1123 }
1124
1125 static void
1126 eh_display_rx_adapter_conf(struct eventmode_conf *em_conf)
1127 {
1128         int nb_rx_adapter = em_conf->nb_rx_adapter;
1129         struct rx_adapter_connection_info *conn;
1130         struct rx_adapter_conf *adapter;
1131         char print_buf[256] = { 0 };
1132         int i, j;
1133
1134         EH_LOG_INFO("Rx adapters configured: %d", nb_rx_adapter);
1135
1136         for (i = 0; i < nb_rx_adapter; i++) {
1137                 adapter = &(em_conf->rx_adapter[i]);
1138                 EH_LOG_INFO(
1139                         "\tRx adaper ID: %-2d\tConnections: %-2d\tEvent dev ID: %-2d"
1140                         "\tRx core: %-2d",
1141                         adapter->adapter_id,
1142                         adapter->nb_connections,
1143                         adapter->eventdev_id,
1144                         adapter->rx_core_id);
1145
1146                 for (j = 0; j < adapter->nb_connections; j++) {
1147                         conn = &(adapter->conn[j]);
1148
1149                         sprintf(print_buf,
1150                                 "\t\tEthdev ID: %-2d", conn->ethdev_id);
1151
1152                         if (conn->ethdev_rx_qid == -1)
1153                                 sprintf(print_buf + strlen(print_buf),
1154                                         "\tEth rx queue: %-2s", "ALL");
1155                         else
1156                                 sprintf(print_buf + strlen(print_buf),
1157                                         "\tEth rx queue: %-2d",
1158                                         conn->ethdev_rx_qid);
1159
1160                         sprintf(print_buf + strlen(print_buf),
1161                                 "\tEvent queue: %-2d", conn->eventq_id);
1162                         EH_LOG_INFO("%s", print_buf);
1163                 }
1164         }
1165         EH_LOG_INFO("");
1166 }
1167
1168 static void
1169 eh_display_tx_adapter_conf(struct eventmode_conf *em_conf)
1170 {
1171         int nb_tx_adapter = em_conf->nb_tx_adapter;
1172         struct tx_adapter_connection_info *conn;
1173         struct tx_adapter_conf *adapter;
1174         char print_buf[256] = { 0 };
1175         int i, j;
1176
1177         EH_LOG_INFO("Tx adapters configured: %d", nb_tx_adapter);
1178
1179         for (i = 0; i < nb_tx_adapter; i++) {
1180                 adapter = &(em_conf->tx_adapter[i]);
1181                 sprintf(print_buf,
1182                         "\tTx adapter ID: %-2d\tConnections: %-2d\tEvent dev ID: %-2d",
1183                         adapter->adapter_id,
1184                         adapter->nb_connections,
1185                         adapter->eventdev_id);
1186                 if (adapter->tx_core_id == (uint32_t)-1)
1187                         sprintf(print_buf + strlen(print_buf),
1188                                 "\tTx core: %-2s", "[INTERNAL PORT]");
1189                 else if (adapter->tx_core_id == RTE_MAX_LCORE)
1190                         sprintf(print_buf + strlen(print_buf),
1191                                 "\tTx core: %-2s", "[NONE]");
1192                 else
1193                         sprintf(print_buf + strlen(print_buf),
1194                                 "\tTx core: %-2d,\tInput event queue: %-2d",
1195                                 adapter->tx_core_id, adapter->tx_ev_queue);
1196
1197                 EH_LOG_INFO("%s", print_buf);
1198
1199                 for (j = 0; j < adapter->nb_connections; j++) {
1200                         conn = &(adapter->conn[j]);
1201
1202                         sprintf(print_buf,
1203                                 "\t\tEthdev ID: %-2d", conn->ethdev_id);
1204
1205                         if (conn->ethdev_tx_qid == -1)
1206                                 sprintf(print_buf + strlen(print_buf),
1207                                         "\tEth tx queue: %-2s", "ALL");
1208                         else
1209                                 sprintf(print_buf + strlen(print_buf),
1210                                         "\tEth tx queue: %-2d",
1211                                         conn->ethdev_tx_qid);
1212                         EH_LOG_INFO("%s", print_buf);
1213                 }
1214         }
1215         EH_LOG_INFO("");
1216 }
1217
1218 static void
1219 eh_display_link_conf(struct eventmode_conf *em_conf)
1220 {
1221         struct eh_event_link_info *link;
1222         char print_buf[256] = { 0 };
1223         int i;
1224
1225         EH_LOG_INFO("Links configured: %d", em_conf->nb_link);
1226
1227         for (i = 0; i < em_conf->nb_link; i++) {
1228                 link = &(em_conf->link[i]);
1229
1230                 sprintf(print_buf,
1231                         "\tEvent dev ID: %-2d\tEvent port: %-2d",
1232                         link->eventdev_id,
1233                         link->event_port_id);
1234
1235                 if (em_conf->ext_params.all_ev_queue_to_ev_port)
1236                         sprintf(print_buf + strlen(print_buf),
1237                                 "Event queue: %-2s\t", "ALL");
1238                 else
1239                         sprintf(print_buf + strlen(print_buf),
1240                                 "Event queue: %-2d\t", link->eventq_id);
1241
1242                 sprintf(print_buf + strlen(print_buf),
1243                         "Lcore: %-2d", link->lcore_id);
1244                 EH_LOG_INFO("%s", print_buf);
1245         }
1246         EH_LOG_INFO("");
1247 }
1248
1249 void
1250 eh_display_conf(struct eh_conf *conf)
1251 {
1252         struct eventmode_conf *em_conf;
1253
1254         if (conf == NULL) {
1255                 EH_LOG_ERR("Invalid event helper configuration");
1256                 return;
1257         }
1258
1259         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
1260                 return;
1261
1262         if (conf->mode_params == NULL) {
1263                 EH_LOG_ERR("Invalid event mode parameters");
1264                 return;
1265         }
1266
1267         /* Get eventmode conf */
1268         em_conf = (struct eventmode_conf *)(conf->mode_params);
1269
1270         /* Display user exposed operating modes */
1271         eh_display_operating_mode(em_conf);
1272
1273         /* Display event device conf */
1274         eh_display_event_dev_conf(em_conf);
1275
1276         /* Display Rx adapter conf */
1277         eh_display_rx_adapter_conf(em_conf);
1278
1279         /* Display Tx adapter conf */
1280         eh_display_tx_adapter_conf(em_conf);
1281
1282         /* Display event-lcore link */
1283         eh_display_link_conf(em_conf);
1284 }
1285
1286 int32_t
1287 eh_devs_init(struct eh_conf *conf)
1288 {
1289         struct eventmode_conf *em_conf;
1290         uint16_t port_id;
1291         int ret;
1292
1293         if (conf == NULL) {
1294                 EH_LOG_ERR("Invalid event helper configuration");
1295                 return -EINVAL;
1296         }
1297
1298         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
1299                 return 0;
1300
1301         if (conf->mode_params == NULL) {
1302                 EH_LOG_ERR("Invalid event mode parameters");
1303                 return -EINVAL;
1304         }
1305
1306         /* Get eventmode conf */
1307         em_conf = conf->mode_params;
1308
1309         /* Eventmode conf would need eth portmask */
1310         em_conf->eth_portmask = conf->eth_portmask;
1311
1312         /* Validate the requested config */
1313         ret = eh_validate_conf(em_conf);
1314         if (ret < 0) {
1315                 EH_LOG_ERR("Failed to validate the requested config %d", ret);
1316                 return ret;
1317         }
1318
1319         /* Display the current configuration */
1320         eh_display_conf(conf);
1321
1322         /* Stop eth devices before setting up adapter */
1323         RTE_ETH_FOREACH_DEV(port_id) {
1324
1325                 /* Use only the ports enabled */
1326                 if ((conf->eth_portmask & (1 << port_id)) == 0)
1327                         continue;
1328
1329                 rte_eth_dev_stop(port_id);
1330         }
1331
1332         /* Setup eventdev */
1333         ret = eh_initialize_eventdev(em_conf);
1334         if (ret < 0) {
1335                 EH_LOG_ERR("Failed to initialize event dev %d", ret);
1336                 return ret;
1337         }
1338
1339         /* Setup Rx adapter */
1340         ret = eh_initialize_rx_adapter(em_conf);
1341         if (ret < 0) {
1342                 EH_LOG_ERR("Failed to initialize rx adapter %d", ret);
1343                 return ret;
1344         }
1345
1346         /* Setup Tx adapter */
1347         ret = eh_initialize_tx_adapter(em_conf);
1348         if (ret < 0) {
1349                 EH_LOG_ERR("Failed to initialize tx adapter %d", ret);
1350                 return ret;
1351         }
1352
1353         /* Start eth devices after setting up adapter */
1354         RTE_ETH_FOREACH_DEV(port_id) {
1355
1356                 /* Use only the ports enabled */
1357                 if ((conf->eth_portmask & (1 << port_id)) == 0)
1358                         continue;
1359
1360                 ret = rte_eth_dev_start(port_id);
1361                 if (ret < 0) {
1362                         EH_LOG_ERR("Failed to start eth dev %d, %d",
1363                                    port_id, ret);
1364                         return ret;
1365                 }
1366         }
1367
1368         return 0;
1369 }
1370
1371 int32_t
1372 eh_devs_uninit(struct eh_conf *conf)
1373 {
1374         struct eventmode_conf *em_conf;
1375         int ret, i, j;
1376         uint16_t id;
1377
1378         if (conf == NULL) {
1379                 EH_LOG_ERR("Invalid event helper configuration");
1380                 return -EINVAL;
1381         }
1382
1383         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
1384                 return 0;
1385
1386         if (conf->mode_params == NULL) {
1387                 EH_LOG_ERR("Invalid event mode parameters");
1388                 return -EINVAL;
1389         }
1390
1391         /* Get eventmode conf */
1392         em_conf = conf->mode_params;
1393
1394         /* Stop and release rx adapters */
1395         for (i = 0; i < em_conf->nb_rx_adapter; i++) {
1396
1397                 id = em_conf->rx_adapter[i].adapter_id;
1398                 ret = rte_event_eth_rx_adapter_stop(id);
1399                 if (ret < 0) {
1400                         EH_LOG_ERR("Failed to stop rx adapter %d", ret);
1401                         return ret;
1402                 }
1403
1404                 for (j = 0; j < em_conf->rx_adapter[i].nb_connections; j++) {
1405
1406                         ret = rte_event_eth_rx_adapter_queue_del(id,
1407                                 em_conf->rx_adapter[i].conn[j].ethdev_id, -1);
1408                         if (ret < 0) {
1409                                 EH_LOG_ERR(
1410                                        "Failed to remove rx adapter queues %d",
1411                                        ret);
1412                                 return ret;
1413                         }
1414                 }
1415
1416                 ret = rte_event_eth_rx_adapter_free(id);
1417                 if (ret < 0) {
1418                         EH_LOG_ERR("Failed to free rx adapter %d", ret);
1419                         return ret;
1420                 }
1421         }
1422
1423         /* Stop and release event devices */
1424         for (i = 0; i < em_conf->nb_eventdev; i++) {
1425
1426                 id = em_conf->eventdev_config[i].eventdev_id;
1427                 rte_event_dev_stop(id);
1428
1429                 ret = rte_event_dev_close(id);
1430                 if (ret < 0) {
1431                         EH_LOG_ERR("Failed to close event dev %d, %d", id, ret);
1432                         return ret;
1433                 }
1434         }
1435
1436         /* Stop and release tx adapters */
1437         for (i = 0; i < em_conf->nb_tx_adapter; i++) {
1438
1439                 id = em_conf->tx_adapter[i].adapter_id;
1440                 ret = rte_event_eth_tx_adapter_stop(id);
1441                 if (ret < 0) {
1442                         EH_LOG_ERR("Failed to stop tx adapter %d", ret);
1443                         return ret;
1444                 }
1445
1446                 for (j = 0; j < em_conf->tx_adapter[i].nb_connections; j++) {
1447
1448                         ret = rte_event_eth_tx_adapter_queue_del(id,
1449                                 em_conf->tx_adapter[i].conn[j].ethdev_id, -1);
1450                         if (ret < 0) {
1451                                 EH_LOG_ERR(
1452                                         "Failed to remove tx adapter queues %d",
1453                                         ret);
1454                                 return ret;
1455                         }
1456                 }
1457
1458                 ret = rte_event_eth_tx_adapter_free(id);
1459                 if (ret < 0) {
1460                         EH_LOG_ERR("Failed to free tx adapter %d", ret);
1461                         return ret;
1462                 }
1463         }
1464
1465         return 0;
1466 }
1467
1468 void
1469 eh_launch_worker(struct eh_conf *conf, struct eh_app_worker_params *app_wrkr,
1470                 uint8_t nb_wrkr_param)
1471 {
1472         struct eh_app_worker_params *match_wrkr;
1473         struct eh_event_link_info *links = NULL;
1474         struct eventmode_conf *em_conf;
1475         uint32_t lcore_id;
1476         uint8_t nb_links;
1477
1478         if (conf == NULL) {
1479                 EH_LOG_ERR("Invalid event helper configuration");
1480                 return;
1481         }
1482
1483         if (conf->mode_params == NULL) {
1484                 EH_LOG_ERR("Invalid event mode parameters");
1485                 return;
1486         }
1487
1488         /* Get eventmode conf */
1489         em_conf = conf->mode_params;
1490
1491         /* Get core ID */
1492         lcore_id = rte_lcore_id();
1493
1494         /* Check if this is eth core */
1495         if (rte_bitmap_get(em_conf->eth_core_mask, lcore_id)) {
1496                 eh_start_worker_eth_core(em_conf, lcore_id);
1497                 return;
1498         }
1499
1500         if (app_wrkr == NULL || nb_wrkr_param == 0) {
1501                 EH_LOG_ERR("Invalid args");
1502                 return;
1503         }
1504
1505         /*
1506          * This is a regular worker thread. The application registers
1507          * multiple workers with various capabilities. Run worker
1508          * based on the selected capabilities of the event
1509          * device configured.
1510          */
1511
1512         /* Get the first matching worker for the event device */
1513         match_wrkr = eh_find_worker(lcore_id, conf, app_wrkr, nb_wrkr_param);
1514         if (match_wrkr == NULL) {
1515                 EH_LOG_ERR("Failed to match worker registered for lcore %d",
1516                            lcore_id);
1517                 goto clean_and_exit;
1518         }
1519
1520         /* Verify sanity of the matched worker */
1521         if (eh_verify_match_worker(match_wrkr) != 1) {
1522                 EH_LOG_ERR("Failed to validate the matched worker");
1523                 goto clean_and_exit;
1524         }
1525
1526         /* Get worker links */
1527         nb_links = eh_get_event_lcore_links(lcore_id, conf, &links);
1528
1529         /* Launch the worker thread */
1530         match_wrkr->worker_thread(links, nb_links);
1531
1532         /* Free links info memory */
1533         free(links);
1534
1535 clean_and_exit:
1536
1537         /* Flag eth_cores to stop, if started */
1538         eh_stop_worker_eth_core();
1539 }
1540
1541 uint8_t
1542 eh_get_tx_queue(struct eh_conf *conf, uint8_t eventdev_id)
1543 {
1544         struct eventdev_params *eventdev_config;
1545         struct eventmode_conf *em_conf;
1546
1547         if (conf == NULL) {
1548                 EH_LOG_ERR("Invalid event helper configuration");
1549                 return -EINVAL;
1550         }
1551
1552         if (conf->mode_params == NULL) {
1553                 EH_LOG_ERR("Invalid event mode parameters");
1554                 return -EINVAL;
1555         }
1556
1557         /* Get eventmode conf */
1558         em_conf = conf->mode_params;
1559
1560         /* Get event device conf */
1561         eventdev_config = eh_get_eventdev_params(em_conf, eventdev_id);
1562
1563         if (eventdev_config == NULL) {
1564                 EH_LOG_ERR("Failed to read eventdev config");
1565                 return -EINVAL;
1566         }
1567
1568         /*
1569          * The last queue is reserved to be used as atomic queue for the
1570          * last stage (eth packet tx stage)
1571          */
1572         return eventdev_config->nb_eventqueue - 1;
1573 }