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.he...@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 --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 -- 2.21.0