1 /* 2 * QDev Hotplug handlers 3 * 4 * Copyright (c) Red Hat 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 * 8 * This work is licensed under the terms of the GNU GPL, version 2 or later. 9 * See the COPYING file in the top-level directory. 10 */ 11 12 #include "qemu/osdep.h" 13 #include "hw/qdev-core.h" 14 #include "hw/boards.h" 15 16 HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev) 17 { 18 MachineState *machine; 19 MachineClass *mc; 20 Object *m_obj = qdev_get_machine(); 21 22 if (object_dynamic_cast(m_obj, TYPE_MACHINE)) { 23 machine = MACHINE(m_obj); 24 mc = MACHINE_GET_CLASS(machine); 25 if (mc->get_hotplug_handler) { 26 return mc->get_hotplug_handler(machine, dev); 27 } 28 } 29 30 return NULL; 31 } 32 33 static bool qdev_hotplug_unplug_allowed_common(DeviceState *dev, BusState *bus, 34 Error **errp) 35 { 36 return true; 37 } 38 39 bool qdev_hotplug_allowed(DeviceState *dev, BusState *bus, Error **errp) 40 { 41 MachineState *machine; 42 MachineClass *mc; 43 Object *m_obj = qdev_get_machine(); 44 45 if (!qdev_hotplug_unplug_allowed_common(dev, bus, errp)) { 46 return false; 47 } 48 49 if (object_dynamic_cast(m_obj, TYPE_MACHINE)) { 50 machine = MACHINE(m_obj); 51 mc = MACHINE_GET_CLASS(machine); 52 if (mc->hotplug_allowed) { 53 return mc->hotplug_allowed(machine, dev, errp); 54 } 55 } 56 57 return true; 58 } 59 60 bool qdev_hotunplug_allowed(DeviceState *dev, Error **errp) 61 { 62 return !qdev_unplug_blocked(dev, errp) && 63 qdev_hotplug_unplug_allowed_common(dev, dev->parent_bus, errp); 64 } 65 66 HotplugHandler *qdev_get_bus_hotplug_handler(DeviceState *dev) 67 { 68 if (dev->parent_bus) { 69 return dev->parent_bus->hotplug_handler; 70 } 71 return NULL; 72 } 73 74 HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) 75 { 76 HotplugHandler *hotplug_ctrl = qdev_get_machine_hotplug_handler(dev); 77 78 if (hotplug_ctrl == NULL && dev->parent_bus) { 79 hotplug_ctrl = qdev_get_bus_hotplug_handler(dev); 80 } 81 return hotplug_ctrl; 82 } 83 84 /* can be used as ->unplug() callback for the simple cases */ 85 void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, 86 DeviceState *dev, Error **errp) 87 { 88 qdev_unrealize(dev); 89 } 90