diff mbox series

[RFC,09/17] global ResetDomain support for legacy reset handlers

Message ID 1229faf2e82151a54b915d167f2071af36aceb5f.1553510737.git.damien.hedde@greensocs.com
State New
Headers show
Series multi-phase reset mechanism | expand

Commit Message

Damien Hedde March 25, 2019, 11:01 a.m. UTC
INIT phase of the global ResetDomain now triggers the legacy reset
handlers.
*qemu_devices_reset* is now equivalent to do a cold reset of the global
ResetDomain.

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/reset.c | 109 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 95 insertions(+), 14 deletions(-)
diff mbox series

Patch

diff --git a/hw/core/reset.c b/hw/core/reset.c
index d013c9feb9..1b25f9c8f8 100644
--- a/hw/core/reset.c
+++ b/hw/core/reset.c
@@ -26,9 +26,31 @@ 
 
 #include "qemu/osdep.h"
 #include "qemu/queue.h"
+#include "qemu/module.h"
 #include "sysemu/reset.h"
 #include "hw/reset-domain.h"
 
+#define TYPE_SYSTEM_RESET_DOMAIN "system-reset-domain"
+#define SYSTEM_RESET_DOMAIN(obj) \
+    OBJECT_CHECK(SystemResetDomain, (obj), TYPE_SYSTEM_RESET_DOMAIN)
+#define SYSTEM_RESET_DOMAIN_CLASS(class) \
+    OBJECT_CLASS_CHECK(SystemResetDomainClass, (class), \
+                       TYPE_SYSTEM_RESET_DOMAIN)
+#define SYSTEM_RESET_DOMAIN_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(SystemResetDomainClass, (obj), \
+                     TYPE_SYSTEM_RESET_DOMAIN)
+
+/**
+ * SystemResetDomainClass:
+ * Class to hold the global reset domain and handlers
+ * @parent_init_phase hold parent init_phase method
+ */
+typedef struct SystemResetDomainClass {
+    ResetDomainClass parent_class;
+
+    ResettableInitPhase parent_init_phase;
+} SystemResetDomainClass;
+
 /* reset/shutdown handler */
 
 typedef struct QEMUResetEntry {
@@ -37,27 +59,35 @@  typedef struct QEMUResetEntry {
     void *opaque;
 } QEMUResetEntry;
 
-static QTAILQ_HEAD(, QEMUResetEntry) reset_handlers =
-    QTAILQ_HEAD_INITIALIZER(reset_handlers);
+/**
+ * SystemResetDomain:
+ * @reset_handlers list of legacy reset handlers
+ */
+typedef struct SystemResetDomain {
+    ResetDomain parent_obj;
+
+    QTAILQ_HEAD(, QEMUResetEntry) reset_handlers;
+} SystemResetDomain;
 
 /* global/system reset domain */
-static ResetDomain *reset_domain;
+static SystemResetDomain *reset_domain;
 
-static ResetDomain *get_reset_domain(void)
+static SystemResetDomain *get_reset_domain(void)
 {
     if (reset_domain == NULL) {
+        Object *obj = object_new(TYPE_SYSTEM_RESET_DOMAIN);
         /*
          * the ref to the object will be deleted by
          * qemu_delete_system_reset_domain function below.
          */
-        reset_domain = RESET_DOMAIN(object_new(TYPE_RESET_DOMAIN));
+        reset_domain = SYSTEM_RESET_DOMAIN(obj);
     }
     return reset_domain;
 }
 
 ResetDomain *qemu_get_system_reset_domain(void)
 {
-    return get_reset_domain();
+    return RESET_DOMAIN(get_reset_domain());
 }
 
 void qemu_delete_system_reset_domain(void)
@@ -71,34 +101,36 @@  void qemu_delete_system_reset_domain(void)
 
 void qemu_register_system_reset_domain_object(Object *obj)
 {
-    ResetDomain *domain = get_reset_domain();
+    ResetDomain *domain = RESET_DOMAIN(get_reset_domain());
 
     reset_domain_register_object(domain, obj);
 }
 
 void qemu_unregister_system_reset_domain_object(Object *obj)
 {
-    ResetDomain *domain = get_reset_domain();
+    ResetDomain *domain = RESET_DOMAIN(get_reset_domain());
 
     reset_domain_unregister_object(domain, obj);
 }
 
 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
 {
+    SystemResetDomain *domain = get_reset_domain();
     QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry));
 
     re->func = func;
     re->opaque = opaque;
