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 [ - + ]: 301 : 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 : : struct rte_dma_info dev_info;
484 : : struct rte_dma_dev *dev;
485 : : int ret;
486 : :
487 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || dev_conf == NULL)
488 : : return -EINVAL;
489 : 0 : dev = &rte_dma_devices[dev_id];
490 : :
491 [ # # ]: 0 : if (dev->data->dev_started != 0) {
492 : 0 : RTE_DMA_LOG(ERR,
493 : : "Device %d must be stopped to allow configuration",
494 : : dev_id);
495 : 0 : return -EBUSY;
496 : : }
497 : :
498 : 0 : ret = rte_dma_info_get(dev_id, &dev_info);
499 [ # # ]: 0 : if (ret != 0) {
500 : 0 : RTE_DMA_LOG(ERR, "Device %d get device info fail", dev_id);
501 : 0 : return -EINVAL;
502 : : }
503 [ # # ]: 0 : if (dev_conf->nb_vchans == 0) {
504 : 0 : RTE_DMA_LOG(ERR,
505 : : "Device %d configure zero vchans", dev_id);
506 : 0 : return -EINVAL;
507 : : }
508 [ # # ]: 0 : if (dev_conf->nb_vchans > dev_info.max_vchans) {
509 : 0 : RTE_DMA_LOG(ERR,
510 : : "Device %d configure too many vchans", dev_id);
511 : 0 : return -EINVAL;
512 : : }
513 [ # # ]: 0 : if ((dev_conf->flags & RTE_DMA_CFG_FLAG_SILENT) &&
514 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_SILENT)) {
515 : 0 : RTE_DMA_LOG(ERR, "Device %d don't support silent", dev_id);
516 : 0 : return -EINVAL;
517 : : }
518 : :
519 [ # # ]: 0 : if ((dev_info.dev_capa & RTE_DMA_CAPA_PRI_POLICY_SP) &&
520 [ # # ]: 0 : (dev_conf->priority >= dev_info.nb_priorities)) {
521 : 0 : RTE_DMA_LOG(ERR, "Device %d configure invalid priority", dev_id);
522 : 0 : return -EINVAL;
523 : : }
524 : :
525 [ # # ]: 0 : if ((dev_conf->flags & RTE_DMA_CFG_FLAG_ENQ_DEQ) &&
526 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_OPS_ENQ_DEQ)) {
527 : 0 : RTE_DMA_LOG(ERR, "Device %d don't support enqueue/dequeue", dev_id);
528 : 0 : return -EINVAL;
529 : : }
530 : :
531 [ # # ]: 0 : if (dev->dev_ops->dev_configure == NULL)
532 : : return -ENOTSUP;
533 : 0 : ret = dev->dev_ops->dev_configure(dev, dev_conf, sizeof(struct rte_dma_conf));
534 [ # # ]: 0 : if (ret == 0)
535 : 0 : memcpy(&dev->data->dev_conf, dev_conf,
536 : : sizeof(struct rte_dma_conf));
537 : :
538 : 0 : rte_dma_trace_configure(dev_id, dev_conf, ret);
539 : :
540 : 0 : return ret;
541 : : }
542 : :
543 : : RTE_EXPORT_SYMBOL(rte_dma_start)
544 : : int
545 : 0 : rte_dma_start(int16_t dev_id)
546 : : {
547 : : struct rte_dma_dev *dev;
548 : : int ret;
549 : :
550 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
551 : : return -EINVAL;
552 : 0 : dev = &rte_dma_devices[dev_id];
553 : :
554 [ # # ]: 0 : if (dev->data->dev_conf.nb_vchans == 0) {
555 : 0 : RTE_DMA_LOG(ERR, "Device %d must be configured first", dev_id);
556 : 0 : return -EINVAL;
557 : : }
558 : :
559 [ # # ]: 0 : if (dev->data->dev_started != 0) {
560 : 0 : RTE_DMA_LOG(WARNING, "Device %d already started", dev_id);
561 : 0 : return 0;
562 : : }
563 : :
564 [ # # ]: 0 : if (dev->dev_ops->dev_start == NULL)
565 : 0 : goto mark_started;
566 : :
567 : 0 : ret = dev->dev_ops->dev_start(dev);
568 : 0 : rte_dma_trace_start(dev_id, ret);
569 [ # # ]: 0 : if (ret != 0)
570 : : return ret;
571 : :
572 : 0 : mark_started:
573 : 0 : dev->data->dev_started = 1;
574 : 0 : return 0;
575 : : }
576 : :
577 : : RTE_EXPORT_SYMBOL(rte_dma_stop)
578 : : int
579 : 0 : rte_dma_stop(int16_t dev_id)
580 : : {
581 : : struct rte_dma_dev *dev;
582 : : int ret;
583 : :
584 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
585 : : return -EINVAL;
586 : 0 : dev = &rte_dma_devices[dev_id];
587 : :
588 [ # # ]: 0 : if (dev->data->dev_started == 0) {
589 : 0 : RTE_DMA_LOG(WARNING, "Device %d already stopped", dev_id);
590 : 0 : return 0;
591 : : }
592 : :
593 [ # # ]: 0 : if (dev->dev_ops->dev_stop == NULL)
594 : 0 : goto mark_stopped;
595 : :
596 : 0 : ret = dev->dev_ops->dev_stop(dev);
597 : 0 : rte_dma_trace_stop(dev_id, ret);
598 [ # # ]: 0 : if (ret != 0)
599 : : return ret;
600 : :
601 : 0 : mark_stopped:
602 : 0 : dev->data->dev_started = 0;
603 : 0 : return 0;
604 : : }
605 : :
606 : : RTE_EXPORT_SYMBOL(rte_dma_close)
607 : : int
608 : 1 : rte_dma_close(int16_t dev_id)
609 : : {
610 : : struct rte_dma_dev *dev;
611 : : int ret;
612 : :
613 [ + - ]: 1 : if (!rte_dma_is_valid(dev_id))
614 : : return -EINVAL;
615 : 1 : dev = &rte_dma_devices[dev_id];
616 : :
617 : : /* Device must be stopped before it can be closed */
618 [ - + ]: 1 : if (dev->data->dev_started == 1) {
619 : 0 : RTE_DMA_LOG(ERR,
620 : : "Device %d must be stopped before closing", dev_id);
621 : 0 : return -EBUSY;
622 : : }
623 : :
624 [ + - ]: 1 : if (dev->dev_ops->dev_close == NULL)
625 : : return -ENOTSUP;
626 : 1 : ret = dev->dev_ops->dev_close(dev);
627 [ + - ]: 1 : if (ret == 0)
628 : 1 : dma_release(dev);
629 : :
630 : 1 : rte_dma_trace_close(dev_id, ret);
631 : :
632 : 1 : return ret;
633 : : }
634 : :
635 : : RTE_EXPORT_SYMBOL(rte_dma_vchan_setup)
636 : : int
637 : 0 : rte_dma_vchan_setup(int16_t dev_id, uint16_t vchan,
638 : : const struct rte_dma_vchan_conf *conf)
639 : : {
640 : : struct rte_dma_info dev_info;
641 : : bool src_is_dev, dst_is_dev;
642 : : struct rte_dma_dev *dev;
643 : : int ret;
644 : :
645 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || conf == NULL)
646 : : return -EINVAL;
647 : 0 : dev = &rte_dma_devices[dev_id];
648 : :
649 [ # # ]: 0 : if (dev->data->dev_started != 0) {
650 : 0 : RTE_DMA_LOG(ERR,
651 : : "Device %d must be stopped to allow configuration",
652 : : dev_id);
653 : 0 : return -EBUSY;
654 : : }
655 : :
656 : 0 : ret = rte_dma_info_get(dev_id, &dev_info);
657 [ # # ]: 0 : if (ret != 0) {
658 : 0 : RTE_DMA_LOG(ERR, "Device %d get device info fail", dev_id);
659 : 0 : return -EINVAL;
660 : : }
661 [ # # ]: 0 : if (dev->data->dev_conf.nb_vchans == 0) {
662 : 0 : RTE_DMA_LOG(ERR, "Device %d must be configured first", dev_id);
663 : 0 : return -EINVAL;
664 : : }
665 [ # # ]: 0 : if (vchan >= dev_info.nb_vchans) {
666 : 0 : RTE_DMA_LOG(ERR, "Device %d vchan out range!", dev_id);
667 : 0 : return -EINVAL;
668 : : }
669 [ # # ]: 0 : if (conf->domain.type != RTE_DMA_INTER_DOMAIN_NONE &&
670 [ # # ]: 0 : conf->direction != RTE_DMA_DIR_MEM_TO_MEM) {
671 : 0 : RTE_DMA_LOG(ERR, "Device %d inter domain only support mem-to-mem transfer", dev_id);
672 : 0 : return -EINVAL;
673 : : }
674 [ # # ]: 0 : if (conf->domain.type == RTE_DMA_INTER_OS_DOMAIN &&
675 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN)) {
676 : 0 : RTE_DMA_LOG(ERR, "Device %d does not support inter os domain", dev_id);
677 : 0 : return -EINVAL;
678 : : }
679 [ # # ]: 0 : if (conf->domain.type == RTE_DMA_INTER_PROCESS_DOMAIN &&
680 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN)) {
681 : 0 : RTE_DMA_LOG(ERR, "Device %d does not support inter process domain", dev_id);
682 : 0 : return -EINVAL;
683 : : }
684 [ # # ]: 0 : if ((conf->domain.type == RTE_DMA_INTER_PROCESS_DOMAIN ||
685 : 0 : conf->domain.type == RTE_DMA_INTER_OS_DOMAIN) &&
686 [ # # # # ]: 0 : (conf->domain.reserved[0] != 0 || conf->domain.reserved[1] != 0)) {
687 : 0 : RTE_DMA_LOG(ERR, "Device %d does not support non-zero reserved fields", dev_id);
688 : 0 : return -EINVAL;
689 : : }
690 [ # # ]: 0 : if (conf->direction != RTE_DMA_DIR_MEM_TO_MEM &&
691 : : conf->direction != RTE_DMA_DIR_MEM_TO_DEV &&
692 : : conf->direction != RTE_DMA_DIR_DEV_TO_MEM &&
693 : : conf->direction != RTE_DMA_DIR_DEV_TO_DEV) {
694 : 0 : RTE_DMA_LOG(ERR, "Device %d direction invalid!", dev_id);
695 : 0 : return -EINVAL;
696 : : }
697 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_MEM_TO_MEM &&
698 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_MEM_TO_MEM)) {
699 : 0 : RTE_DMA_LOG(ERR,
700 : : "Device %d don't support mem2mem transfer", dev_id);
701 : 0 : return -EINVAL;
702 : : }
703 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_MEM_TO_DEV &&
704 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_MEM_TO_DEV)) {
705 : 0 : RTE_DMA_LOG(ERR,
706 : : "Device %d don't support mem2dev transfer", dev_id);
707 : 0 : return -EINVAL;
708 : : }
709 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_DEV_TO_MEM &&
710 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_DEV_TO_MEM)) {
711 : 0 : RTE_DMA_LOG(ERR,
712 : : "Device %d don't support dev2mem transfer", dev_id);
713 : 0 : return -EINVAL;
714 : : }
715 [ # # ]: 0 : if (conf->direction == RTE_DMA_DIR_DEV_TO_DEV &&
716 [ # # ]: 0 : !(dev_info.dev_capa & RTE_DMA_CAPA_DEV_TO_DEV)) {
717 : 0 : RTE_DMA_LOG(ERR,
718 : : "Device %d don't support dev2dev transfer", dev_id);
719 : 0 : return -EINVAL;
720 : : }
721 [ # # ]: 0 : if (conf->nb_desc < dev_info.min_desc ||
722 [ # # ]: 0 : conf->nb_desc > dev_info.max_desc) {
723 : 0 : RTE_DMA_LOG(ERR,
724 : : "Device %d number of descriptors invalid", dev_id);
725 : 0 : return -EINVAL;
726 : : }
727 : 0 : src_is_dev = conf->direction == RTE_DMA_DIR_DEV_TO_MEM ||
728 : : conf->direction == RTE_DMA_DIR_DEV_TO_DEV;
729 [ # # # # : 0 : if ((conf->src_port.port_type == RTE_DMA_PORT_NONE && src_is_dev) ||
# # ]
730 [ # # ]: 0 : (conf->src_port.port_type != RTE_DMA_PORT_NONE && !src_is_dev)) {
731 : 0 : RTE_DMA_LOG(ERR, "Device %d source port type invalid", dev_id);
732 : 0 : return -EINVAL;
733 : : }
734 : 0 : dst_is_dev = conf->direction == RTE_DMA_DIR_MEM_TO_DEV ||
735 : : conf->direction == RTE_DMA_DIR_DEV_TO_DEV;
736 [ # # # # : 0 : if ((conf->dst_port.port_type == RTE_DMA_PORT_NONE && dst_is_dev) ||
# # ]
737 [ # # ]: 0 : (conf->dst_port.port_type != RTE_DMA_PORT_NONE && !dst_is_dev)) {
738 : 0 : RTE_DMA_LOG(ERR,
739 : : "Device %d destination port type invalid", dev_id);
740 : 0 : return -EINVAL;
741 : : }
742 : :
743 [ # # ]: 0 : if (dev->dev_ops->vchan_setup == NULL)
744 : : return -ENOTSUP;
745 : 0 : ret = dev->dev_ops->vchan_setup(dev, vchan, conf, sizeof(struct rte_dma_vchan_conf));
746 : 0 : rte_dma_trace_vchan_setup(dev_id, vchan, conf, ret);
747 : :
748 : 0 : return ret;
749 : : }
750 : :
751 : : RTE_EXPORT_SYMBOL(rte_dma_stats_get)
752 : : int
753 : 0 : rte_dma_stats_get(int16_t dev_id, uint16_t vchan, struct rte_dma_stats *stats)
754 : : {
755 : : const struct rte_dma_dev *dev;
756 : :
757 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || stats == NULL)
758 : : return -EINVAL;
759 : 0 : dev = &rte_dma_devices[dev_id];
760 : :
761 [ # # # # ]: 0 : if (vchan >= dev->data->dev_conf.nb_vchans &&
762 : : vchan != RTE_DMA_ALL_VCHAN) {
763 : 0 : RTE_DMA_LOG(ERR,
764 : : "Device %d vchan %u out of range", dev_id, vchan);
765 : 0 : return -EINVAL;
766 : : }
767 : :
768 [ # # ]: 0 : if (dev->dev_ops->stats_get == NULL)
769 : : return -ENOTSUP;
770 : : memset(stats, 0, sizeof(struct rte_dma_stats));
771 : 0 : return dev->dev_ops->stats_get(dev, vchan, stats, sizeof(struct rte_dma_stats));
772 : : }
773 : :
774 : : RTE_EXPORT_SYMBOL(rte_dma_stats_reset)
775 : : int
776 : 0 : rte_dma_stats_reset(int16_t dev_id, uint16_t vchan)
777 : : {
778 : : struct rte_dma_dev *dev;
779 : : int ret;
780 : :
781 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
782 : : return -EINVAL;
783 : 0 : dev = &rte_dma_devices[dev_id];
784 : :
785 [ # # # # ]: 0 : if (vchan >= dev->data->dev_conf.nb_vchans &&
786 : : vchan != RTE_DMA_ALL_VCHAN) {
787 : 0 : RTE_DMA_LOG(ERR,
788 : : "Device %d vchan %u out of range", dev_id, vchan);
789 : 0 : return -EINVAL;
790 : : }
791 : :
792 [ # # ]: 0 : if (dev->dev_ops->stats_reset == NULL)
793 : : return -ENOTSUP;
794 : 0 : ret = dev->dev_ops->stats_reset(dev, vchan);
795 : 0 : rte_dma_trace_stats_reset(dev_id, vchan, ret);
796 : :
797 : 0 : return ret;
798 : : }
799 : :
800 : : RTE_EXPORT_SYMBOL(rte_dma_vchan_status)
801 : : int
802 : 0 : rte_dma_vchan_status(int16_t dev_id, uint16_t vchan, enum rte_dma_vchan_status *status)
803 : : {
804 : : struct rte_dma_dev *dev;
805 : :
806 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || status == NULL)
807 : : return -EINVAL;
808 : 0 : dev = &rte_dma_devices[dev_id];
809 : :
810 [ # # ]: 0 : if (vchan >= dev->data->dev_conf.nb_vchans) {
811 : 0 : RTE_DMA_LOG(ERR, "Device %u vchan %u out of range", dev_id, vchan);
812 : 0 : return -EINVAL;
813 : : }
814 : :
815 [ # # ]: 0 : if (dev->dev_ops->vchan_status == NULL)
816 : : return -ENOTSUP;
817 : 0 : return dev->dev_ops->vchan_status(dev, vchan, status);
818 : : }
819 : :
820 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_create, 25.11)
821 : : int
822 : 0 : rte_dma_access_pair_group_create(int16_t dev_id, rte_uuid_t domain_id, rte_uuid_t token,
823 : : int16_t *group_id, rte_dma_access_pair_group_event_cb_t cb)
824 : : {
825 : : struct rte_dma_info dev_info;
826 : : struct rte_dma_dev *dev;
827 : :
828 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || group_id == NULL)
829 : : return -EINVAL;
830 : 0 : dev = &rte_dma_devices[dev_id];
831 : :
832 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
833 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
834 : 0 : return -EINVAL;
835 : : }
836 : :
837 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
838 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
839 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
840 : : dev_id);
841 : 0 : return -EINVAL;
842 : : }
843 : :
844 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_create == NULL)
845 : : return -ENOTSUP;
846 : 0 : return (*dev->dev_ops->access_pair_group_create)(dev, domain_id, token, group_id, cb);
847 : : }
848 : :
849 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_destroy, 25.11)
850 : : int
851 : 0 : rte_dma_access_pair_group_destroy(int16_t dev_id, int16_t group_id)
852 : : {
853 : : struct rte_dma_info dev_info;
854 : : struct rte_dma_dev *dev;
855 : :
856 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
857 : : return -EINVAL;
858 : 0 : dev = &rte_dma_devices[dev_id];
859 : :
860 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
861 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
862 : 0 : return -EINVAL;
863 : : }
864 : :
865 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
866 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
867 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
868 : : dev_id);
869 : 0 : return -EINVAL;
870 : : }
871 : :
872 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_destroy == NULL)
873 : : return -ENOTSUP;
874 : 0 : return (*dev->dev_ops->access_pair_group_destroy)(dev, group_id);
875 : : }
876 : :
877 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_join, 25.11)
878 : : int
879 : 0 : rte_dma_access_pair_group_join(int16_t dev_id, rte_uuid_t domain_id, rte_uuid_t token,
880 : : int16_t group_id, rte_dma_access_pair_group_event_cb_t cb)
881 : : {
882 : : struct rte_dma_info dev_info;
883 : : struct rte_dma_dev *dev;
884 : :
885 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
886 : : return -EINVAL;
887 : 0 : dev = &rte_dma_devices[dev_id];
888 : :
889 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
890 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
891 : 0 : return -EINVAL;
892 : : }
893 : :
894 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
895 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
896 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
897 : : dev_id);
898 : 0 : return -EINVAL;
899 : : }
900 : :
901 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_join == NULL)
902 : : return -ENOTSUP;
903 : 0 : return (*dev->dev_ops->access_pair_group_join)(dev, domain_id, token, group_id, cb);
904 : : }
905 : :
906 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_leave, 25.11)
907 : : int
908 : 0 : rte_dma_access_pair_group_leave(int16_t dev_id, int16_t group_id)
909 : : {
910 : : struct rte_dma_info dev_info;
911 : : struct rte_dma_dev *dev;
912 : :
913 [ # # ]: 0 : if (!rte_dma_is_valid(dev_id))
914 : : return -EINVAL;
915 : 0 : dev = &rte_dma_devices[dev_id];
916 : :
917 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
918 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
919 : 0 : return -EINVAL;
920 : : }
921 : :
922 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
923 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
924 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
925 : : dev_id);
926 : 0 : return -EINVAL;
927 : : }
928 : :
929 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_leave == NULL)
930 : : return -ENOTSUP;
931 : 0 : return (*dev->dev_ops->access_pair_group_leave)(dev, group_id);
932 : : }
933 : :
934 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dma_access_pair_group_handler_get, 25.11)
935 : : int
936 : 0 : rte_dma_access_pair_group_handler_get(int16_t dev_id, int16_t group_id, rte_uuid_t domain_id,
937 : : uint16_t *handler)
938 : : {
939 : : struct rte_dma_info dev_info;
940 : : struct rte_dma_dev *dev;
941 : :
942 [ # # # # ]: 0 : if (!rte_dma_is_valid(dev_id) || handler == NULL)
943 : : return -EINVAL;
944 : 0 : dev = &rte_dma_devices[dev_id];
945 : :
946 [ # # ]: 0 : if (rte_dma_info_get(dev_id, &dev_info)) {
947 : 0 : RTE_DMA_LOG(ERR, "Device %d info query failure", dev_id);
948 : 0 : return -EINVAL;
949 : : }
950 : :
951 [ # # ]: 0 : if (!((dev_info.dev_capa & RTE_DMA_CAPA_INTER_PROCESS_DOMAIN) ||
952 : : (dev_info.dev_capa & RTE_DMA_CAPA_INTER_OS_DOMAIN))) {
953 : 0 : RTE_DMA_LOG(ERR, "Device %d doesn't support inter-process or inter-os domain",
954 : : dev_id);
955 : 0 : return -EINVAL;
956 : : }
957 : :
958 [ # # ]: 0 : if (*dev->dev_ops->access_pair_group_handler_get == NULL)
959 : : return -ENOTSUP;
960 : 0 : return (*dev->dev_ops->access_pair_group_handler_get)(dev, group_id, domain_id, handler);
961 : : }
962 : :
963 : : static const char *
964 : : dma_capability_name(uint64_t capability)
965 : : {
966 : : static const struct {
967 : : uint64_t capability;
968 : : const char *name;
969 : : } capa_names[] = {
970 : : { RTE_DMA_CAPA_MEM_TO_MEM, "mem2mem" },
971 : : { RTE_DMA_CAPA_MEM_TO_DEV, "mem2dev" },
972 : : { RTE_DMA_CAPA_DEV_TO_MEM, "dev2mem" },
973 : : { RTE_DMA_CAPA_DEV_TO_DEV, "dev2dev" },
974 : : { RTE_DMA_CAPA_SVA, "sva" },
975 : : { RTE_DMA_CAPA_SILENT, "silent" },
976 : : { RTE_DMA_CAPA_HANDLES_ERRORS, "handles_errors" },
977 : : { RTE_DMA_CAPA_M2D_AUTO_FREE, "m2d_auto_free" },
978 : : { RTE_DMA_CAPA_PRI_POLICY_SP, "pri_policy_sp" },
979 : : { RTE_DMA_CAPA_INTER_PROCESS_DOMAIN, "inter_process_domain" },
980 : : { RTE_DMA_CAPA_INTER_OS_DOMAIN, "inter_os_domain" },
981 : : { RTE_DMA_CAPA_OPS_COPY, "copy" },
982 : : { RTE_DMA_CAPA_OPS_COPY_SG, "copy_sg" },
983 : : { RTE_DMA_CAPA_OPS_FILL, "fill" },
984 : : };
985 : :
986 : : const char *name = "unknown";
987 : : uint32_t i;
988 : :
989 [ + - + - : 149 : for (i = 0; i < RTE_DIM(capa_names); i++) {
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
990 [ + + + + : 149 : if (capability == capa_names[i].capability) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + ]
991 : 18 : name = capa_names[i].name;
992 : 18 : break;
993 : : }
994 : : }
995 : :
996 : : return name;
997 : : }
998 : :
999 : : static void
1000 : 1 : dma_dump_capability(FILE *f, uint64_t dev_capa)
1001 : : {
1002 : : uint64_t capa;
1003 : :
1004 : : (void)fprintf(f, " dev_capa: 0x%" PRIx64 " -", dev_capa);
1005 [ + + ]: 6 : while (dev_capa > 0) {
1006 : 5 : capa = 1ull << rte_ctz64(dev_capa);
1007 : : (void)fprintf(f, " %s", dma_capability_name(capa));
1008 : 5 : dev_capa &= ~capa;
1009 : : }
1010 : : (void)fprintf(f, "\n");
1011 : 1 : }
1012 : :
1013 : : RTE_EXPORT_SYMBOL(rte_dma_dump)
1014 : : int
1015 : 1 : rte_dma_dump(int16_t dev_id, FILE *f)
1016 : : {
1017 : : const struct rte_dma_dev *dev;
1018 : : struct rte_dma_info dev_info;
1019 : : int ret;
1020 : :
1021 [ + - + - ]: 1 : if (!rte_dma_is_valid(dev_id) || f == NULL)
1022 : : return -EINVAL;
1023 : 1 : dev = &rte_dma_devices[dev_id];
1024 : :
1025 : 1 : ret = rte_dma_info_get(dev_id, &dev_info);
1026 [ - + ]: 1 : if (ret != 0) {
1027 : 0 : RTE_DMA_LOG(ERR, "Device %d get device info fail", dev_id);
1028 : 0 : return -EINVAL;
1029 : : }
1030 : :
1031 : 2 : (void)fprintf(f, "DMA Dev %d, '%s' [%s]\n",
1032 : 1 : dev->data->dev_id,
1033 : 1 : dev->data->dev_name,
1034 [ + - ]: 1 : dev->data->dev_started ? "started" : "stopped");
1035 : 1 : dma_dump_capability(f, dev_info.dev_capa);
1036 : 1 : (void)fprintf(f, " max_vchans_supported: %u\n", dev_info.max_vchans);
1037 : 1 : (void)fprintf(f, " nb_vchans_configured: %u\n", dev_info.nb_vchans);
1038 : 1 : (void)fprintf(f, " silent_mode: %s\n",
1039 [ + - ]: 1 : dev->data->dev_conf.flags & RTE_DMA_CFG_FLAG_SILENT ? "on" : "off");
1040 : 1 : (void)fprintf(f, " ops_mode: %s\n",
1041 [ + - ]: 1 : dev->data->dev_conf.flags & RTE_DMA_CFG_FLAG_ENQ_DEQ ? "on" : "off");
1042 : :
1043 [ + - ]: 1 : if (dev->dev_ops->dev_dump != NULL)
1044 : 1 : ret = dev->dev_ops->dev_dump(dev, f);
1045 : 1 : rte_dma_trace_dump(dev_id, f, ret);
1046 : :
1047 : 1 : return ret;
1048 : : }
1049 : :
1050 : : static int
1051 : 0 : dummy_copy(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1052 : : __rte_unused rte_iova_t src, __rte_unused rte_iova_t dst,
1053 : : __rte_unused uint32_t length, __rte_unused uint64_t flags)
1054 : : {
1055 : 0 : RTE_DMA_LOG(ERR, "copy is not configured or not supported.");
1056 : 0 : return -EINVAL;
1057 : : }
1058 : :
1059 : : static int
1060 : 0 : dummy_copy_sg(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1061 : : __rte_unused const struct rte_dma_sge *src,
1062 : : __rte_unused const struct rte_dma_sge *dst,
1063 : : __rte_unused uint16_t nb_src, __rte_unused uint16_t nb_dst,
1064 : : __rte_unused uint64_t flags)
1065 : : {
1066 : 0 : RTE_DMA_LOG(ERR, "copy_sg is not configured or not supported.");
1067 : 0 : return -EINVAL;
1068 : : }
1069 : :
1070 : : static int
1071 : 0 : dummy_fill(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1072 : : __rte_unused uint64_t pattern, __rte_unused rte_iova_t dst,
1073 : : __rte_unused uint32_t length, __rte_unused uint64_t flags)
1074 : : {
1075 : 0 : RTE_DMA_LOG(ERR, "fill is not configured or not supported.");
1076 : 0 : return -EINVAL;
1077 : : }
1078 : :
1079 : : static int
1080 : 0 : dummy_submit(__rte_unused void *dev_private, __rte_unused uint16_t vchan)
1081 : : {
1082 : 0 : RTE_DMA_LOG(ERR, "submit is not configured or not supported.");
1083 : 0 : return -EINVAL;
1084 : : }
1085 : :
1086 : : static uint16_t
1087 : 0 : dummy_completed(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1088 : : __rte_unused const uint16_t nb_cpls,
1089 : : __rte_unused uint16_t *last_idx, __rte_unused bool *has_error)
1090 : : {
1091 : 0 : RTE_DMA_LOG(ERR, "completed is not configured or not supported.");
1092 : 0 : return 0;
1093 : : }
1094 : :
1095 : : static uint16_t
1096 : 0 : dummy_completed_status(__rte_unused void *dev_private,
1097 : : __rte_unused uint16_t vchan,
1098 : : __rte_unused const uint16_t nb_cpls,
1099 : : __rte_unused uint16_t *last_idx,
1100 : : __rte_unused enum rte_dma_status_code *status)
1101 : : {
1102 : 0 : RTE_DMA_LOG(ERR,
1103 : : "completed_status is not configured or not supported.");
1104 : 0 : return 0;
1105 : : }
1106 : :
1107 : : static uint16_t
1108 : 0 : dummy_burst_capacity(__rte_unused const void *dev_private,
1109 : : __rte_unused uint16_t vchan)
1110 : : {
1111 : 0 : RTE_DMA_LOG(ERR, "burst_capacity is not configured or not supported.");
1112 : 0 : return 0;
1113 : : }
1114 : :
1115 : : static uint16_t
1116 : 0 : dummy_enqueue(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1117 : : __rte_unused struct rte_dma_op **ops, __rte_unused uint16_t nb_ops)
1118 : : {
1119 : 0 : RTE_DMA_LOG(ERR, "Enqueue not configured or not supported.");
1120 : 0 : return 0;
1121 : : }
1122 : :
1123 : : static uint16_t
1124 : 0 : dummy_dequeue(__rte_unused void *dev_private, __rte_unused uint16_t vchan,
1125 : : __rte_unused struct rte_dma_op **ops, __rte_unused uint16_t nb_ops)
1126 : : {
1127 : 0 : RTE_DMA_LOG(ERR, "Enqueue not configured or not supported.");
1128 : 0 : return 0;
1129 : : }
1130 : :
1131 : : static void
1132 : : dma_fp_object_dummy(struct rte_dma_fp_object *obj)
1133 : : {
1134 : 66 : obj->dev_private = NULL;
1135 : 66 : obj->copy = dummy_copy;
1136 : 66 : obj->copy_sg = dummy_copy_sg;
1137 : 66 : obj->fill = dummy_fill;
1138 : 66 : obj->submit = dummy_submit;
1139 : 66 : obj->completed = dummy_completed;
1140 : 66 : obj->completed_status = dummy_completed_status;
1141 : 66 : obj->burst_capacity = dummy_burst_capacity;
1142 : 66 : obj->enqueue = dummy_enqueue;
1143 : 64 : obj->dequeue = dummy_dequeue;
1144 : 1 : }
1145 : :
1146 : : static int
1147 : 3 : dmadev_handle_dev_list(const char *cmd __rte_unused,
1148 : : const char *params __rte_unused,
1149 : : struct rte_tel_data *d)
1150 : : {
1151 : : int dev_id;
1152 : :
1153 : 3 : rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
1154 [ + + ]: 195 : for (dev_id = 0; dev_id < dma_devices_max; dev_id++)
1155 [ + + ]: 192 : if (rte_dma_is_valid(dev_id))
1156 : 3 : rte_tel_data_add_array_int(d, dev_id);
1157 : :
1158 : 3 : return 0;
1159 : : }
1160 : :
1161 : : /* Parse an unsigned integer telemetry parameter, returning the value or
1162 : : * -EINVAL. 'max' must be <= INT_MAX.
1163 : : */
1164 : : static int
1165 : 9 : dmadev_parse_uint(const char *str, char **end, unsigned long max)
1166 : : {
1167 : : unsigned long val;
1168 : :
1169 [ + + + + ]: 9 : if (str == NULL || !isdigit((unsigned char)*str))
1170 : : return -EINVAL;
1171 : :
1172 : 3 : errno = 0;
1173 : 3 : val = strtoul(str, end, 0);
1174 [ + - + - ]: 3 : if (errno != 0 || val > max)
1175 : : return -EINVAL;
1176 : :
1177 : 3 : return (int)val;
1178 : : }
1179 : :
1180 : : #define ADD_CAPA(td, dc, c) rte_tel_data_add_dict_int(td, dma_capability_name(c), !!(dc & c))
1181 : :
1182 : : static int
1183 : 3 : dmadev_handle_dev_info(const char *cmd __rte_unused,
1184 : : const char *params, struct rte_tel_data *d)
1185 : : {
1186 : : struct rte_dma_info dma_info;
1187 : : struct rte_tel_data *dma_caps;
1188 : : int dev_id, ret;
1189 : : uint64_t dev_capa;
1190 : : char *end_param;
1191 : :
1192 : 3 : dev_id = dmadev_parse_uint(params, &end_param, INT16_MAX);
1193 [ + + ]: 3 : if (dev_id < 0)
1194 : : return -EINVAL;
1195 [ - + ]: 1 : if (*end_param != '\0')
1196 : 0 : RTE_DMA_LOG(WARNING, "Extra parameters passed to dmadev telemetry command, ignoring");
1197 : :
1198 : : /* Function info_get validates dev_id so we don't need to. */
1199 : 1 : ret = rte_dma_info_get(dev_id, &dma_info);
1200 [ + - ]: 1 : if (ret < 0)
1201 : : return -EINVAL;
1202 : 1 : dev_capa = dma_info.dev_capa;
1203 : :
1204 : 1 : rte_tel_data_start_dict(d);
1205 : 1 : rte_tel_data_add_dict_string(d, "name", dma_info.dev_name);
1206 : 1 : rte_tel_data_add_dict_int(d, "nb_vchans", dma_info.nb_vchans);
1207 : 1 : rte_tel_data_add_dict_int(d, "nb_priorities", dma_info.nb_priorities);
1208 : 1 : rte_tel_data_add_dict_int(d, "numa_node", dma_info.numa_node);
1209 : 1 : rte_tel_data_add_dict_int(d, "max_vchans", dma_info.max_vchans);
1210 : 1 : rte_tel_data_add_dict_int(d, "max_desc", dma_info.max_desc);
1211 : 1 : rte_tel_data_add_dict_int(d, "min_desc", dma_info.min_desc);
1212 : 1 : rte_tel_data_add_dict_int(d, "max_sges", dma_info.max_sges);
1213 : :
1214 : 1 : dma_caps = rte_tel_data_alloc();
1215 [ + - ]: 1 : if (!dma_caps)
1216 : : return -ENOMEM;
1217 : :
1218 : 1 : rte_tel_data_start_dict(dma_caps);
1219 : 1 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_MEM_TO_MEM);
1220 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_MEM_TO_DEV);
1221 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_DEV_TO_MEM);
1222 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_DEV_TO_DEV);
1223 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_SVA);
1224 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_SILENT);
1225 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_HANDLES_ERRORS);
1226 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_M2D_AUTO_FREE);
1227 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_PRI_POLICY_SP);
1228 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_INTER_PROCESS_DOMAIN);
1229 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_INTER_OS_DOMAIN);
1230 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_OPS_COPY);
1231 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_OPS_COPY_SG);
1232 : 2 : ADD_CAPA(dma_caps, dev_capa, RTE_DMA_CAPA_OPS_FILL);
1233 : 1 : rte_tel_data_add_dict_container(d, "capabilities", dma_caps, 0);
1234 : :
1235 : 1 : return 0;
1236 : : }
1237 : :
1238 : : #define ADD_DICT_STAT(s) rte_tel_data_add_dict_uint(d, #s, dma_stats.s)
1239 : :
1240 : : static int
1241 : 3 : dmadev_handle_dev_stats(const char *cmd __rte_unused,
1242 : : const char *params,
1243 : : struct rte_tel_data *d)
1244 : : {
1245 : : struct rte_dma_info dma_info;
1246 : : struct rte_dma_stats dma_stats;
1247 : : int dev_id, ret, vchan_id;
1248 : : char *end_param;
1249 : :
1250 : 3 : dev_id = dmadev_parse_uint(params, &end_param, INT16_MAX);
1251 [ + + ]: 3 : if (dev_id < 0)
1252 : : return -EINVAL;
1253 : :
1254 : : /* Function info_get validates dev_id so we don't need to. */
1255 : 1 : ret = rte_dma_info_get(dev_id, &dma_info);
1256 [ + - ]: 1 : if (ret < 0)
1257 : : return -EINVAL;
1258 : :
1259 : : /* If the device has one vchan the user does not need to supply the
1260 : : * vchan id and only the device id is needed, no extra parameters.
1261 : : */
1262 [ - + - - ]: 1 : if (dma_info.nb_vchans == 1 && *end_param == '\0')
1263 : : vchan_id = 0;
1264 : : else {
1265 [ - + ]: 1 : if (*end_param != ',')
1266 : : return -EINVAL;
1267 : 0 : vchan_id = dmadev_parse_uint(end_param + 1, &end_param, UINT16_MAX);
1268 [ # # ]: 0 : if (vchan_id < 0)
1269 : : return -EINVAL;
1270 : : }
1271 [ # # ]: 0 : if (*end_param != '\0')
1272 : 0 : RTE_DMA_LOG(WARNING, "Extra parameters passed to dmadev telemetry command, ignoring");
1273 : :
1274 : 0 : ret = rte_dma_stats_get(dev_id, vchan_id, &dma_stats);
1275 [ # # ]: 0 : if (ret < 0)
1276 : : return -EINVAL;
1277 : :
1278 : 0 : rte_tel_data_start_dict(d);
1279 : 0 : ADD_DICT_STAT(submitted);
1280 : 0 : ADD_DICT_STAT(completed);
1281 : 0 : ADD_DICT_STAT(errors);
1282 : :
1283 : 0 : return 0;
1284 : : }
1285 : :
1286 : : #ifndef RTE_EXEC_ENV_WINDOWS
1287 : : static int
1288 : 3 : dmadev_handle_dev_dump(const char *cmd __rte_unused,
1289 : : const char *params,
1290 : : struct rte_tel_data *d)
1291 : : {
1292 : : char *buf, *end_param;
1293 : : int dev_id, ret;
1294 : : FILE *f;
1295 : :
1296 : 3 : dev_id = dmadev_parse_uint(params, &end_param, INT16_MAX);
1297 [ + + ]: 3 : if (dev_id < 0)
1298 : : return -EINVAL;
1299 [ - + ]: 1 : if (*end_param != '\0')
1300 : 0 : RTE_DMA_LOG(WARNING, "Extra parameters passed to dmadev telemetry command, ignoring");
1301 : :
1302 : 1 : buf = calloc(RTE_TEL_MAX_SINGLE_STRING_LEN, sizeof(char));
1303 [ + - ]: 1 : if (buf == NULL)
1304 : : return -ENOMEM;
1305 : :
1306 : 1 : f = fmemopen(buf, RTE_TEL_MAX_SINGLE_STRING_LEN - 1, "w+");
1307 [ - + ]: 1 : if (f == NULL) {
1308 : 0 : free(buf);
1309 : 0 : return -EINVAL;
1310 : : }
1311 : :
1312 : 1 : ret = rte_dma_dump(dev_id, f);
1313 : 1 : fclose(f);
1314 [ + - ]: 1 : if (ret == 0) {
1315 : 1 : rte_tel_data_start_dict(d);
1316 : 1 : rte_tel_data_string(d, buf);
1317 : : }
1318 : :
1319 : 1 : free(buf);
1320 : 1 : return ret;
1321 : : }
1322 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1323 : :
1324 : 301 : RTE_INIT(dmadev_init_telemetry)
1325 : : {
1326 : 301 : rte_telemetry_register_cmd("/dmadev/list", dmadev_handle_dev_list,
1327 : : "Returns list of available dmadev devices by IDs. No parameters.");
1328 : 301 : rte_telemetry_register_cmd("/dmadev/info", dmadev_handle_dev_info,
1329 : : "Returns information for a dmadev. Parameters: int dev_id");
1330 : 301 : rte_telemetry_register_cmd("/dmadev/stats", dmadev_handle_dev_stats,
1331 : : "Returns the stats for a dmadev vchannel. Parameters: int dev_id, vchan_id (Optional if only one vchannel)");
1332 : : #ifndef RTE_EXEC_ENV_WINDOWS
1333 : 301 : rte_telemetry_register_cmd("/dmadev/dump", dmadev_handle_dev_dump,
1334 : : "Returns dump information for a dmadev. Parameters: int dev_id");
1335 : : #endif
1336 : 301 : }
|