1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation.
3 * Copyright(c) 2014 6WIND S.A.
11 #include <rte_compat.h>
13 #include <rte_class.h>
15 #include <rte_devargs.h>
16 #include <rte_debug.h>
17 #include <rte_errno.h>
18 #include <rte_kvargs.h>
20 #include <rte_spinlock.h>
21 #include <rte_malloc.h>
22 #include <rte_string_fns.h>
24 #include "eal_private.h"
25 #include "hotplug_mp.h"
28 * The device event callback description.
30 * It contains callback address to be registered by user application,
31 * the pointer to the parameters for callback, and the device name.
33 struct dev_event_callback {
34 TAILQ_ENTRY(dev_event_callback) next; /**< Callbacks list */
35 rte_dev_event_cb_fn cb_fn; /**< Callback address */
36 void *cb_arg; /**< Callback parameter */
37 char *dev_name; /**< Callback device name, NULL is for all device */
38 uint32_t active; /**< Callback is executing */
41 /** @internal Structure to keep track of registered callbacks */
42 TAILQ_HEAD(dev_event_cb_list, dev_event_callback);
44 /* The device event callback list for all registered callbacks. */
45 static struct dev_event_cb_list dev_event_cbs;
47 /* spinlock for device callbacks */
48 static rte_spinlock_t dev_event_lock = RTE_SPINLOCK_INITIALIZER;
51 struct rte_dev_iterator *it;
56 #define CTX(it, bus_str, cls_str) \
57 (&(const struct dev_next_ctx){ \
64 (((struct dev_next_ctx *)(intptr_t)ptr)->it)
67 (((struct dev_next_ctx *)(intptr_t)ptr)->bus_str)
70 (((struct dev_next_ctx *)(intptr_t)ptr)->cls_str)
72 static int cmp_dev_name(const struct rte_device *dev, const void *_name)
74 const char *name = _name;
76 return strcmp(dev->name, name);
79 int rte_eal_dev_attach(const char *name, const char *devargs)
83 if (name == NULL || devargs == NULL) {
84 RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
88 bus = rte_bus_find_by_device_name(name);
90 RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
94 if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
95 return rte_eal_hotplug_add(bus->name, name, devargs);
98 "Device attach is only supported for PCI and vdev devices.\n");
103 int rte_eal_dev_detach(struct rte_device *dev)
109 RTE_LOG(ERR, EAL, "Invalid device provided.\n");
113 bus = rte_bus_find_by_device(dev);
115 RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
120 if (bus->unplug == NULL) {
121 RTE_LOG(ERR, EAL, "Bus function not supported\n");
125 ret = bus->unplug(dev);
127 RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
132 /* helper function to build devargs, caller should free the memory */
134 build_devargs(const char *busname, const char *devname,
135 const char *drvargs, char **devargs)
139 length = snprintf(NULL, 0, "%s:%s,%s", busname, devname, drvargs);
143 *devargs = malloc(length + 1);
144 if (*devargs == NULL)
147 length = snprintf(*devargs, length + 1, "%s:%s,%s",
148 busname, devname, drvargs);
158 rte_eal_hotplug_add(const char *busname, const char *devname,
165 ret = build_devargs(busname, devname, drvargs, &devargs);
169 ret = rte_dev_probe(devargs);
175 /* probe device at local process. */
177 local_dev_probe(const char *devargs, struct rte_device **new_dev)
179 struct rte_device *dev;
180 struct rte_devargs *da;
184 da = calloc(1, sizeof(*da));
188 ret = rte_devargs_parse(da, devargs);
192 if (da->bus->plug == NULL) {
193 RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)\n",
199 ret = rte_devargs_insert(da);
203 ret = da->bus->scan();
207 dev = da->bus->find_device(NULL, cmp_dev_name, da->name);
209 RTE_LOG(ERR, EAL, "Cannot find device (%s)\n",
215 if (dev->driver != NULL) {
216 RTE_LOG(ERR, EAL, "Device is already plugged\n");
220 ret = dev->bus->plug(dev);
222 RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n",
231 if (rte_devargs_remove(da) != 0) {
238 int __rte_experimental
239 rte_dev_probe(const char *devargs)
241 struct eal_dev_mp_req req;
242 struct rte_device *dev;
245 memset(&req, 0, sizeof(req));
246 req.t = EAL_DEV_REQ_TYPE_ATTACH;
247 strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
249 if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
251 * If in secondary process, just send IPC request to
254 ret = eal_dev_hotplug_request_to_primary(&req);
257 "Failed to send hotplug request to primary\n");
262 "Failed to hotplug add device\n");
266 /* attach a shared device from primary start from here: */
268 /* primary attach the new device itself. */
269 ret = local_dev_probe(devargs, &dev);
273 "Failed to attach device on primary process\n");
276 * it is possible that secondary process failed to attached a
277 * device that primary process have during initialization,
278 * so for -EEXIST case, we still need to sync with secondary
285 /* primary send attach sync request to secondary. */
286 ret = eal_dev_hotplug_request_to_secondary(&req);
288 /* if any communication error, we need to rollback. */
291 "Failed to send hotplug add request to secondary\n");
297 * if any secondary failed to attach, we need to consider if rollback
300 if (req.result != 0) {
302 "Failed to attach device on secondary process\n");
305 /* for -EEXIST, we don't need to rollback. */
314 req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK;
316 /* primary send rollback request to secondary. */
317 if (eal_dev_hotplug_request_to_secondary(&req) != 0)
318 RTE_LOG(WARNING, EAL,
319 "Failed to rollback device attach on secondary."
320 "Devices in secondary may not sync with primary\n");
322 /* primary rollback itself. */
323 if (local_dev_remove(dev) != 0)
324 RTE_LOG(WARNING, EAL,
325 "Failed to rollback device attach on primary."
326 "Devices in secondary may not sync with primary\n");
332 rte_eal_hotplug_remove(const char *busname, const char *devname)
334 struct rte_device *dev;
337 bus = rte_bus_find_by_name(busname);
339 RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname);
343 dev = bus->find_device(NULL, cmp_dev_name, devname);
345 RTE_LOG(ERR, EAL, "Cannot find plugged device (%s)\n", devname);
349 return rte_dev_remove(dev);
352 /* remove device at local process. */
354 local_dev_remove(struct rte_device *dev)
358 if (dev->driver == NULL) {
359 RTE_LOG(ERR, EAL, "Device is already unplugged\n");
363 if (dev->bus->unplug == NULL) {
364 RTE_LOG(ERR, EAL, "Function unplug not supported by bus (%s)\n",
369 ret = dev->bus->unplug(dev);
371 RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
376 rte_devargs_remove(dev->devargs);
381 int __rte_experimental
382 rte_dev_remove(struct rte_device *dev)
384 struct eal_dev_mp_req req;
388 ret = build_devargs(dev->devargs->bus->name, dev->name, "", &devargs);
392 memset(&req, 0, sizeof(req));
393 req.t = EAL_DEV_REQ_TYPE_DETACH;
394 strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
397 if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
399 * If in secondary process, just send IPC request to
402 ret = eal_dev_hotplug_request_to_primary(&req);
405 "Failed to send hotplug request to primary\n");
410 "Failed to hotplug remove device\n");
414 /* detach a device from primary start from here: */
416 /* primary send detach sync request to secondary */
417 ret = eal_dev_hotplug_request_to_secondary(&req);
420 * if communication error, we need to rollback, because it is possible
421 * part of the secondary processes still detached it successfully.
425 "Failed to send device detach request to secondary\n");
431 * if any secondary failed to detach, we need to consider if rollback
434 if (req.result != 0) {
436 "Failed to detach device on secondary process\n");
439 * if -ENOENT, we don't need to rollback, since devices is
440 * already detached on secondary process.
446 /* primary detach the device itself. */
447 ret = local_dev_remove(dev);
449 /* if primary failed, still need to consider if rollback is necessary */
452 "Failed to detach device on primary process\n");
453 /* if -ENOENT, we don't need to rollback */
462 req.t = EAL_DEV_REQ_TYPE_DETACH_ROLLBACK;
464 /* primary send rollback request to secondary. */
465 if (eal_dev_hotplug_request_to_secondary(&req) != 0)
466 RTE_LOG(WARNING, EAL,
467 "Failed to rollback device detach on secondary."
468 "Devices in secondary may not sync with primary\n");
473 int __rte_experimental
474 rte_dev_event_callback_register(const char *device_name,
475 rte_dev_event_cb_fn cb_fn,
478 struct dev_event_callback *event_cb;
484 rte_spinlock_lock(&dev_event_lock);
486 if (TAILQ_EMPTY(&dev_event_cbs))
487 TAILQ_INIT(&dev_event_cbs);
489 TAILQ_FOREACH(event_cb, &dev_event_cbs, next) {
490 if (event_cb->cb_fn == cb_fn && event_cb->cb_arg == cb_arg) {
491 if (device_name == NULL && event_cb->dev_name == NULL)
493 if (device_name == NULL || event_cb->dev_name == NULL)
495 if (!strcmp(event_cb->dev_name, device_name))
500 /* create a new callback. */
501 if (event_cb == NULL) {
502 event_cb = malloc(sizeof(struct dev_event_callback));
503 if (event_cb != NULL) {
504 event_cb->cb_fn = cb_fn;
505 event_cb->cb_arg = cb_arg;
506 event_cb->active = 0;
508 event_cb->dev_name = NULL;
510 event_cb->dev_name = strdup(device_name);
511 if (event_cb->dev_name == NULL) {
516 TAILQ_INSERT_TAIL(&dev_event_cbs, event_cb, next);
519 "Failed to allocate memory for device "
526 "The callback is already exist, no need "
527 "to register again.\n");
531 rte_spinlock_unlock(&dev_event_lock);
535 rte_spinlock_unlock(&dev_event_lock);
539 int __rte_experimental
540 rte_dev_event_callback_unregister(const char *device_name,
541 rte_dev_event_cb_fn cb_fn,
545 struct dev_event_callback *event_cb, *next;
550 rte_spinlock_lock(&dev_event_lock);
551 /*walk through the callbacks and remove all that match. */
552 for (event_cb = TAILQ_FIRST(&dev_event_cbs); event_cb != NULL;
555 next = TAILQ_NEXT(event_cb, next);
557 if (device_name != NULL && event_cb->dev_name != NULL) {
558 if (!strcmp(event_cb->dev_name, device_name)) {
559 if (event_cb->cb_fn != cb_fn ||
560 (cb_arg != (void *)-1 &&
561 event_cb->cb_arg != cb_arg))
564 } else if (device_name != NULL) {
569 * if this callback is not executing right now,
572 if (event_cb->active == 0) {
573 TAILQ_REMOVE(&dev_event_cbs, event_cb, next);
580 rte_spinlock_unlock(&dev_event_lock);
584 void __rte_experimental
585 rte_dev_event_callback_process(const char *device_name,
586 enum rte_dev_event_type event)
588 struct dev_event_callback *cb_lst;
590 if (device_name == NULL)
593 rte_spinlock_lock(&dev_event_lock);
595 TAILQ_FOREACH(cb_lst, &dev_event_cbs, next) {
596 if (cb_lst->dev_name) {
597 if (strcmp(cb_lst->dev_name, device_name))
601 rte_spinlock_unlock(&dev_event_lock);
602 cb_lst->cb_fn(device_name, event,
604 rte_spinlock_lock(&dev_event_lock);
607 rte_spinlock_unlock(&dev_event_lock);
612 rte_dev_iterator_init(struct rte_dev_iterator *it,
615 struct rte_devargs devargs;
616 struct rte_class *cls = NULL;
617 struct rte_bus *bus = NULL;
619 /* Having both bus_str and cls_str NULL is illegal,
620 * marking this iterator as invalid unless
621 * everything goes well.
626 devargs.data = dev_str;
627 if (rte_devargs_layers_parse(&devargs, dev_str))
632 /* The string should have at least
633 * one layer specified.
635 if (bus == NULL && cls == NULL) {
637 "Either bus or class must be specified.\n");
641 if (bus != NULL && bus->dev_iterate == NULL) {
642 RTE_LOG(ERR, EAL, "Bus %s not supported\n", bus->name);
646 if (cls != NULL && cls->dev_iterate == NULL) {
647 RTE_LOG(ERR, EAL, "Class %s not supported\n", cls->name);
651 it->bus_str = devargs.bus_str;
652 it->cls_str = devargs.cls_str;
653 it->dev_str = dev_str;
657 it->class_device = NULL;
663 dev_str_sane_copy(const char *str)
668 end = strcspn(str, ",/");
669 if (str[end] == ',') {
670 copy = strdup(&str[end + 1]);
680 slash = strchr(copy, '/');
688 class_next_dev_cmp(const struct rte_class *cls,
691 struct rte_dev_iterator *it;
692 const char *cls_str = NULL;
695 if (cls->dev_iterate == NULL)
698 cls_str = CLSCTX(ctx);
699 dev = it->class_device;
700 /* it->cls_str != NULL means a class
701 * was specified in the devstr.
703 if (it->cls_str != NULL && cls != it->cls)
705 /* If an error occurred previously,
706 * no need to test further.
710 dev = cls->dev_iterate(dev, cls_str, it);
711 it->class_device = dev;
716 bus_next_dev_cmp(const struct rte_bus *bus,
719 struct rte_device *dev = NULL;
720 struct rte_class *cls = NULL;
721 struct rte_dev_iterator *it;
722 const char *bus_str = NULL;
724 if (bus->dev_iterate == NULL)
727 bus_str = BUSCTX(ctx);
729 /* it->bus_str != NULL means a bus
730 * was specified in the devstr.
732 if (it->bus_str != NULL && bus != it->bus)
734 /* If an error occurred previously,
735 * no need to test further.
739 if (it->cls_str == NULL) {
740 dev = bus->dev_iterate(dev, bus_str, it);
743 /* cls_str != NULL */
746 dev = bus->dev_iterate(dev, bus_str, it);
752 cls = TAILQ_PREV(it->cls, rte_class_list, next);
753 cls = rte_class_find(cls, class_next_dev_cmp, ctx);
758 goto next_dev_on_bus;
765 rte_dev_iterator_next(struct rte_dev_iterator *it)
767 struct rte_bus *bus = NULL;
768 int old_errno = rte_errno;
769 char *bus_str = NULL;
770 char *cls_str = NULL;
773 if (it->bus_str == NULL && it->cls_str == NULL) {
774 /* Invalid iterator. */
779 bus = TAILQ_PREV(it->bus, rte_bus_list, next);
780 if (it->bus_str != NULL) {
781 bus_str = dev_str_sane_copy(it->bus_str);
785 if (it->cls_str != NULL) {
786 cls_str = dev_str_sane_copy(it->cls_str);
790 while ((bus = rte_bus_find(bus, bus_next_dev_cmp,
791 CTX(it, bus_str, cls_str)))) {
792 if (it->device != NULL) {
796 if (it->bus_str != NULL ||
801 rte_errno = old_errno;