diff mbox series

[v6,07/11] hw/core/qdev: update hotplug reset regarding resettable

Message ID 20191220115035.709876-8-damien.hedde@greensocs.com
State New
Headers show
Series Multi-phase reset mechanism | expand

Commit Message

Damien Hedde Dec. 20, 2019, 11:50 a.m. UTC
This commit make use of the resettable API to reset the device being
hotplugged when it is realized. Also it ensures it is put in a reset
state coherent with the parent it is plugged into.

Note that there is a difference in the reset. Instead of resetting
only the hotplugged device, we reset also its subtree (switch to
resettable API). This is not expected to be a problem because
sub-buses are just realized too. If a hotplugged device has any
sub-buses it is logical to reset them too at this point.

The recently added should_be_hidden and PCI's partially_hotplugged
mechanisms do not interfere with realize operation:
+ In the should_be_hidden use case, device creation is
delayed.
+ The partially_hotplugged mechanism prevents a device to be
unplugged and unrealized from qdev POV and unrealized.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---

v6 update: clear the reset state before doing any reset. Although it
is apparently highly improbable that a device be realized again after
being unrealized. See here for a discussion about this point and the
partially_hotplugged/shoud_be_hidden cases.
https://lists.nongnu.org/archive/html/qemu-devel/2019-11/msg04897.html
---
 include/hw/resettable.h |  8 ++++++++
 hw/core/qdev.c          | 15 ++++++++++++++-
 hw/core/resettable.c    |  5 +++++
 3 files changed, 27 insertions(+), 1 deletion(-)

Comments

Richard Henderson Dec. 28, 2019, 11:58 p.m. UTC | #1
On 12/20/19 10:50 PM, Damien Hedde wrote:
> +void resettable_state_clear(ResettableState *state)
> +{
> +    memset(state, 0, sizeof(ResettableState));
> +}

Worth moving this into the header as inline?  Anyway,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~
Damien Hedde Jan. 13, 2020, 4:51 p.m. UTC | #2
On 12/29/19 12:58 AM, Richard Henderson wrote:
> On 12/20/19 10:50 PM, Damien Hedde wrote:
>> +void resettable_state_clear(ResettableState *state)
>> +{
>> +    memset(state, 0, sizeof(ResettableState));
>> +}
> 
> Worth moving this into the header as inline?  Anyway,

I can but it is really not a function which matters a lot since it is
only called during realize. I hesitated not to add the function since it
is used at only one place.

I'm not sure what's bets in that case.

Damien
diff mbox series

Patch

diff --git a/include/hw/resettable.h b/include/hw/resettable.h
index 2227c654a5..4ae2a3363c 100644
--- a/include/hw/resettable.h
+++ b/include/hw/resettable.h
@@ -153,6 +153,14 @@  struct ResettableState {
     bool exit_phase_in_progress;
 };
 
+/**
+ * resettable_state_clear:
+ * Clear the state. It puts the state to the initial (zeroed) state required
+ * to reuse an object. Typically used in realize step of base classes
+ * implementing the interface.
+ */
+void resettable_state_clear(ResettableState *state);
+
 /**
  * resettable_reset:
  * Trigger a reset on an object @obj of type @type. @obj must implement
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 9b22c7c879..495b5338e2 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -948,6 +948,12 @@  static void device_set_realized(Object *obj, bool value, Error **errp)
             }
         }
 
+        /*
+         * Clear the reset state, in case the object was previously unrealized
+         * with a dirty state.
+         */
+        resettable_state_clear(&dev->reset);
+
         QLIST_FOREACH(bus, &dev->child_bus, sibling) {
             object_property_set_bool(OBJECT(bus), true, "realized",
                                          &local_err);
@@ -956,7 +962,14 @@  static void device_set_realized(Object *obj, bool value, Error **errp)
             }
         }
         if (dev->hotplugged) {
-            device_legacy_reset(dev);
+            /*
+             * Reset the device, as well as its subtree which, at this point,
+             * should be realized too.
+             */
+            resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD);
+            resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus),
+                                     NULL);
+            resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD);
         }
         dev->pending_deleted_event = false;
 
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
index 9104a84b99..9f6d586fce 100644
--- a/hw/core/resettable.c
+++ b/hw/core/resettable.c
@@ -15,6 +15,11 @@ 
 #include "hw/resettable.h"
 #include "trace.h"
 
+void resettable_state_clear(ResettableState *state)
+{
+    memset(state, 0, sizeof(ResettableState));
+}
+
 /**
  * resettable_phase_enter/hold/exit:
  * Function executing a phase recursively in a resettable object and its