Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2021 HiSilicon Limited
3 : : * Copyright(c) 2021 Intel Corporation
4 : : */
5 : :
6 : : #include <ctype.h>
7 : : #include <errno.h>
8 : : #include <inttypes.h>
9 : : #include <stdlib.h>
10 : :
11 : : #include <eal_export.h>
12 : : #include <rte_eal.h>
13 : : #include <rte_lcore.h>
14 : : #include <rte_log.h>
15 : : #include <rte_malloc.h>
16 : : #include <rte_memzone.h>
17 : : #include <rte_string_fns.h>
18 : : #include <rte_telemetry.h>
19 : :
20 : : #include "rte_dmadev.h"
21 : : #include "rte_dmadev_pmd.h"
22 : : #include "rte_dmadev_trace.h"
23 : :
24 : : static int16_t dma_devices_max;
25 : :
26 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dma_fp_objs)
27 : : struct rte_dma_fp_object *rte_dma_fp_objs;
28 : : static struct rte_dma_dev *rte_dma_devices;
29 : : static struct {
30 : : /* Hold the dev_max information of the primary process. This field is
31 : : * set by the primary process and is read by the secondary process.
32 : : */
33 : : int16_t dev_max;
34 : : struct rte_dma_dev_data data[0];
35 : : } *dma_devices_shared_data;
36 : :
37 [ - + ]: 303 : RTE_LOG_REGISTER_DEFAULT(rte_dma_logtype, INFO);
38 : : #define RTE_LOGTYPE_DMADEV rte_dma_logtype
39 : :
40 : : #define RTE_DMA_LOG(level, ...) \
41 : : RTE_LOG_LINE(level, DMADEV, "" __VA_ARGS__)
42 : :
43 : : RTE_EXPORT_SYMBOL(rte_dma_dev_max)
44 : : int
45 : 0 : rte_dma_dev_max(size_t dev_max)
46 : : {
47 : : /* This function may be called before rte_eal_init(), so no rte library
48 : : * function can be called in this function.
49 : : */
50 [ # # ]: 0 : if (dev_max == 0 || dev_max > INT16_MAX)
51 : : return -EINVAL;
52 : :
53 [ # # ]: 0 : if (dma_devices_max > 0)
54 : : return -EINVAL;
55 : :
56 : 0 : dma_devices_max = dev_max;
57 : :
58 : 0 : return 0;
59 : : }
60 : :
61 : : RTE_EXPORT_SYMBOL(rte_dma_next_dev)
62 : : int16_t
63 : 0 : rte_dma_next_dev(int16_t start_dev_id)
64 : : {
65 : : int16_t dev_id = start_dev_id;
66 [ # # # # ]: 0 : while (dev_id < dma_devices_max && rte_dma_devices[dev_id].state == RTE_DMA_DEV_UNUSED)
67 : 0 : dev_id++;
68 : :
69 [ # # ]: 0 : if (dev_id < dma_devices_max)
70 : 0 : return dev_id;
71 : :
72 : : return -1;
73 : : }
74 : :
75 : : static int
76 : 2 : dma_check_name(const char *name)
77 : : {
78 : : size_t name_len;
79 : :
80 [ - + ]: 2 : if (name == NULL) {
81 : 0 : RTE_DMA_LOG(ERR, "Name can't be NULL");
82 : 0 : return -EINVAL;
83 : : }
84 : :
85 : 2 : name_len = strnlen(name, RTE_DEV_NAME_MAX_LEN);
86 [ - + ]: 2 : if (name_len == 0) {
87 : 0 : RTE_DMA_LOG(ERR, "Zero length DMA device name");
88 : 0 : return -EINVAL;
89 : : }
90 [ - + ]: 2 : if (name_len >= RTE_DEV_NAME_MAX_LEN) {
91 : 0 : RTE_DMA_LOG(ERR, "DMA device name is too long");
92 : 0 : return -EINVAL;
93 : : }
94 : :
95 : : return 0;
96 : : }
97 : :
98 : : static int16_t
99 : : dma_find_free_id(void)
100 : : {
101 : : int16_t i;
102 : :
103 [ + - + - ]: 1 : if (rte_dma_devices == NULL || dma_devices_shared_data == NULL)
104 : : return -1;
105 : :
106 [ + - ]: 1 : for (i = 0; i < dma_devices_max; i++) {
107 [ - + ]: 1 : if (dma_devices_shared_data->data[i].dev_name[0] == '\0')
108 : : return i;
109 : : }
110 : :
111 : : return -1;
112 : : }
113 : :
114 : : static struct rte_dma_dev*
115 : 2 : dma_find_by_name(const char *name)
116 : : {
117 : : int16_t i;
118 : :
119 [ + - ]: 2 : if (rte_dma_devices == NULL)
120 : : return NULL;
121 : :
122 [ + + ]: 66 : for (i = 0; i < dma_devices_max; i++) {
123 [ + + ]: 65 : if ((rte_dma_devices[i].state != RTE_DMA_DEV_UNUSED) &&
124 [ + - ]: 1 : (!strcmp(name, rte_dma_devices[i].data->dev_name)))
125 : 1 : return &rte_dma_devices[i];
126 : : }
127 : :
128 : : return NULL;
129 : : }
130 : :
131 : : static void dma_fp_object_dummy(struct rte_dma_fp_object *obj);
132 : :
133 : : static int
134 : 1 : dma_fp_data_prepare(void)
135 : : {
136 : : size_t size;
137 : : void *ptr;
138 : : int i;
139 : :
140 [ + - ]: 1 : if (rte_dma_fp_objs != NULL)
141 : : return 0;
142 : :
143 : : /* Fast-path object must align cacheline, but the return value of malloc
144 : : * may not be aligned to the cache line. Therefore, extra memory is
145 : : * applied for realignment.
146 : : * note: We do not call posix_memalign/aligned_alloc because it is
147 : : * version dependent on libc.
148 : : */
149 : 1 : size = dma_devices_max * sizeof(struct rte_dma_fp_object) +
150 : : RTE_CACHE_LINE_SIZE;
151 : 1 : ptr = malloc(size);
152 [ + - ]: 1 : if (ptr == NULL)
153 : : return -ENOMEM;
154 : : memset(ptr, 0, size);
155 : :
156 : 1 : rte_dma_fp_objs = RTE_PTR_ALIGN(ptr, RTE_CACHE_LINE_SIZE);
157 [ + + ]: 65 : for (i = 0; i < dma_devices_max; i++)
158 : 64 : dma_fp_object_dummy(&rte_dma_fp_objs[i]);
159 : :
160 : : return 0;
161 : : }
162 : :
163 : : static int
164 : 1 : dma_dev_data_prepare(void)
165 : : {
166 : : size_t size;
167 : : void *ptr;
168 : :
169 [ + - ]: 1 : if (rte_dma_devices != NULL)
170 : : return 0;
171 : :
172 : : /* The DMA device object is expected to align cacheline,
173 : : * but the return value of malloc may not be aligned to the cache line.
174 : : * Therefore, extra memory is applied for realignment.
175 : : * Note: posix_memalign/aligned_alloc are not used
176 : : * because not always available, depending on libc.
177 : : */
178 : 1 : size = dma_devices_max * sizeof(struct rte_dma_dev) + RTE_CACHE_LINE_SIZE;
179 : 1 : ptr = malloc(size);
180 [ + - ]: 1 : if (ptr == NULL)
181 : : return -ENOMEM;
182 : : memset(ptr, 0, size);
183 : :
184 : 1 : rte_dma_devices = RTE_PTR_ALIGN(ptr, RTE_CACHE_LINE_SIZE);
185 : :
186 : 1 : return 0;
187 : : }
188 : :
189 : : static int
190 : 1 : dma_shared_data_prepare(void)
191 : : {
192 : : const char *mz_name = "rte_dma_dev_data";
193 : : const struct rte_memzone *mz;
194 : : size_t size;
195 : :
196 [ + - ]: 1 : if (dma_devices_shared_data != NULL)
197 : : return 0;
198 : :
199 : 1 : size = sizeof(*dma_devices_shared_data) +
200 : 1 : sizeof(struct rte_dma_dev_data) * dma_devices_max;
201 : :
202 [ + - ]: 1 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
203 : 1 : mz = rte_memzone_reserve(mz_name, size, rte_socket_id(), 0);
204 : : else
205 : 0 : mz = rte_memzone_lookup(mz_name);
206 [ + - ]: 1 : if (mz == NULL)
207 : : return -ENOMEM;
208 : :
209 : 1 : dma_devices_shared_data = mz->addr;
210 [ + - ]: 1 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
211 : 1 : memset(dma_devices_shared_data, 0, size);
212 : 1 : dma_devices_shared_data->dev_max = dma_devices_max;
213 : : } else {
214 : 0 : dma_devices_max = dma_devices_shared_data->dev_max;
215 : : }
216 : :
217 : : return 0;
218 : : }
219 : :
220 : : static int
221 : 1 : dma_data_prepare(void)
222 : : {
223 : : int ret;
224 : :
225 [ + - ]: 1 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
226 [ + - ]: 1 : if (dma_devices_max == 0)
227 : 1 : dma_devices_max = RTE_DMADEV_DEFAULT_MAX;
228 : 1 : ret = dma_fp_data_prepare();
229 [ + - ]: 1 : if (ret)
230 : : return ret;
231 : 1 : ret = dma_dev_data_prepare();
232 [ + - ]: 1 : if (ret)
233 : : return ret;
234 : 1 : ret = dma_shared_data_prepare();
235 [ - + ]: 1 : if (ret)
236 : 0 : return ret;
237 : : } else {
238 : 0 : ret = dma_shared_data_prepare();
239 [ # # ]: 0 : if (ret)
240 : : return ret;
241 : 0 : ret = dma_fp_data_prepare();
242 [ # # ]: 0 : if (ret)
243 : : return ret;
244 : 0 : ret = dma_dev_data_prepare();
245 [ # # ]: 0 : if (ret)
246 : 0 : return ret;
247 : : }
248 : :
249 : : return 0;
250 : : }
251 : :
252 : : static struct rte_dma_dev *
253 : 1 : dma_allocate_primary(const char *name, int numa_node, size_t private_data_size)
254 : : {
255 : : struct rte_dma_dev *dev;
256 : : void *dev_private;
257 : : int16_t dev_id;
258 : : int ret;
259 : :
260 : 1 : ret = dma_data_prepare();
261 [ - + ]: 1 : if (ret < 0) {
262 : 0 : RTE_DMA_LOG(ERR, "Cannot initialize dmadevs data");
263 : 0 : return NULL;
264 : : }
265 : :
266 : 1 : dev = dma_find_by_name(name);
267 [ - + ]: 1 : if (dev != NULL) {
268 : 0 : RTE_DMA_LOG(ERR, "DMA device already allocated");
269 : 0 : return NULL;
270 : : }
271 : :
272 : 1 : dev_private = rte_zmalloc_socket(name, private_data_size,
273 : : RTE_CACHE_LINE_SIZE, numa_node);
274 [ - + ]: 1 : if (dev_private == NULL) {
275 : 0 : RTE_DMA_LOG(ERR, "Cannot allocate private data");
276 : 0 : return NULL;
277 : : }
278 : :
279 : : dev_id = dma_find_free_id();
280 [ - + ]: 1 : if (dev_id < 0) {
281 : 0 : RTE_DMA_LOG(ERR, "Reached maximum number of DMA devices");
282 : 0 : rte_free(dev_private);
283 : 0 : return NULL;
284 : : }
285 : :
286 : 1 : dev = &rte_dma_devices[dev_id];
287 : 1 : dev->data = &dma_devices_shared_data->data[dev_id];
288 : 1 : rte_strscpy(dev->data->dev_name, name, sizeof(dev->data->dev_name));
289 : 1 : dev->data->dev_id = dev_id;
290 : 1 : dev->data->numa_node = numa_node;
291 : 1 : dev->data->dev_private = dev_private;
292 : :
293 : 1 : return dev;
294 : : }
295 : :
296 : : static struct rte_dma_dev *
297 : 0 : dma_attach_secondary(const char *name)
298 : : {
299 : : struct rte_dma_dev *dev;
300 : : int16_t i;
301 : : int ret;
302 : :
303 : 0 : ret = dma_data_prepare();
304 [ # # ]: 0 : if (ret < 0) {
305 : 0 : RTE_DMA_LOG(ERR, "Cannot initialize dmadevs data");
306 : 0 : return NULL;
307 : : }
308 : :
309 [ # # ]: 0 : for (i = 0; i < dma_devices_max; i++) {
310 [ # # ]: 0 : if (!strcmp(dma_devices_shared_data->data[i].dev_name, name))
311 : : break;
312 : : }
313 [ # # ]: 0 : if (i == dma_devices_max) {
314 : 0 : RTE_DMA_LOG(ERR,
315 : : "Device %s is not driven by the primary process",
316 : : name);
317 : 0 : return NULL;
318 : : }
319 : :
320 : 0 : dev = &rte_dma_devices[i];
321 : 0 : dev->data = &dma_devices_shared_data->data[i];
322 : :
323 : 0 : return dev;
324 : : }
325 : :
326 : : static struct rte_dma_dev *
327 : 1 : dma_allocate(const char *name, int numa_node, size_t private_data_size)
328 : : {
329 : : struct rte_dma_dev *dev;
330 : :
331 [ + - ]: 1 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
332 : 1 : dev = dma_allocate_primary(name, numa_node, private_data_size);
333 : : else
334 : 0 : dev = dma_attach_secondary(name);
335 : :
336 [ + - ]: 1 : if (dev) {
337 : 1 : dev->fp_obj = &rte_dma_fp_objs[dev->data->dev_id];
338 : : dma_fp_object_dummy(dev->fp_obj);
339 : : }
340 : :
341 : 1 : return dev;
342 : : }
343 : :
344 : : static void
345 : 1 : dma_release(struct rte_dma_dev *dev)
346 : : {
347 [ + - ]: 1 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
348 : 1 : rte_free(dev->data->dev_private);
349 : 1 : memset(dev->data, 0, sizeof(struct rte_dma_dev_data));
350 : : }
351 : :
352 : 1 : dma_fp_object_dummy(dev->fp_obj);
353 : : memset(dev, 0, sizeof(struct rte_dma_dev));
354 : 1 : }
355 : :
356 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dma_pmd_allocate)
357 : : struct rte_dma_dev *
358 : 1 : rte_dma_pmd_allocate(const char *name, int numa_node, size_t private_data_size)
359 : : {
360 : : struct rte_dma_dev *dev;
361 : :
362 [ + - + - ]: 1 : if (dma_check_name(name) != 0 || private_data_size == 0)
363 : : return NULL;
364 : :
365 : 1 : dev = dma_allocate(name, numa_node, private_data_size);
366 [ + - ]: 1 : if (dev == NULL)
367 : : return NULL;
368 : :
369 : 1 : dev->state = RTE_DMA_DEV_REGISTERED;
370 : :
371 : 1 : return dev;
372 : : }
373 : :
374 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dma_pmd_release)
375 : : int
376 : 1 : rte_dma_pmd_release(const char *name)
377 : : {
378 : : struct rte_dma_dev *dev;
379 : :
380 [ + - ]: 1 : if (dma_check_name(name) != 0)
381 : : return -EINVAL;
382 : :
383 : 1 : dev = dma_find_by_name(name);
384 [ + - ]: 1 : if (dev == NULL)
385 : : return -EINVAL;
386 : :
387 [ + - ]: 1 : if (dev->state == RTE_DMA_DEV_READY)
388 : 1 : return rte_dma_close(dev->data->dev_id);
389 : :
390 : 0 : dma_release(dev);
391 : 0 : return 0;
392 : : }
393 : :
394 : : RTE_EXPORT_SYMBOL(rte_dma_get_dev_id_by_name)
395 : : int
396 : 0 : rte_dma_get_dev_id_by_name(const char *name)
397 : : {
398 : : struct rte_dma_dev *dev;
399 : :
400 [ # # ]: 0 : if (dma_check_name(name) != 0)
401 : : return -EINVAL;
402 : :
403 : 0 : dev = dma_find_by_name(name);
404 [ # # ]: 0 : if (dev == NULL)
405 : : return -EINVAL;
406 : :
407 : 0 : return dev->data->dev_id;
408 : : }
409 : :
410 : : RTE_EXPORT_SYMBOL(rte_dma_is_valid)
411 : : bool
412 : 197 : rte_dma_is_valid(int16_t dev_id)
413 : : {
414 [ + - ]: 197 : return (dev_id >= 0) && (dev_id < dma_devices_max) &&
415 [ + - + - ]: 394 : rte_dma_devices != NULL &&
416 [ + + ]: 197 : rte_dma_devices[dev_id].state != RTE_DMA_DEV_UNUSED;
417 : : }
418 : :
419 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dma_pmd_get_dev_by_id)
420 : : struct rte_dma_dev *
421 : 0 : rte_dma_pmd_get_dev_by_id(int16_t dev_id)
422 : : {
423 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
424 : : return NULL;
425 : :
426 : 0 : return &rte_dma_devices[dev_id];
427 : : }
428 : :
429 : : RTE_EXPORT_SYMBOL(rte_dma_count_avail)
430 : : uint16_t
431 : 0 : rte_dma_count_avail(void)
432 : : {
433 : : uint16_t count = 0;
434 : : uint16_t i;
435 : :
436 [ # # ]: 0 : if (rte_dma_devices == NULL)
437 : : return count;
438 : :
439 [ # # ]: 0 : for (i = 0; i < dma_devices_max; i++) {
440 [ # # ]: 0 : if (rte_dma_devices[i].state != RTE_DMA_DEV_UNUSED)
441 : 0 : count++;
442 : : }
443 : :
444 : : return count;
445 : : }
446 : :
447 : : RTE_EXPORT_SYMBOL(rte_dma_info_get)
448 : : int
449 : 3 : rte_dma_info_get(int16_t dev_id, struct rte_dma_info *dev_info)
450 : : {
451 : : const struct rte_dma_dev *dev;
452 : : int ret;
453 : :
454 [ + - + - ]: 3 : if (!rte_dma_is_valid(dev_id) || dev_info == NULL)
455 : : return -EINVAL;
456 : 3 : dev = &rte_dma_devices[dev_id];
457 : :
458 [ + - ]: 3 : if (dev->dev_ops->dev_info_get == NULL)
459 : : return -ENOTSUP;
460 : : memset(dev_info, 0, sizeof(struct rte_dma_info));
461 : 3 : ret = dev->dev_ops->dev_info_get(dev, dev_info, sizeof(struct rte_dma_info));
462 [ + - ]: 3 : if (ret != 0)
463 : : return ret;
464 : :
465 [ - + - - ]: 3 : if ((dev_info->dev_capa & RTE_DMA_CAPA_PRI_POLICY_SP) && (dev_info->nb_priorities <= 1)) {
466 : 0 : RTE_DMA_LOG(ERR, "Num of priorities must be > 1 for Device %d", dev_id);
467 : 0 : return -EINVAL;
468 : : }
469 : :
470 : 3 : dev_info->dev_name = dev->data->dev_name;
471 : 3 : dev_info->numa_node = dev->device->numa_node;
472 [ - + ]: 3 : dev_info->nb_vchans = dev->data->dev_conf.nb_vchans;
473 : :
474 : 3 : rte_dma_trace_info_get(dev_id, dev_info);
475 : :
476 : 3 : return 0;
477 : : }
478 : :
479 : : RTE_EXPORT_SYMBOL(rte_dma_configure)
480 : : int
481 : 0 : rte_dma_configure(int16_t dev_id, const struct rte_dma_conf *dev_conf)
482 : : {
483 : : const uint64_t valid_flags = RTE_DMA_CFG_FLAG_SILENT | RTE_DMA_CFG_FLAG_ENQ_DEQ;
484 : : struct rte_dma_info dev_info;
485 : : struct rte_dma_dev *dev;
486 : : int ret;
487 : :
488 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || dev_conf == NULL)
489 : : return -EINVAL;
490 : 0 : dev = &rte_dma_devices[dev_id];
491 : :
492 [ # # ]: 0 : if (dev->data->dev_started != 0) {
493 : 0 : RTE_DMA_LOG(ERR,
494 : : "Device %d must be stopped to allow configuration",
495 : : dev_id);
496 : 0 : return -EBUSY;
497 : : }
498 : :
499 : 0 : ret = rte_dma_info_get(dev_id, &dev_info);
500 [ # # ]: 0 : if (ret != 0) {
501 : 0 : RTE_DMA_LOG(ERR, "Device %d get device info fail", dev_id);
502 : 0 : return -EINVAL;
503 : : }
504 [ # # ]: 0 : if (dev_conf->nb_vchans == 0) {
505 : 0 : RTE_DMA_LOG(ERR,
506 : : "Device %d configure zero vchans", dev_id);
507 : 0 : return -EINVAL;
508 : : }
509 [ # # ]: 0 : if (dev_conf->nb_vchans > dev_info.max_vchans) {
510 : 0 : RTE_DMA_LOG(ERR,
511 : : "Device %d configure too many vchans", dev_id);
512 : 0 : return -EINVAL;
513 : : }
514 : :
515 [ # # ]: 0 : if (dev_info.dev_capa & RTE_DMA_CAPA_PRI_POLICY_SP) {
516 [ # # ]: 0 : if (dev_conf->priority >= dev_info.nb_priorities) {
517 : 0 : RTE_DMA_LOG(ERR, "Device %d configure invalid priority", dev_id);
518 : 0 : return -EINVAL;
519 : : }
520 : : } else {
521 [ # # ]: 0 : if (dev_conf->priority != 0) {
522 : 0 : RTE_DMA_LOG(ERR, "Device %d should not configure priority", dev_id);
523 : 0 : return -EINVAL;
524 : : }
525 : : }
526 : :
527 [ # # ]: 0 : if ((dev_conf->flags & ~valid_flags) != 0) {
528 : 0 : RTE_DMA_LOG(ERR, "Device %d configure invalid flags", dev_id);
529 : 0 : return -EINVAL;
530 : : }
531 [ # # ]: 0 : if ((dev_conf->flags & RTE_DMA_CFG_FLAG_SILENT) &&
532 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_SILENT)) {
533 : 0 : RTE_DMA_LOG(ERR, "Device %d don't support silent", dev_id);
534 : 0 : return -EINVAL;
535 : : }
536 [ # # ]: 0 : if ((dev_conf->flags & RTE_DMA_CFG_FLAG_ENQ_DEQ) &&
537 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_OPS_ENQ_DEQ)) {
538 : 0 : RTE_DMA_LOG(ERR, "Device %d don't support enqueue/dequeue", dev_id);
539 : 0 : return -EINVAL;
540 : : }
541 : :
542 [ # # ]: 0 : if (dev->dev_ops->dev_configure == NULL)
543 : : return -ENOTSUP;
544 : 0 : ret = dev->dev_ops->dev_configure(dev, dev_conf, sizeof(struct rte_dma_conf));
545 [ # # ]: 0 : if (ret == 0)
546 : 0 : memcpy(&dev->data->dev_conf, dev_conf,
547 : : sizeof(struct rte_dma_conf));
548 : :
549 : 0 : rte_dma_trace_configure(dev_id, dev_conf, ret);
550 : :
551 : 0 : return ret;
552 : : }
553 : :
554 : : RTE_EXPORT_SYMBOL(rte_dma_start)
555 : : int
556 : 0 : rte_dma_start(int16_t dev_id)
557 : : {
558 : : struct rte_dma_dev *dev;
559 : : int ret;
560 : :
561 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
562 : : return -EINVAL;
563 : 0 : dev = &rte_dma_devices[dev_id];
564 : :
565 [ # # ]: 0 : if (dev->data->dev_conf.nb_vchans == 0) {
566 : 0 : RTE_DMA_LOG(ERR, "Device %d must be configured first", dev_id);
567 : 0 : return -EINVAL;
568 : : }
569 : :
570 [ # # ]: 0 : if (dev->data->dev_started != 0) {
571 : 0 : RTE_DMA_LOG(WARNING, "Device %d already started", dev_id);
572 : 0 : return 0;
573 : : }
574 : :
575 [ # # ]: 0 : if (dev->dev_ops->dev_start == NULL)
576 : 0 : goto mark_started;
577 : :
578 : 0 : ret = dev->dev_ops->dev_start(dev);
579 : 0 : rte_dma_trace_start(dev_id, ret);
580 [ # # ]: 0 : if (ret != 0)
581 : : return ret;
582 : :
583 : 0 : mark_started:
584 : 0 : dev->data->dev_started = 1;
585 : 0 : return 0;
586 : : }
587 : :
588 : : RTE_EXPORT_SYMBOL(rte_dma_stop)
589 : : int
590 : 0 : rte_dma_stop(int16_t dev_id)
591 : : {
592 : : struct rte_dma_dev *dev;
593 : : int ret;
594 : :
595 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
596 : : return -EINVAL;
597 : 0 : dev = &rte_dma_devices[dev_id];
598 : :
599 [ # # ]: 0 : if (dev->data->dev_started == 0) {
600 : 0 : RTE_DMA_LOG(WARNING, "Device %d already stopped", dev_id);
601 : 0 : return 0;
602 : : }
603 : :
604 [ # # ]: 0 : if (dev->dev_ops->dev_stop == NULL)
605 : 0 : goto mark_stopped;
606 : :
607 : 0 : ret = dev->dev_ops->dev_stop(dev);
608 : 0 : rte_dma_trace_stop(dev_id, ret);
609 [ # # ]: 0 : if (ret != 0)
610 : : return ret;
611 : :
612 : 0 : mark_stopped:
613 : 0 : dev->data->dev_started = 0;
614 : 0 : return 0;
615 : : }
616 : :
617 : : RTE_EXPORT_SYMBOL(rte_dma_close)
618 : : int
619 : 1 : rte_dma_close(int16_t dev_id)
620 : : {
621 : : struct rte_dma_dev *dev;
622 : : int ret;
623 : :
624 [ + - ]: 1 : if (!rte_dma_is_valid(dev_id))
625 : : return -EINVAL;
626 : 1 : dev = &rte_dma_devices[dev_id];
627 : :
628 : : /* Device must be stopped before it can be closed */
629 [ - + ]: 1 : if (dev->data->dev_started == 1) {
630 : 0 : RTE_DMA_LOG(ERR,
631 : : "Device %d must be stopped before closing", dev_id);
632 : 0 : return -EBUSY;
633 : : }
634 : :
635 [ + - ]: 1 : if (dev->dev_ops->dev_close == NULL)
636 : : return -ENOTSUP;
637 : 1 : ret = dev->dev_ops->dev_close(dev);
638 [ + - ]: 1 : if (ret == 0)
639 : 1 : dma_release(dev);
640 : :
641 : 1 : rte_dma_trace_close(dev_id, ret);
642 : :
643 : 1 : return ret;
644 : : }
645 : :
646 : : /* Perform verification on rte_dma_vchan_conf only. */
647 : : static int
648 : 0 : dma_check_vchan_conf(int16_t dev_id, const struct rte_dma_vchan_conf *conf)
649 : : {
650 : : bool src_is_dev, dst_is_dev;
651 : :
652 [ # # ]: 0 : if (conf->direction != RTE_DMA_DIR_MEM_TO_MEM &&
653 : : conf->direction != RTE_DMA_DIR_MEM_TO_DEV &&
654 : : conf->direction != RTE_DMA_DIR_DEV_TO_MEM &&
655 : : conf->direction != RTE_DMA_DIR_DEV_TO_DEV) {
656 : 0 : RTE_DMA_LOG(ERR, "Device %d direction invalid!", dev_id);
657 : 0 : return -EINVAL;
658 : : }
659 : :
660 [ # # ]: 0 : if (conf->src_port.port_type != RTE_DMA_PORT_NONE &&
661 : : conf->src_port.port_type != RTE_DMA_PORT_PCIE) {
662 : 0 : RTE_DMA_LOG(ERR, "Device %d source port type unsupported", dev_id);
663 : 0 : return -EINVAL;
664 : : }
665 [ # # # # ]: 0 : if (conf->src_port.reserved[0] != 0 || conf->src_port.reserved[1] != 0) {
666 : 0 : RTE_DMA_LOG(ERR, "Device %d src_port has non-zero reserved fields", dev_id);
667 : 0 : return -EINVAL;
668 : : }
669 : 0 : src_is_dev = conf->direction == RTE_DMA_DIR_DEV_TO_MEM ||
670 : : conf->direction == RTE_DMA_DIR_DEV_TO_DEV;
671 [ # # # # : 0 : if ((conf->src_port.port_type == RTE_DMA_PORT_NONE && src_is_dev) ||
# # ]
672 [ # # ]: 0 : (conf->src_port.port_type != RTE_DMA_PORT_NONE && !src_is_dev)) {
673 : 0 : RTE_DMA_LOG(ERR, "Device %d source port type invalid", dev_id);
674 : 0 : return -EINVAL;
675 : : }
676 : :
677 [ # # ]: 0 : if (conf->dst_port.port_type != RTE_DMA_PORT_NONE &&
678 : : conf->dst_port.port_type != RTE_DMA_PORT_PCIE) {
679 : 0 : RTE_DMA_LOG(ERR, "Device %d destination port type unsupported", dev_id);
680 : 0 : return -EINVAL;
681 : : }
682 [ # # # # ]: 0 : if (conf->dst_port.reserved[0] != 0 || conf->dst_port.reserved[1] != 0) {
683 : 0 : RTE_DMA_LOG(ERR, "Device %d dst_port has non-zero reserved fields", dev_id);
684 : 0 : return -EINVAL;
685 : : }
686 : 0 : dst_is_dev = conf->direction == RTE_DMA_DIR_MEM_TO_DEV ||
687 : : conf->direction == RTE_DMA_DIR_DEV_TO_DEV;
688 [ # # # # : 0 : if ((conf->dst_port.port_type == RTE_DMA_PORT_NONE && dst_is_dev) ||
# # ]
689 [ # # ]: 0 : (conf->dst_port.port_type != RTE_DMA_PORT_NONE && !dst_is_dev)) {
690 : 0 : RTE_DMA_LOG(ERR,
691 : : "Device %d destination port type invalid", dev_id);
692 : 0 : return -EINVAL;
693 : : }
694 : :
695 [ # # # # ]: 0 : if (conf->auto_free.reserved[0] != 0 || conf->auto_free.reserved[1] != 0) {
696 : 0 : RTE_DMA_LOG(ERR, "Device %d auto_free has non-zero reserved fields", dev_id);
697 : 0 : return -EINVAL;
698 : : }
699 : :
700 [ # # ]: 0 : if (conf->domain.type != RTE_DMA_INTER_DOMAIN_NONE &&
701 : : conf->domain.type != RTE_DMA_INTER_PROCESS_DOMAIN &&
702 : : conf->domain.type != RTE_DMA_INTER_OS_DOMAIN) {
703 : 0 : RTE_DMA_LOG(ERR, "Device %d domain type invalid!", dev_id);
704 : 0 : return -EINVAL;
705 : : }
706 [ # # # # ]: 0 : if (conf->domain.reserved[0] != 0 || conf->domain.reserved[1] != 0) {
707 : 0 : RTE_DMA_LOG(ERR, "Device %d domain has non-zero reserved fields", dev_id);
708 : 0 : return -EINVAL;
709 : : }
710 [ # # # # ]: 0 : if (conf->domain.type != RTE_DMA_INTER_DOMAIN_NONE &&
711 : : conf->direction != RTE_DMA_DIR_MEM_TO_MEM) {
712 : 0 : RTE_DMA_LOG(ERR, "Device %d inter domain only support mem-to-mem transfer", dev_id);
713 : 0 : return -EINVAL;
714 : : }
715 : :
716 : : return 0;
717 : : }
718 : :
719 : : RTE_EXPORT_SYMBOL(rte_dma_vchan_setup)
720 : : int
721 : 0 : rte_dma_vchan_setup(int16_t dev_id, uint16_t vchan,
722 : : const struct rte_dma_vchan_conf *conf)
723 : : {
724 : : struct rte_dma_info dev_info;
725 : : struct rte_dma_dev *dev;
726 : : int ret;
727 : :
728 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || conf == NULL)
729 : : return -EINVAL;
730 : 0 : dev = &rte_dma_devices[dev_id];
731 : :
732 [ # # ]: 0 : if (dev->data->dev_started != 0) {
733 : 0 : RTE_DMA_LOG(ERR,
734 : : "Device %d must be stopped to allow configuration",
735 : : dev_id);
736 : 0 : return -EBUSY;
737 : : }
738 : :
739 : 0 : ret = dma_check_vchan_conf(dev_id, conf);
740 [ # # ]: 0 : if (ret != 0)
741 : : return ret;
742 : :
743 : 0 : ret = rte_dma_info_get(dev_id, &dev_info);
744 [ # # ]: 0 : if (ret != 0) {
745 : 0 : RTE_DMA_LOG(ERR, "Device %d get device info fail", dev_id);
746 : 0 : return -EINVAL;
747 : : }
748 [ # # ]: 0 : if (dev->data->dev_conf.nb_vchans == 0) {
749 : 0 : RTE_DMA_LOG(ERR, "Device %d must be configured first", dev_id);
750 : 0 : return -EINVAL;
751 : : }
752 [ # # ]: 0 : if (vchan >= dev_info.nb_vchans) {
753 : 0 : RTE_DMA_LOG(ERR, "Device %d vchan out range!", dev_id);
754 : 0 : return -EINVAL;
755 : : }
756 : :
757 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_MEM_TO_MEM &&
758 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_MEM_TO_MEM)) {
759 : 0 : RTE_DMA_LOG(ERR,
760 : : "Device %d don't support mem2mem transfer", dev_id);
761 : 0 : return -EINVAL;
762 : : }
763 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_MEM_TO_DEV &&
764 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_MEM_TO_DEV)) {
765 : 0 : RTE_DMA_LOG(ERR,
766 : : "Device %d don't support mem2dev transfer", dev_id);
767 : 0 : return -EINVAL;
768 : : }
769 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_DEV_TO_MEM &&
770 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_DEV_TO_MEM)) {
771 : 0 : RTE_DMA_LOG(ERR,
772 : : "Device %d don't support dev2mem transfer", dev_id);
773 : 0 : return -EINVAL;
774 : : }
775 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_DEV_TO_DEV &&
776 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_DEV_TO_DEV)) {
777 : 0 : RTE_DMA_LOG(ERR,
778 : : "Device %d don't support dev2dev transfer", dev_id);
779 : 0 : return -EINVAL;
780 : : }
781 [ # # ]: 0 : if (conf->nb_desc < dev_info.min_desc ||
782 [ # # ]: 0 : conf->nb_desc > dev_info.max_desc) {
783 : 0 : RTE_DMA_LOG(ERR,
784 : : "Device %d number of descriptors invalid", dev_id);
785 : 0 : return -EINVAL;
786 : : }
787 : :
788 [ # # ]: 0 : if (conf->auto_free.m2d.pool != NULL &&
789 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_M2D_AUTO_FREE)) {
790 : 0 : RTE_DMA_LOG(ERR, "Device %d does not support m2d auto free", dev_id);
791 : 0 : return -EINVAL;
792 : : }
793 : :
794 [ # # ]: 0 : if (conf->domain.type == RTE_DMA_INTER_OS_DOMAIN &&
795 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN)) {
796 : 0 : RTE_DMA_LOG(ERR, "Device %d does not support inter os domain", dev_id);
797 : 0 : return -EINVAL;
798 : : }
799 [ # # ]: 0 : if (conf->domain.type == RTE_DMA_INTER_PROCESS_DOMAIN &&
800 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN)) {
801 : 0 : RTE_DMA_LOG(ERR, "Device %d does not support inter process domain", dev_id);
802 : 0 : return -EINVAL;
803 : : }
804 : :
805 [ # # ]: 0 : if (dev->dev_ops->vchan_setup == NULL)
806 : : return -ENOTSUP;
807 : 0 : ret = dev->dev_ops->vchan_setup(dev, vchan, conf, sizeof(struct rte_dma_vchan_conf));
808 : 0 : rte_dma_trace_vchan_setup(dev_id, vchan, conf, ret);
809 : :
810 : 0 : return ret;
811 : : }
812 : :
813 : : RTE_EXPORT_SYMBOL(rte_dma_stats_get)
814 : : int
815 : 0 : rte_dma_stats_get(int16_t dev_id, uint16_t vchan, struct rte_dma_stats *stats)
816 : : {
817 : : const struct rte_dma_dev *dev;
818 : :
819 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || stats == NULL)
820 : : return -EINVAL;
821 : 0 : dev = &rte_dma_devices[dev_id];
822 : :
823 [ # # # # ]: 0 : if (vchan >= dev->data->dev_conf.nb_vchans &&
824 : : vchan != RTE_DMA_ALL_VCHAN) {
825 : 0 : RTE_DMA_LOG(ERR,
826 : : "Device %d vchan %u out of range", dev_id, vchan);
827 : 0 : return -EINVAL;
828 : : }
829 : :
830 [ # # ]: 0 : if (dev->dev_ops->stats_get == NULL)
831 : : return -ENOTSUP;
832 : : memset(stats, 0, sizeof(struct rte_dma_stats));
833 : 0 : return dev->dev_ops->stats_get(dev, vchan, stats, sizeof(struct rte_dma_stats));
834 : : }
835 : :
836 : : RTE_EXPORT_SYMBOL(rte_dma_stats_reset)
837 : : int
838 : 0 : rte_dma_stats_reset(int16_t dev_id, uint16_t vchan)
839 : : {
840 : : struct rte_dma_dev *dev;
841 : : int ret;
842 : :
843 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
844 : : return -EINVAL;
845 : 0 : dev = &rte_dma_devices[dev_id];
846 : :
847 [ # # # # ]: 0 : if (vchan >= dev->data->dev_conf.nb_vchans &&
848 : : vchan != RTE_DMA_ALL_VCHAN) {
849 : 0 : RTE_DMA_LOG(ERR,
850 : : "Device %d vchan %u out of range", dev_id, vchan);
851 : 0 : return -EINVAL;
852 : : }
853 : :
854 [ # # ]: 0 : if (dev->dev_ops->stats_reset == NULL)
855 : : return -ENOTSUP;
856 : 0 : ret = dev->dev_ops->stats_reset(dev, vchan);
857 : 0 : rte_dma_trace_stats_reset(dev_id, vchan, ret);
858 : :
859 : 0 : return ret;
860 : : }
861 : :
862 : : RTE_EXPORT_SYMBOL(rte_dma_vchan_status)
863 : : int
864 : 0 : rte_dma_vchan_status(int16_t dev_id, uint16_t vchan, enum rte_dma_vchan_status *status)
865 : : {
866 : : struct rte_dma_dev *dev;
867 : :
868 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || status == NULL)
869 : : return -EINVAL;
870 : 0 : dev = &rte_dma_devices[dev_id];
871 : :
872 [ # # ]: 0 : if (vchan >= dev->data->dev_conf.nb_vchans) {
873 : 0 : RTE_DMA_LOG(ERR, "Device %u vchan %u out of range", dev_id, vchan);
874 : 0 : return -EINVAL;
875 : : }
876 : :
877 [ # # ]: 0 : if (dev->dev_ops->vchan_status == NULL)
878 : : return -ENOTSUP;
879 : 0 : return dev->dev_ops->vchan_status(dev, vchan, status);
880 : : }
881 : :
882 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_create, 25.11)
883 : : int
884 : 0 : rte_dma_access_pair_group_create(int16_t dev_id, rte_uuid_t domain_id, rte_uuid_t token,
885 : : int16_t *group_id, rte_dma_access_pair_group_event_cb_t cb)
886 : : {
887 : : struct rte_dma_info dev_info;
888 : : struct rte_dma_dev *dev;
889 : :
890 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || group_id == NULL)
891 : : return -EINVAL;
892 : 0 : dev = &rte_dma_devices[dev_id];
893 : :
894 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
895 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
896 : 0 : return -EINVAL;
897 : : }
898 : :
899 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
900 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
901 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
902 : : dev_id);
903 : 0 : return -EINVAL;
904 : : }
905 : :
906 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_create == NULL)
907 : : return -ENOTSUP;
908 : 0 : return (*dev->dev_ops->access_pair_group_create)(dev, domain_id, token, group_id, cb);
909 : : }
910 : :
911 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_destroy, 25.11)
912 : : int
913 : 0 : rte_dma_access_pair_group_destroy(int16_t dev_id, int16_t group_id)
914 : : {
915 : : struct rte_dma_info dev_info;
916 : : struct rte_dma_dev *dev;
917 : :
918 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
919 : : return -EINVAL;
920 : 0 : dev = &rte_dma_devices[dev_id];
921 : :
922 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
923 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
924 : 0 : return -EINVAL;
925 : : }
926 : :
927 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
928 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
929 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
930 : : dev_id);
931 : 0 : return -EINVAL;
932 : : }
933 : :
934 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_destroy == NULL)
935 : : return -ENOTSUP;
936 : 0 : return (*dev->dev_ops->access_pair_group_destroy)(dev, group_id);
937 : : }
938 : :
939 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_join, 25.11)
940 : : int
941 : 0 : rte_dma_access_pair_group_join(int16_t dev_id, rte_uuid_t domain_id, rte_uuid_t token,
942 : : int16_t group_id, rte_dma_access_pair_group_event_cb_t cb)
943 : : {
944 : : struct rte_dma_info dev_info;
945 : : struct rte_dma_dev *dev;
946 : :
947 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
948 : : return -EINVAL;
949 : 0 : dev = &rte_dma_devices[dev_id];
950 : :
951 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
952 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
953 : 0 : return -EINVAL;
954 : : }
955 : :
956 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
957 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
958 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
959 : : dev_id);
960 : 0 : return -EINVAL;
961 : : }
962 : :
963 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_join == NULL)
964 : : return -ENOTSUP;
965 : 0 : return (*dev->dev_ops->access_pair_group_join)(dev, domain_id, token, group_id, cb);
966 : : }
967 : :
968 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_leave, 25.11)
969 : : int
970 : 0 : rte_dma_access_pair_group_leave(int16_t dev_id, int16_t group_id)
971 : : {
972 : : struct rte_dma_info dev_info;
973 : : struct rte_dma_dev *dev;
974 : :
975 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
976 : : return -EINVAL;
977 : 0 : dev = &rte_dma_devices[dev_id];
978 : :
979 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
980 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
981 : 0 : return -EINVAL;
982 : : }
983 : :
984 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
985 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
986 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
987 : : dev_id);
988 : 0 : return -EINVAL;
989 : : }
990 : :
991 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_leave == NULL)
992 : : return -ENOTSUP;
993 : 0 : return (*dev->dev_ops->access_pair_group_leave)(dev, group_id);
994 : : }
995 : :
996 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_handler_get, 25.11)
997 : : int
998 : 0 : rte_dma_access_pair_group_handler_get(int16_t dev_id, int16_t group_id, rte_uuid_t domain_id,
999 : : uint16_t *handler)
1000 : : {
1001 : : struct rte_dma_info dev_info;
1002 : : struct rte_dma_dev *dev;
1003 : :
1004 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || handler == NULL)
1005 : : return -EINVAL;
1006 : 0 : dev = &rte_dma_devices[dev_id];
1007 : :
1008 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
1009 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
1010 : 0 : return -EINVAL;
1011 : : }
1012 : :
1013 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
1014 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
1015 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
1016 : : dev_id);
1017 : 0 : return -EINVAL;
1018 : : }
1019 : :
1020 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_handler_get == NULL)
1021 : : return -ENOTSUP;
1022 : 0 : return (*dev->dev_ops->access_pair_group_handler_get)(dev, group_id, domain_id, handler);
1023 : : }
1024 : :
1025 : : static const char *
1026 : : dma_capability_name(uint64_t capability)
1027 : : {
1028 : : static const struct {
1029 : : uint64_t capability;
1030 : : const char *name;
1031 : : } capa_names[] = {
1032 : : { RTE_DMA_CAPA_MEM_TO_MEM, "mem2mem" },
1033 : : { RTE_DMA_CAPA_MEM_TO_DEV, "mem2dev" },
1034 : : { RTE_DMA_CAPA_DEV_TO_MEM, "dev2mem" },
1035 : : { RTE_DMA_CAPA_DEV_TO_DEV, "dev2dev" },
1036 : : { RTE_DMA_CAPA_SVA, "sva" },
1037 : : { RTE_DMA_CAPA_SILENT, "silent" },
1038 : : { RTE_DMA_CAPA_HANDLES_ERRORS, "handles_errors" },
1039 : : { RTE_DMA_CAPA_M2D_AUTO_FREE, "m2d_auto_free" },
1040 : : { RTE_DMA_CAPA_PRI_POLICY_SP, "pri_policy_sp" },
1041 : : { RTE_DMA_CAPA_INTER_PROCESS_DOMAIN, "inter_process_domain" },
1042 : : { RTE_DMA_CAPA_INTER_OS_DOMAIN, "inter_os_domain" },
1043 : : { RTE_DMA_CAPA_OPS_COPY, "copy" },
1044 : : { RTE_DMA_CAPA_OPS_COPY_SG, "copy_sg" },
1045 : : { RTE_DMA_CAPA_OPS_FILL, "fill" },
1046 : : };
1047 : :
1048 : : const char *name = "unknown";
1049 : : uint32_t i;
1050 : :
1051 [ + - + - : 149 : for (i = 0; i < RTE_DIM(capa_names); i++) {
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
1052 [ + + + + : 149 : if (capability == capa_names[i].capability) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + ]
1053 : 18 : name = capa_names[i].name;
1054 : 18 : break;
1055 : : }
1056 : : }
1057 : :
1058 : : return name;
1059 : : }
1060 : :
1061 : : static void
1062 : 1 : dma_dump_capability(FILE *f, uint64_t dev_capa)
1063 : : {
1064 : : uint64_t capa;
1065 : :
1066 : : (void)fprintf(f, " dev_capa: 0x%" PRIx64 " -", dev_capa);
1067 [ + + ]: 6 : while (dev_capa > 0) {
1068 : 5 : capa = 1ull << rte_ctz64(dev_capa);
1069 : : (void)fprintf(f, " %s", dma_capability_name(capa));
1070 : 5 : dev_capa &= ~capa;
1071 : : }
1072 : : (void)fprintf(f, "\n");
1073 : 1 : }
1074 : :
1075 : : RTE_EXPORT_SYMBOL(rte_dma_dump)
1076 : : int
1077 : 1 : rte_dma_dump(int16_t dev_id, FILE *f)
1078 : : {
1079 : : const struct rte_dma_dev *dev;
1080 : : struct rte_dma_info dev_info;
1081 : : int ret;
1082 : :
1083 [ + - + - ]: 1 : if (!rte_dma_is_valid(dev_id) || f == NULL)
1084 : : return -EINVAL;
1085 : 1 : dev = &rte_dma_devices[dev_id];
1086 : :
1087 : 1 : ret = rte_dma_info_get(dev_id, &dev_info);
1088 [ - + ]: 1 : if (ret != 0) {
1089 : 0 : RTE_DMA_LOG(ERR, "Device %d get device info fail", dev_id);
1090 : 0 : return -EINVAL;
1091 : : }
1092 : :
1093 : 2 : (void)fprintf(f, "DMA Dev %d, '%s' [%s]\n",
1094 : 1 : dev->data->dev_id,
1095 : 1 : dev->data->dev_name,
1096 [ + - ]: 1 : dev->data->dev_started ? "started" : "stopped");
1097 : 1 : dma_dump_capability(f, dev_info.dev_capa);
1098 : 1 : (void)fprintf(f, " max_vchans_supported: %u\n", dev_info.max_vchans);
1099 : 1 : (void)fprintf(f, " nb_vchans_configured: %u\n", dev_info.nb_vchans);
1100 : 1 : (void)fprintf(f, " silent_mode: %s\n",
1101 [ + - ]: 1 : dev->data->dev_conf.flags & RTE_DMA_CFG_FLAG_SILENT ? "on" : "off");
1102 : 1 : (void)fprintf(f, " ops_mode: %s\n",
1103 [ + - ]: 1 : dev->data->dev_conf.flags & RTE_DMA_CFG_FLAG_ENQ_DEQ ? "on" : "off");
1104 : :
1105 [ + - ]: 1 : if (dev->dev_ops->dev_dump != NULL)
1106 : 1 : ret = dev->dev_ops->dev_dump(dev, f);
1107 : 1 : rte_dma_trace_dump(dev_id, f, ret);
1108 : :
1109 : 1 : return ret;
1110 : : }
1111 : :
1112 : : static int
1113 : 0 : dummy_copy(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1114 : : __rte_unused rte_iova_t src, __rte_unused rte_iova_t dst,
1115 : : __rte_unused uint32_t length, __rte_unused uint64_t flags)
1116 : : {
1117 : 0 : RTE_DMA_LOG(ERR, "copy is not configured or not supported.");
1118 : 0 : return -EINVAL;
1119 : : }
1120 : :
1121 : : static int
1122 : 0 : dummy_copy_sg(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1123 : : __rte_unused const struct rte_dma_sge *src,
1124 : : __rte_unused const struct rte_dma_sge *dst,
1125 : : __rte_unused uint16_t nb_src, __rte_unused uint16_t nb_dst,
1126 : : __rte_unused uint64_t flags)
1127 : : {
1128 : 0 : RTE_DMA_LOG(ERR, "copy_sg is not configured or not supported.");
1129 : 0 : return -EINVAL;
1130 : : }
1131 : :
1132 : : static int
1133 : 0 : dummy_fill(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1134 : : __rte_unused uint64_t pattern, __rte_unused rte_iova_t dst,
1135 : : __rte_unused uint32_t length, __rte_unused uint64_t flags)
1136 : : {
1137 : 0 : RTE_DMA_LOG(ERR, "fill is not configured or not supported.");
1138 : 0 : return -EINVAL;
1139 : : }
1140 : :
1141 : : static int
1142 : 0 : dummy_submit(__rte_unused void *dev_private, __rte_unused uint16_t vchan)
1143 : : {
1144 : 0 : RTE_DMA_LOG(ERR, "submit is not configured or not supported.");
1145 : 0 : return -EINVAL;
1146 : : }
1147 : :
1148 : : static uint16_t
1149 : 0 : dummy_completed(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1150 : : __rte_unused const uint16_t nb_cpls,
1151 : : __rte_unused uint16_t *last_idx, __rte_unused bool *has_error)
1152 : : {
1153 : 0 : RTE_DMA_LOG(ERR, "completed is not configured or not supported.");
1154 : 0 : return 0;
1155 : : }
1156 : :
1157 : : static uint16_t
1158 : 0 : dummy_completed_status(__rte_unused void *dev_private,
1159 : : __rte_unused uint16_t vchan,
1160 : : __rte_unused const uint16_t nb_cpls,
1161 : : __rte_unused uint16_t *last_idx,
1162 : : __rte_unused enum rte_dma_status_code *status)
1163 : : {
1164 : 0 : RTE_DMA_LOG(ERR,
1165 : : "completed_status is not configured or not supported.");
1166 : 0 : return 0;
1167 : : }
1168 : :
1169 : : static uint16_t
1170 : 0 : dummy_burst_capacity(__rte_unused const void *dev_private,
1171 : : __rte_unused uint16_t vchan)
1172 : : {
1173 : 0 : RTE_DMA_LOG(ERR, "burst_capacity is not configured or not supported.");
1174 : 0 : return 0;
1175 : : }
1176 : :
1177 : : static uint16_t
1178 : 0 : dummy_enqueue(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1179 : : __rte_unused struct rte_dma_op **ops, __rte_unused uint16_t nb_ops)
1180 : : {
1181 : 0 : RTE_DMA_LOG(ERR, "Enqueue not configured or not supported.");
1182 : 0 : return 0;
1183 : : }
1184 : :
1185 : : static uint16_t
1186 : 0 : dummy_dequeue(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1187 : : __rte_unused struct rte_dma_op **ops, __rte_unused uint16_t nb_ops)
1188 : : {
1189 : 0 : RTE_DMA_LOG(ERR, "Enqueue not configured or not supported.");
1190 : 0 : return 0;
1191 : : }
1192 : :
1193 : : static void
1194 : : dma_fp_object_dummy(struct rte_dma_fp_object *obj)
1195 : : {
1196 : 66 : obj->dev_private = NULL;
1197 : 66 : obj->copy = dummy_copy;
1198 : 66 : obj->copy_sg = dummy_copy_sg;
1199 : 66 : obj->fill = dummy_fill;
1200 : 66 : obj->submit = dummy_submit;
1201 : 66 : obj->completed = dummy_completed;
1202 : 66 : obj->completed_status = dummy_completed_status;
1203 : 66 : obj->burst_capacity = dummy_burst_capacity;
1204 : 66 : obj->enqueue = dummy_enqueue;
1205 : 64 : obj->dequeue = dummy_dequeue;
1206 : 1 : }
1207 : :
1208 : : static int
1209 : 3 : dmadev_handle_dev_list(const char *cmd __rte_unused,
1210 : : const char *params __rte_unused,
1211 : : struct rte_tel_data *d)
1212 : : {
1213 : : int dev_id;
1214 : :
1215 : 3 : rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
1216 [ + + ]: 195 : for (dev_id = 0; dev_id < dma_devices_max; dev_id++)
1217 [ + + ]: 192 : if (rte_dma_is_valid(dev_id))
1218 : 3 : rte_tel_data_add_array_int(d, dev_id);
1219 : :
1220 : 3 : return 0;
1221 : : }
1222 : :
1223 : : /* Parse an unsigned integer telemetry parameter, returning the value or
1224 : : * -EINVAL. 'max' must be <= INT_MAX.
1225 : : */
1226 : : static int
1227 : 9 : dmadev_parse_uint(const char *str, char **end, unsigned long max)
1228 : : {
1229 : : unsigned long val;
1230 : :
1231 [ + + + + ]: 9 : if (str == NULL || !isdigit((unsigned char)*str))
1232 : : return -EINVAL;
1233 : :
1234 : 3 : errno = 0;
1235 : 3 : val = strtoul(str, end, 0);
1236 [ + - + - ]: 3 : if (errno != 0 || val > max)
1237 : : return -EINVAL;
1238 : :
1239 : 3 : return (int)val;
1240 : : }
1241 : :
1242 : : #define ADD_CAPA(td, dc, c) rte_tel_data_add_dict_int(td, dma_capability_name(c), !!(dc & c))
1243 : :
1244 : : static int
1245 : 3 : dmadev_handle_dev_info(const char *cmd __rte_unused,
1246 : : const char *params, struct rte_tel_data *d)
1247 : : {
1248 : : struct rte_dma_info dma_info;
1249 : : struct rte_tel_data *dma_caps;
1250 : : int dev_id, ret;
1251 : : uint64_t dev_capa;
1252 : : char *end_param;
1253 : :
1254 : 3 : dev_id = dmadev_parse_uint(params, &end_param, INT16_MAX);
1255 [ + + ]: 3 : if (dev_id < 0)
1256 : : return -EINVAL;
1257 [ - + ]: 1 : if (*end_param != '\0')
1258 : 0 : RTE_DMA_LOG(WARNING, "Extra parameters passed to dmadev telemetry command, ignoring");
1259 : :
1260 : : /* Function info_get validates dev_id so we don't need to. */
1261 : 1 : ret = rte_dma_info_get(dev_id, &dma_info);
1262 [ + - ]: 1 : if (ret < 0)
1263 : : return -EINVAL;
1264 : 1 : dev_capa = dma_info.dev_capa;
1265 : :
1266 : 1 : rte_tel_data_start_dict(d);
1267 : 1 : rte_tel_data_add_dict_string(d, "name", dma_info.dev_name);
1268 : 1 : rte_tel_data_add_dict_int(d, "nb_vchans", dma_info.nb_vchans);
1269 : 1 : rte_tel_data_add_dict_int(d, "nb_priorities", dma_info.nb_priorities);
1270 : 1 : rte_tel_data_add_dict_int(d, "numa_node", dma_info.numa_node);
1271 : 1 : rte_tel_data_add_dict_int(d, "max_vchans", dma_info.max_vchans);
1272 : 1 : rte_tel_data_add_dict_int(d, "max_desc", dma_info.max_desc);
1273 : 1 : rte_tel_data_add_dict_int(d, "min_desc", dma_info.min_desc);
1274 : 1 : rte_tel_data_add_dict_int(d, "max_sges", dma_info.max_sges);
1275 : :
1276 : 1 : dma_caps = rte_tel_data_alloc();
1277 [ + - ]: 1 : if (!dma_caps)
1278 : : return -ENOMEM;
1279 : :
1280 : 1 : rte_tel_data_start_dict(dma_caps);
1281 : 1 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_MEM_TO_MEM);
1282 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_MEM_TO_DEV);
1283 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_DEV_TO_MEM);
1284 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_DEV_TO_DEV);
1285 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_SVA);
1286 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_SILENT);
1287 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_HANDLES_ERRORS);
1288 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_M2D_AUTO_FREE);
1289 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_PRI_POLICY_SP);
1290 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_INTER_PROCESS_DOMAIN);
1291 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_INTER_OS_DOMAIN);
1292 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_OPS_COPY);
1293 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_OPS_COPY_SG);
1294 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_OPS_FILL);
1295 : 1 : rte_tel_data_add_dict_container(d, "capabilities", dma_caps, 0);
1296 : :
1297 : 1 : return 0;
1298 : : }
1299 : :
1300 : : #define ADD_DICT_STAT(s) rte_tel_data_add_dict_uint(d, #s, dma_stats.s)
1301 : :
1302 : : static int
1303 : 3 : dmadev_handle_dev_stats(const char *cmd __rte_unused,
1304 : : const char *params,
1305 : : struct rte_tel_data *d)
1306 : : {
1307 : : struct rte_dma_info dma_info;
1308 : : struct rte_dma_stats dma_stats;
1309 : : int dev_id, ret, vchan_id;
1310 : : char *end_param;
1311 : :
1312 : 3 : dev_id = dmadev_parse_uint(params, &end_param, INT16_MAX);
1313 [ + + ]: 3 : if (dev_id < 0)
1314 : : return -EINVAL;
1315 : :
1316 : : /* Function info_get validates dev_id so we don't need to. */
1317 : 1 : ret = rte_dma_info_get(dev_id, &dma_info);
1318 [ + - ]: 1 : if (ret < 0)
1319 : : return -EINVAL;
1320 : :
1321 : : /* If the device has one vchan the user does not need to supply the
1322 : : * vchan id and only the device id is needed, no extra parameters.
1323 : : */
1324 [ - + - - ]: 1 : if (dma_info.nb_vchans == 1 && *end_param == '\0')
1325 : : vchan_id = 0;
1326 : : else {
1327 [ - + ]: 1 : if (*end_param != ',')
1328 : : return -EINVAL;
1329 : 0 : vchan_id = dmadev_parse_uint(end_param + 1, &end_param, UINT16_MAX);
1330 [ # # ]: 0 : if (vchan_id < 0)
1331 : : return -EINVAL;
1332 : : }
1333 [ # # ]: 0 : if (*end_param != '\0')
1334 : 0 : RTE_DMA_LOG(WARNING, "Extra parameters passed to dmadev telemetry command, ignoring");
1335 : :
1336 : 0 : ret = rte_dma_stats_get(dev_id, vchan_id, &dma_stats);
1337 [ # # ]: 0 : if (ret < 0)
1338 : : return -EINVAL;
1339 : :
1340 : 0 : rte_tel_data_start_dict(d);
1341 : 0 : ADD_DICT_STAT(submitted);
1342 : 0 : ADD_DICT_STAT(completed);
1343 : 0 : ADD_DICT_STAT(errors);
1344 : :
1345 : 0 : return 0;
1346 : : }
1347 : :
1348 : : #ifndef RTE_EXEC_ENV_WINDOWS
1349 : : static int
1350 : 3 : dmadev_handle_dev_dump(const char *cmd __rte_unused,
1351 : : const char *params,
1352 : : struct rte_tel_data *d)
1353 : : {
1354 : : char *buf, *end_param;
1355 : : int dev_id, ret;
1356 : : FILE *f;
1357 : :
1358 : 3 : dev_id = dmadev_parse_uint(params, &end_param, INT16_MAX);
1359 [ + + ]: 3 : if (dev_id < 0)
1360 : : return -EINVAL;
1361 [ - + ]: 1 : if (*end_param != '\0')
1362 : 0 : RTE_DMA_LOG(WARNING, "Extra parameters passed to dmadev telemetry command, ignoring");
1363 : :
1364 : 1 : buf = calloc(RTE_TEL_MAX_SINGLE_STRING_LEN, sizeof(char));
1365 [ + - ]: 1 : if (buf == NULL)
1366 : : return -ENOMEM;
1367 : :
1368 : 1 : f = fmemopen(buf, RTE_TEL_MAX_SINGLE_STRING_LEN - 1, "w+");
1369 [ - + ]: 1 : if (f == NULL) {
1370 : 0 : free(buf);
1371 : 0 : return -EINVAL;
1372 : : }
1373 : :
1374 : 1 : ret = rte_dma_dump(dev_id, f);
1375 : 1 : fclose(f);
1376 [ + - ]: 1 : if (ret == 0) {
1377 : 1 : rte_tel_data_start_dict(d);
1378 : 1 : rte_tel_data_string(d, buf);
1379 : : }
1380 : :
1381 : 1 : free(buf);
1382 : 1 : return ret;
1383 : : }
1384 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1385 : :
1386 : 303 : RTE_INIT(dmadev_init_telemetry)
1387 : : {
1388 : 303 : rte_telemetry_register_cmd("/dmadev/list", dmadev_handle_dev_list,
1389 : : "Returns list of available dmadev devices by IDs. No parameters.");
1390 : 303 : rte_telemetry_register_cmd("/dmadev/info", dmadev_handle_dev_info,
1391 : : "Returns information for a dmadev. Parameters: int dev_id");
1392 : 303 : rte_telemetry_register_cmd("/dmadev/stats", dmadev_handle_dev_stats,
1393 : : "Returns the stats for a dmadev vchannel. Parameters: int dev_id, vchan_id (Optional if only one vchannel)");
1394 : : #ifndef RTE_EXEC_ENV_WINDOWS
1395 : 303 : rte_telemetry_register_cmd("/dmadev/dump", dmadev_handle_dev_dump,
1396 : : "Returns dump information for a dmadev. Parameters: int dev_id");
1397 : : #endif
1398 : 303 : }
|