Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2016 RehiveTech. All rights reserved.
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <inttypes.h>
7 : : #include <stdio.h>
8 : : #include <stdlib.h>
9 : : #include <stdint.h>
10 : : #include <stdbool.h>
11 : : #include <sys/queue.h>
12 : :
13 : : #include <rte_os_shim.h>
14 : : #include <eal_export.h>
15 : : #include <rte_eal.h>
16 : : #include <dev_driver.h>
17 : : #include <bus_driver.h>
18 : : #include <rte_common.h>
19 : : #include <rte_devargs.h>
20 : : #include <rte_log.h>
21 : : #include <rte_memory.h>
22 : : #include <rte_tailq.h>
23 : : #include <rte_spinlock.h>
24 : : #include <rte_string_fns.h>
25 : : #include <rte_errno.h>
26 : :
27 : : #include "bus_vdev_driver.h"
28 : :
29 : : #define VDEV_MP_KEY "bus_vdev_mp"
30 : :
31 : : int vdev_logtype_bus;
32 : : #define RTE_LOGTYPE_VDEV_BUS vdev_logtype_bus
33 : :
34 : : #define VDEV_LOG(level, ...) \
35 : : RTE_LOG_LINE_PREFIX(level, VDEV_BUS, "%s(): ", __func__, __VA_ARGS__)
36 : :
37 : : /* Forward declare to access virtual bus name */
38 : : static struct rte_bus rte_vdev_bus;
39 : :
40 : : /* The lock needs to be recursive because a vdev can manage another vdev. */
41 : : static rte_spinlock_recursive_t vdev_device_list_lock =
42 : : RTE_SPINLOCK_RECURSIVE_INITIALIZER;
43 : :
44 : : struct vdev_custom_scan {
45 : : TAILQ_ENTRY(vdev_custom_scan) next;
46 : : rte_vdev_scan_callback callback;
47 : : void *user_arg;
48 : : };
49 : : TAILQ_HEAD(vdev_custom_scans, vdev_custom_scan);
50 : : static struct vdev_custom_scans vdev_custom_scans =
51 : : TAILQ_HEAD_INITIALIZER(vdev_custom_scans);
52 : : static rte_spinlock_t vdev_custom_scan_lock = RTE_SPINLOCK_INITIALIZER;
53 : :
54 : : /* register a driver */
55 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_vdev_register)
56 : : void
57 : 12040 : rte_vdev_register(struct rte_vdev_driver *driver)
58 : : {
59 : 12040 : rte_bus_add_driver(&rte_vdev_bus, &driver->driver);
60 : 12040 : }
61 : :
62 : : /* unregister a driver */
63 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_vdev_unregister)
64 : : void
65 : 0 : rte_vdev_unregister(struct rte_vdev_driver *driver)
66 : : {
67 : 0 : rte_bus_remove_driver(&rte_vdev_bus, &driver->driver);
68 : 0 : }
69 : :
70 : : RTE_EXPORT_SYMBOL(rte_vdev_add_custom_scan)
71 : : int
72 : 0 : rte_vdev_add_custom_scan(rte_vdev_scan_callback callback, void *user_arg)
73 : : {
74 : : struct vdev_custom_scan *custom_scan;
75 : :
76 : : rte_spinlock_lock(&vdev_custom_scan_lock);
77 : :
78 : : /* check if already registered */
79 [ # # ]: 0 : TAILQ_FOREACH(custom_scan, &vdev_custom_scans, next) {
80 [ # # ]: 0 : if (custom_scan->callback == callback &&
81 [ # # ]: 0 : custom_scan->user_arg == user_arg)
82 : : break;
83 : : }
84 : :
85 [ # # ]: 0 : if (custom_scan == NULL) {
86 : 0 : custom_scan = malloc(sizeof(struct vdev_custom_scan));
87 [ # # ]: 0 : if (custom_scan != NULL) {
88 : 0 : custom_scan->callback = callback;
89 : 0 : custom_scan->user_arg = user_arg;
90 : 0 : TAILQ_INSERT_TAIL(&vdev_custom_scans, custom_scan, next);
91 : : }
92 : : }
93 : :
94 : : rte_spinlock_unlock(&vdev_custom_scan_lock);
95 : :
96 [ # # ]: 0 : return (custom_scan == NULL) ? -1 : 0;
97 : : }
98 : :
99 : : RTE_EXPORT_SYMBOL(rte_vdev_remove_custom_scan)
100 : : int
101 : 0 : rte_vdev_remove_custom_scan(rte_vdev_scan_callback callback, void *user_arg)
102 : : {
103 : : struct vdev_custom_scan *custom_scan, *tmp_scan;
104 : :
105 : : rte_spinlock_lock(&vdev_custom_scan_lock);
106 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(custom_scan, &vdev_custom_scans, next,
107 : : tmp_scan) {
108 [ # # ]: 0 : if (custom_scan->callback != callback ||
109 [ # # # # ]: 0 : (custom_scan->user_arg != (void *)-1 &&
110 : : custom_scan->user_arg != user_arg))
111 : 0 : continue;
112 [ # # ]: 0 : TAILQ_REMOVE(&vdev_custom_scans, custom_scan, next);
113 : 0 : free(custom_scan);
114 : : }
115 : : rte_spinlock_unlock(&vdev_custom_scan_lock);
116 : :
117 : 0 : return 0;
118 : : }
119 : :
120 : : static int
121 : 41 : vdev_parse(const char *name, void *addr)
122 : : {
123 : : struct rte_vdev_driver **out = addr;
124 : : struct rte_vdev_driver *driver = NULL;
125 : :
126 [ + + ]: 1039 : RTE_BUS_FOREACH_DRV(driver, &rte_vdev_bus) {
127 [ + + ]: 1024 : if (strncmp(driver->driver.name, name,
128 : : strlen(driver->driver.name)) == 0)
129 : : break;
130 [ + + ]: 998 : if (driver->driver.alias &&
131 [ + - ]: 357 : strncmp(driver->driver.alias, name,
132 : : strlen(driver->driver.alias)) == 0)
133 : : break;
134 : : }
135 : 41 : if (driver != NULL &&
136 [ + + ]: 41 : addr != NULL)
137 : 10 : *out = driver;
138 : 41 : return driver == NULL;
139 : : }
140 : :
141 : : static int
142 : 0 : vdev_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
143 : : {
144 : : struct rte_vdev_device *vdev = RTE_BUS_DEVICE(dev, *vdev);
145 : 0 : const struct rte_vdev_driver *driver = RTE_BUS_DRIVER(vdev->device.driver, *driver);
146 : :
147 [ # # ]: 0 : if (driver->dma_map != NULL)
148 : 0 : return driver->dma_map(vdev, addr, iova, len);
149 : :
150 : : return 0;
151 : : }
152 : :
153 : : static int
154 : 0 : vdev_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
155 : : {
156 : : struct rte_vdev_device *vdev = RTE_BUS_DEVICE(dev, *vdev);
157 : 0 : const struct rte_vdev_driver *driver = RTE_BUS_DRIVER(vdev->device.driver, *driver);
158 : :
159 [ # # ]: 0 : if (driver->dma_unmap != NULL)
160 : 0 : return driver->dma_unmap(vdev, addr, iova, len);
161 : :
162 : : return 0;
163 : : }
164 : :
165 : : /*
166 : : * Check if a vdev driver matches a vdev device by name.
167 : : */
168 : : static bool
169 : 913 : vdev_bus_match(const struct rte_driver *drv, const struct rte_device *dev)
170 : : {
171 : 913 : const char *name = dev->name;
172 : :
173 : : /* Check driver name match */
174 [ + + ]: 913 : if (strncmp(drv->name, name, strlen(drv->name)) == 0)
175 : : return true;
176 : :
177 : : /* Check driver alias match */
178 [ + + + + ]: 844 : if (drv->alias && strncmp(drv->alias, name, strlen(drv->alias)) == 0)
179 : 2 : return true;
180 : :
181 : : return false;
182 : : }
183 : :
184 : : static int
185 [ + - ]: 71 : vdev_probe_device(struct rte_driver *drv, struct rte_device *dev)
186 : : {
187 : : struct rte_vdev_device *vdev_dev = RTE_BUS_DEVICE(dev, *vdev_dev);
188 : : struct rte_vdev_driver *vdev_drv = RTE_BUS_DRIVER(drv, *vdev_drv);
189 : : const char *name;
190 : : enum rte_iova_mode iova_mode;
191 : :
192 : : name = rte_vdev_device_name(vdev_dev);
193 : 71 : VDEV_LOG(DEBUG, "Search driver to probe device %s", name);
194 : :
195 : 71 : iova_mode = rte_eal_iova_mode();
196 [ + + - + ]: 71 : if ((vdev_drv->drv_flags & RTE_VDEV_DRV_NEED_IOVA_AS_VA) && (iova_mode == RTE_IOVA_PA)) {
197 : 0 : VDEV_LOG(ERR, "%s requires VA IOVA mode but current mode is PA, not initializing",
198 : : name);
199 : 0 : return -1;
200 : : }
201 : :
202 : 71 : return vdev_drv->probe(vdev_dev);
203 : : }
204 : :
205 : : /* The caller shall be responsible for thread-safe */
206 : : static struct rte_vdev_device *
207 : 127 : find_vdev(const char *name)
208 : : {
209 : : struct rte_vdev_device *dev;
210 : :
211 [ + - ]: 127 : if (!name)
212 : : return NULL;
213 : :
214 [ + + + - ]: 182 : RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
215 : : const char *devname = rte_vdev_device_name(dev);
216 : :
217 [ + + ]: 109 : if (!strcmp(devname, name))
218 : 54 : return dev;
219 : : }
220 : :
221 : : return NULL;
222 : : }
223 : :
224 : : static struct rte_devargs *
225 : 60 : alloc_devargs(const char *name, const char *args)
226 : : {
227 : : struct rte_devargs *devargs;
228 : : int ret;
229 : :
230 : 60 : devargs = calloc(1, sizeof(*devargs));
231 [ + - ]: 60 : if (!devargs)
232 : : return NULL;
233 : :
234 : 60 : devargs->bus = &rte_vdev_bus;
235 [ + + ]: 60 : if (args)
236 : 54 : devargs->data = strdup(args);
237 : : else
238 : 6 : devargs->data = strdup("");
239 [ - + ]: 60 : if (devargs->data == NULL) {
240 : 0 : free(devargs);
241 : 0 : return NULL;
242 : : }
243 : 60 : devargs->args = devargs->data;
244 : :
245 [ - + ]: 60 : ret = strlcpy(devargs->name, name, sizeof(devargs->name));
246 [ - + ]: 60 : if (ret < 0 || ret >= (int)sizeof(devargs->name)) {
247 : 0 : rte_devargs_reset(devargs);
248 : 0 : free(devargs);
249 : 0 : return NULL;
250 : : }
251 : :
252 : : return devargs;
253 : : }
254 : :
255 : : static int
256 : 60 : insert_vdev(const char *name, const char *args,
257 : : struct rte_vdev_device **p_dev,
258 : : bool init)
259 : : {
260 : : struct rte_vdev_device *dev;
261 : : struct rte_devargs *devargs;
262 : : int ret;
263 : :
264 [ + - ]: 60 : if (name == NULL)
265 : : return -EINVAL;
266 : :
267 : 60 : devargs = alloc_devargs(name, args);
268 : :
269 [ + - ]: 60 : if (!devargs)
270 : : return -ENOMEM;
271 : :
272 : 60 : dev = calloc(1, sizeof(*dev));
273 [ - + ]: 60 : if (!dev) {
274 : : ret = -ENOMEM;
275 : 0 : goto fail;
276 : : }
277 : :
278 : 60 : dev->device.numa_node = SOCKET_ID_ANY;
279 : :
280 [ - + ]: 60 : if (find_vdev(name)) {
281 : : /*
282 : : * A vdev is expected to have only one port.
283 : : * So there is no reason to try probing again,
284 : : * even with new arguments.
285 : : */
286 : : ret = -EEXIST;
287 : 0 : goto fail;
288 : : }
289 : :
290 [ + + ]: 60 : if (init)
291 : 59 : rte_devargs_insert(&devargs);
292 : 60 : dev->device.devargs = devargs;
293 : 60 : dev->device.name = devargs->name;
294 : 60 : rte_bus_add_device(&rte_vdev_bus, &dev->device);
295 : :
296 [ + + ]: 60 : if (p_dev)
297 : 59 : *p_dev = dev;
298 : :
299 : : return 0;
300 : 0 : fail:
301 : 0 : rte_devargs_reset(devargs);
302 : 0 : free(devargs);
303 : 0 : free(dev);
304 : 0 : return ret;
305 : : }
306 : :
307 : : RTE_EXPORT_SYMBOL(rte_vdev_init)
308 : : int
309 : 59 : rte_vdev_init(const char *name, const char *args)
310 : : {
311 : : struct rte_vdev_device *dev;
312 : : int ret;
313 : :
314 : 59 : rte_spinlock_recursive_lock(&vdev_device_list_lock);
315 : 59 : ret = insert_vdev(name, args, &dev, true);
316 [ + - ]: 59 : if (ret == 0) {
317 : : struct rte_driver *drv = NULL;
318 : :
319 : 59 : next_driver:
320 : 59 : drv = rte_bus_find_driver(&rte_vdev_bus, drv, &dev->device);
321 [ - + ]: 59 : if (drv == NULL) {
322 : 0 : VDEV_LOG(ERR, "no driver found for %s", name);
323 : : ret = -1;
324 [ + - ]: 59 : } else if (rte_dev_is_probed(&dev->device)) {
325 : : ret = -EEXIST;
326 : : } else {
327 : 59 : dev->device.driver = drv;
328 : 59 : ret = rte_vdev_bus.probe_device(drv, &dev->device);
329 [ + + ]: 59 : if (ret != 0)
330 : 4 : dev->device.driver = NULL;
331 : : }
332 [ + + ]: 59 : if (ret < 0) {
333 : : /* If fails, remove it from vdev list */
334 : 4 : rte_bus_remove_device(&rte_vdev_bus, &dev->device);
335 : 4 : rte_devargs_remove(dev->device.devargs);
336 : 4 : free(dev);
337 [ - + ]: 55 : } else if (ret > 0) {
338 : 0 : goto next_driver;
339 : : }
340 : : }
341 : 59 : rte_spinlock_recursive_unlock(&vdev_device_list_lock);
342 : 59 : return ret;
343 : : }
344 : :
345 : : static int
346 : 14 : vdev_unplug_device(struct rte_device *rte_dev)
347 : : {
348 : 67 : const struct rte_vdev_driver *driver = RTE_BUS_DRIVER(rte_dev->driver, *driver);
349 : : struct rte_vdev_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
350 : :
351 [ + - + - ]: 67 : if (driver->remove)
352 : 67 : return driver->remove(dev);
353 : :
354 : : return 0;
355 : : }
356 : :
357 : : RTE_EXPORT_SYMBOL(rte_vdev_uninit)
358 : : int
359 : 54 : rte_vdev_uninit(const char *name)
360 : : {
361 : : struct rte_vdev_device *dev;
362 : : int ret;
363 : :
364 [ + - ]: 54 : if (name == NULL)
365 : : return -EINVAL;
366 : :
367 : 54 : rte_spinlock_recursive_lock(&vdev_device_list_lock);
368 : :
369 : 54 : dev = find_vdev(name);
370 [ + + ]: 54 : if (!dev) {
371 : : ret = -ENOENT;
372 : 1 : goto unlock;
373 : : }
374 : :
375 [ + - ]: 53 : if (rte_dev_is_probed(&dev->device)) {
376 : : ret = vdev_unplug_device(&dev->device);
377 : : } else {
378 : 0 : VDEV_LOG(DEBUG, "no driver attach to device %s", name);
379 : : ret = 1;
380 : : }
381 [ - + ]: 53 : if (ret)
382 : 0 : goto unlock;
383 : :
384 : 53 : rte_bus_remove_device(&rte_vdev_bus, &dev->device);
385 : 53 : rte_devargs_remove(dev->device.devargs);
386 : 53 : free(dev);
387 : :
388 : 54 : unlock:
389 : 54 : rte_spinlock_recursive_unlock(&vdev_device_list_lock);
390 : 54 : return ret;
391 : : }
392 : :
393 : : struct vdev_param {
394 : : #define VDEV_SCAN_REQ 1
395 : : #define VDEV_SCAN_ONE 2
396 : : #define VDEV_SCAN_REP 3
397 : : int type;
398 : : int num;
399 : : char name[RTE_DEV_NAME_MAX_LEN];
400 : : };
401 : :
402 : : /**
403 : : * This function works as the action for both primary and secondary process
404 : : * for static vdev discovery when a secondary process is booting.
405 : : *
406 : : * step 1, secondary process sends a sync request to ask for vdev in primary;
407 : : * step 2, primary process receives the request, and send vdevs one by one;
408 : : * step 3, primary process sends back reply, which indicates how many vdevs
409 : : * are sent.
410 : : */
411 : : static int
412 [ + + - ]: 32 : vdev_action(const struct rte_mp_msg *mp_msg, const void *peer)
413 : : {
414 : : struct rte_vdev_device *dev;
415 : : struct rte_mp_msg mp_resp;
416 : : struct vdev_param *ou = (struct vdev_param *)&mp_resp.param;
417 : : const struct vdev_param *in = (const struct vdev_param *)mp_msg->param;
418 : : const char *devname;
419 : : int num;
420 : : int ret;
421 : :
422 : : strlcpy(mp_resp.name, VDEV_MP_KEY, sizeof(mp_resp.name));
423 : 32 : mp_resp.len_param = sizeof(*ou);
424 : 32 : mp_resp.num_fds = 0;
425 : :
426 [ + + - ]: 32 : switch (in->type) {
427 : 31 : case VDEV_SCAN_REQ:
428 : 31 : ou->type = VDEV_SCAN_ONE;
429 : 31 : ou->num = 1;
430 : : num = 0;
431 : :
432 : 31 : rte_spinlock_recursive_lock(&vdev_device_list_lock);
433 [ + + + - ]: 32 : RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
434 : : devname = rte_vdev_device_name(dev);
435 [ - + ]: 1 : if (strlen(devname) == 0) {
436 : 0 : VDEV_LOG(INFO, "vdev with no name is not sent");
437 : 0 : continue;
438 : : }
439 : 1 : VDEV_LOG(INFO, "send vdev, %s", devname);
440 : : strlcpy(ou->name, devname, RTE_DEV_NAME_MAX_LEN);
441 [ - + ]: 1 : if (rte_mp_sendmsg(&mp_resp) < 0)
442 : 0 : VDEV_LOG(ERR, "send vdev, %s, failed, %s",
443 : : devname, strerror(rte_errno));
444 : 1 : num++;
445 : : }
446 : 31 : rte_spinlock_recursive_unlock(&vdev_device_list_lock);
447 : :
448 : 31 : ou->type = VDEV_SCAN_REP;
449 : 31 : ou->num = num;
450 [ - + ]: 31 : if (rte_mp_reply(&mp_resp, peer) < 0)
451 : 0 : VDEV_LOG(ERR, "Failed to reply a scan request");
452 : : break;
453 : 1 : case VDEV_SCAN_ONE:
454 : 1 : VDEV_LOG(INFO, "receive vdev, %s", in->name);
455 : 1 : ret = insert_vdev(in->name, NULL, NULL, false);
456 [ - + ]: 1 : if (ret == -EEXIST)
457 : 0 : VDEV_LOG(DEBUG, "device already exist, %s", in->name);
458 [ - + ]: 1 : else if (ret < 0)
459 : 0 : VDEV_LOG(ERR, "failed to add vdev, %s", in->name);
460 : : break;
461 : 0 : default:
462 : 0 : VDEV_LOG(ERR, "vdev cannot recognize this message");
463 : : }
464 : :
465 : 32 : return 0;
466 : : }
467 : :
468 : : static int
469 : 225 : vdev_scan(void)
470 : : {
471 : : struct rte_vdev_device *dev;
472 : : struct rte_devargs *devargs;
473 : : struct vdev_custom_scan *custom_scan;
474 : :
475 [ + + ]: 225 : if (rte_mp_action_register(VDEV_MP_KEY, vdev_action) < 0 &&
476 [ + - ]: 10 : rte_errno != EEXIST) {
477 : : /* for primary, unsupported IPC is not an error */
478 [ + - ]: 10 : if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
479 [ + - ]: 10 : rte_errno == ENOTSUP)
480 : 10 : goto scan;
481 : 0 : VDEV_LOG(ERR, "Failed to add vdev mp action");
482 : 0 : return -1;
483 : : }
484 : :
485 [ + + ]: 215 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
486 : : struct rte_mp_msg mp_req, *mp_rep;
487 : : struct rte_mp_reply mp_reply;
488 : 32 : struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
489 : : struct vdev_param *req = (struct vdev_param *)mp_req.param;
490 : : struct vdev_param *resp;
491 : :
492 : : strlcpy(mp_req.name, VDEV_MP_KEY, sizeof(mp_req.name));
493 : 32 : mp_req.len_param = sizeof(*req);
494 : 32 : mp_req.num_fds = 0;
495 : 32 : req->type = VDEV_SCAN_REQ;
496 [ + + ]: 32 : if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
497 [ + - ]: 31 : mp_reply.nb_received == 1) {
498 : 31 : mp_rep = &mp_reply.msgs[0];
499 : : resp = (struct vdev_param *)mp_rep->param;
500 : 31 : VDEV_LOG(INFO, "Received %d vdevs", resp->num);
501 : 31 : free(mp_reply.msgs);
502 : : } else
503 : 1 : VDEV_LOG(ERR, "Failed to request vdev from primary");
504 : :
505 : : /* Fall through to allow private vdevs in secondary process */
506 : : }
507 : :
508 : 225 : scan:
509 : : /* call custom scan callbacks if any */
510 : : rte_spinlock_lock(&vdev_custom_scan_lock);
511 [ - + ]: 225 : TAILQ_FOREACH(custom_scan, &vdev_custom_scans, next) {
512 [ # # ]: 0 : if (custom_scan->callback != NULL)
513 : : /*
514 : : * the callback should update devargs list
515 : : * by calling rte_devargs_insert() with
516 : : * devargs.bus = rte_bus_find_by_name("vdev");
517 : : * devargs.type = RTE_DEVTYPE_VIRTUAL;
518 : : * devargs.policy = RTE_DEV_ALLOWED;
519 : : */
520 : 0 : custom_scan->callback(custom_scan->user_arg);
521 : : }
522 : : rte_spinlock_unlock(&vdev_custom_scan_lock);
523 : :
524 : : /* for virtual devices we scan the devargs_list populated via cmdline */
525 [ + + ]: 238 : RTE_EAL_DEVARGS_FOREACH(rte_vdev_bus.name, devargs) {
526 : :
527 : 13 : dev = calloc(1, sizeof(*dev));
528 [ + - ]: 13 : if (!dev)
529 : : return -1;
530 : :
531 : 13 : rte_spinlock_recursive_lock(&vdev_device_list_lock);
532 : :
533 [ + + ]: 13 : if (find_vdev(devargs->name)) {
534 : 1 : rte_spinlock_recursive_unlock(&vdev_device_list_lock);
535 : 1 : free(dev);
536 : 1 : continue;
537 : : }
538 : :
539 : 12 : dev->device.devargs = devargs;
540 : 12 : dev->device.numa_node = SOCKET_ID_ANY;
541 : 12 : dev->device.name = devargs->name;
542 : :
543 : 12 : rte_bus_add_device(&rte_vdev_bus, &dev->device);
544 : :
545 : 12 : rte_spinlock_recursive_unlock(&vdev_device_list_lock);
546 : : }
547 : :
548 : : return 0;
549 : : }
550 : :
551 : : static void
552 : 15 : vdev_free_device(struct rte_device *dev)
553 : : {
554 : 15 : free(RTE_BUS_DEVICE(dev, struct rte_vdev_device));
555 : 15 : }
556 : :
557 : : static int
558 : 294 : vdev_cleanup(struct rte_bus *bus)
559 : : {
560 : : int error;
561 : :
562 : 294 : rte_spinlock_recursive_lock(&vdev_device_list_lock);
563 : 294 : error = rte_bus_generic_cleanup(bus);
564 : 294 : rte_spinlock_recursive_unlock(&vdev_device_list_lock);
565 : :
566 : 294 : return error;
567 : : }
568 : :
569 : : static struct rte_device *
570 : 7 : vdev_find_device(const struct rte_bus *bus, const struct rte_device *start,
571 : : rte_dev_cmp_t cmp, const void *data)
572 : : {
573 : : struct rte_device *dev;
574 : :
575 : 7 : rte_spinlock_recursive_lock(&vdev_device_list_lock);
576 : 7 : dev = rte_bus_generic_find_device(bus, start, cmp, data);
577 : 7 : rte_spinlock_recursive_unlock(&vdev_device_list_lock);
578 : :
579 : 7 : return dev;
580 : : }
581 : :
582 : : static enum rte_iova_mode
583 : 225 : vdev_get_iommu_class(void)
584 : : {
585 : : const char *name;
586 : : struct rte_vdev_device *dev;
587 : : struct rte_vdev_driver *driver;
588 : :
589 [ + + + - ]: 234 : RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
590 : : name = rte_vdev_device_name(dev);
591 [ - + ]: 10 : if (vdev_parse(name, &driver))
592 : 0 : continue;
593 : :
594 [ + + ]: 10 : if (driver->drv_flags & RTE_VDEV_DRV_NEED_IOVA_AS_VA)
595 : : return RTE_IOVA_VA;
596 : : }
597 : :
598 : : return RTE_IOVA_DC;
599 : : }
600 : :
601 : : static struct rte_bus rte_vdev_bus = {
602 : : .scan = vdev_scan,
603 : : .probe = rte_bus_generic_probe,
604 : : .free_device = vdev_free_device,
605 : : .cleanup = vdev_cleanup,
606 : : .find_device = vdev_find_device,
607 : : .match = vdev_bus_match,
608 : : .probe_device = vdev_probe_device,
609 : : .unplug_device = vdev_unplug_device,
610 : : .parse = vdev_parse,
611 : : .dma_map = vdev_dma_map,
612 : : .dma_unmap = vdev_dma_unmap,
613 : : .get_iommu_class = vdev_get_iommu_class,
614 : : .dev_iterate = rte_bus_generic_dev_iterate,
615 : : };
616 : :
617 : 301 : RTE_REGISTER_BUS(vdev, rte_vdev_bus);
618 [ - + ]: 301 : RTE_LOG_REGISTER_DEFAULT(vdev_logtype_bus, NOTICE);
|