Signed-off-by: Igor Mammedov <imamm...@redhat.com> --- hw/core/hotplug.c | 30 ++++++++++++++++++++++++++++++ hw/core/qdev.c | 15 +++++++++++++++ include/hw/hotplug.h | 2 ++ include/hw/qdev-core.h | 6 ++++++ 4 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c index 5573d9d..1a13ca3 100644 --- a/hw/core/hotplug.c +++ b/hw/core/hotplug.c @@ -11,6 +11,36 @@ */ #include "hw/hotplug.h" #include "qemu/module.h" +#include <string.h> + +HotplugHandler *hotplug_handler_get_from_path(const char *path) +{ + Object *obj; + const char *sep; + bool ambiguous = false; + HotplugHandler *hh = NULL; + char *current_path = g_strdup(path); + + while ((sep = strrchr(current_path, '/'))) { + char *old_path = current_path; + if (!sep || sep == current_path) { + break; + } + + current_path = g_strndup(current_path, sep - current_path); + g_free(old_path); + + obj = object_resolve_path(current_path, &ambiguous); + g_assert(!ambiguous); + hh = (HotplugHandler *)object_dynamic_cast(obj, TYPE_HOTPLUG_HANDLER); + if (hh != NULL) { + break; + } + } + + g_free(current_path); + return hh; +} void hotplug_handler_plug(HotplugHandler *plug_handler, DeviceState *plugged_dev, diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 9f0a522..a8d6eea 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -743,6 +743,21 @@ static void device_set_realized(Object *obj, bool value, Error **err) local_err == NULL) { hotplug_handler_plug(dev->parent_bus->hotplug_handler, dev, &local_err); + } else if (dc->hotplug_path != NULL && local_err == NULL) { + HotplugHandler *hotplug_ctrl; + char *target_name; + char *path = dc->hotplug_path(dev); + + hotplug_ctrl = hotplug_handler_get_from_path(path); + g_assert(hotplug_ctrl); + + target_name = g_strdup(strrchr(path, '/') + 1); + object_property_set_link(OBJECT(hotplug_ctrl), OBJECT(dev), + target_name, &local_err); + g_free(target_name); + g_free(path); + + hotplug_handler_plug(hotplug_ctrl, dev, &local_err); } if (qdev_get_vmsd(dev) && local_err == NULL) { diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h index a6533cb..7a3815e 100644 --- a/include/hw/hotplug.h +++ b/include/hw/hotplug.h @@ -75,4 +75,6 @@ void hotplug_handler_plug(HotplugHandler *plug_handler, void hotplug_handler_unplug(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp); + +HotplugHandler *hotplug_handler_get_from_path(const char *path); #endif diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index dbe473c..6cd936d 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -116,6 +116,12 @@ typedef struct DeviceClass { bool cannot_instantiate_with_device_add_yet; bool hotpluggable; + /* + * Returns path to link<> that should be set/unset on dev hotplug. + * Used for link based bussless devices hotplug. + */ + char* (*hotplug_path)(DeviceState *dev); + /* callbacks */ void (*reset)(DeviceState *dev); DeviceRealize realize; -- 1.7.1