0c3847490dedf007099ef5cf98739e3d83221a7f
[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_ethdev.h>
5 #include <rte_eventdev.h>
6
7 #include "event_helper.h"
8
9 static int
10 eh_set_default_conf_eventdev(struct eventmode_conf *em_conf)
11 {
12         int lcore_count, nb_eventdev, nb_eth_dev, ret;
13         struct eventdev_params *eventdev_config;
14         struct rte_event_dev_info dev_info;
15
16         /* Get the number of event devices */
17         nb_eventdev = rte_event_dev_count();
18         if (nb_eventdev == 0) {
19                 EH_LOG_ERR("No event devices detected");
20                 return -EINVAL;
21         }
22
23         if (nb_eventdev != 1) {
24                 EH_LOG_ERR("Event mode does not support multiple event devices. "
25                            "Please provide only one event device.");
26                 return -EINVAL;
27         }
28
29         /* Get the number of eth devs */
30         nb_eth_dev = rte_eth_dev_count_avail();
31         if (nb_eth_dev == 0) {
32                 EH_LOG_ERR("No eth devices detected");
33                 return -EINVAL;
34         }
35
36         /* Get the number of lcores */
37         lcore_count = rte_lcore_count();
38
39         /* Read event device info */
40         ret = rte_event_dev_info_get(0, &dev_info);
41         if (ret < 0) {
42                 EH_LOG_ERR("Failed to read event device info %d", ret);
43                 return ret;
44         }
45
46         /* Check if enough ports are available */
47         if (dev_info.max_event_ports < 2) {
48                 EH_LOG_ERR("Not enough event ports available");
49                 return -EINVAL;
50         }
51
52         /* Get the first event dev conf */
53         eventdev_config = &(em_conf->eventdev_config[0]);
54
55         /* Save number of queues & ports available */
56         eventdev_config->eventdev_id = 0;
57         eventdev_config->nb_eventqueue = dev_info.max_event_queues;
58         eventdev_config->nb_eventport = dev_info.max_event_ports;
59         eventdev_config->ev_queue_mode = RTE_EVENT_QUEUE_CFG_ALL_TYPES;
60
61         /* Check if there are more queues than required */
62         if (eventdev_config->nb_eventqueue > nb_eth_dev + 1) {
63                 /* One queue is reserved for Tx */
64                 eventdev_config->nb_eventqueue = nb_eth_dev + 1;
65         }
66
67         /* Check if there are more ports than required */
68         if (eventdev_config->nb_eventport > lcore_count) {
69                 /* One port per lcore is enough */
70                 eventdev_config->nb_eventport = lcore_count;
71         }
72
73         /* Update the number of event devices */
74         em_conf->nb_eventdev++;
75
76         return 0;
77 }
78
79 static int
80 eh_validate_conf(struct eventmode_conf *em_conf)
81 {
82         int ret;
83
84         /*
85          * Check if event devs are specified. Else probe the event devices
86          * and initialize the config with all ports & queues available
87          */
88         if (em_conf->nb_eventdev == 0) {
89                 ret = eh_set_default_conf_eventdev(em_conf);
90                 if (ret != 0)
91                         return ret;
92         }
93
94         return 0;
95 }
96
97 static int
98 eh_initialize_eventdev(struct eventmode_conf *em_conf)
99 {
100         struct rte_event_queue_conf eventq_conf = {0};
101         struct rte_event_dev_info evdev_default_conf;
102         struct rte_event_dev_config eventdev_conf;
103         struct eventdev_params *eventdev_config;
104         int nb_eventdev = em_conf->nb_eventdev;
105         uint8_t eventdev_id;
106         int nb_eventqueue;
107         uint8_t i, j;
108         int ret;
109
110         for (i = 0; i < nb_eventdev; i++) {
111
112                 /* Get eventdev config */
113                 eventdev_config = &(em_conf->eventdev_config[i]);
114
115                 /* Get event dev ID */
116                 eventdev_id = eventdev_config->eventdev_id;
117
118                 /* Get the number of queues */
119                 nb_eventqueue = eventdev_config->nb_eventqueue;
120
121                 /* Reset the default conf */
122                 memset(&evdev_default_conf, 0,
123                         sizeof(struct rte_event_dev_info));
124
125                 /* Get default conf of eventdev */
126                 ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
127                 if (ret < 0) {
128                         EH_LOG_ERR(
129                                 "Error in getting event device info[devID:%d]",
130                                 eventdev_id);
131                         return ret;
132                 }
133
134                 memset(&eventdev_conf, 0, sizeof(struct rte_event_dev_config));
135                 eventdev_conf.nb_events_limit =
136                                 evdev_default_conf.max_num_events;
137                 eventdev_conf.nb_event_queues = nb_eventqueue;
138                 eventdev_conf.nb_event_ports =
139                                 eventdev_config->nb_eventport;
140                 eventdev_conf.nb_event_queue_flows =
141                                 evdev_default_conf.max_event_queue_flows;
142                 eventdev_conf.nb_event_port_dequeue_depth =
143                                 evdev_default_conf.max_event_port_dequeue_depth;
144                 eventdev_conf.nb_event_port_enqueue_depth =
145                                 evdev_default_conf.max_event_port_enqueue_depth;
146
147                 /* Configure event device */
148                 ret = rte_event_dev_configure(eventdev_id, &eventdev_conf);
149                 if (ret < 0) {
150                         EH_LOG_ERR("Error in configuring event device");
151                         return ret;
152                 }
153
154                 /* Configure event queues */
155                 for (j = 0; j < nb_eventqueue; j++) {
156
157                         memset(&eventq_conf, 0,
158                                         sizeof(struct rte_event_queue_conf));
159
160                         /* Per event dev queues can be ATQ or SINGLE LINK */
161                         eventq_conf.event_queue_cfg =
162                                         eventdev_config->ev_queue_mode;
163                         /*
164                          * All queues need to be set with sched_type as
165                          * schedule type for the application stage. One queue
166                          * would be reserved for the final eth tx stage. This
167                          * will be an atomic queue.
168                          */
169                         if (j == nb_eventqueue-1) {
170                                 eventq_conf.schedule_type =
171                                         RTE_SCHED_TYPE_ATOMIC;
172                         } else {
173                                 eventq_conf.schedule_type =
174                                         em_conf->ext_params.sched_type;
175                         }
176
177                         /* Set max atomic flows to 1024 */
178                         eventq_conf.nb_atomic_flows = 1024;
179                         eventq_conf.nb_atomic_order_sequences = 1024;
180
181                         /* Setup the queue */
182                         ret = rte_event_queue_setup(eventdev_id, j,
183                                         &eventq_conf);
184                         if (ret < 0) {
185                                 EH_LOG_ERR("Failed to setup event queue %d",
186                                            ret);
187                                 return ret;
188                         }
189                 }
190
191                 /* Configure event ports */
192                 for (j = 0; j <  eventdev_config->nb_eventport; j++) {
193                         ret = rte_event_port_setup(eventdev_id, j, NULL);
194                         if (ret < 0) {
195                                 EH_LOG_ERR("Failed to setup event port %d",
196                                            ret);
197                                 return ret;
198                         }
199                 }
200         }
201
202         /* Start event devices */
203         for (i = 0; i < nb_eventdev; i++) {
204
205                 /* Get eventdev config */
206                 eventdev_config = &(em_conf->eventdev_config[i]);
207
208                 ret = rte_event_dev_start(eventdev_config->eventdev_id);
209                 if (ret < 0) {
210                         EH_LOG_ERR("Failed to start event device %d, %d",
211                                    i, ret);
212                         return ret;
213                 }
214         }
215         return 0;
216 }
217
218 int32_t
219 eh_devs_init(struct eh_conf *conf)
220 {
221         struct eventmode_conf *em_conf;
222         uint16_t port_id;
223         int ret;
224
225         if (conf == NULL) {
226                 EH_LOG_ERR("Invalid event helper configuration");
227                 return -EINVAL;
228         }
229
230         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
231                 return 0;
232
233         if (conf->mode_params == NULL) {
234                 EH_LOG_ERR("Invalid event mode parameters");
235                 return -EINVAL;
236         }
237
238         /* Get eventmode conf */
239         em_conf = conf->mode_params;
240
241         /* Validate the requested config */
242         ret = eh_validate_conf(em_conf);
243         if (ret < 0) {
244                 EH_LOG_ERR("Failed to validate the requested config %d", ret);
245                 return ret;
246         }
247
248         /* Stop eth devices before setting up adapter */
249         RTE_ETH_FOREACH_DEV(port_id) {
250
251                 /* Use only the ports enabled */
252                 if ((conf->eth_portmask & (1 << port_id)) == 0)
253                         continue;
254
255                 rte_eth_dev_stop(port_id);
256         }
257
258         /* Setup eventdev */
259         ret = eh_initialize_eventdev(em_conf);
260         if (ret < 0) {
261                 EH_LOG_ERR("Failed to initialize event dev %d", ret);
262                 return ret;
263         }
264
265         /* Start eth devices after setting up adapter */
266         RTE_ETH_FOREACH_DEV(port_id) {
267
268                 /* Use only the ports enabled */
269                 if ((conf->eth_portmask & (1 << port_id)) == 0)
270                         continue;
271
272                 ret = rte_eth_dev_start(port_id);
273                 if (ret < 0) {
274                         EH_LOG_ERR("Failed to start eth dev %d, %d",
275                                    port_id, ret);
276                         return ret;
277                 }
278         }
279
280         return 0;
281 }
282
283 int32_t
284 eh_devs_uninit(struct eh_conf *conf)
285 {
286         struct eventmode_conf *em_conf;
287         uint16_t id;
288         int ret, i;
289
290         if (conf == NULL) {
291                 EH_LOG_ERR("Invalid event helper configuration");
292                 return -EINVAL;
293         }
294
295         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
296                 return 0;
297
298         if (conf->mode_params == NULL) {
299                 EH_LOG_ERR("Invalid event mode parameters");
300                 return -EINVAL;
301         }
302
303         /* Get eventmode conf */
304         em_conf = conf->mode_params;
305
306         /* Stop and release event devices */
307         for (i = 0; i < em_conf->nb_eventdev; i++) {
308
309                 id = em_conf->eventdev_config[i].eventdev_id;
310                 rte_event_dev_stop(id);
311
312                 ret = rte_event_dev_close(id);
313                 if (ret < 0) {
314                         EH_LOG_ERR("Failed to close event dev %d, %d", id, ret);
315                         return ret;
316                 }
317         }
318
319         return 0;
320 }