diff options
author | Igor Mammedov | 2014-02-05 16:36:46 +0100 |
---|---|---|
committer | Michael S. Tsirkin | 2014-02-10 09:23:35 +0100 |
commit | 1a37eca107cece3ed454bae29eef0bd1fac4a244 (patch) | |
tree | 48db83a3a7ecc56cf02291f8b784de5c1f340ce4 /hw/core | |
parent | qdev: add to BusState "hotplug-handler" link (diff) | |
download | qemu-1a37eca107cece3ed454bae29eef0bd1fac4a244.tar.gz qemu-1a37eca107cece3ed454bae29eef0bd1fac4a244.tar.xz qemu-1a37eca107cece3ed454bae29eef0bd1fac4a244.zip |
qdev: add "hotpluggable" property to Device
Currently it's possible to make PCIDevice not hotpluggable
by using no_hotplug field of PCIDeviceClass. However it
limits this only to PCI devices and prevents from
generalizing hotplug code.
So add similar field to DeviceClass so it could be reused
with other Devices and would allow to replace PCI specific
hotplug callbacks with generic implementation. Following
patches will replace PCIDeviceClass.no_hotplug with this
new property.
In addition expose field as "hotpluggable" readonly property,
to make it possible to read its value via QOM interface.
Make DeviceClass hotpluggable by default as it was assumed
before.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/core')
-rw-r--r-- | hw/core/qdev.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/hw/core/qdev.c b/hw/core/qdev.c index c9f0c330e2..5c864dbfa7 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -215,6 +215,12 @@ void qdev_unplug(DeviceState *dev, Error **errp) } assert(dc->unplug != NULL); + if (!dc->hotpluggable) { + error_set(errp, QERR_DEVICE_NO_HOTPLUG, + object_get_typename(OBJECT(dev))); + return; + } + qdev_hot_removed = true; if (dc->unplug(dev) < 0) { @@ -694,6 +700,11 @@ static void device_set_realized(Object *obj, bool value, Error **err) DeviceClass *dc = DEVICE_GET_CLASS(dev); Error *local_err = NULL; + if (dev->hotplugged && !dc->hotpluggable) { + error_set(err, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj)); + return; + } + if (value && !dev->realized) { if (!obj->parent && local_err == NULL) { static int unattached_count; @@ -734,6 +745,14 @@ static void device_set_realized(Object *obj, bool value, Error **err) dev->realized = value; } +static bool device_get_hotpluggable(Object *obj, Error **err) +{ + DeviceClass *dc = DEVICE_GET_CLASS(obj); + DeviceState *dev = DEVICE(obj); + + return dc->hotpluggable && dev->parent_bus->allow_hotplug; +} + static void device_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); @@ -750,6 +769,8 @@ static void device_initfn(Object *obj) object_property_add_bool(obj, "realized", device_get_realized, device_set_realized, NULL); + object_property_add_bool(obj, "hotpluggable", + device_get_hotpluggable, NULL, NULL); class = object_get_class(OBJECT(dev)); do { @@ -786,6 +807,14 @@ static void device_class_base_init(ObjectClass *class, void *data) * so do not propagate them to the subclasses. */ klass->props = NULL; + + /* by default all devices were considered as hotpluggable, + * so with intent to check it in generic qdev_unplug() / + * device_set_realized() functions make every device + * hotpluggable. Devices that shouldn't be hotpluggable, + * should override it in their class_init() + */ + klass->hotpluggable = true; } static void device_unparent(Object *obj) |