Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
3 : : */
4 : :
5 : : /*
6 : : * Architecture Overview
7 : : * =====================
8 : : * CDX is a Hardware Architecture designed for AMD FPGA devices. It
9 : : * consists of sophisticated mechanism for interaction between FPGA,
10 : : * Firmware and the APUs (Application CPUs).
11 : : *
12 : : * Firmware resides on RPU (Realtime CPUs) which interacts with
13 : : * the FPGA program manager and the APUs. The RPU provides memory-mapped
14 : : * interface (RPU if) which is used to communicate with APUs.
15 : : *
16 : : * The diagram below shows an overview of the AMD CDX architecture:
17 : : *
18 : : * +--------------------------------------+
19 : : * | DPDK |
20 : : * | DPDK CDX drivers |
21 : : * | | |
22 : : * | DPDK AMD CDX bus |
23 : : * | | |
24 : : * +-----------------------------|--------+
25 : : * |
26 : : * +-----------------------------|--------+
27 : : * | Application CPUs (APU) | |
28 : : * | | |
29 : : * | VFIO CDX driver |
30 : : * | Linux OS | |
31 : : * | Linux AMD CDX bus |
32 : : * | | |
33 : : * +-----------------------------|--------+
34 : : * |
35 : : * |
36 : : * +------------------------| RPU if |----+
37 : : * | | |
38 : : * | V |
39 : : * | Realtime CPUs (RPU) |
40 : : * | |
41 : : * +--------------------------------------+
42 : : * |
43 : : * +---------------------|----------------+
44 : : * | FPGA | |
45 : : * | +-----------------------+ |
46 : : * | | | | |
47 : : * | +-------+ +-------+ +-------+ |
48 : : * | | dev 1 | | dev 2 | | dev 3 | |
49 : : * | +-------+ +-------+ +-------+ |
50 : : * +--------------------------------------+
51 : : *
52 : : * The RPU firmware extracts the device information from the loaded FPGA
53 : : * image and implements a mechanism that allows the APU drivers to
54 : : * enumerate such devices (device personality and resource details) via
55 : : * a dedicated communication channel.
56 : : *
57 : : * VFIO CDX driver provides the CDX device resources like MMIO and interrupts
58 : : * to map to user-space. DPDK CDX bus uses sysfs interface and the vfio-cdx
59 : : * driver to discover and initialize the CDX devices for user-space
60 : : * applications.
61 : : */
62 : :
63 : : /**
64 : : * @file
65 : : * CDX probing using Linux sysfs.
66 : : */
67 : :
68 : : #include <string.h>
69 : : #include <dirent.h>
70 : :
71 : : #include <rte_eal_paging.h>
72 : : #include <rte_errno.h>
73 : : #include <rte_devargs.h>
74 : : #include <rte_kvargs.h>
75 : : #include <rte_malloc.h>
76 : : #include <rte_vfio.h>
77 : :
78 : : #include <eal_export.h>
79 : : #include <eal_filesystem.h>
80 : :
81 : : #include "bus_cdx_driver.h"
82 : : #include "cdx_logs.h"
83 : : #include "private.h"
84 : :
85 : : #define CDX_BUS_NAME cdx
86 : : #define CDX_DEV_PREFIX "cdx-"
87 : :
88 : : /* CDX Bus iterators */
89 : : #define FOREACH_DEVICE_ON_CDXBUS(p) \
90 : : RTE_TAILQ_FOREACH(p, &rte_cdx_bus.device_list, next)
91 : :
92 : : #define FOREACH_DRIVER_ON_CDXBUS(p) \
93 : : RTE_TAILQ_FOREACH(p, &rte_cdx_bus.driver_list, next)
94 : :
95 : : struct rte_cdx_bus rte_cdx_bus;
96 : :
97 : : enum cdx_params {
98 : : RTE_CDX_PARAM_NAME,
99 : : };
100 : :
101 : : static const char * const cdx_params_keys[] = {
102 : : [RTE_CDX_PARAM_NAME] = "name",
103 : : NULL,
104 : : };
105 : :
106 : : /* Add a device to CDX bus */
107 : : static void
108 : : cdx_add_device(struct rte_cdx_device *cdx_dev)
109 : : {
110 : 0 : TAILQ_INSERT_TAIL(&rte_cdx_bus.device_list, cdx_dev, next);
111 : : }
112 : :
113 : : static int
114 : 0 : cdx_get_kernel_driver_by_path(const char *filename, char *driver_name,
115 : : size_t len)
116 : : {
117 : : int count;
118 : : char path[PATH_MAX];
119 : : char *name;
120 : :
121 [ # # ]: 0 : if (!filename || !driver_name)
122 : : return -1;
123 : :
124 : 0 : count = readlink(filename, path, PATH_MAX);
125 [ # # ]: 0 : if (count >= PATH_MAX)
126 : : return -1;
127 : :
128 : : /* For device does not have a driver */
129 [ # # ]: 0 : if (count < 0)
130 : : return 1;
131 : :
132 : 0 : path[count] = '\0';
133 : :
134 : 0 : name = strrchr(path, '/');
135 [ # # ]: 0 : if (name) {
136 : 0 : strlcpy(driver_name, name + 1, len);
137 : 0 : return 0;
138 : : }
139 : :
140 : : return -1;
141 : : }
142 : :
143 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_cdx_map_device)
144 : 0 : int rte_cdx_map_device(struct rte_cdx_device *dev)
145 : : {
146 : 0 : return cdx_vfio_map_resource(dev);
147 : : }
148 : :
149 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_cdx_unmap_device)
150 : 0 : void rte_cdx_unmap_device(struct rte_cdx_device *dev)
151 : : {
152 : 0 : cdx_vfio_unmap_resource(dev);
153 : 0 : }
154 : :
155 : : static struct rte_devargs *
156 : 0 : cdx_devargs_lookup(const char *dev_name)
157 : : {
158 : : struct rte_devargs *devargs;
159 : :
160 [ # # ]: 0 : RTE_EAL_DEVARGS_FOREACH("cdx", devargs) {
161 [ # # ]: 0 : if (strcmp(devargs->name, dev_name) == 0)
162 : 0 : return devargs;
163 : : }
164 : : return NULL;
165 : : }
166 : :
167 : : static bool
168 : 0 : cdx_ignore_device(const char *dev_name)
169 : : {
170 : 0 : struct rte_devargs *devargs = cdx_devargs_lookup(dev_name);
171 : :
172 [ # # # ]: 0 : switch (rte_cdx_bus.bus.conf.scan_mode) {
173 : 0 : case RTE_BUS_SCAN_ALLOWLIST:
174 [ # # # # ]: 0 : if (devargs && devargs->policy == RTE_DEV_ALLOWED)
175 : 0 : return false;
176 : : break;
177 : 0 : case RTE_BUS_SCAN_UNDEFINED:
178 : : case RTE_BUS_SCAN_BLOCKLIST:
179 [ # # # # ]: 0 : if (devargs == NULL || devargs->policy != RTE_DEV_BLOCKED)
180 : 0 : return false;
181 : : break;
182 : : }
183 : : return true;
184 : : }
185 : :
186 : : /*
187 : : * Scan one cdx sysfs entry, and fill the devices list from it.
188 : : * It checks if the CDX device is bound to vfio-cdx driver. In case
189 : : * the device is vfio bound, it reads the vendor and device id and
190 : : * stores it for device-driver matching.
191 : : */
192 : : static int
193 : 0 : cdx_scan_one(const char *dirname, const char *dev_name)
194 : : {
195 : : char filename[PATH_MAX];
196 : : struct rte_cdx_device *dev = NULL;
197 : : char driver[PATH_MAX];
198 : : unsigned long tmp;
199 : : int ret;
200 : :
201 : 0 : dev = calloc(1, sizeof(*dev));
202 [ # # ]: 0 : if (!dev)
203 : : return -ENOMEM;
204 : :
205 : 0 : dev->device.bus = &rte_cdx_bus.bus;
206 : 0 : memcpy(dev->name, dev_name, RTE_DEV_NAME_MAX_LEN);
207 : 0 : dev->device.name = dev->name;
208 : :
209 : : /* parse driver */
210 : : snprintf(filename, sizeof(filename), "%s/driver", dirname);
211 : 0 : ret = cdx_get_kernel_driver_by_path(filename, driver, sizeof(driver));
212 [ # # ]: 0 : if (ret < 0) {
213 : 0 : CDX_BUS_ERR("Fail to get kernel driver");
214 : 0 : free(dev);
215 : 0 : return -1;
216 : : }
217 : :
218 : : /* Allocate interrupt instance for cdx device */
219 : 0 : dev->intr_handle =
220 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
221 [ # # ]: 0 : if (dev->intr_handle == NULL) {
222 : 0 : CDX_BUS_ERR("Failed to create interrupt instance for %s",
223 : : dev->device.name);
224 : 0 : free(dev);
225 : 0 : return -ENOMEM;
226 : : }
227 : :
228 : : /*
229 : : * Check if device is bound to 'vfio-cdx' driver, so that user-space
230 : : * can gracefully access the device.
231 : : */
232 [ # # # # ]: 0 : if (ret || strcmp(driver, "vfio-cdx")) {
233 : : ret = 0;
234 : 0 : goto err;
235 : : }
236 : :
237 : : /* get vendor id */
238 : : snprintf(filename, sizeof(filename), "%s/vendor", dirname);
239 [ # # ]: 0 : if (eal_parse_sysfs_value(filename, &tmp) < 0) {
240 : : ret = -1;
241 : 0 : goto err;
242 : : }
243 : 0 : dev->id.vendor_id = (uint16_t)tmp;
244 : :
245 : : /* get device id */
246 : : snprintf(filename, sizeof(filename), "%s/device", dirname);
247 [ # # ]: 0 : if (eal_parse_sysfs_value(filename, &tmp) < 0) {
248 : : ret = -1;
249 : 0 : goto err;
250 : : }
251 : 0 : dev->id.device_id = (uint16_t)tmp;
252 : :
253 : : cdx_add_device(dev);
254 : :
255 : 0 : return 0;
256 : :
257 : 0 : err:
258 : 0 : rte_intr_instance_free(dev->intr_handle);
259 : 0 : free(dev);
260 : 0 : return ret;
261 : : }
262 : :
263 : : /*
264 : : * Scan the content of the CDX bus, and the devices in the devices
265 : : * list.
266 : : */
267 : : static int
268 : 185 : cdx_scan(void)
269 : : {
270 : : struct dirent *e;
271 : : DIR *dir;
272 : : char dirname[PATH_MAX];
273 : :
274 : 185 : dir = opendir(RTE_CDX_BUS_DEVICES_PATH);
275 [ + - ]: 185 : if (dir == NULL) {
276 : 185 : CDX_BUS_INFO("%s(): opendir failed: %s", __func__,
277 : : strerror(errno));
278 : 185 : return 0;
279 : : }
280 : :
281 [ # # ]: 0 : while ((e = readdir(dir)) != NULL) {
282 [ # # ]: 0 : if (e->d_name[0] == '.')
283 : 0 : continue;
284 : :
285 [ # # ]: 0 : if (cdx_ignore_device(e->d_name))
286 : 0 : continue;
287 : :
288 : : snprintf(dirname, sizeof(dirname), "%s/%s",
289 : : RTE_CDX_BUS_DEVICES_PATH, e->d_name);
290 : :
291 [ # # ]: 0 : if (cdx_scan_one(dirname, e->d_name) < 0)
292 : 0 : goto error;
293 : : }
294 : 0 : closedir(dir);
295 : 0 : return 0;
296 : :
297 : : error:
298 : 0 : closedir(dir);
299 : 0 : return -1;
300 : : }
301 : :
302 : : /* map a particular resource from a file */
303 : : void *
304 : 0 : cdx_map_resource(void *requested_addr, int fd, uint64_t offset, size_t size,
305 : : int additional_flags)
306 : : {
307 : : void *mapaddr;
308 : :
309 : : /* Map the cdx MMIO memory resource of device */
310 : 0 : mapaddr = rte_mem_map(requested_addr, size,
311 : : RTE_PROT_READ | RTE_PROT_WRITE,
312 : : RTE_MAP_SHARED | additional_flags, fd, offset);
313 [ # # ]: 0 : if (mapaddr == NULL) {
314 : 0 : CDX_BUS_ERR("%s(): cannot map resource(%d, %p, 0x%zx, 0x%"PRIx64"): %s (%p)",
315 : : __func__, fd, requested_addr, size, offset,
316 : : rte_strerror(rte_errno), mapaddr);
317 : : }
318 : 0 : CDX_BUS_DEBUG("CDX MMIO memory mapped at %p", mapaddr);
319 : :
320 : 0 : return mapaddr;
321 : : }
322 : :
323 : : /* unmap a particular resource */
324 : : void
325 : 0 : cdx_unmap_resource(void *requested_addr, size_t size)
326 : : {
327 [ # # ]: 0 : if (requested_addr == NULL)
328 : : return;
329 : :
330 : 0 : CDX_BUS_DEBUG("Unmapping CDX memory at %p", requested_addr);
331 : :
332 : : /* Unmap the CDX memory resource of device */
333 [ # # ]: 0 : if (rte_mem_unmap(requested_addr, size)) {
334 : 0 : CDX_BUS_ERR("%s(): cannot mem unmap(%p, %#zx): %s", __func__,
335 : : requested_addr, size, rte_strerror(rte_errno));
336 : : }
337 : : }
338 : : /*
339 : : * Match the CDX Driver and Device using device id and vendor id.
340 : : */
341 : : static bool
342 : : cdx_match(const struct rte_cdx_driver *cdx_drv,
343 : : const struct rte_cdx_device *cdx_dev)
344 : : {
345 : : const struct rte_cdx_id *id_table;
346 : :
347 [ # # ]: 0 : for (id_table = cdx_drv->id_table; id_table->vendor_id != 0;
348 : 0 : id_table++) {
349 : : /* check if device's identifiers match the driver's ones */
350 [ # # # # ]: 0 : if (id_table->vendor_id != cdx_dev->id.vendor_id &&
351 : : id_table->vendor_id != RTE_CDX_ANY_ID)
352 : 0 : continue;
353 [ # # # # ]: 0 : if (id_table->device_id != cdx_dev->id.device_id &&
354 : : id_table->device_id != RTE_CDX_ANY_ID)
355 : 0 : continue;
356 : :
357 : : return 1;
358 : : }
359 : :
360 : : return 0;
361 : : }
362 : :
363 : : /*
364 : : * If vendor id and device id match, call the probe() function of the
365 : : * driver.
366 : : */
367 : : static int
368 : 0 : cdx_probe_one_driver(struct rte_cdx_driver *dr,
369 : : struct rte_cdx_device *dev)
370 : : {
371 : 0 : const char *dev_name = dev->name;
372 : : bool already_probed;
373 : : int ret;
374 : :
375 : : /* The device is not blocked; Check if driver supports it */
376 [ # # ]: 0 : if (!cdx_match(dr, dev))
377 : : /* Match of device and driver failed */
378 : : return 1;
379 : :
380 : 0 : already_probed = rte_dev_is_probed(&dev->device);
381 [ # # ]: 0 : if (already_probed) {
382 : 0 : CDX_BUS_INFO("Device %s is already probed", dev_name);
383 : 0 : return -EEXIST;
384 : : }
385 : :
386 : 0 : CDX_BUS_DEBUG(" probe device %s using driver: %s", dev_name,
387 : : dr->driver.name);
388 : :
389 [ # # ]: 0 : if (dr->drv_flags & RTE_CDX_DRV_NEED_MAPPING) {
390 : 0 : ret = cdx_vfio_map_resource(dev);
391 [ # # ]: 0 : if (ret != 0) {
392 : 0 : CDX_BUS_ERR("CDX map device failed: %d", ret);
393 : 0 : goto error_map_device;
394 : : }
395 : : }
396 : :
397 : : /* call the driver probe() function */
398 : 0 : ret = dr->probe(dr, dev);
399 [ # # ]: 0 : if (ret) {
400 : 0 : CDX_BUS_ERR("Probe CDX driver: %s device: %s failed: %d",
401 : : dr->driver.name, dev_name, ret);
402 : 0 : goto error_probe;
403 : : } else {
404 : 0 : dev->device.driver = &dr->driver;
405 : : }
406 : 0 : dev->driver = dr;
407 : :
408 : 0 : return ret;
409 : :
410 : : error_probe:
411 : 0 : cdx_vfio_unmap_resource(dev);
412 : 0 : rte_intr_instance_free(dev->intr_handle);
413 : 0 : dev->intr_handle = NULL;
414 : : error_map_device:
415 : : return ret;
416 : : }
417 : :
418 : : /*
419 : : * If vendor/device ID match, call the probe() function of all
420 : : * registered driver for the given device. Return < 0 if initialization
421 : : * failed, return 1 if no driver is found for this device.
422 : : */
423 : : static int
424 : 0 : cdx_probe_all_drivers(struct rte_cdx_device *dev)
425 : : {
426 : : struct rte_cdx_driver *dr = NULL;
427 : : int rc = 0;
428 : :
429 [ # # ]: 0 : FOREACH_DRIVER_ON_CDXBUS(dr) {
430 : 0 : rc = cdx_probe_one_driver(dr, dev);
431 [ # # ]: 0 : if (rc < 0)
432 : : /* negative value is an error */
433 : 0 : return rc;
434 [ # # ]: 0 : if (rc > 0)
435 : : /* positive value means driver doesn't support it */
436 : : continue;
437 : : return 0;
438 : : }
439 : : return 1;
440 : : }
441 : :
442 : : /*
443 : : * Scan the content of the CDX bus, and call the probe() function for
444 : : * all registered drivers that have a matching entry in its id_table
445 : : * for discovered devices.
446 : : */
447 : : static int
448 : 180 : cdx_probe(void)
449 : : {
450 : : struct rte_cdx_device *dev = NULL;
451 : : size_t probed = 0, failed = 0;
452 : : int ret = 0;
453 : :
454 [ - + ]: 180 : FOREACH_DEVICE_ON_CDXBUS(dev) {
455 : 0 : probed++;
456 : :
457 : 0 : ret = cdx_probe_all_drivers(dev);
458 [ # # ]: 0 : if (ret < 0) {
459 : 0 : CDX_BUS_ERR("Requested device %s cannot be used",
460 : : dev->name);
461 : 0 : rte_errno = errno;
462 : 0 : failed++;
463 : : }
464 : : }
465 : :
466 [ + - ]: 180 : return (probed && probed == failed) ? -1 : 0;
467 : : }
468 : :
469 : : static int
470 : 37 : cdx_parse(const char *name, void *addr)
471 : : {
472 : : const char **out = addr;
473 : : int ret;
474 : :
475 : 37 : ret = strncmp(name, CDX_DEV_PREFIX, strlen(CDX_DEV_PREFIX));
476 : :
477 [ - + ]: 37 : if (ret == 0 && addr)
478 : 0 : *out = name;
479 : :
480 : 37 : return ret;
481 : : }
482 : :
483 : : /* register a driver */
484 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_cdx_register)
485 : : void
486 : 0 : rte_cdx_register(struct rte_cdx_driver *driver)
487 : : {
488 : 0 : TAILQ_INSERT_TAIL(&rte_cdx_bus.driver_list, driver, next);
489 : 0 : driver->bus = &rte_cdx_bus;
490 : 0 : }
491 : :
492 : : /* unregister a driver */
493 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_cdx_unregister)
494 : : void
495 : 0 : rte_cdx_unregister(struct rte_cdx_driver *driver)
496 : : {
497 [ # # ]: 0 : TAILQ_REMOVE(&rte_cdx_bus.driver_list, driver, next);
498 : 0 : driver->bus = NULL;
499 : 0 : }
500 : :
501 : : static struct rte_device *
502 : 0 : cdx_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
503 : : const void *data)
504 : : {
505 : : const struct rte_cdx_device *cdx_start;
506 : : struct rte_cdx_device *cdx_dev;
507 : :
508 [ # # ]: 0 : if (start != NULL) {
509 : 0 : cdx_start = RTE_DEV_TO_CDX_DEV_CONST(start);
510 : 0 : cdx_dev = TAILQ_NEXT(cdx_start, next);
511 : : } else {
512 : 0 : cdx_dev = TAILQ_FIRST(&rte_cdx_bus.device_list);
513 : : }
514 [ # # ]: 0 : while (cdx_dev != NULL) {
515 [ # # ]: 0 : if (cmp(&cdx_dev->device, data) == 0)
516 : 0 : return &cdx_dev->device;
517 : 0 : cdx_dev = TAILQ_NEXT(cdx_dev, next);
518 : : }
519 : : return NULL;
520 : : }
521 : :
522 : : /* Remove a device from CDX bus */
523 : : static void
524 : : cdx_remove_device(struct rte_cdx_device *cdx_dev)
525 : : {
526 [ # # ]: 0 : TAILQ_REMOVE(&rte_cdx_bus.device_list, cdx_dev, next);
527 : : }
528 : :
529 : : /*
530 : : * If vendor/device ID match, call the remove() function of the
531 : : * driver.
532 : : */
533 : : static int
534 : 0 : cdx_detach_dev(struct rte_cdx_device *dev)
535 : : {
536 : : struct rte_cdx_driver *dr;
537 : : int ret = 0;
538 : :
539 [ # # ]: 0 : if (dev == NULL)
540 : : return -EINVAL;
541 : :
542 : 0 : dr = dev->driver;
543 : :
544 : 0 : CDX_BUS_DEBUG("detach device %s using driver: %s",
545 : : dev->device.name, dr->driver.name);
546 : :
547 [ # # ]: 0 : if (dr->remove) {
548 : 0 : ret = dr->remove(dev);
549 [ # # ]: 0 : if (ret < 0)
550 : : return ret;
551 : : }
552 : :
553 : : /* clear driver structure */
554 : 0 : dev->driver = NULL;
555 : 0 : dev->device.driver = NULL;
556 : :
557 : 0 : rte_cdx_unmap_device(dev);
558 : :
559 : 0 : rte_intr_instance_free(dev->intr_handle);
560 : 0 : dev->intr_handle = NULL;
561 : :
562 : 0 : return 0;
563 : : }
564 : :
565 : : static int
566 : 0 : cdx_plug(struct rte_device *dev)
567 : : {
568 : 0 : return cdx_probe_all_drivers(RTE_DEV_TO_CDX_DEV(dev));
569 : : }
570 : :
571 : : static int
572 : 0 : cdx_unplug(struct rte_device *dev)
573 : : {
574 : : struct rte_cdx_device *cdx_dev;
575 : : int ret;
576 : :
577 : 0 : cdx_dev = RTE_DEV_TO_CDX_DEV(dev);
578 : 0 : ret = cdx_detach_dev(cdx_dev);
579 [ # # ]: 0 : if (ret == 0) {
580 : : cdx_remove_device(cdx_dev);
581 : 0 : rte_devargs_remove(dev->devargs);
582 : 0 : free(cdx_dev);
583 : : }
584 : 0 : return ret;
585 : : }
586 : :
587 : : static int
588 : 0 : cdx_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
589 : : {
590 : : RTE_SET_USED(dev);
591 : :
592 : 0 : return rte_vfio_container_dma_map(RTE_VFIO_DEFAULT_CONTAINER_FD,
593 : : (uintptr_t)addr, iova, len);
594 : : }
595 : :
596 : : static int
597 : 0 : cdx_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
598 : : {
599 : : RTE_SET_USED(dev);
600 : :
601 : 0 : return rte_vfio_container_dma_unmap(RTE_VFIO_DEFAULT_CONTAINER_FD,
602 : : (uintptr_t)addr, iova, len);
603 : : }
604 : :
605 : : static enum rte_iova_mode
606 : 185 : cdx_get_iommu_class(void)
607 : : {
608 [ + - ]: 185 : if (TAILQ_EMPTY(&rte_cdx_bus.device_list))
609 : 185 : return RTE_IOVA_DC;
610 : :
611 : : return RTE_IOVA_VA;
612 : : }
613 : :
614 : : static int
615 : 0 : cdx_dev_match(const struct rte_device *dev,
616 : : const void *_kvlist)
617 : : {
618 : : const struct rte_kvargs *kvlist = _kvlist;
619 : : const char *key = cdx_params_keys[RTE_CDX_PARAM_NAME];
620 : : const char *name;
621 : :
622 : : /* no kvlist arg, all devices match */
623 [ # # ]: 0 : if (kvlist == NULL)
624 : : return 0;
625 : :
626 : : /* if key is present in kvlist and does not match, filter device */
627 : 0 : name = rte_kvargs_get(kvlist, key);
628 [ # # # # ]: 0 : if (name != NULL && strcmp(name, dev->name))
629 : 0 : return -1;
630 : :
631 : : return 0;
632 : : }
633 : :
634 : : static void *
635 : 0 : cdx_dev_iterate(const void *start,
636 : : const char *str,
637 : : const struct rte_dev_iterator *it __rte_unused)
638 : : {
639 : : rte_bus_find_device_t find_device;
640 : : struct rte_kvargs *kvargs = NULL;
641 : : struct rte_device *dev;
642 : :
643 [ # # ]: 0 : if (str != NULL) {
644 : 0 : kvargs = rte_kvargs_parse(str, cdx_params_keys);
645 [ # # ]: 0 : if (kvargs == NULL) {
646 : 0 : CDX_BUS_ERR("cannot parse argument list %s", str);
647 : 0 : rte_errno = EINVAL;
648 : 0 : return NULL;
649 : : }
650 : : }
651 : 0 : find_device = rte_cdx_bus.bus.find_device;
652 : 0 : dev = find_device(start, cdx_dev_match, kvargs);
653 : 0 : rte_kvargs_free(kvargs);
654 : 0 : return dev;
655 : : }
656 : :
657 : : struct rte_cdx_bus rte_cdx_bus = {
658 : : .bus = {
659 : : .scan = cdx_scan,
660 : : .probe = cdx_probe,
661 : : .find_device = cdx_find_device,
662 : : .plug = cdx_plug,
663 : : .unplug = cdx_unplug,
664 : : .parse = cdx_parse,
665 : : .dma_map = cdx_dma_map,
666 : : .dma_unmap = cdx_dma_unmap,
667 : : .get_iommu_class = cdx_get_iommu_class,
668 : : .dev_iterate = cdx_dev_iterate,
669 : : },
670 : : .device_list = TAILQ_HEAD_INITIALIZER(rte_cdx_bus.device_list),
671 : : .driver_list = TAILQ_HEAD_INITIALIZER(rte_cdx_bus.driver_list),
672 : : };
673 : :
674 : 252 : RTE_REGISTER_BUS(cdx, rte_cdx_bus.bus);
675 [ - + ]: 252 : RTE_LOG_REGISTER_DEFAULT(cdx_logtype_bus, NOTICE);
|