diff options
Diffstat (limited to 'qdev-monitor.c')
-rw-r--r-- | qdev-monitor.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/qdev-monitor.c b/qdev-monitor.c index 5f2fcdfc45..bb3d8ba360 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -836,6 +836,40 @@ static DeviceState *find_device_state(const char *id, Error **errp) return DEVICE(obj); } +void qdev_unplug(DeviceState *dev, Error **errp) +{ + DeviceClass *dc = DEVICE_GET_CLASS(dev); + HotplugHandler *hotplug_ctrl; + HotplugHandlerClass *hdc; + + if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) { + error_setg(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name); + return; + } + + if (!dc->hotpluggable) { + error_setg(errp, QERR_DEVICE_NO_HOTPLUG, + object_get_typename(OBJECT(dev))); + return; + } + + qdev_hot_removed = true; + + hotplug_ctrl = qdev_get_hotplug_handler(dev); + /* hotpluggable device MUST have HotplugHandler, if it doesn't + * then something is very wrong with it */ + g_assert(hotplug_ctrl); + + /* If device supports async unplug just request it to be done, + * otherwise just remove it synchronously */ + hdc = HOTPLUG_HANDLER_GET_CLASS(hotplug_ctrl); + if (hdc->unplug_request) { + hotplug_handler_unplug_request(hotplug_ctrl, dev, errp); + } else { + hotplug_handler_unplug(hotplug_ctrl, dev, errp); + } +} + void qmp_device_del(const char *id, Error **errp) { DeviceState *dev = find_device_state(id, errp); |