Add 3 methods in device class corresponding to the local part of the 3-phases reset. This allows specialization classes not to care about the ressetting counter and sub-buses. The exit phase method is called only if resetting counter hits 0.
Also, these methods are called in `device_reset`. Specializations can switch from the single-phase reset to the 3-phases reset with no effects on the `device_reset` behavior. Signed-off-by: Damien Hedde <damien.he...@greensocs.com> --- hw/core/qdev.c | 44 ++++++++++++++++++++++++++++++++++++++++++ include/hw/qdev-core.h | 17 ++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 98d173f34f..884a49efa4 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -280,21 +280,30 @@ static void device_reset_init_phase(Object *obj, bool cold) if (dc->reset) { dc->reset(dev); } + if (dc->reset_phases.init) { + dc->reset_phases.init(OBJECT(dev), cold); + } } static void device_reset_hold_phase(Object *obj) { DeviceState *dev = DEVICE(obj); + DeviceClass *dc = DEVICE_GET_CLASS(obj); BusState *child; QLIST_FOREACH(child, &dev->child_bus, sibling) { resettable_hold_phase(OBJECT(child)); } + + if (dc->reset_phases.hold) { + dc->reset_phases.hold(OBJECT(dev)); + } } static void device_reset_exit_phase(Object *obj) { DeviceState *dev = DEVICE(obj); + DeviceClass *dc = DEVICE_GET_CLASS(obj); BusState *child; QLIST_FOREACH(child, &dev->child_bus, sibling) { @@ -303,6 +312,12 @@ static void device_reset_exit_phase(Object *obj) assert(dev->resetting > 0); dev->resetting -= 1; + + if (dev->resetting == 0) { + if (dc->reset_phases.exit) { + dc->reset_phases.exit(OBJECT(dev)); + } + } } static int qdev_reset_one(DeviceState *dev, void *opaque) @@ -1143,6 +1158,24 @@ void device_class_set_parent_unrealize(DeviceClass *dc, dc->unrealize = dev_unrealize; } +void device_class_set_parent_reset_phases(DeviceClass *dc, + ResettableInitPhase dev_reset_init, + ResettableHoldPhase dev_reset_hold, + ResettableExitPhase dev_reset_exit, + ResettablePhases *parent_phases) +{ + *parent_phases = dc->reset_phases; + if (dev_reset_init) { + dc->reset_phases.init = dev_reset_init; + } + if (dev_reset_hold) { + dc->reset_phases.hold = dev_reset_hold; + } + if (dev_reset_exit) { + dc->reset_phases.exit = dev_reset_exit; + } +} + void device_reset(DeviceState *dev) { DeviceClass *klass = DEVICE_GET_CLASS(dev); @@ -1150,6 +1183,17 @@ void device_reset(DeviceState *dev) if (klass->reset) { klass->reset(dev); } + dev->resetting += 1; + if (klass->reset_phases.init) { + klass->reset_phases.init(OBJECT(dev), false); + } + if (klass->reset_phases.hold) { + klass->reset_phases.hold(OBJECT(dev)); + } + dev->resetting -= 1; + if (klass->reset_phases.exit) { + klass->reset_phases.exit(OBJECT(dev)); + } } Object *qdev_get_machine(void) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index f4aa8dbaa2..0ef4d6c920 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -6,6 +6,7 @@ #include "qom/object.h" #include "hw/irq.h" #include "hw/hotplug.h" +#include "hw/resettable.h" enum { DEV_NVECTORS_UNSPECIFIED = -1, @@ -110,6 +111,7 @@ typedef struct DeviceClass { DeviceReset reset; DeviceRealize realize; DeviceUnrealize unrealize; + ResettablePhases reset_phases; /* device state */ const struct VMStateDescription *vmsd; @@ -455,6 +457,21 @@ void device_class_set_parent_unrealize(DeviceClass *dc, DeviceUnrealize dev_unrealize, DeviceUnrealize *parent_unrealize); +/** + * @device_class_set_parent_reset_phases: + * + * Save @dc current reset phases into @parent_phases and override @dc phases + * by the given new methods (@dev_reset_init, @dev_reset_hold and + * @dev_reset_exit). + * Each phase is overriden only if the new one is not NULL allowing to + * override a subset of phases. + */ +void device_class_set_parent_reset_phases(DeviceClass *dc, + ResettableInitPhase dev_reset_init, + ResettableHoldPhase dev_reset_hold, + ResettableExitPhase dev_reset_exit, + ResettablePhases *parent_phases); + const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev); const char *qdev_fw_name(DeviceState *dev); -- 2.21.0