diff mbox series

[RFC,02/17] Create the ResetDomain QOM object

Message ID 60e1f016cfd490b733aa649bbdc8723cdd1fd6b1.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
ResetDomain is an object implementing the Resettable interface.
It is a container of several other Resettable and therefore allows to control
reset operation over a group of Resettable.

Addition and removal in a ResetDomain is done using the functions
*reset_domain_register_object* and *reset_domain_unregister_object*

Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
---
 hw/core/Makefile.objs     |   1 +
 hw/core/reset-domain.c    | 121 ++++++++++++++++++++++++++++++++++++++
 include/hw/reset-domain.h |  49 +++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 hw/core/reset-domain.c
 create mode 100644 include/hw/reset-domain.h
diff mbox series

Patch

diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index 97007454a8..320f71707c 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -2,6 +2,7 @@ 
 common-obj-y += qdev.o qdev-properties.o
 common-obj-y += bus.o reset.o
 common-obj-y += resettable.o
+common-obj-y += reset-domain.o
 common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
 common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
 # irq.o needed for qdev GPIO handling:
diff --git a/hw/core/reset-domain.c b/hw/core/reset-domain.c
new file mode 100644
index 0000000000..b701eb5bdd
--- /dev/null
+++ b/hw/core/reset-domain.c
@@ -0,0 +1,121 @@ 
+/*
+ * Reset Domain object.
+ *
+ * Copyright (c) 2019 GreenSocs
+ *
+ * Authors:
+ *   Damien Hedde
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "hw/reset-domain.h"
+
+void reset_domain_register_object(ResetDomain *domain, Object *obj)
+{
+    struct ResetDomainEntry *rde;
+
+    INTERFACE_CHECK(ResettableClass, obj, TYPE_RESETTABLE);
+
+    rde = g_malloc0(sizeof(*rde));
+    rde->obj = obj;
+    object_ref(obj);
+    QLIST_INSERT_HEAD(&domain->members, rde, node);
+}
+
+void reset_domain_unregister_object(ResetDomain *domain, Object *obj)
+{
+    struct ResetDomainEntry *rde;
+
+    INTERFACE_CHECK(ResettableClass, obj, TYPE_RESETTABLE);
+
+    QLIST_FOREACH(rde, &domain->members, node) {
+        if (rde->obj == obj) {
+            QLIST_REMOVE(rde, node);
+            object_unref(rde->obj);
+            g_free(rde);
+            return;
+        }
+    }
+}
+
+static void reset_domain_init_phase(Object *obj, bool cold)
+{
+    struct ResetDomainEntry *rde;
+    ResetDomain *domain = RESET_DOMAIN(obj);
+
+    QLIST_FOREACH(rde, &domain->members, node) {
+        resettable_init_phase(rde->obj, cold);
+    }
+}
+
+static void reset_domain_hold_phase(Object *obj)
+{
+    struct ResetDomainEntry *rde;
+    ResetDomain *domain = RESET_DOMAIN(obj);
+
+    QLIST_FOREACH(rde, &domain->members, node) {
+        resettable_hold_phase(rde->obj);
+    }
+}
+
+static void reset_domain_exit_phase(Object *obj)
+{
+    struct ResetDomainEntry *rde;
+    ResetDomain *domain = RESET_DOMAIN(obj);
+
+    QLIST_FOREACH(rde, &domain->members, node) {
+        resettable_exit_phase(rde->obj);
+    }
+}
+
+static void reset_domain_init(Object *obj)
+{
+    ResetDomain *domain = RESET_DOMAIN(obj);
+
+    QLIST_INIT(&domain->members);
+}
+
+static void reset_domain_finalize(Object *obj)
+{
+    ResetDomain *domain = RESET_DOMAIN(obj);
+    struct ResetDomainEntry *rde, *nrde;
+
+    QLIST_FOREACH_SAFE(rde, &domain->members, node, nrde) {
+        QLIST_REMOVE(rde, node);
+        object_unref(rde->obj);
+        g_free(rde);
+    }
+}
+
+static void reset_domain_class_init(ObjectClass *class, void *data)
+{
+    ResettableClass *rc = RESETTABLE_CLASS(class);
+
+    rc->phases.init = reset_domain_init_phase;
+    rc->phases.hold = reset_domain_hold_phase;
+    rc->phases.exit = reset_domain_exit_phase;
+}
+
+static const TypeInfo reset_domain_type_info = {
+    .name = TYPE_RESET_DOMAIN,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(ResetDomain),
+    .instance_init = reset_domain_init,
+    .instance_finalize = reset_domain_finalize,
+    .class_init = reset_domain_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_RESETTABLE },
+        { }
+    },
+};
+
+static void reset_register_types(void)
+{
+    type_register_static(&reset_domain_type_info);
+}
+
+type_init(reset_register_types)
diff --git a/include/hw/reset-domain.h b/include/hw/reset-domain.h
new file mode 100644
index 0000000000..03b3a981de
--- /dev/null
+++ b/include/hw/reset-domain.h
@@ -0,0 +1,49 @@ 
+#ifndef HW_RESET_DOMAIN_H
+#define HW_RESET_DOMAIN_H
+
+#include "resettable.h"
+#include "qemu/queue.h"
+
+#define TYPE_RESET_DOMAIN "reset-domain"
+
+#define RESET_DOMAIN(obj) OBJECT_CHECK(ResetDomain, (obj), TYPE_RESET_DOMAIN)
+
+/**
+ * ResetDomainClass:
+ * A ResetDomain holds several Resettable objects and implement the Resettable
+ * interface too.
+ * Doing a reset on it will also reset all objects it contained. Phases of
+ * every object will be executed in order: init_reset of all objects first, etc.
+ */
+typedef ObjectClass ResetDomainClass;
+
+/**
+ * ResetDomain:
+ * @members is a list of ResetDomainEntry. Every entry hold a pointer to a
+ * Resettable object.
+ * To avoid object to disapear while in the ResetDomain, the ResetDomain
+ * increases the refcount.
+ */
+struct ResetDomainEntry {
+    Object *obj;
+    QLIST_ENTRY(ResetDomainEntry) node;
+};
+typedef struct ResetDomain {
+    Object parent_obj;
+
+    QLIST_HEAD(, ResetDomainEntry) members;
+} ResetDomain;
+
+/**
+ * reset_domain_register_objet:
+ * Register the Resettable object @obj into a ResetDomain @domain.
+ */
+void reset_domain_register_object(ResetDomain *domain, Object *obj);
+
+/**
+ * reset_domain_unregister_objet:
+ * Unregister the Resettable object @obj into a ResetDomain @domain.
+ */
+void reset_domain_unregister_object(ResetDomain *domain, Object *obj);
+
+#endif