event/dlb: add eventdev probe
[dpdk.git] / drivers / event / dlb / dlb.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016-2020 Intel Corporation
3  */
4
5 #include <assert.h>
6 #include <errno.h>
7 #include <nmmintrin.h>
8 #include <pthread.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <sys/fcntl.h>
14 #include <sys/mman.h>
15 #include <unistd.h>
16
17 #include <rte_common.h>
18 #include <rte_config.h>
19 #include <rte_cycles.h>
20 #include <rte_debug.h>
21 #include <rte_dev.h>
22 #include <rte_errno.h>
23 #include <rte_io.h>
24 #include <rte_kvargs.h>
25 #include <rte_log.h>
26 #include <rte_malloc.h>
27 #include <rte_mbuf.h>
28 #include <rte_prefetch.h>
29 #include <rte_ring.h>
30 #include <rte_string_fns.h>
31
32 #include <rte_eventdev.h>
33 #include <rte_eventdev_pmd.h>
34
35 #include "dlb_priv.h"
36 #include "dlb_inline_fns.h"
37
38 /*
39  * Resources exposed to eventdev.
40  */
41 #if (RTE_EVENT_MAX_QUEUES_PER_DEV > UINT8_MAX)
42 #error "RTE_EVENT_MAX_QUEUES_PER_DEV cannot fit in member max_event_queues"
43 #endif
44
45 struct process_local_port_data
46 dlb_port[DLB_MAX_NUM_PORTS][NUM_DLB_PORT_TYPES];
47
48 /* Wrapper for string to int conversion. Substituted for atoi(...), which is
49  * unsafe.
50  */
51 #define DLB_BASE_10 10
52
53 static int
54 dlb_string_to_int(int *result, const char *str)
55 {
56         long ret;
57         char *endstr;
58
59         if (str == NULL || result == NULL)
60                 return -EINVAL;
61
62         errno = 0;
63         ret = strtol(str, &endstr, DLB_BASE_10);
64         if (errno)
65                 return -errno;
66
67         /* long int and int may be different width for some architectures */
68         if (ret < INT_MIN || ret > INT_MAX || endstr == str)
69                 return -EINVAL;
70
71         *result = ret;
72         return 0;
73 }
74
75 static int
76 set_numa_node(const char *key __rte_unused, const char *value, void *opaque)
77 {
78         int *socket_id = opaque;
79         int ret;
80
81         ret = dlb_string_to_int(socket_id, value);
82         if (ret < 0)
83                 return ret;
84
85         if (*socket_id > RTE_MAX_NUMA_NODES)
86                 return -EINVAL;
87
88         return 0;
89 }
90
91 static int
92 set_max_num_events(const char *key __rte_unused,
93                    const char *value,
94                    void *opaque)
95 {
96         int *max_num_events = opaque;
97         int ret;
98
99         if (value == NULL || opaque == NULL) {
100                 DLB_LOG_ERR("NULL pointer\n");
101                 return -EINVAL;
102         }
103
104         ret = dlb_string_to_int(max_num_events, value);
105         if (ret < 0)
106                 return ret;
107
108         if (*max_num_events < 0 || *max_num_events > DLB_MAX_NUM_LDB_CREDITS) {
109                 DLB_LOG_ERR("dlb: max_num_events must be between 0 and %d\n",
110                             DLB_MAX_NUM_LDB_CREDITS);
111                 return -EINVAL;
112         }
113
114         return 0;
115 }
116
117 static int
118 set_num_dir_credits(const char *key __rte_unused,
119                     const char *value,
120                     void *opaque)
121 {
122         int *num_dir_credits = opaque;
123         int ret;
124
125         if (value == NULL || opaque == NULL) {
126                 DLB_LOG_ERR("NULL pointer\n");
127                 return -EINVAL;
128         }
129
130         ret = dlb_string_to_int(num_dir_credits, value);
131         if (ret < 0)
132                 return ret;
133
134         if (*num_dir_credits < 0 ||
135             *num_dir_credits > DLB_MAX_NUM_DIR_CREDITS) {
136                 DLB_LOG_ERR("dlb: num_dir_credits must be between 0 and %d\n",
137                             DLB_MAX_NUM_DIR_CREDITS);
138                 return -EINVAL;
139         }
140
141         return 0;
142 }
143
144 static int
145 set_dev_id(const char *key __rte_unused,
146            const char *value,
147            void *opaque)
148 {
149         int *dev_id = opaque;
150         int ret;
151
152         if (value == NULL || opaque == NULL) {
153                 DLB_LOG_ERR("NULL pointer\n");
154                 return -EINVAL;
155         }
156
157         ret = dlb_string_to_int(dev_id, value);
158         if (ret < 0)
159                 return ret;
160
161         return 0;
162 }
163
164 static int
165 set_defer_sched(const char *key __rte_unused,
166                 const char *value,
167                 void *opaque)
168 {
169         int *defer_sched = opaque;
170
171         if (value == NULL || opaque == NULL) {
172                 DLB_LOG_ERR("NULL pointer\n");
173                 return -EINVAL;
174         }
175
176         if (strncmp(value, "on", 2) != 0) {
177                 DLB_LOG_ERR("Invalid defer_sched argument \"%s\" (expected \"on\")\n",
178                             value);
179                 return -EINVAL;
180         }
181
182         *defer_sched = 1;
183
184         return 0;
185 }
186
187 static int
188 set_num_atm_inflights(const char *key __rte_unused,
189                       const char *value,
190                       void *opaque)
191 {
192         int *num_atm_inflights = opaque;
193         int ret;
194
195         if (value == NULL || opaque == NULL) {
196                 DLB_LOG_ERR("NULL pointer\n");
197                 return -EINVAL;
198         }
199
200         ret = dlb_string_to_int(num_atm_inflights, value);
201         if (ret < 0)
202                 return ret;
203
204         if (*num_atm_inflights < 0 ||
205             *num_atm_inflights > DLB_MAX_NUM_ATM_INFLIGHTS) {
206                 DLB_LOG_ERR("dlb: atm_inflights must be between 0 and %d\n",
207                             DLB_MAX_NUM_ATM_INFLIGHTS);
208                 return -EINVAL;
209         }
210
211         return 0;
212 }
213
214 void
215 dlb_entry_points_init(struct rte_eventdev *dev)
216 {
217         static struct rte_eventdev_ops dlb_eventdev_entry_ops = {
218         };
219
220         /* Expose PMD's eventdev interface */
221         dev->dev_ops = &dlb_eventdev_entry_ops;
222 }
223
224 int
225 dlb_primary_eventdev_probe(struct rte_eventdev *dev,
226                            const char *name,
227                            struct dlb_devargs *dlb_args)
228 {
229         RTE_SET_USED(dev);
230         RTE_SET_USED(name);
231         RTE_SET_USED(dlb_args);
232
233         return 0;
234 }
235
236 int
237 dlb_secondary_eventdev_probe(struct rte_eventdev *dev,
238                              const char *name)
239 {
240         RTE_SET_USED(dev);
241         RTE_SET_USED(name);
242
243         return 0;
244 }
245
246 int
247 dlb_parse_params(const char *params,
248                  const char *name,
249                  struct dlb_devargs *dlb_args)
250 {
251         int ret = 0;
252         static const char * const args[] = { NUMA_NODE_ARG,
253                                              DLB_MAX_NUM_EVENTS,
254                                              DLB_NUM_DIR_CREDITS,
255                                              DEV_ID_ARG,
256                                              DLB_DEFER_SCHED_ARG,
257                                              DLB_NUM_ATM_INFLIGHTS_ARG,
258                                              NULL };
259
260         if (params && params[0] != '\0') {
261                 struct rte_kvargs *kvlist = rte_kvargs_parse(params, args);
262
263                 if (kvlist == NULL) {
264                         DLB_LOG_INFO("Ignoring unsupported parameters when creating device '%s'\n",
265                                      name);
266                 } else {
267                         int ret = rte_kvargs_process(kvlist, NUMA_NODE_ARG,
268                                                      set_numa_node,
269                                                      &dlb_args->socket_id);
270                         if (ret != 0) {
271                                 DLB_LOG_ERR("%s: Error parsing numa node parameter",
272                                             name);
273                                 rte_kvargs_free(kvlist);
274                                 return ret;
275                         }
276
277                         ret = rte_kvargs_process(kvlist, DLB_MAX_NUM_EVENTS,
278                                                  set_max_num_events,
279                                                  &dlb_args->max_num_events);
280                         if (ret != 0) {
281                                 DLB_LOG_ERR("%s: Error parsing max_num_events parameter",
282                                             name);
283                                 rte_kvargs_free(kvlist);
284                                 return ret;
285                         }
286
287                         ret = rte_kvargs_process(kvlist,
288                                         DLB_NUM_DIR_CREDITS,
289                                         set_num_dir_credits,
290                                         &dlb_args->num_dir_credits_override);
291                         if (ret != 0) {
292                                 DLB_LOG_ERR("%s: Error parsing num_dir_credits parameter",
293                                             name);
294                                 rte_kvargs_free(kvlist);
295                                 return ret;
296                         }
297
298                         ret = rte_kvargs_process(kvlist, DEV_ID_ARG,
299                                                  set_dev_id,
300                                                  &dlb_args->dev_id);
301                         if (ret != 0) {
302                                 DLB_LOG_ERR("%s: Error parsing dev_id parameter",
303                                             name);
304                                 rte_kvargs_free(kvlist);
305                                 return ret;
306                         }
307
308                         ret = rte_kvargs_process(kvlist, DLB_DEFER_SCHED_ARG,
309                                                  set_defer_sched,
310                                                  &dlb_args->defer_sched);
311                         if (ret != 0) {
312                                 DLB_LOG_ERR("%s: Error parsing defer_sched parameter",
313                                             name);
314                                 rte_kvargs_free(kvlist);
315                                 return ret;
316                         }
317
318                         ret = rte_kvargs_process(kvlist,
319                                                  DLB_NUM_ATM_INFLIGHTS_ARG,
320                                                  set_num_atm_inflights,
321                                                  &dlb_args->num_atm_inflights);
322                         if (ret != 0) {
323                                 DLB_LOG_ERR("%s: Error parsing atm_inflights parameter",
324                                             name);
325                                 rte_kvargs_free(kvlist);
326                                 return ret;
327                         }
328
329                         rte_kvargs_free(kvlist);
330                 }
331         }
332         return ret;
333 }
334 RTE_LOG_REGISTER(eventdev_dlb_log_level, pmd.event.dlb, NOTICE);