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