-    QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
+    QTAILQ_INSERT_TAIL(&domain->reset_handlers, re, entry);
 }
 
 void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
 {
+    SystemResetDomain *domain = get_reset_domain();
     QEMUResetEntry *re;
 
-    QTAILQ_FOREACH(re, &reset_handlers, entry) {
+    QTAILQ_FOREACH(re, &domain->reset_handlers, entry) {
         if (re->func == func && re->opaque == opaque) {
-            QTAILQ_REMOVE(&reset_handlers, re, entry);
+            QTAILQ_REMOVE(&domain->reset_handlers, re, entry);
             g_free(re);
             return;
         }
@@ -112,15 +144,64 @@  void qemu_devices_reset(void)
 
 void qemu_system_reset_domain_reset(bool cold)
 {
-    ResetDomain *domain = get_reset_domain();
+    resettable_reset(OBJECT(get_reset_domain()), cold);
+}
+
+static void system_reset_domain_init_phase(Object *obj, bool cold)
+{
+    SystemResetDomain *domain = SYSTEM_RESET_DOMAIN(obj);
+    SystemResetDomainClass *srdc = SYSTEM_RESET_DOMAIN_GET_CLASS(obj);
     QEMUResetEntry *re, *nre;
 
     /* call function handlers first */
-    QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
+    QTAILQ_FOREACH_SAFE(re, &domain->reset_handlers, entry, nre) {
         re->func(re->opaque);
     }
 
     /* then handle the objects in the ResetDomain */
-    resettable_reset(OBJECT(domain), cold);
+    srdc->parent_init_phase(OBJECT(domain), cold);
+}
+
+static void system_reset_domain_init(Object *obj)
+{
+    SystemResetDomain *domain = SYSTEM_RESET_DOMAIN(obj);
+
+    QTAILQ_INIT(&domain->reset_handlers);
+}
+
+static void system_reset_domain_finalize(Object *obj)
+{
+    SystemResetDomain *domain = SYSTEM_RESET_DOMAIN(obj);
+    QEMUResetEntry *re, *nre;
+
+    QTAILQ_FOREACH_SAFE(re, &domain->reset_handlers, entry, nre) {
+        QTAILQ_REMOVE(&domain->reset_handlers, re, entry);
+        g_free(re);
+    }
+}
+
+static void system_reset_domain_class_init(ObjectClass *class, void *data)
+{
+    ResettableClass *rc = RESETTABLE_CLASS(class);
+    SystemResetDomainClass *srdc = SYSTEM_RESET_DOMAIN_CLASS(class);
+
+    srdc->parent_init_phase = rc->phases.init;
+    rc->phases.init = system_reset_domain_init_phase;
+}
+
+static const TypeInfo system_reset_domain_type_info = {
+    .name = TYPE_SYSTEM_RESET_DOMAIN,
+    .parent = TYPE_RESET_DOMAIN,
+    .instance_size = sizeof(SystemResetDomain),
+    .instance_init = system_reset_domain_init,
+    .instance_finalize = system_reset_domain_finalize,
+    .class_init = system_reset_domain_class_init,
+    .class_size = sizeof(SystemResetDomainClass),
+};
+
+static void system_reset_register_types(void)
+{
+    type_register_static(&system_reset_domain_type_info);
 }
 
+type_init(system_reset_register_types)