From e7cce67f27bce49d8b6d09f4e66059d1fd117ebb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 2 May 2012 13:30:54 +0200 Subject: [PATCH 01/22] qom: Add object_class_get_parent() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simple bit of functionality was missing and we'll need it soon, so add it. Signed-off-by: Paolo Bonzini Reviewed-by: Anthony Liguori [AF: Document possible NULL return value] Signed-off-by: Andreas Färber --- include/qemu/object.h | 8 ++++++++ qom/object.c | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/qemu/object.h b/include/qemu/object.h index d93b77293f..487559c5c0 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -547,6 +547,14 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *klass, ObjectClass *object_class_dynamic_cast(ObjectClass *klass, const char *typename); +/** + * object_class_get_parent: + * @klass: The class to obtain the parent for. + * + * Returns: The parent for @klass or %NULL if none. + */ +ObjectClass *object_class_get_parent(ObjectClass *klass); + /** * object_class_get_name: * @klass: The class to obtain the QOM typename for. diff --git a/qom/object.c b/qom/object.c index 6f839ad8c9..9582230879 100644 --- a/qom/object.c +++ b/qom/object.c @@ -545,6 +545,19 @@ ObjectClass *object_class_by_name(const char *typename) return type->class; } +ObjectClass *object_class_get_parent(ObjectClass *class) +{ + TypeImpl *type = type_get_parent(class->type); + + if (!type) { + return NULL; + } + + type_initialize(type); + + return type->class; +} + typedef struct OCFData { void (*fn)(ObjectClass *klass, void *opaque); From 5d9d3f4757897fe5c376e25e944c08f36c412907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 27 May 2012 00:32:40 +0200 Subject: [PATCH 02/22] qom: Introduce object_property_is_{child,link}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids hardcoding partial string comparisons. Signed-off-by: Alexander Barabash Signed-off-by: Andreas Färber Reviewed-by: Paolo Bonzini --- qom/object.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/qom/object.c b/qom/object.c index 9582230879..105c649e8d 100644 --- a/qom/object.c +++ b/qom/object.c @@ -296,6 +296,16 @@ void object_initialize(void *data, const char *typename) object_initialize_with_type(data, type); } +static inline bool object_property_is_child(ObjectProperty *prop) +{ + return strstart(prop->type, "child<", NULL); +} + +static inline bool object_property_is_link(ObjectProperty *prop) +{ + return strstart(prop->type, "link<", NULL); +} + static void object_property_del_all(Object *obj) { while (!QTAILQ_EMPTY(&obj->properties)) { @@ -318,7 +328,7 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp) ObjectProperty *prop; QTAILQ_FOREACH(prop, &obj->properties, node) { - if (strstart(prop->type, "child<", NULL) && prop->opaque == child) { + if (object_property_is_child(prop) && prop->opaque == child) { object_property_del(obj, prop->name, errp); break; } @@ -1008,7 +1018,7 @@ gchar *object_get_canonical_path(Object *obj) g_assert(obj->parent != NULL); QTAILQ_FOREACH(prop, &obj->parent->properties, node) { - if (!strstart(prop->type, "child<", NULL)) { + if (!object_property_is_child(prop)) { continue; } @@ -1042,9 +1052,9 @@ Object *object_resolve_path_component(Object *parent, gchar *part) return NULL; } - if (strstart(prop->type, "link<", NULL)) { + if (object_property_is_link(prop)) { return *(Object **)prop->opaque; - } else if (strstart(prop->type, "child<", NULL)) { + } else if (object_property_is_child(prop)) { return prop->opaque; } else { return NULL; @@ -1087,7 +1097,7 @@ static Object *object_resolve_partial_path(Object *parent, QTAILQ_FOREACH(prop, &parent->properties, node) { Object *found; - if (!strstart(prop->type, "child<", NULL)) { + if (!object_property_is_child(prop)) { continue; } From 32efc535b86626646442de7fe5793f3a47f4ce91 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 11 Apr 2012 23:30:20 +0200 Subject: [PATCH 03/22] qom: Add object_child_foreach() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A utility function that will be used to implement hierarchical realization. Signed-off-by: Paolo Bonzini Reviewed-by: Anthony Liguori [AF: Drop unrelated whitespace change, add Returns: in documentation] [AF: Use new object_property_is_child() helper.] Signed-off-by: Andreas Färber --- include/qemu/object.h | 14 ++++++++++++++ qom/object.c | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/qemu/object.h b/include/qemu/object.h index 487559c5c0..ce9e51f2ae 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -917,6 +917,20 @@ void object_property_add_str(Object *obj, const char *name, void (*set)(Object *, const char *, struct Error **), struct Error **errp); +/** + * object_child_foreach: + * @obj: the object whose children will be navigated + * @fn: the iterator function to be called + * @opaque: an opaque value that will be passed to the iterator + * + * Call @fn passing each child of @obj and @opaque to it, until @fn returns + * non-zero. + * + * Returns: The last value returned by @fn, or 0 if there is no child. + */ +int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), + void *opaque); + /** * container_get: * @root: root of the #path, e.g., object_get_root() diff --git a/qom/object.c b/qom/object.c index 105c649e8d..7a70d52e3a 100644 --- a/qom/object.c +++ b/qom/object.c @@ -607,6 +607,23 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data); } +int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), + void *opaque) +{ + ObjectProperty *prop; + int ret = 0; + + QTAILQ_FOREACH(prop, &obj->properties, node) { + if (object_property_is_child(prop)) { + ret = fn(prop->opaque, opaque); + if (ret != 0) { + break; + } + } + } + return ret; +} + static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) { GSList **list = opaque; From 3b50e311b48795707fed6d4f474711db87e341b9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 2 May 2012 13:30:55 +0200 Subject: [PATCH 04/22] qom: Add class_base_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The class_base_init TypeInfo callback was present in one of the early QOM versions but removed (on my request...) before committing. We will need it soon, add it. Signed-off-by: Paolo Bonzini Reviewed-by: Anthony Liguori Signed-off-by: Andreas Färber --- include/qemu/object.h | 10 ++++++++-- qom/object.c | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/qemu/object.h b/include/qemu/object.h index ce9e51f2ae..3c29c17bc0 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -291,10 +291,15 @@ struct Object * has occurred to allow a class to set its default virtual method pointers. * This is also the function to use to override virtual methods from a parent * class. + * @class_base_init: This function is called for all base classes after all + * parent class initialization has occurred, but before the class itself + * is initialized. This is the function to use to undo the effects of + * memcpy from the parent class to the descendents. * @class_finalize: This function is called during class destruction and is * meant to release and dynamic parameters allocated by @class_init. - * @class_data: Data to pass to the @class_init and @class_finalize functions. - * This can be useful when building dynamic classes. + * @class_data: Data to pass to the @class_init, @class_base_init and + * @class_finalize functions. This can be useful when building dynamic + * classes. * @interfaces: The list of interfaces associated with this type. This * should point to a static array that's terminated with a zero filled * element. @@ -312,6 +317,7 @@ struct TypeInfo size_t class_size; void (*class_init)(ObjectClass *klass, void *data); + void (*class_base_init)(ObjectClass *klass, void *data); void (*class_finalize)(ObjectClass *klass, void *data); void *class_data; diff --git a/qom/object.c b/qom/object.c index 7a70d52e3a..36379a1397 100644 --- a/qom/object.c +++ b/qom/object.c @@ -45,6 +45,7 @@ struct TypeImpl size_t instance_size; void (*class_init)(ObjectClass *klass, void *data); + void (*class_base_init)(ObjectClass *klass, void *data); void (*class_finalize)(ObjectClass *klass, void *data); void *class_data; @@ -112,6 +113,7 @@ TypeImpl *type_register(const TypeInfo *info) ti->instance_size = info->instance_size; ti->class_init = info->class_init; + ti->class_base_init = info->class_base_init; ti->class_finalize = info->class_finalize; ti->class_data = info->class_data; @@ -232,6 +234,13 @@ static void type_initialize(TypeImpl *ti) memcpy((void *)ti->class + sizeof(ObjectClass), (void *)parent->class + sizeof(ObjectClass), parent->class_size - sizeof(ObjectClass)); + + while (parent) { + if (parent->class_base_init) { + parent->class_base_init(ti->class, ti->class_data); + } + parent = type_get_parent(parent); + } } memset((void *)ti->class + class_size, 0, ti->class_size - class_size); From 745549c8d0273d3a3d9c3701534a34e70e2ea031 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 31 Mar 2012 16:45:54 +0200 Subject: [PATCH 05/22] qom: Make Object a type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right now the base Object class has a special NULL type. Change this so that we will be able to add class_init and class_base_init callbacks. To do this, remove some special casing of ObjectClass that is not really necessary. Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- include/qemu/object.h | 2 +- qom/object.c | 63 ++++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/include/qemu/object.h b/include/qemu/object.h index 3c29c17bc0..ff5444f487 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -33,7 +33,7 @@ typedef struct TypeInfo TypeInfo; typedef struct InterfaceClass InterfaceClass; typedef struct InterfaceInfo InterfaceInfo; -#define TYPE_OBJECT NULL +#define TYPE_OBJECT "object" /** * SECTION:object.h diff --git a/qom/object.c b/qom/object.c index 36379a1397..dac9de57c2 100644 --- a/qom/object.c +++ b/qom/object.c @@ -210,7 +210,7 @@ static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface) static void type_initialize(TypeImpl *ti) { - size_t class_size = sizeof(ObjectClass); + TypeImpl *parent; int i; if (ti->class) { @@ -221,29 +221,23 @@ static void type_initialize(TypeImpl *ti) ti->instance_size = type_object_get_size(ti); ti->class = g_malloc0(ti->class_size); - ti->class->type = ti; - - if (type_has_parent(ti)) { - TypeImpl *parent = type_get_parent(ti); + parent = type_get_parent(ti); + if (parent) { type_initialize(parent); - class_size = parent->class_size; g_assert(parent->class_size <= ti->class_size); - - memcpy((void *)ti->class + sizeof(ObjectClass), - (void *)parent->class + sizeof(ObjectClass), - parent->class_size - sizeof(ObjectClass)); - - while (parent) { - if (parent->class_base_init) { - parent->class_base_init(ti->class, ti->class_data); - } - parent = type_get_parent(parent); - } + memcpy(ti->class, parent->class, parent->class_size); } - memset((void *)ti->class + class_size, 0, ti->class_size - class_size); + ti->class->type = ti; + + while (parent) { + if (parent->class_base_init) { + parent->class_base_init(ti->class, ti->class_data); + } + parent = type_get_parent(parent); + } for (i = 0; i < ti->num_interfaces; i++) { type_class_interface_init(ti, &ti->interfaces[i]); @@ -477,19 +471,6 @@ Object *object_dynamic_cast(Object *obj, const char *typename) } -static void register_types(void) -{ - static TypeInfo interface_info = { - .name = TYPE_INTERFACE, - .instance_size = sizeof(Interface), - .abstract = true, - }; - - type_interface = type_register_static(&interface_info); -} - -type_init(register_types) - Object *object_dynamic_cast_assert(Object *obj, const char *typename) { Object *inst; @@ -1243,3 +1224,23 @@ void object_property_add_str(Object *obj, const char *name, property_release_str, prop, errp); } + +static void register_types(void) +{ + static TypeInfo interface_info = { + .name = TYPE_INTERFACE, + .instance_size = sizeof(Interface), + .abstract = true, + }; + + static TypeInfo object_info = { + .name = TYPE_OBJECT, + .instance_size = sizeof(Object), + .abstract = true, + }; + + type_interface = type_register_static(&interface_info); + type_register_static(&object_info); +} + +type_init(register_types) From 9c4b4cc436b3b05f5af79ba06c23acbe64319231 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 23 May 2012 18:58:15 +0200 Subject: [PATCH 06/22] qom: Drop type_register_static_alias() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's unused. Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- include/qemu/object.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/qemu/object.h b/include/qemu/object.h index ff5444f487..b16d99be8c 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -527,8 +527,6 @@ const char *object_get_typename(Object *obj); */ Type type_register_static(const TypeInfo *info); -#define type_register_static_alias(info, name) do { } while (0) - /** * type_register: * @info: The #TypeInfo of the new type From 049cb3cfdac182bbaab39a07936eb45fd1d83a4a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 4 Apr 2012 15:58:40 +0200 Subject: [PATCH 07/22] qom: Assert that public types have a non-NULL parent field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This protects against unwanted effects of changing TYPE_OBJECT from NULL to a string. Suggested-by: Andreas Färber Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- qom/object.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/qom/object.c b/qom/object.c index dac9de57c2..cec2d406b8 100644 --- a/qom/object.c +++ b/qom/object.c @@ -95,7 +95,7 @@ static TypeImpl *type_table_lookup(const char *name) return g_hash_table_lookup(type_table_get(), name); } -TypeImpl *type_register(const TypeInfo *info) +static TypeImpl *type_register_internal(const TypeInfo *info) { TypeImpl *ti = g_malloc0(sizeof(*ti)); @@ -137,6 +137,12 @@ TypeImpl *type_register(const TypeInfo *info) return ti; } +TypeImpl *type_register(const TypeInfo *info) +{ + assert(info->parent); + return type_register_internal(info); +} + TypeImpl *type_register_static(const TypeInfo *info) { return type_register(info); @@ -204,7 +210,7 @@ static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface) char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent); info.name = name; - iface->type = type_register(&info); + iface->type = type_register_internal(&info); g_free(name); } @@ -1239,8 +1245,8 @@ static void register_types(void) .abstract = true, }; - type_interface = type_register_static(&interface_info); - type_register_static(&object_info); + type_interface = type_register_internal(&interface_info); + type_register_internal(&object_info); } type_init(register_types) From 7bc3018b32a007f0a6cf6ee7e431cc6dfc6e7f84 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 23 May 2012 19:25:34 +0200 Subject: [PATCH 08/22] m48t59: Rename "type" property to "model" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This resolves a name conflict with the qdev "type" property that is about to move into Object. Signed-off-by: Paolo Bonzini [AF: Add braces missing in original code.] Signed-off-by: Andreas Färber --- hw/m48t59.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/hw/m48t59.c b/hw/m48t59.c index 0c50f450ad..dd6cb37ba6 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -65,7 +65,7 @@ struct M48t59State { /* NVRAM storage */ uint8_t *buffer; /* Model parameters */ - uint32_t type; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */ + uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */ /* NVRAM storage */ uint16_t addr; uint8_t lock; @@ -197,10 +197,11 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val) NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val); /* check for NVRAM access */ - if ((NVRAM->type == 2 && addr < 0x7f8) || - (NVRAM->type == 8 && addr < 0x1ff8) || - (NVRAM->type == 59 && addr < 0x1ff0)) + if ((NVRAM->model == 2 && addr < 0x7f8) || + (NVRAM->model == 8 && addr < 0x1ff8) || + (NVRAM->model == 59 && addr < 0x1ff0)) { goto do_write; + } /* TOD access */ switch (addr) { @@ -334,10 +335,11 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val) tmp = from_bcd(val); if (tmp >= 0 && tmp <= 99) { get_time(NVRAM, &tm); - if (NVRAM->type == 8) + if (NVRAM->model == 8) { tm.tm_year = from_bcd(val) + 68; // Base year is 1968 - else + } else { tm.tm_year = from_bcd(val); + } set_time(NVRAM, &tm); } break; @@ -362,10 +364,11 @@ uint32_t m48t59_read (void *opaque, uint32_t addr) uint32_t retval = 0xFF; /* check for NVRAM access */ - if ((NVRAM->type == 2 && addr < 0x078f) || - (NVRAM->type == 8 && addr < 0x1ff8) || - (NVRAM->type == 59 && addr < 0x1ff0)) + if ((NVRAM->model == 2 && addr < 0x078f) || + (NVRAM->model == 8 && addr < 0x1ff8) || + (NVRAM->model == 59 && addr < 0x1ff0)) { goto do_read; + } /* TOD access */ switch (addr) { @@ -439,10 +442,11 @@ uint32_t m48t59_read (void *opaque, uint32_t addr) case 0x07FF: /* year */ get_time(NVRAM, &tm); - if (NVRAM->type == 8) + if (NVRAM->model == 8) { retval = to_bcd(tm.tm_year - 68); // Base year is 1968 - else + } else { retval = to_bcd(tm.tm_year); + } break; default: /* Check lock registers state */ @@ -633,7 +637,7 @@ static const MemoryRegionOps m48t59_io_ops = { /* Initialisation routine */ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base, - uint32_t io_base, uint16_t size, int type) + uint32_t io_base, uint16_t size, int model) { DeviceState *dev; SysBusDevice *s; @@ -641,7 +645,7 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base, M48t59State *state; dev = qdev_create(NULL, "m48t59"); - qdev_prop_set_uint32(dev, "type", type); + qdev_prop_set_uint32(dev, "model", model); qdev_prop_set_uint32(dev, "size", size); qdev_prop_set_uint32(dev, "io_base", io_base); qdev_init_nofail(dev); @@ -661,14 +665,14 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base, } M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, - int type) + int model) { M48t59ISAState *d; ISADevice *dev; M48t59State *s; dev = isa_create(bus, "m48t59_isa"); - qdev_prop_set_uint32(&dev->qdev, "type", type); + qdev_prop_set_uint32(&dev->qdev, "model", model); qdev_prop_set_uint32(&dev->qdev, "size", size); qdev_prop_set_uint32(&dev->qdev, "io_base", io_base); qdev_init_nofail(&dev->qdev); @@ -686,7 +690,7 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, static void m48t59_init_common(M48t59State *s) { s->buffer = g_malloc0(s->size); - if (s->type == 59) { + if (s->model == 59) { s->alrm_timer = qemu_new_timer_ns(rtc_clock, &alarm_cb, s); s->wd_timer = qemu_new_timer_ns(vm_clock, &watchdog_cb, s); } @@ -722,7 +726,7 @@ static int m48t59_init1(SysBusDevice *dev) static Property m48t59_isa_properties[] = { DEFINE_PROP_UINT32("size", M48t59ISAState, state.size, -1), - DEFINE_PROP_UINT32("type", M48t59ISAState, state.type, -1), + DEFINE_PROP_UINT32("model", M48t59ISAState, state.model, -1), DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -746,7 +750,7 @@ static TypeInfo m48t59_isa_info = { static Property m48t59_properties[] = { DEFINE_PROP_UINT32("size", M48t59SysBusState, state.size, -1), - DEFINE_PROP_UINT32("type", M48t59SysBusState, state.type, -1), + DEFINE_PROP_UINT32("model", M48t59SysBusState, state.model, -1), DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base, 0), DEFINE_PROP_END_OF_LIST(), }; From edc92115a9300cca65946d5b2d56bec637a38f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Thu, 7 Jun 2012 16:32:53 +0200 Subject: [PATCH 09/22] arm_l2x0: Rename "type" property to "cache-type" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves a name conflict with the qdev "type" property that is about to be moved to Object. Signed-off-by: Andreas Färber Acked-by: Mark Langsdorf --- hw/arm_l2x0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/arm_l2x0.c b/hw/arm_l2x0.c index 09f290c85f..de6a0863d8 100644 --- a/hw/arm_l2x0.c +++ b/hw/arm_l2x0.c @@ -161,7 +161,7 @@ static int l2x0_priv_init(SysBusDevice *dev) } static Property l2x0_properties[] = { - DEFINE_PROP_UINT32("type", l2x0_state, cache_type, 0x1c100100), + DEFINE_PROP_UINT32("cache-type", l2x0_state, cache_type, 0x1c100100), DEFINE_PROP_END_OF_LIST(), }; From 2f262e06f01a38cb8a218b7c5ad71233883a6b55 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Apr 2012 17:33:51 +0200 Subject: [PATCH 10/22] qdev: Push "type" property up to Object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that Object is a type, add an instance_init function and push the "type" property from qdev to there. Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/qdev.c | 6 ------ qom/object.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 6a8f6bda2b..a9a9f891da 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -515,11 +515,6 @@ char* qdev_get_fw_dev_path(DeviceState *dev) return strdup(path); } -static char *qdev_get_type(Object *obj, Error **errp) -{ - return g_strdup(object_get_typename(obj)); -} - /** * Legacy property handling */ @@ -638,7 +633,6 @@ static void device_initfn(Object *obj) qdev_property_add_static(dev, prop, NULL); } - object_property_add_str(OBJECT(dev), "type", qdev_get_type, NULL, NULL); qdev_prop_set_defaults(dev, qdev_get_props(dev)); } diff --git a/qom/object.c b/qom/object.c index cec2d406b8..d5c6ff7471 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1231,6 +1231,16 @@ void object_property_add_str(Object *obj, const char *name, prop, errp); } +static char *qdev_get_type(Object *obj, Error **errp) +{ + return g_strdup(object_get_typename(obj)); +} + +static void object_instance_init(Object *obj) +{ + object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); +} + static void register_types(void) { static TypeInfo interface_info = { @@ -1242,6 +1252,7 @@ static void register_types(void) static TypeInfo object_info = { .name = TYPE_OBJECT, .instance_size = sizeof(Object), + .instance_init = object_instance_init, .abstract = true, }; From 3cb75a7cba7e808c0ae007e4d86750849642304e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Mar 2012 18:01:36 +0200 Subject: [PATCH 11/22] qdev: Move bus properties to a separate global MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simple code movement in order to simplify future refactoring. Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/i2c.c | 10 ++++++---- hw/ide/qdev.c | 10 ++++++---- hw/intel-hda.c | 10 ++++++---- hw/pci.c | 22 ++++++++++++---------- hw/scsi-bus.c | 14 ++++++++------ hw/spapr_vio.c | 10 ++++++---- hw/usb/bus.c | 15 +++++++++------ hw/usb/dev-smartcard-reader.c | 10 ++++++---- hw/virtio-serial-bus.c | 12 +++++++----- 9 files changed, 66 insertions(+), 47 deletions(-) diff --git a/hw/i2c.c b/hw/i2c.c index 23dfccba14..cb10b1dec6 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -17,13 +17,15 @@ struct i2c_bus uint8_t saved_address; }; +static Property i2c_props[] = { + DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static struct BusInfo i2c_bus_info = { .name = "I2C", .size = sizeof(i2c_bus), - .props = (Property[]) { - DEFINE_PROP_UINT8("address", struct I2CSlave, address, 0), - DEFINE_PROP_END_OF_LIST(), - } + .props = i2c_props, }; static void i2c_bus_pre_save(void *opaque) diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index a46578d685..b67df3d1e6 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -27,14 +27,16 @@ static char *idebus_get_fw_dev_path(DeviceState *dev); +static Property ide_props[] = { + DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), + DEFINE_PROP_END_OF_LIST(), +}; + static struct BusInfo ide_bus_info = { .name = "IDE", .size = sizeof(IDEBus), .get_fw_dev_path = idebus_get_fw_dev_path, - .props = (Property[]) { - DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), - DEFINE_PROP_END_OF_LIST(), - }, + .props = ide_props, }; void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index bb11af286a..0994f6b2a5 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -29,13 +29,15 @@ /* --------------------------------------------------------------------- */ /* hda bus */ +static Property hda_props[] = { + DEFINE_PROP_UINT32("cad", HDACodecDevice, cad, -1), + DEFINE_PROP_END_OF_LIST() +}; + static struct BusInfo hda_codec_bus_info = { .name = "HDA", .size = sizeof(HDACodecBus), - .props = (Property[]) { - DEFINE_PROP_UINT32("cad", HDACodecDevice, cad, -1), - DEFINE_PROP_END_OF_LIST() - } + .props = hda_props, }; void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, diff --git a/hw/pci.c b/hw/pci.c index 127b7aca73..377039ec99 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -44,6 +44,17 @@ static char *pcibus_get_dev_path(DeviceState *dev); static char *pcibus_get_fw_dev_path(DeviceState *dev); static int pcibus_reset(BusState *qbus); +static Property pci_props[] = { + DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), + DEFINE_PROP_STRING("romfile", PCIDevice, romfile), + DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), + DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, + QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), + DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present, + QEMU_PCI_CAP_SERR_BITNR, true), + DEFINE_PROP_END_OF_LIST() +}; + struct BusInfo pci_bus_info = { .name = "PCI", .size = sizeof(PCIBus), @@ -51,16 +62,7 @@ struct BusInfo pci_bus_info = { .get_dev_path = pcibus_get_dev_path, .get_fw_dev_path = pcibus_get_fw_dev_path, .reset = pcibus_reset, - .props = (Property[]) { - DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), - DEFINE_PROP_STRING("romfile", PCIDevice, romfile), - DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), - DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, - QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), - DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present, - QEMU_PCI_CAP_SERR_BITNR, true), - DEFINE_PROP_END_OF_LIST() - } + .props = pci_props, }; static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 4a798210ce..3423b6c834 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -12,17 +12,19 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev); static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf); static void scsi_req_dequeue(SCSIRequest *req); +static Property scsi_props[] = { + DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0), + DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1), + DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1), + DEFINE_PROP_END_OF_LIST(), +}; + static struct BusInfo scsi_bus_info = { .name = "SCSI", .size = sizeof(SCSIBus), .get_dev_path = scsibus_get_dev_path, .get_fw_dev_path = scsibus_get_fw_dev_path, - .props = (Property[]) { - DEFINE_PROP_UINT32("channel", SCSIDevice, channel, 0), - DEFINE_PROP_UINT32("scsi-id", SCSIDevice, id, -1), - DEFINE_PROP_UINT32("lun", SCSIDevice, lun, -1), - DEFINE_PROP_END_OF_LIST(), - }, + .props = scsi_props, }; static int next_scsi_bus; diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 315ab8091c..ab4362a230 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -49,13 +49,15 @@ do { } while (0) #endif +static Property spapr_vio_props[] = { + DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \ + DEFINE_PROP_END_OF_LIST(), +}; + static struct BusInfo spapr_vio_bus_info = { .name = "spapr-vio", .size = sizeof(VIOsPAPRBus), - .props = (Property[]) { - DEFINE_PROP_UINT32("irq", VIOsPAPRDevice, vio_irq_num, 0), \ - DEFINE_PROP_END_OF_LIST(), - }, + .props = spapr_vio_props, }; VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 2068640a58..3faf4cb2ee 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -11,19 +11,22 @@ static char *usb_get_dev_path(DeviceState *dev); static char *usb_get_fw_dev_path(DeviceState *qdev); static int usb_qdev_exit(DeviceState *qdev); +static Property usb_props[] = { + DEFINE_PROP_STRING("port", USBDevice, port_path), + DEFINE_PROP_BIT("full-path", USBDevice, flags, + USB_DEV_FLAG_FULL_PATH, true), + DEFINE_PROP_END_OF_LIST() +}; + static struct BusInfo usb_bus_info = { .name = "USB", .size = sizeof(USBBus), .print_dev = usb_bus_dev_print, .get_dev_path = usb_get_dev_path, .get_fw_dev_path = usb_get_fw_dev_path, - .props = (Property[]) { - DEFINE_PROP_STRING("port", USBDevice, port_path), - DEFINE_PROP_BIT("full-path", USBDevice, flags, - USB_DEV_FLAG_FULL_PATH, true), - DEFINE_PROP_END_OF_LIST() - }, + .props = usb_props, }; + static int next_usb_bus = 0; static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses); diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 3b7604e8b1..357b7e8a3e 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1055,13 +1055,15 @@ static Answer *ccid_peek_next_answer(USBCCIDState *s) : &s->pending_answers[s->pending_answers_start % PENDING_ANSWERS_NUM]; } +static Property ccid_props[] = { + DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static struct BusInfo ccid_bus_info = { .name = "ccid-bus", .size = sizeof(CCIDBus), - .props = (Property[]) { - DEFINE_PROP_UINT32("slot", struct CCIDCardState, slot, 0), - DEFINE_PROP_END_OF_LIST(), - } + .props = ccid_props, }; void ccid_card_send_apdu_to_guest(CCIDCardState *card, diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 72287d10ce..ccdbdb3add 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -728,15 +728,17 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); +static Property virtser_props[] = { + DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID), + DEFINE_PROP_STRING("name", VirtIOSerialPort, name), + DEFINE_PROP_END_OF_LIST() +}; + static struct BusInfo virtser_bus_info = { .name = "virtio-serial-bus", .size = sizeof(VirtIOSerialBus), .print_dev = virtser_bus_dev_print, - .props = (Property[]) { - DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID), - DEFINE_PROP_STRING("name", VirtIOSerialPort, name), - DEFINE_PROP_END_OF_LIST() - } + .props = virtser_props, }; static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) From bce544740a87cac1636f01c8a28502fec1694b3d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Mar 2012 18:12:47 +0200 Subject: [PATCH 12/22] qdev: Move bus properties to abstract superclasses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In qdev, each bus in practice identified an abstract superclass, but this was mostly hidden. In QOM, instead, these abstract classes are explicit so we can move bus properties there. All bus property walks are removed, and all device property walks are changed to look along the class hierarchy instead. We would have duplicates if class A defines some properties and its subclass B does not define any, because class_b->props will be left equal to class_a->props. The solution here is to reintroduce the class_base_init TypeInfo callback, that was present in one of the early QOM versions but removed (on my request...) before committing. This breaks global bus properties, an obscure feature when used with the command-line which is actually useful and used when used by backwards-compatible machine types. So this patch also adjusts the global bus properties in hw/pc_piix.c to refer to the abstract class. Globals and other properties must be modified in the same patch to avoid complications related to initialization ordering. Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/i2c.c | 2 +- hw/ide/qdev.c | 2 +- hw/intel-hda.c | 2 +- hw/pc_piix.c | 7 +++--- hw/pci.c | 2 +- hw/qdev-monitor.c | 41 ++++++++++++++---------------- hw/qdev-properties.c | 38 +++++++++++++++------------- hw/qdev.c | 47 ++++++++++++++++------------------- hw/qdev.h | 5 ---- hw/scsi-bus.c | 2 +- hw/spapr_vio.c | 2 +- hw/usb/bus.c | 2 +- hw/usb/dev-smartcard-reader.c | 2 +- hw/virtio-serial-bus.c | 2 +- 14 files changed, 73 insertions(+), 83 deletions(-) diff --git a/hw/i2c.c b/hw/i2c.c index cb10b1dec6..af5979e65d 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -25,7 +25,6 @@ static Property i2c_props[] = { static struct BusInfo i2c_bus_info = { .name = "I2C", .size = sizeof(i2c_bus), - .props = i2c_props, }; static void i2c_bus_pre_save(void *opaque) @@ -221,6 +220,7 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data) DeviceClass *k = DEVICE_CLASS(klass); k->init = i2c_slave_qdev_init; k->bus_info = &i2c_bus_info; + k->props = i2c_props; } static TypeInfo i2c_slave_type_info = { diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index b67df3d1e6..a91e878ca2 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -36,7 +36,6 @@ static struct BusInfo ide_bus_info = { .name = "IDE", .size = sizeof(IDEBus), .get_fw_dev_path = idebus_get_fw_dev_path, - .props = ide_props, }; void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id) @@ -251,6 +250,7 @@ static void ide_device_class_init(ObjectClass *klass, void *data) DeviceClass *k = DEVICE_CLASS(klass); k->init = ide_qdev_init; k->bus_info = &ide_bus_info; + k->props = ide_props; } static TypeInfo ide_device_type_info = { diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 0994f6b2a5..e2bd41eb66 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -37,7 +37,6 @@ static Property hda_props[] = { static struct BusInfo hda_codec_bus_info = { .name = "HDA", .size = sizeof(HDACodecBus), - .props = hda_props, }; void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, @@ -1278,6 +1277,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data) k->init = hda_codec_dev_init; k->exit = hda_codec_dev_exit; k->bus_info = &hda_codec_bus_info; + k->props = hda_props; } static TypeInfo hda_codec_device_type_info = { diff --git a/hw/pc_piix.c b/hw/pc_piix.c index f49b0aaf89..d68f77a9c0 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -29,6 +29,7 @@ #include "apic.h" #include "pci.h" #include "pci_ids.h" +#include "usb.h" #include "net.h" #include "boards.h" #include "ide.h" @@ -374,7 +375,7 @@ static QEMUMachine pc_machine_v1_1 = { .property = "vapic",\ .value = "off",\ },{\ - .driver = "USB",\ + .driver = TYPE_USB_DEVICE,\ .property = "full-path",\ .value = "no",\ } @@ -447,7 +448,7 @@ static QEMUMachine pc_machine_v0_14 = { #define PC_COMPAT_0_13 \ PC_COMPAT_0_14,\ {\ - .driver = "PCI",\ + .driver = TYPE_PCI_DEVICE,\ .property = "command_serr_enable",\ .value = "off",\ },{\ @@ -519,7 +520,7 @@ static QEMUMachine pc_machine_v0_12 = { .property = "vectors",\ .value = stringify(0),\ },{\ - .driver = "PCI",\ + .driver = TYPE_PCI_DEVICE,\ .property = "rombar",\ .value = stringify(0),\ } diff --git a/hw/pci.c b/hw/pci.c index 377039ec99..09ce4e7698 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -62,7 +62,6 @@ struct BusInfo pci_bus_info = { .get_dev_path = pcibus_get_dev_path, .get_fw_dev_path = pcibus_get_fw_dev_path, .reset = pcibus_reset, - .props = pci_props, }; static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); @@ -2003,6 +2002,7 @@ static void pci_device_class_init(ObjectClass *klass, void *data) k->unplug = pci_unplug_device; k->exit = pci_unregister_device; k->bus_info = &pci_bus_info; + k->props = pci_props; } static TypeInfo pci_device_type_info = { diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index b01ef0600e..b608eb443f 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -123,7 +123,6 @@ int qdev_device_help(QemuOpts *opts) const char *driver; Property *prop; ObjectClass *klass; - DeviceClass *info; driver = qemu_opt_get(opts, "driver"); if (driver && !strcmp(driver, "?")) { @@ -149,30 +148,22 @@ int qdev_device_help(QemuOpts *opts) if (!klass) { return 0; } - info = DEVICE_CLASS(klass); - - for (prop = info->props; prop && prop->name; prop++) { - /* - * TODO Properties without a parser are just for dirty hacks. - * qdev_prop_ptr is the only such PropertyInfo. It's marked - * for removal. This conditional should be removed along with - * it. - */ - if (!prop->info->set) { - continue; /* no way to set it, don't show */ - } - error_printf("%s.%s=%s\n", driver, prop->name, - prop->info->legacy_name ?: prop->info->name); - } - if (info->bus_info) { - for (prop = info->bus_info->props; prop && prop->name; prop++) { + do { + for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) { + /* + * TODO Properties without a parser are just for dirty hacks. + * qdev_prop_ptr is the only such PropertyInfo. It's marked + * for removal. This conditional should be removed along with + * it. + */ if (!prop->info->set) { continue; /* no way to set it, don't show */ } error_printf("%s.%s=%s\n", driver, prop->name, prop->info->legacy_name ?: prop->info->name); } - } + klass = object_class_get_parent(klass); + } while (klass != object_class_by_name(TYPE_DEVICE)); return 1; } @@ -482,7 +473,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) static void qbus_print(Monitor *mon, BusState *bus, int indent); static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, - const char *prefix, int indent) + int indent) { if (!props) return; @@ -501,7 +492,7 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, error_free(err); continue; } - qdev_printf("%s-prop: %s = %s\n", prefix, props->name, + qdev_printf("%s = %s\n", props->name, value && *value ? value : ""); g_free(value); } @@ -509,6 +500,7 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, static void qdev_print(Monitor *mon, DeviceState *dev, int indent) { + ObjectClass *class; BusState *child; qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)), dev->id ? dev->id : ""); @@ -519,8 +511,11 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) if (dev->num_gpio_out) { qdev_printf("gpio-out %d\n", dev->num_gpio_out); } - qdev_print_props(mon, dev, qdev_get_props(dev), "dev", indent); - qdev_print_props(mon, dev, dev->parent_bus->info->props, "bus", indent); + class = object_get_class(OBJECT(dev)); + do { + qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent); + class = object_class_get_parent(class); + } while (class != object_class_by_name(TYPE_DEVICE)); if (dev->parent_bus->info->print_dev) dev->parent_bus->info->print_dev(mon, dev, indent); QLIST_FOREACH(child, &dev->child_bus, sibling) { diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 9ae318717e..04e8326108 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -915,17 +915,18 @@ static Property *qdev_prop_walk(Property *props, const char *name) static Property *qdev_prop_find(DeviceState *dev, const char *name) { + ObjectClass *class; Property *prop; /* device properties */ - prop = qdev_prop_walk(qdev_get_props(dev), name); - if (prop) - return prop; - - /* bus properties */ - prop = qdev_prop_walk(dev->parent_bus->info->props, name); - if (prop) - return prop; + class = object_get_class(OBJECT(dev)); + do { + prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name); + if (prop) { + return prop; + } + class = object_class_get_parent(class); + } while (class != object_class_by_name(TYPE_DEVICE)); return NULL; } @@ -1145,17 +1146,20 @@ void qdev_prop_register_global_list(GlobalProperty *props) void qdev_prop_set_globals(DeviceState *dev) { - GlobalProperty *prop; + ObjectClass *class = object_get_class(OBJECT(dev)); - QTAILQ_FOREACH(prop, &global_props, next) { - if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 && - strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) { - continue; + do { + GlobalProperty *prop; + QTAILQ_FOREACH(prop, &global_props, next) { + if (strcmp(object_class_get_name(class), prop->driver) != 0) { + continue; + } + if (qdev_prop_parse(dev, prop->property, prop->value) != 0) { + exit(1); + } } - if (qdev_prop_parse(dev, prop->property, prop->value) != 0) { - exit(1); - } - } + class = object_class_get_parent(class); + } while (class); } static int qdev_add_one_global(QemuOpts *opts, void *opaque) diff --git a/hw/qdev.c b/hw/qdev.c index a9a9f891da..f239902291 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -45,18 +45,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev) return dc->vmsd; } -BusInfo *qdev_get_bus_info(DeviceState *dev) -{ - DeviceClass *dc = DEVICE_GET_CLASS(dev); - return dc->bus_info; -} - -Property *qdev_get_props(DeviceState *dev) -{ - DeviceClass *dc = DEVICE_GET_CLASS(dev); - return dc->props; -} - const char *qdev_fw_name(DeviceState *dev) { DeviceClass *dc = DEVICE_GET_CLASS(dev); @@ -78,20 +66,12 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop, void qdev_set_parent_bus(DeviceState *dev, BusState *bus) { - Property *prop; - if (qdev_hotplug) { assert(bus->allow_hotplug); } dev->parent_bus = bus; QTAILQ_INSERT_HEAD(&bus->children, dev, sibling); - - for (prop = qdev_get_bus_info(dev)->props; prop && prop->name; prop++) { - qdev_property_add_legacy(dev, prop, NULL); - qdev_property_add_static(dev, prop, NULL); - } - qdev_prop_set_defaults(dev, dev->parent_bus->info->props); } /* Create a new device. This only initializes the device state structure @@ -618,6 +598,7 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, static void device_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); + ObjectClass *class; Property *prop; if (qdev_hotplug) { @@ -628,12 +609,15 @@ static void device_initfn(Object *obj) dev->instance_id_alias = -1; dev->state = DEV_STATE_CREATED; - for (prop = qdev_get_props(dev); prop && prop->name; prop++) { - qdev_property_add_legacy(dev, prop, NULL); - qdev_property_add_static(dev, prop, NULL); - } - - qdev_prop_set_defaults(dev, qdev_get_props(dev)); + class = object_get_class(OBJECT(dev)); + do { + for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) { + qdev_property_add_legacy(dev, prop, NULL); + qdev_property_add_static(dev, prop, NULL); + } + qdev_prop_set_defaults(dev, DEVICE_CLASS(class)->props); + class = object_class_get_parent(class); + } while (class != object_class_by_name(TYPE_DEVICE)); } /* Unlink device from bus and free the structure. */ @@ -661,6 +645,16 @@ static void device_finalize(Object *obj) QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling); } +static void device_class_base_init(ObjectClass *class, void *data) +{ + DeviceClass *klass = DEVICE_CLASS(class); + + /* We explicitly look up properties in the superclasses, + * so do not propagate them to the subclasses. + */ + klass->props = NULL; +} + void device_reset(DeviceState *dev) { DeviceClass *klass = DEVICE_GET_CLASS(dev); @@ -687,6 +681,7 @@ static TypeInfo device_type_info = { .instance_size = sizeof(DeviceState), .instance_init = device_initfn, .instance_finalize = device_finalize, + .class_base_init = device_class_base_init, .abstract = true, .class_size = sizeof(DeviceClass), }; diff --git a/hw/qdev.h b/hw/qdev.h index 5386b165bc..5f62f80d35 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -96,7 +96,6 @@ struct BusInfo { bus_get_dev_path get_dev_path; bus_get_fw_dev_path get_fw_dev_path; qbus_resetfn *reset; - Property *props; }; struct BusState { @@ -347,10 +346,6 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev); const char *qdev_fw_name(DeviceState *dev); -BusInfo *qdev_get_bus_info(DeviceState *dev); - -Property *qdev_get_props(DeviceState *dev); - Object *qdev_get_machine(void); /* FIXME: make this a link<> */ diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 3423b6c834..a1d75b9cc7 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -24,7 +24,6 @@ static struct BusInfo scsi_bus_info = { .size = sizeof(SCSIBus), .get_dev_path = scsibus_get_dev_path, .get_fw_dev_path = scsibus_get_fw_dev_path, - .props = scsi_props, }; static int next_scsi_bus; @@ -1601,6 +1600,7 @@ static void scsi_device_class_init(ObjectClass *klass, void *data) k->init = scsi_qdev_init; k->unplug = qdev_simple_unplug_cb; k->exit = scsi_qdev_exit; + k->props = scsi_props; } static TypeInfo scsi_device_type_info = { diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index ab4362a230..cf849529dc 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -57,7 +57,6 @@ static Property spapr_vio_props[] = { static struct BusInfo spapr_vio_bus_info = { .name = "spapr-vio", .size = sizeof(VIOsPAPRBus), - .props = spapr_vio_props, }; VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) @@ -797,6 +796,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data) k->init = spapr_vio_busdev_init; k->reset = spapr_vio_busdev_reset; k->bus_info = &spapr_vio_bus_info; + k->props = spapr_vio_props; } static TypeInfo spapr_vio_type_info = { diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 3faf4cb2ee..64887d5ecb 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -24,7 +24,6 @@ static struct BusInfo usb_bus_info = { .print_dev = usb_bus_dev_print, .get_dev_path = usb_get_dev_path, .get_fw_dev_path = usb_get_fw_dev_path, - .props = usb_props, }; static int next_usb_bus = 0; @@ -583,6 +582,7 @@ static void usb_device_class_init(ObjectClass *klass, void *data) k->init = usb_qdev_init; k->unplug = qdev_simple_unplug_cb; k->exit = usb_qdev_exit; + k->props = usb_props; } static TypeInfo usb_device_type_info = { diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 357b7e8a3e..a4ab6e589a 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1063,7 +1063,6 @@ static Property ccid_props[] = { static struct BusInfo ccid_bus_info = { .name = "ccid-bus", .size = sizeof(CCIDBus), - .props = ccid_props, }; void ccid_card_send_apdu_to_guest(CCIDCardState *card, @@ -1347,6 +1346,7 @@ static void ccid_card_class_init(ObjectClass *klass, void *data) k->bus_info = &ccid_bus_info; k->init = ccid_card_init; k->exit = ccid_card_exit; + k->props = ccid_props; } static TypeInfo ccid_card_type_info = { diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index ccdbdb3add..d47d870594 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -738,7 +738,6 @@ static struct BusInfo virtser_bus_info = { .name = "virtio-serial-bus", .size = sizeof(VirtIOSerialBus), .print_dev = virtser_bus_dev_print, - .props = virtser_props, }; static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) @@ -985,6 +984,7 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data) k->bus_info = &virtser_bus_info; k->exit = virtser_port_qdev_exit; k->unplug = qdev_simple_unplug_cb; + k->props = virtser_props; } static TypeInfo virtio_serial_port_type_info = { From 4b3582b06b6105ac182a051e4f3647da2c99fd66 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 3 Apr 2012 10:05:07 +0200 Subject: [PATCH 13/22] qdev: Clean up global properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that global properties do not depend on buses anymore, set them directly in the device instance_init function. Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/qdev-monitor.c | 1 - hw/qdev.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index b608eb443f..390d467e89 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -440,7 +440,6 @@ DeviceState *qdev_device_add(QemuOpts *opts) /* create device, set properties */ qdev = DEVICE(object_new(driver)); qdev_set_parent_bus(qdev, bus); - qdev_prop_set_globals(qdev); id = qemu_opts_id(opts); if (id) { diff --git a/hw/qdev.c b/hw/qdev.c index f239902291..483f2e619d 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -111,7 +111,6 @@ DeviceState *qdev_try_create(BusState *bus, const char *type) } qdev_set_parent_bus(dev, bus); - qdev_prop_set_globals(dev); return dev; } @@ -618,6 +617,7 @@ static void device_initfn(Object *obj) qdev_prop_set_defaults(dev, DEVICE_CLASS(class)->props); class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); + qdev_prop_set_globals(dev); } /* Unlink device from bus and free the structure. */ From fdae245f56f97387bb33b2db03aa015f206c24b2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Apr 2012 22:40:26 +0200 Subject: [PATCH 14/22] qdev: Remove qdev_prop_set_defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead, qdev_property_add_static can set the default. Signed-off-by: Paolo Bonzini Reviewed-by: Anthony Liguori Signed-off-by: Andreas Färber --- hw/qdev-properties.c | 22 ---------------------- hw/qdev.c | 26 +++++++++++++++++++++++--- hw/qdev.h | 1 - 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index 04e8326108..f4b9a0e2c8 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -1106,28 +1106,6 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) *ptr = value; } -void qdev_prop_set_defaults(DeviceState *dev, Property *props) -{ - Object *obj = OBJECT(dev); - if (!props) - return; - for (; props->name; props++) { - Error *errp = NULL; - if (props->qtype == QTYPE_NONE) { - continue; - } - if (props->qtype == QTYPE_QBOOL) { - object_property_set_bool(obj, props->defval, props->name, &errp); - } else if (props->info->enum_table) { - object_property_set_str(obj, props->info->enum_table[props->defval], - props->name, &errp); - } else if (props->qtype == QTYPE_QINT) { - object_property_set_int(obj, props->defval, props->name, &errp); - } - assert_no_error(errp); - } -} - static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); static void qdev_prop_register_global(GlobalProperty *prop) diff --git a/hw/qdev.c b/hw/qdev.c index 483f2e619d..7f18590594 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -579,6 +579,9 @@ void qdev_property_add_legacy(DeviceState *dev, Property *prop, void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp) { + Error *local_err = NULL; + Object *obj = OBJECT(dev); + /* * TODO qdev_prop_ptr does not have getters or setters. It must * go now that it can be replaced with links. The test should be @@ -588,10 +591,28 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, return; } - object_property_add(OBJECT(dev), prop->name, prop->info->name, + object_property_add(obj, prop->name, prop->info->name, prop->info->get, prop->info->set, prop->info->release, - prop, errp); + prop, &local_err); + + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (prop->qtype == QTYPE_NONE) { + return; + } + + if (prop->qtype == QTYPE_QBOOL) { + object_property_set_bool(obj, prop->defval, prop->name, &local_err); + } else if (prop->info->enum_table) { + object_property_set_str(obj, prop->info->enum_table[prop->defval], + prop->name, &local_err); + } else if (prop->qtype == QTYPE_QINT) { + object_property_set_int(obj, prop->defval, prop->name, &local_err); + } + assert_no_error(local_err); } static void device_initfn(Object *obj) @@ -614,7 +635,6 @@ static void device_initfn(Object *obj) qdev_property_add_legacy(dev, prop, NULL); qdev_property_add_static(dev, prop, NULL); } - qdev_prop_set_defaults(dev, DEVICE_CLASS(class)->props); class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); qdev_prop_set_globals(dev); diff --git a/hw/qdev.h b/hw/qdev.h index 5f62f80d35..1af5382cad 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -309,7 +309,6 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value); void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); /* FIXME: Remove opaque pointer properties. */ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); -void qdev_prop_set_defaults(DeviceState *dev, Property *props); void qdev_prop_register_global_list(GlobalProperty *props); void qdev_prop_set_globals(DeviceState *dev); From 09e5ab6360ce78fc0acbfe29ac100f8148397ca6 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 3 Feb 2012 12:28:43 -0600 Subject: [PATCH 15/22] qdev: Use wrapper for qdev_get_path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier to remove it from BusInfo. Signed-off-by: Anthony Liguori Signed-off-by: Paolo Bonzini [AF: Drop now unnecessary NULL initialization in scsibus_get_dev_path()] Signed-off-by: Andreas Färber --- exec.c | 4 ++-- hw/qdev.c | 16 ++++++++++++++++ hw/qdev.h | 2 ++ hw/scsi-bus.c | 6 ++---- hw/usb/bus.c | 5 ++--- hw/usb/desc.c | 5 +++-- savevm.c | 12 ++++++------ 7 files changed, 33 insertions(+), 17 deletions(-) diff --git a/exec.c b/exec.c index 5c9b7627bf..b5d688567e 100644 --- a/exec.c +++ b/exec.c @@ -2603,8 +2603,8 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) assert(new_block); assert(!new_block->idstr[0]); - if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) { - char *id = dev->parent_bus->info->get_dev_path(dev); + if (dev) { + char *id = qdev_get_dev_path(dev); if (id) { snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id); g_free(id); diff --git a/hw/qdev.c b/hw/qdev.c index 7f18590594..7b2802dee0 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -494,6 +494,22 @@ char* qdev_get_fw_dev_path(DeviceState *dev) return strdup(path); } +char *qdev_get_dev_path(DeviceState *dev) +{ + BusInfo *businfo; + + if (!dev || !dev->parent_bus) { + return NULL; + } + + businfo = dev->parent_bus->info; + if (businfo->get_dev_path) { + return businfo->get_dev_path(dev); + } + + return NULL; +} + /** * Legacy property handling */ diff --git a/hw/qdev.h b/hw/qdev.h index 1af5382cad..013ccf2b7a 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -352,4 +352,6 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus); extern int qdev_hotplug; +char *qdev_get_dev_path(DeviceState *dev); + #endif diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index a1d75b9cc7..e79bb54a9d 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -1453,12 +1453,10 @@ static char *scsibus_get_dev_path(DeviceState *dev) { SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev); DeviceState *hba = dev->parent_bus->parent; - char *id = NULL; + char *id; char *path; - if (hba && hba->parent_bus && hba->parent_bus->info->get_dev_path) { - id = hba->parent_bus->info->get_dev_path(hba); - } + id = qdev_get_dev_path(hba); if (id) { path = g_strdup_printf("%s/%d:%d:%d", id, d->channel, d->id, d->lun); } else { diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 64887d5ecb..8b08f93389 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -467,9 +467,8 @@ static char *usb_get_dev_path(DeviceState *qdev) DeviceState *hcd = qdev->parent_bus->parent; char *id = NULL; - if ((dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) && - hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) { - id = hcd->parent_bus->info->get_dev_path(hcd); + if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) { + id = qdev_get_dev_path(hcd); } if (id) { char *ret = g_strdup_printf("%s/%s", id, dev->port->path); diff --git a/hw/usb/desc.c b/hw/usb/desc.c index e8a3c6af3d..0a9d3c9f60 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -432,12 +432,13 @@ void usb_desc_create_serial(USBDevice *dev) const USBDesc *desc = usb_device_get_usb_desc(dev); int index = desc->id.iSerialNumber; char serial[64]; + char *path; int dst; assert(index != 0 && desc->str[index] != NULL); dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]); - if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) { - char *path = hcd->parent_bus->info->get_dev_path(hcd); + path = qdev_get_dev_path(hcd); + if (path) { dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path); } dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path); diff --git a/savevm.c b/savevm.c index 2d18babd6e..818ddfc859 100644 --- a/savevm.c +++ b/savevm.c @@ -1248,8 +1248,8 @@ int register_savevm_live(DeviceState *dev, se->is_ram = 1; } - if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) { - char *id = dev->parent_bus->info->get_dev_path(dev); + if (dev) { + char *id = qdev_get_dev_path(dev); if (id) { pstrcpy(se->idstr, sizeof(se->idstr), id); pstrcat(se->idstr, sizeof(se->idstr), "/"); @@ -1292,8 +1292,8 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque) SaveStateEntry *se, *new_se; char id[256] = ""; - if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) { - char *path = dev->parent_bus->info->get_dev_path(dev); + if (dev) { + char *path = qdev_get_dev_path(dev); if (path) { pstrcpy(id, sizeof(id), path); pstrcat(id, sizeof(id), "/"); @@ -1334,8 +1334,8 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, se->alias_id = alias_id; se->no_migrate = vmsd->unmigratable; - if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) { - char *id = dev->parent_bus->info->get_dev_path(dev); + if (dev) { + char *id = qdev_get_dev_path(dev); if (id) { pstrcpy(se->idstr, sizeof(se->idstr), id); pstrcat(se->idstr, sizeof(se->idstr), "/"); From 8185d21639ab749979445734ec671122aa96e805 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 2 May 2012 12:06:55 +0200 Subject: [PATCH 16/22] qdev: Move SysBus initialization to sysbus.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TYPE_SYSTEM_BUS will be local to hw/sysbus.c, so move existing references to main_system_bus and system_bus_info there. Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/qdev.c | 26 ++------------------------ hw/sysbus.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 7b2802dee0..7816a3776a 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -34,10 +34,6 @@ int qdev_hotplug = 0; static bool qdev_hot_added = false; static bool qdev_hot_removed = false; -/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ -static BusState *main_system_bus; -static void main_system_bus_create(void); - /* Register a new device type. */ const VMStateDescription *qdev_get_vmsd(DeviceState *dev) { @@ -188,14 +184,6 @@ static int qdev_reset_one(DeviceState *dev, void *opaque) return 0; } -BusState *sysbus_get_default(void) -{ - if (!main_system_bus) { - main_system_bus_create(); - } - return main_system_bus; -} - static int qbus_reset_one(BusState *bus, void *opaque) { if (bus->info->reset) { @@ -415,7 +403,7 @@ void qbus_create_inplace(BusState *bus, BusInfo *info, if (parent) { QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling); parent->num_child_bus++; - } else if (bus != main_system_bus) { + } else if (bus != sysbus_get_default()) { /* TODO: once all bus devices are qdevified, only reset handler for main_system_bus should be registered here. */ qemu_register_reset(qbus_reset_all_fn, bus); @@ -432,16 +420,6 @@ BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name) return bus; } -static void main_system_bus_create(void) -{ - /* assign main_system_bus before qbus_create_inplace() - * in order to make "if (bus != main_system_bus)" work */ - main_system_bus = g_malloc0(system_bus_info.size); - main_system_bus->qdev_allocated = 1; - qbus_create_inplace(main_system_bus, &system_bus_info, NULL, - "main-system-bus"); -} - void qbus_free(BusState *bus) { DeviceState *dev; @@ -453,7 +431,7 @@ void qbus_free(BusState *bus) QLIST_REMOVE(bus, sibling); bus->parent->num_child_bus--; } else { - assert(bus != main_system_bus); /* main_system_bus is never freed */ + assert(bus != sysbus_get_default()); /* main_system_bus is never freed */ qemu_unregister_reset(qbus_reset_all_fn, bus); } g_free((void*)bus->name); diff --git a/hw/sysbus.c b/hw/sysbus.c index db4efccef4..fe5c4212ff 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -256,6 +256,27 @@ static TypeInfo sysbus_device_type_info = { .class_init = sysbus_device_class_init, }; +/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ +static BusState *main_system_bus; + +static void main_system_bus_create(void) +{ + /* assign main_system_bus before qbus_create_inplace() + * in order to make "if (bus != sysbus_get_default())" work */ + main_system_bus = g_malloc0(system_bus_info.size); + main_system_bus->qdev_allocated = 1; + qbus_create_inplace(main_system_bus, &system_bus_info, NULL, + "main-system-bus"); +} + +BusState *sysbus_get_default(void) +{ + if (!main_system_bus) { + main_system_bus_create(); + } + return main_system_bus; +} + static void sysbus_register_types(void) { type_register_static(&sysbus_device_type_info); From 0d936928ef87ca1bb7b41b5b89c400c699a7691c Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 2 May 2012 09:00:20 +0200 Subject: [PATCH 17/22] qdev: Convert busses to QEMU Object Model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is far less interesting than it sounds. We simply add an Object to each BusState and then register the types appropriately. Most of the interesting refactoring will follow in the next patches. Since we're changing fundamental type names (BusInfo -> BusClass), it all needs to convert at once. Fortunately, not a lot of code is affected. Signed-off-by: Anthony Liguori Signed-off-by: Paolo Bonzini [AF: Made all new bus TypeInfos static const.] [AF: Made qbus_free() call object_delete(), required {qom,glib}_allocated] Signed-off-by: Andreas Färber --- hw/i2c.c | 15 ++++--- hw/ide/internal.h | 3 ++ hw/ide/qdev.c | 21 +++++++--- hw/intel-hda.c | 12 +++--- hw/intel-hda.h | 3 ++ hw/isa-bus.c | 23 +++++++---- hw/isa.h | 3 ++ hw/pci-hotplug.c | 6 +-- hw/pci.c | 29 +++++++++----- hw/pci_bridge.c | 2 +- hw/pci_internals.h | 3 +- hw/qdev-monitor.c | 33 ++++++++++------ hw/qdev.c | 73 +++++++++++++++++++++++++---------- hw/qdev.h | 46 ++++++++++++---------- hw/s390-virtio-bus.c | 12 +++--- hw/s390-virtio-bus.h | 4 ++ hw/scsi-bus.c | 23 +++++++---- hw/scsi.h | 3 ++ hw/spapr_vio.c | 12 +++--- hw/spapr_vio.h | 3 ++ hw/ssi.c | 15 ++++--- hw/sysbus.c | 27 ++++++++----- hw/sysbus.h | 3 ++ hw/usb.h | 3 ++ hw/usb/bus.c | 25 ++++++++---- hw/usb/dev-smartcard-reader.c | 15 ++++--- hw/virtio-serial-bus.c | 24 +++++++++--- 27 files changed, 299 insertions(+), 142 deletions(-) diff --git a/hw/i2c.c b/hw/i2c.c index af5979e65d..319b249da3 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -22,9 +22,13 @@ static Property i2c_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo i2c_bus_info = { - .name = "I2C", - .size = sizeof(i2c_bus), +#define TYPE_I2C_BUS "i2c-bus" +#define I2C_BUS(obj) OBJECT_CHECK(i2c_bus, (obj), TYPE_I2C_BUS) + +static const TypeInfo i2c_bus_info = { + .name = TYPE_I2C_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(i2c_bus), }; static void i2c_bus_pre_save(void *opaque) @@ -62,7 +66,7 @@ i2c_bus *i2c_init_bus(DeviceState *parent, const char *name) { i2c_bus *bus; - bus = FROM_QBUS(i2c_bus, qbus_create(&i2c_bus_info, parent, name)); + bus = FROM_QBUS(i2c_bus, qbus_create(TYPE_I2C_BUS, parent, name)); vmstate_register(NULL, -1, &vmstate_i2c_bus, bus); return bus; } @@ -219,7 +223,7 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = i2c_slave_qdev_init; - k->bus_info = &i2c_bus_info; + k->bus_type = TYPE_I2C_BUS; k->props = i2c_props; } @@ -234,6 +238,7 @@ static TypeInfo i2c_slave_type_info = { static void i2c_slave_register_types(void) { + type_register_static(&i2c_bus_info); type_register_static(&i2c_slave_type_info); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index f8a027d0e4..1a02f57bf5 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -25,6 +25,9 @@ typedef struct IDEState IDEState; typedef struct IDEDMA IDEDMA; typedef struct IDEDMAOps IDEDMAOps; +#define TYPE_IDE_BUS "IDE" +#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) + /* Bits of HD_STATUS */ #define ERR_STAT 0x01 #define INDEX_STAT 0x02 diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index a91e878ca2..c122395401 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -32,15 +32,23 @@ static Property ide_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo ide_bus_info = { - .name = "IDE", - .size = sizeof(IDEBus), - .get_fw_dev_path = idebus_get_fw_dev_path, +static void ide_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->get_fw_dev_path = idebus_get_fw_dev_path; +} + +static const TypeInfo ide_bus_info = { + .name = TYPE_IDE_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(IDEBus), + .class_init = ide_bus_class_init, }; void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id) { - qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, NULL); + qbus_create_inplace(&idebus->qbus, TYPE_IDE_BUS, dev, NULL); idebus->bus_id = bus_id; } @@ -249,7 +257,7 @@ static void ide_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = ide_qdev_init; - k->bus_info = &ide_bus_info; + k->bus_type = TYPE_IDE_BUS; k->props = ide_props; } @@ -264,6 +272,7 @@ static TypeInfo ide_device_type_info = { static void ide_register_types(void) { + type_register_static(&ide_bus_info); type_register_static(&ide_hd_info); type_register_static(&ide_cd_info); type_register_static(&ide_drive_info); diff --git a/hw/intel-hda.c b/hw/intel-hda.c index e2bd41eb66..e343096534 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -34,16 +34,17 @@ static Property hda_props[] = { DEFINE_PROP_END_OF_LIST() }; -static struct BusInfo hda_codec_bus_info = { - .name = "HDA", - .size = sizeof(HDACodecBus), +static const TypeInfo hda_codec_bus_info = { + .name = TYPE_HDA_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(HDACodecBus), }; void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, hda_codec_response_func response, hda_codec_xfer_func xfer) { - qbus_create_inplace(&bus->qbus, &hda_codec_bus_info, dev, NULL); + qbus_create_inplace(&bus->qbus, TYPE_HDA_BUS, dev, NULL); bus->response = response; bus->xfer = xfer; } @@ -1276,7 +1277,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data) DeviceClass *k = DEVICE_CLASS(klass); k->init = hda_codec_dev_init; k->exit = hda_codec_dev_exit; - k->bus_info = &hda_codec_bus_info; + k->bus_type = TYPE_HDA_BUS; k->props = hda_props; } @@ -1291,6 +1292,7 @@ static TypeInfo hda_codec_device_type_info = { static void intel_hda_register_types(void) { + type_register_static(&hda_codec_bus_info); type_register_static(&intel_hda_info); type_register_static(&hda_codec_device_type_info); } diff --git a/hw/intel-hda.h b/hw/intel-hda.h index a1cca5b1bb..22e0968d50 100644 --- a/hw/intel-hda.h +++ b/hw/intel-hda.h @@ -14,6 +14,9 @@ #define HDA_CODEC_DEVICE_GET_CLASS(obj) \ OBJECT_GET_CLASS(HDACodecDeviceClass, (obj), TYPE_HDA_CODEC_DEVICE) +#define TYPE_HDA_BUS "HDA" +#define HDA_BUS(obj) OBJECT_CHECK(HDACodecBus, (obj), TYPE_HDA_BUS) + typedef struct HDACodecBus HDACodecBus; typedef struct HDACodecDevice HDACodecDevice; diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 5a43f03a7c..f9b237387a 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -28,11 +28,19 @@ target_phys_addr_t isa_mem_base = 0; static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent); static char *isabus_get_fw_dev_path(DeviceState *dev); -static struct BusInfo isa_bus_info = { - .name = "ISA", - .size = sizeof(ISABus), - .print_dev = isabus_dev_print, - .get_fw_dev_path = isabus_get_fw_dev_path, +static void isa_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->print_dev = isabus_dev_print; + k->get_fw_dev_path = isabus_get_fw_dev_path; +} + +static const TypeInfo isa_bus_info = { + .name = TYPE_ISA_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(ISABus), + .class_init = isa_bus_class_init, }; ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io) @@ -46,7 +54,7 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io) qdev_init_nofail(dev); } - isabus = FROM_QBUS(ISABus, qbus_create(&isa_bus_info, dev, NULL)); + isabus = FROM_QBUS(ISABus, qbus_create(TYPE_ISA_BUS, dev, NULL)); isabus->address_space_io = address_space_io; return isabus; } @@ -198,7 +206,7 @@ static void isa_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = isa_qdev_init; - k->bus_info = &isa_bus_info; + k->bus_type = TYPE_ISA_BUS; } static TypeInfo isa_device_type_info = { @@ -212,6 +220,7 @@ static TypeInfo isa_device_type_info = { static void isabus_register_types(void) { + type_register_static(&isa_bus_info); type_register_static(&isabus_bridge_info); type_register_static(&isa_device_type_info); } diff --git a/hw/isa.h b/hw/isa.h index f7bc4b5a95..f7ddf23628 100644 --- a/hw/isa.h +++ b/hw/isa.h @@ -19,6 +19,9 @@ typedef struct ISADevice ISADevice; #define ISA_DEVICE_GET_CLASS(obj) \ OBJECT_GET_CLASS(ISADeviceClass, (obj), TYPE_ISA_DEVICE) +#define TYPE_ISA_BUS "ISA" +#define ISA_BUS(obj) OBJECT_CHECK(ISABus, (obj), TYPE_ISA_BUS) + typedef struct ISADeviceClass { DeviceClass parent_class; int (*init)(ISADevice *dev); diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index 61257f457b..e7fb780a08 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -80,11 +80,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, SCSIBus *scsibus; SCSIDevice *scsidev; - scsibus = DO_UPCAST(SCSIBus, qbus, QLIST_FIRST(&adapter->child_bus)); - if (!scsibus || strcmp(scsibus->qbus.info->name, "SCSI") != 0) { - error_report("Device is not a SCSI adapter"); - return -1; - } + scsibus = SCSI_BUS(QLIST_FIRST(&adapter->child_bus)); /* * drive_init() tries to find a default for dinfo->unit. Doesn't diff --git a/hw/pci.c b/hw/pci.c index 09ce4e7698..d6ce9a54fa 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -55,13 +55,21 @@ static Property pci_props[] = { DEFINE_PROP_END_OF_LIST() }; -struct BusInfo pci_bus_info = { - .name = "PCI", - .size = sizeof(PCIBus), - .print_dev = pcibus_dev_print, - .get_dev_path = pcibus_get_dev_path, - .get_fw_dev_path = pcibus_get_fw_dev_path, - .reset = pcibus_reset, +static void pci_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->print_dev = pcibus_dev_print; + k->get_dev_path = pcibus_get_dev_path; + k->get_fw_dev_path = pcibus_get_fw_dev_path; + k->reset = pcibus_reset; +} + +static const TypeInfo pci_bus_info = { + .name = TYPE_PCI_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(PCIBus), + .class_init = pci_bus_class_init, }; static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); @@ -266,7 +274,7 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, MemoryRegion *address_space_io, uint8_t devfn_min) { - qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name); + qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name); assert(PCI_FUNC(devfn_min) == 0); bus->devfn_min = devfn_min; bus->address_space_mem = address_space_mem; @@ -287,7 +295,7 @@ PCIBus *pci_bus_new(DeviceState *parent, const char *name, PCIBus *bus; bus = g_malloc0(sizeof(*bus)); - bus->qbus.qdev_allocated = 1; + bus->qbus.glib_allocated = true; pci_bus_new_inplace(bus, parent, name, address_space_mem, address_space_io, devfn_min); return bus; @@ -2001,7 +2009,7 @@ static void pci_device_class_init(ObjectClass *klass, void *data) k->init = pci_qdev_init; k->unplug = pci_unplug_device; k->exit = pci_unregister_device; - k->bus_info = &pci_bus_info; + k->bus_type = TYPE_PCI_BUS; k->props = pci_props; } @@ -2016,6 +2024,7 @@ static TypeInfo pci_device_type_info = { static void pci_register_types(void) { + type_register_static(&pci_bus_info); type_register_static(&pci_device_type_info); } diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c index 866f0b6c52..253e034981 100644 --- a/hw/pci_bridge.c +++ b/hw/pci_bridge.c @@ -324,7 +324,7 @@ int pci_bridge_initfn(PCIDevice *dev) br->bus_name = dev->qdev.id; } - qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev, + qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev, br->bus_name); sec_bus->parent_dev = dev; sec_bus->map_irq = br->map_irq; diff --git a/hw/pci_internals.h b/hw/pci_internals.h index 96690b72d3..399c6d475c 100644 --- a/hw/pci_internals.h +++ b/hw/pci_internals.h @@ -12,7 +12,8 @@ * Use accessor function in pci.h, pci_bridge.h */ -extern struct BusInfo pci_bus_info; +#define TYPE_PCI_BUS "PCI" +#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS) struct PCIBus { BusState qbus; diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 390d467e89..691b864c54 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -75,8 +75,8 @@ static void qdev_print_devinfo(ObjectClass *klass, void *opaque) } error_printf("name \"%s\"", object_class_get_name(klass)); - if (dc->bus_info) { - error_printf(", bus %s", dc->bus_info->name); + if (dc->bus_type) { + error_printf(", bus %s", dc->bus_type); } if (qdev_class_has_alias(dc)) { error_printf(", alias \"%s\"", qdev_class_get_alias(dc)); @@ -262,7 +262,7 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem) } static BusState *qbus_find_recursive(BusState *bus, const char *name, - const BusInfo *info) + const char *bus_typename) { DeviceState *dev; BusState *child, *ret; @@ -271,7 +271,8 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, if (name && (strcmp(bus->name, name) != 0)) { match = 0; } - if (info && (bus->info != info)) { + if (bus_typename && + (strcmp(object_get_typename(OBJECT(bus)), bus_typename) != 0)) { match = 0; } if (match) { @@ -280,7 +281,7 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, QTAILQ_FOREACH(dev, &bus->children, sibling) { QLIST_FOREACH(child, &dev->child_bus, sibling) { - ret = qbus_find_recursive(child, name, info); + ret = qbus_find_recursive(child, name, bus_typename); if (ret) { return ret; } @@ -415,16 +416,16 @@ DeviceState *qdev_device_add(QemuOpts *opts) if (!bus) { return NULL; } - if (bus->info != k->bus_info) { + if (strcmp(object_get_typename(OBJECT(bus)), k->bus_type) != 0) { qerror_report(QERR_BAD_BUS_FOR_DEVICE, - driver, bus->info->name); + driver, object_get_typename(OBJECT(bus))); return NULL; } } else { - bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_info); + bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type); if (!bus) { qerror_report(QERR_NO_BUS_FOR_DEVICE, - driver, k->bus_info->name); + driver, k->bus_type); return NULL; } } @@ -497,6 +498,15 @@ static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props, } } +static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent) +{ + BusClass *bc = BUS_GET_CLASS(bus); + + if (bc->print_dev) { + bc->print_dev(mon, dev, indent); + } +} + static void qdev_print(Monitor *mon, DeviceState *dev, int indent) { ObjectClass *class; @@ -515,8 +525,7 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent); class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); - if (dev->parent_bus->info->print_dev) - dev->parent_bus->info->print_dev(mon, dev, indent); + bus_print_dev(dev->parent_bus, mon, dev, indent + 2); QLIST_FOREACH(child, &dev->child_bus, sibling) { qbus_print(mon, child, indent); } @@ -528,7 +537,7 @@ static void qbus_print(Monitor *mon, BusState *bus, int indent) qdev_printf("bus: %s\n", bus->name); indent += 2; - qdev_printf("type %s\n", bus->info->name); + qdev_printf("type %s\n", object_get_typename(OBJECT(bus))); QTAILQ_FOREACH(dev, &bus->children, sibling) { qdev_print(mon, dev, indent); } diff --git a/hw/qdev.c b/hw/qdev.c index 7816a3776a..63012b5252 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -81,7 +81,7 @@ DeviceState *qdev_create(BusState *bus, const char *name) if (!dev) { if (bus) { hw_error("Unknown device '%s' for bus '%s'\n", name, - bus->info->name); + object_get_typename(OBJECT(bus))); } else { hw_error("Unknown device '%s' for default sysbus\n", name); } @@ -186,8 +186,9 @@ static int qdev_reset_one(DeviceState *dev, void *opaque) static int qbus_reset_one(BusState *bus, void *opaque) { - if (bus->info->reset) { - return bus->info->reset(bus); + BusClass *bc = BUS_GET_CLASS(bus); + if (bc->reset) { + return bc->reset(bus); } return 0; } @@ -370,13 +371,13 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id) return NULL; } -void qbus_create_inplace(BusState *bus, BusInfo *info, - DeviceState *parent, const char *name) +/* FIXME move this logic into instance_init */ +static void do_qbus_create_inplace(BusState *bus, const char *typename, + DeviceState *parent, const char *name) { char *buf; int i,len; - bus->info = info; bus->parent = parent; if (name) { @@ -390,9 +391,9 @@ void qbus_create_inplace(BusState *bus, BusInfo *info, bus->name = buf; } else { /* no id -> use lowercase bus type for bus name */ - len = strlen(info->name) + 16; + len = strlen(typename) + 16; buf = g_malloc(len); - len = snprintf(buf, len, "%s.%d", info->name, + len = snprintf(buf, len, "%s.%d", typename, parent ? parent->num_child_bus : 0); for (i = 0; i < len; i++) buf[i] = qemu_tolower(buf[i]); @@ -410,13 +411,20 @@ void qbus_create_inplace(BusState *bus, BusInfo *info, } } -BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name) +void qbus_create_inplace(BusState *bus, const char *typename, + DeviceState *parent, const char *name) +{ + object_initialize(bus, typename); + do_qbus_create_inplace(bus, typename, parent, name); +} + +BusState *qbus_create(const char *typename, DeviceState *parent, const char *name) { BusState *bus; - bus = g_malloc0(info->size); - bus->qdev_allocated = 1; - qbus_create_inplace(bus, info, parent, name); + bus = BUS(object_new(typename)); + bus->qom_allocated = true; + do_qbus_create_inplace(bus, typename, parent, name); return bus; } @@ -435,11 +443,27 @@ void qbus_free(BusState *bus) qemu_unregister_reset(qbus_reset_all_fn, bus); } g_free((void*)bus->name); - if (bus->qdev_allocated) { - g_free(bus); + if (bus->qom_allocated) { + object_delete(OBJECT(bus)); + } else { + object_finalize(OBJECT(bus)); + if (bus->glib_allocated) { + g_free(bus); + } } } +static char *bus_get_fw_dev_path(BusState *bus, DeviceState *dev) +{ + BusClass *bc = BUS_GET_CLASS(bus); + + if (bc->get_fw_dev_path) { + return bc->get_fw_dev_path(dev); + } + + return NULL; +} + static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size) { int l = 0; @@ -447,8 +471,8 @@ static int qdev_get_fw_dev_path_helper(DeviceState *dev, char *p, int size) if (dev && dev->parent_bus) { char *d; l = qdev_get_fw_dev_path_helper(dev->parent_bus->parent, p, size); - if (dev->parent_bus->info->get_fw_dev_path) { - d = dev->parent_bus->info->get_fw_dev_path(dev); + d = bus_get_fw_dev_path(dev->parent_bus, dev); + if (d) { l += snprintf(p + l, size - l, "%s", d); g_free(d); } else { @@ -474,15 +498,15 @@ char* qdev_get_fw_dev_path(DeviceState *dev) char *qdev_get_dev_path(DeviceState *dev) { - BusInfo *businfo; + BusClass *bc; if (!dev || !dev->parent_bus) { return NULL; } - businfo = dev->parent_bus->info; - if (businfo->get_dev_path) { - return businfo->get_dev_path(dev); + bc = BUS_GET_CLASS(dev->parent_bus); + if (bc->get_dev_path) { + return bc->get_dev_path(dev); } return NULL; @@ -700,8 +724,17 @@ static TypeInfo device_type_info = { .class_size = sizeof(DeviceClass), }; +static const TypeInfo bus_info = { + .name = TYPE_BUS, + .parent = TYPE_OBJECT, + .instance_size = sizeof(BusState), + .abstract = true, + .class_size = sizeof(BusClass), +}; + static void qdev_register_types(void) { + type_register_static(&bus_info); type_register_static(&device_type_info); } diff --git a/hw/qdev.h b/hw/qdev.h index 013ccf2b7a..736271ecef 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -17,7 +17,7 @@ typedef struct CompatProperty CompatProperty; typedef struct BusState BusState; -typedef struct BusInfo BusInfo; +typedef struct BusClass BusClass; enum DevState { DEV_STATE_CREATED = 1, @@ -55,7 +55,7 @@ typedef struct DeviceClass { qdev_initfn init; qdev_event unplug; qdev_event exit; - BusInfo *bus_info; + const char *bus_type; } DeviceClass; /* This structure should not be accessed directly. We declare it here @@ -79,31 +79,40 @@ struct DeviceState { int alias_required_for_version; }; -typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent); -typedef char *(*bus_get_dev_path)(DeviceState *dev); /* * This callback is used to create Open Firmware device path in accordance with * OF spec http://forthworks.com/standards/of1275.pdf. Indicidual bus bindings * can be found here http://playground.sun.com/1275/bindings/. */ -typedef char *(*bus_get_fw_dev_path)(DeviceState *dev); -typedef int (qbus_resetfn)(BusState *bus); -struct BusInfo { - const char *name; - size_t size; - bus_dev_printfn print_dev; - bus_get_dev_path get_dev_path; - bus_get_fw_dev_path get_fw_dev_path; - qbus_resetfn *reset; +#define TYPE_BUS "bus" +#define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) +#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) +#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS) + +struct BusClass { + ObjectClass parent_class; + + /* FIXME first arg should be BusState */ + void (*print_dev)(Monitor *mon, DeviceState *dev, int indent); + char *(*get_dev_path)(DeviceState *dev); + char *(*get_fw_dev_path)(DeviceState *dev); + int (*reset)(BusState *bus); }; +/** + * BusState: + * @qom_allocated: Indicates whether the object was allocated by QOM. + * @glib_allocated: Indicates whether the object was initialized in-place + * yet is expected to be freed with g_free(). + */ struct BusState { + Object obj; DeviceState *parent; - BusInfo *info; const char *name; int allow_hotplug; - int qdev_allocated; + bool qom_allocated; + bool glib_allocated; QTAILQ_HEAD(ChildrenHead, DeviceState) children; QLIST_ENTRY(BusState) sibling; }; @@ -174,9 +183,9 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id); typedef int (qbus_walkerfn)(BusState *bus, void *opaque); typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque); -void qbus_create_inplace(BusState *bus, BusInfo *info, +void qbus_create_inplace(BusState *bus, const char *typename, DeviceState *parent, const char *name); -BusState *qbus_create(BusInfo *info, DeviceState *parent, const char *name); +BusState *qbus_create(const char *typename, DeviceState *parent, const char *name); /* Returns > 0 if either devfn or busfn skip walk somewhere in cursion, * < 0 if either devfn or busfn terminate walk somewhere in cursion, * 0 otherwise. */ @@ -317,9 +326,6 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, char *qdev_get_fw_dev_path(DeviceState *dev); -/* This is a nasty hack to allow passing a NULL bus to qdev_create. */ -extern struct BusInfo system_bus_info; - /** * @qdev_property_add_static - add a @Property to a device referencing a * field in a struct. diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 23ef35b3bb..2aec756da1 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -45,9 +45,10 @@ #define VIRTIO_EXT_CODE 0x2603 -struct BusInfo s390_virtio_bus_info = { - .name = "s390-virtio", - .size = sizeof(VirtIOS390Bus), +static const TypeInfo s390_virtio_bus_info = { + .name = TYPE_S390_VIRTIO_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(VirtIOS390Bus), }; static const VirtIOBindings virtio_s390_bindings; @@ -92,7 +93,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) /* Create bus on bridge device */ - _bus = qbus_create(&s390_virtio_bus_info, dev, "s390-virtio"); + _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio"); bus = DO_UPCAST(VirtIOS390Bus, bus, _bus); bus->dev_page = *ram_size; @@ -460,7 +461,7 @@ static void virtio_s390_device_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->init = s390_virtio_busdev_init; - dc->bus_info = &s390_virtio_bus_info; + dc->bus_type = TYPE_S390_VIRTIO_BUS; dc->unplug = qdev_simple_unplug_cb; } @@ -521,6 +522,7 @@ static TypeInfo s390_virtio_bridge_info = { static void s390_virtio_register_types(void) { + type_register_static(&s390_virtio_bus_info); type_register_static(&virtio_s390_device_info); type_register_static(&s390_virtio_serial); type_register_static(&s390_virtio_blk); diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h index 4b99d02298..4873134ae9 100644 --- a/hw/s390-virtio-bus.h +++ b/hw/s390-virtio-bus.h @@ -52,6 +52,10 @@ #define VIRTIO_S390_DEVICE_GET_CLASS(obj) \ OBJECT_GET_CLASS(VirtIOS390DeviceClass, (obj), TYPE_VIRTIO_S390_DEVICE) +#define TYPE_S390_VIRTIO_BUS "s390-virtio-bus" +#define S390_VIRTIO_BUS(obj) \ + OBJECT_CHECK(VirtIOS390Bus, (obj), TYPE_S390_VIRTIO_BUS) + typedef struct VirtIOS390Device VirtIOS390Device; typedef struct VirtIOS390DeviceClass { diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index e79bb54a9d..276c794f47 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -19,11 +19,19 @@ static Property scsi_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo scsi_bus_info = { - .name = "SCSI", - .size = sizeof(SCSIBus), - .get_dev_path = scsibus_get_dev_path, - .get_fw_dev_path = scsibus_get_fw_dev_path, +static void scsi_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->get_dev_path = scsibus_get_dev_path; + k->get_fw_dev_path = scsibus_get_fw_dev_path; +} + +static const TypeInfo scsi_bus_info = { + .name = TYPE_SCSI_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(SCSIBus), + .class_init = scsi_bus_class_init, }; static int next_scsi_bus; @@ -66,7 +74,7 @@ static void scsi_device_unit_attention_reported(SCSIDevice *s) /* Create a scsi bus, and attach devices to it. */ void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info) { - qbus_create_inplace(&bus->qbus, &scsi_bus_info, host, NULL); + qbus_create_inplace(&bus->qbus, TYPE_SCSI_BUS, host, NULL); bus->busnr = next_scsi_bus++; bus->info = info; bus->qbus.allow_hotplug = 1; @@ -1594,7 +1602,7 @@ const VMStateDescription vmstate_scsi_device = { static void scsi_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); - k->bus_info = &scsi_bus_info; + k->bus_type = TYPE_SCSI_BUS; k->init = scsi_qdev_init; k->unplug = qdev_simple_unplug_cb; k->exit = scsi_qdev_exit; @@ -1612,6 +1620,7 @@ static TypeInfo scsi_device_type_info = { static void scsi_register_types(void) { + type_register_static(&scsi_bus_info); type_register_static(&scsi_device_type_info); } diff --git a/hw/scsi.h b/hw/scsi.h index 2eb66f7393..76f06d41de 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -136,6 +136,9 @@ struct SCSIBusInfo { void *(*load_request)(QEMUFile *f, SCSIRequest *req); }; +#define TYPE_SCSI_BUS "SCSI" +#define SCSI_BUS(obj) OBJECT_CHECK(SCSIBus, (obj), TYPE_SCSI_BUS) + struct SCSIBus { BusState qbus; int busnr; diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index cf849529dc..b7611ff865 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -54,9 +54,10 @@ static Property spapr_vio_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo spapr_vio_bus_info = { - .name = "spapr-vio", - .size = sizeof(VIOsPAPRBus), +static const TypeInfo spapr_vio_bus_info = { + .name = TYPE_SPAPR_VIO_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(VIOsPAPRBus), }; VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) @@ -743,7 +744,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void) /* Create bus on bridge device */ - qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio"); + qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio"); bus = DO_UPCAST(VIOsPAPRBus, bus, qbus); bus->next_reg = 0x1000; @@ -795,7 +796,7 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data) DeviceClass *k = DEVICE_CLASS(klass); k->init = spapr_vio_busdev_init; k->reset = spapr_vio_busdev_reset; - k->bus_info = &spapr_vio_bus_info; + k->bus_type = TYPE_SPAPR_VIO_BUS; k->props = spapr_vio_props; } @@ -810,6 +811,7 @@ static TypeInfo spapr_vio_type_info = { static void spapr_vio_register_types(void) { + type_register_static(&spapr_vio_bus_info); type_register_static(&spapr_vio_bridge_info); type_register_static(&spapr_vio_type_info); } diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h index 87816e456d..2adad77d02 100644 --- a/hw/spapr_vio.h +++ b/hw/spapr_vio.h @@ -40,6 +40,9 @@ enum VIOsPAPR_TCEAccess { #define VIO_SPAPR_DEVICE_GET_CLASS(obj) \ OBJECT_GET_CLASS(VIOsPAPRDeviceClass, (obj), TYPE_VIO_SPAPR_DEVICE) +#define TYPE_SPAPR_VIO_BUS "spapr-vio-bus" +#define SPAPR_VIO_BUS(obj) OBJECT_CHECK(VIOsPAPRBus, (obj), TYPE_SPAPR_VIO_BUS) + struct VIOsPAPRDevice; typedef struct VIOsPAPR_RTCE { diff --git a/hw/ssi.c b/hw/ssi.c index 8f2d9bc034..8db99c29e4 100644 --- a/hw/ssi.c +++ b/hw/ssi.c @@ -16,9 +16,13 @@ struct SSIBus { BusState qbus; }; -static struct BusInfo ssi_bus_info = { - .name = "SSI", - .size = sizeof(SSIBus), +#define TYPE_SSI_BUS "SSI" +#define SSI_BUS(obj) OBJECT_CHECK(SSIBus, (obj), TYPE_SSI_BUS) + +static const TypeInfo ssi_bus_info = { + .name = TYPE_SSI_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(SSIBus), }; static int ssi_slave_init(DeviceState *dev) @@ -40,7 +44,7 @@ static void ssi_slave_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->init = ssi_slave_init; - dc->bus_info = &ssi_bus_info; + dc->bus_type = TYPE_SSI_BUS; } static TypeInfo ssi_slave_info = { @@ -62,7 +66,7 @@ DeviceState *ssi_create_slave(SSIBus *bus, const char *name) SSIBus *ssi_create_bus(DeviceState *parent, const char *name) { BusState *bus; - bus = qbus_create(&ssi_bus_info, parent, name); + bus = qbus_create(TYPE_SSI_BUS, parent, name); return FROM_QBUS(SSIBus, bus); } @@ -82,6 +86,7 @@ uint32_t ssi_transfer(SSIBus *bus, uint32_t val) static void ssi_slave_register_types(void) { + type_register_static(&ssi_bus_info); type_register_static(&ssi_slave_info); } diff --git a/hw/sysbus.c b/hw/sysbus.c index fe5c4212ff..2347f510bd 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -24,11 +24,19 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent); static char *sysbus_get_fw_dev_path(DeviceState *dev); -struct BusInfo system_bus_info = { - .name = "System", - .size = sizeof(BusState), - .print_dev = sysbus_dev_print, - .get_fw_dev_path = sysbus_get_fw_dev_path, +static void system_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->print_dev = sysbus_dev_print; + k->get_fw_dev_path = sysbus_get_fw_dev_path; +} + +static const TypeInfo system_bus_info = { + .name = TYPE_SYSTEM_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(BusState), + .class_init = system_bus_class_init, }; void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) @@ -244,7 +252,7 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = sysbus_device_init; - k->bus_info = &system_bus_info; + k->bus_type = TYPE_SYSTEM_BUS; } static TypeInfo sysbus_device_type_info = { @@ -263,10 +271,10 @@ static void main_system_bus_create(void) { /* assign main_system_bus before qbus_create_inplace() * in order to make "if (bus != sysbus_get_default())" work */ - main_system_bus = g_malloc0(system_bus_info.size); - main_system_bus->qdev_allocated = 1; - qbus_create_inplace(main_system_bus, &system_bus_info, NULL, + main_system_bus = g_malloc0(system_bus_info.instance_size); + qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL, "main-system-bus"); + main_system_bus->glib_allocated = true; } BusState *sysbus_get_default(void) @@ -279,6 +287,7 @@ BusState *sysbus_get_default(void) static void sysbus_register_types(void) { + type_register_static(&system_bus_info); type_register_static(&sysbus_device_type_info); } diff --git a/hw/sysbus.h b/hw/sysbus.h index 22555cd443..acfbcfba52 100644 --- a/hw/sysbus.h +++ b/hw/sysbus.h @@ -10,6 +10,9 @@ #define QDEV_MAX_PIO 32 #define QDEV_MAX_IRQ 512 +#define TYPE_SYSTEM_BUS "System" +#define SYSTEM_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) + typedef struct SysBusDevice SysBusDevice; #define TYPE_SYS_BUS_DEVICE "sys-bus-device" diff --git a/hw/usb.h b/hw/usb.h index ae7ccda18c..2a56fe554f 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -421,6 +421,9 @@ void musb_set_size(MUSBState *s, int epnum, int size, int is_tx); /* usb-bus.c */ +#define TYPE_USB_BUS "usb-bus" +#define USB_BUS(obj) OBJECT_CHECK(USBBus, (obj), TYPE_USB_BUS) + struct USBBus { BusState qbus; USBBusOps *ops; diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 8b08f93389..f87cc5f443 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -18,12 +18,20 @@ static Property usb_props[] = { DEFINE_PROP_END_OF_LIST() }; -static struct BusInfo usb_bus_info = { - .name = "USB", - .size = sizeof(USBBus), - .print_dev = usb_bus_dev_print, - .get_dev_path = usb_get_dev_path, - .get_fw_dev_path = usb_get_fw_dev_path, +static void usb_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->print_dev = usb_bus_dev_print; + k->get_dev_path = usb_get_dev_path; + k->get_fw_dev_path = usb_get_fw_dev_path; +} + +static const TypeInfo usb_bus_info = { + .name = TYPE_USB_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(USBBus), + .class_init = usb_bus_class_init, }; static int next_usb_bus = 0; @@ -47,7 +55,7 @@ const VMStateDescription vmstate_usb_device = { void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host) { - qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL); + qbus_create_inplace(&bus->qbus, TYPE_USB_BUS, host, NULL); bus->ops = ops; bus->busnr = next_usb_bus++; bus->qbus.allow_hotplug = 1; /* Yes, we can */ @@ -577,7 +585,7 @@ USBDevice *usbdevice_create(const char *cmdline) static void usb_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); - k->bus_info = &usb_bus_info; + k->bus_type = TYPE_USB_BUS; k->init = usb_qdev_init; k->unplug = qdev_simple_unplug_cb; k->exit = usb_qdev_exit; @@ -595,6 +603,7 @@ static TypeInfo usb_device_type_info = { static void usb_register_types(void) { + type_register_static(&usb_bus_info); type_register_static(&usb_device_type_info); } diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index a4ab6e589a..6cf4a1aeaa 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1060,9 +1060,13 @@ static Property ccid_props[] = { DEFINE_PROP_END_OF_LIST(), }; -static struct BusInfo ccid_bus_info = { - .name = "ccid-bus", - .size = sizeof(CCIDBus), +#define TYPE_CCID_BUS "ccid-bus" +#define CCID_BUS(obj) OBJECT_CHECK(CCIDBus, (obj), TYPE_CCID_BUS) + +static const TypeInfo ccid_bus_info = { + .name = TYPE_CCID_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(CCIDBus), }; void ccid_card_send_apdu_to_guest(CCIDCardState *card, @@ -1192,7 +1196,7 @@ static int ccid_initfn(USBDevice *dev) usb_desc_create_serial(dev); usb_desc_init(dev); - qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL); + qbus_create_inplace(&s->bus.qbus, TYPE_CCID_BUS, &dev->qdev, NULL); s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); s->bus.qbus.allow_hotplug = 1; s->card = NULL; @@ -1343,7 +1347,7 @@ static TypeInfo ccid_info = { static void ccid_card_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); - k->bus_info = &ccid_bus_info; + k->bus_type = TYPE_CCID_BUS; k->init = ccid_card_init; k->exit = ccid_card_exit; k->props = ccid_props; @@ -1360,6 +1364,7 @@ static TypeInfo ccid_card_type_info = { static void ccid_register_types(void) { + type_register_static(&ccid_bus_info); type_register_static(&ccid_card_type_info); type_register_static(&ccid_info); usb_legacy_register(CCID_DEV_NAME, "ccid", NULL); diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index d47d870594..96382a4ea1 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -734,10 +734,21 @@ static Property virtser_props[] = { DEFINE_PROP_END_OF_LIST() }; -static struct BusInfo virtser_bus_info = { - .name = "virtio-serial-bus", - .size = sizeof(VirtIOSerialBus), - .print_dev = virtser_bus_dev_print, +#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus" +#define VIRTIO_SERIAL_BUS(obj) \ + OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS) + +static void virtser_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + k->print_dev = virtser_bus_dev_print; +} + +static const TypeInfo virtser_bus_info = { + .name = TYPE_VIRTIO_SERIAL_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(VirtIOSerialBus), + .class_init = virtser_bus_class_init, }; static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) @@ -905,7 +916,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf) vser = DO_UPCAST(VirtIOSerial, vdev, vdev); /* Spawn a new virtio-serial bus on which the ports will ride as devices */ - qbus_create_inplace(&vser->bus.qbus, &virtser_bus_info, dev, NULL); + qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, dev, NULL); vser->bus.qbus.allow_hotplug = 1; vser->bus.vser = vser; QTAILQ_INIT(&vser->ports); @@ -981,7 +992,7 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = virtser_port_qdev_init; - k->bus_info = &virtser_bus_info; + k->bus_type = TYPE_VIRTIO_SERIAL_BUS; k->exit = virtser_port_qdev_exit; k->unplug = qdev_simple_unplug_cb; k->props = virtser_props; @@ -998,6 +1009,7 @@ static TypeInfo virtio_serial_port_type_info = { static void virtio_serial_register_types(void) { + type_register_static(&virtser_bus_info); type_register_static(&virtio_serial_port_type_info); } From f968fc6892daf02865cce8af277cc755be690eda Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 2 May 2012 10:39:01 +0200 Subject: [PATCH 18/22] qdev: Connect busses with their parent devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes SysBus part of the root hierarchy and all busses children of their respective parent DeviceState. Signed-off-by: Anthony Liguori Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/qdev.c | 4 ++++ hw/sysbus.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/hw/qdev.c b/hw/qdev.c index 63012b5252..dc46e7bd10 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -404,6 +404,7 @@ static void do_qbus_create_inplace(BusState *bus, const char *typename, if (parent) { QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling); parent->num_child_bus++; + object_property_add_child(OBJECT(parent), bus->name, OBJECT(bus), NULL); } else if (bus != sysbus_get_default()) { /* TODO: once all bus devices are qdevified, only reset handler for main_system_bus should be registered here. */ @@ -656,6 +657,9 @@ static void device_initfn(Object *obj) class = object_class_get_parent(class); } while (class != object_class_by_name(TYPE_DEVICE)); qdev_prop_set_globals(dev); + + object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS, + (Object **)&dev->parent_bus, NULL); } /* Unlink device from bus and free the structure. */ diff --git a/hw/sysbus.c b/hw/sysbus.c index 2347f510bd..9d8b1eaf7d 100644 --- a/hw/sysbus.c +++ b/hw/sysbus.c @@ -275,6 +275,9 @@ static void main_system_bus_create(void) qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL, "main-system-bus"); main_system_bus->glib_allocated = true; + object_property_add_child(container_get(qdev_get_machine(), + "/unattached"), + "sysbus", OBJECT(main_system_bus), NULL); } BusState *sysbus_get_default(void) From 0866aca1de15a12547f52ff8563cf7c163e1898e Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 23 Dec 2011 15:34:39 -0600 Subject: [PATCH 19/22] qbus: Make child devices links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make qbus children show up as link<> properties. There is no stable addressing for qbus children so we use an unstable naming convention. This is okay in QOM though because the composition name is expected to be what's stable. Signed-off-by: Anthony Liguori Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/acpi_piix4.c | 10 ++++--- hw/i2c.c | 5 ++-- hw/intel-hda.c | 15 ++++++----- hw/lsi53c895a.c | 5 ++-- hw/qdev-monitor.c | 26 +++++++++++------- hw/qdev.c | 64 ++++++++++++++++++++++++++++++++++++-------- hw/qdev.h | 10 +++++-- hw/s390-virtio-bus.c | 25 +++++++++-------- hw/scsi-bus.c | 13 +++++---- hw/spapr_pci.c | 7 ++--- hw/spapr_vio.c | 25 ++++++++--------- hw/spapr_vty.c | 6 +++-- hw/ssi.c | 14 +++++----- hw/virtio-scsi.c | 6 ++--- qom/object.c | 11 ++++++-- 15 files changed, 159 insertions(+), 83 deletions(-) diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 0345490ee0..a11c8e7ae0 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -284,7 +284,7 @@ static const VMStateDescription vmstate_acpi = { static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) { - DeviceState *qdev, *next; + BusChild *kid, *next; BusState *bus = qdev_get_parent_bus(&s->dev.qdev); int slot = ffs(slots) - 1; bool slot_free = true; @@ -292,7 +292,8 @@ static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) /* Mark request as complete */ s->pci0_status.down &= ~(1U << slot); - QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) { + QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { + DeviceState *qdev = kid->child; PCIDevice *dev = PCI_DEVICE(qdev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); if (PCI_SLOT(dev->devfn) == slot) { @@ -313,7 +314,7 @@ static void piix4_update_hotplug(PIIX4PMState *s) { PCIDevice *dev = &s->dev; BusState *bus = qdev_get_parent_bus(&dev->qdev); - DeviceState *qdev, *next; + BusChild *kid, *next; /* Execute any pending removes during reset */ while (s->pci0_status.down) { @@ -323,7 +324,8 @@ static void piix4_update_hotplug(PIIX4PMState *s) s->pci0_hotplug_enable = ~0; s->pci0_slot_device_present = 0; - QTAILQ_FOREACH_SAFE(qdev, &bus->children, sibling, next) { + QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { + DeviceState *qdev = kid->child; PCIDevice *pdev = PCI_DEVICE(qdev); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev); int slot = PCI_SLOT(pdev->devfn); diff --git a/hw/i2c.c b/hw/i2c.c index 319b249da3..296bece119 100644 --- a/hw/i2c.c +++ b/hw/i2c.c @@ -86,11 +86,12 @@ int i2c_bus_busy(i2c_bus *bus) /* TODO: Make this handle multiple masters. */ int i2c_start_transfer(i2c_bus *bus, uint8_t address, int recv) { - DeviceState *qdev; + BusChild *kid; I2CSlave *slave = NULL; I2CSlaveClass *sc; - QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) { + QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; I2CSlave *candidate = I2C_SLAVE_FROM_QDEV(qdev); if (candidate->address == address) { slave = candidate; diff --git a/hw/intel-hda.c b/hw/intel-hda.c index e343096534..c11fd30cab 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -78,10 +78,11 @@ static int hda_codec_dev_exit(DeviceState *qdev) HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad) { - DeviceState *qdev; + BusChild *kid; HDACodecDevice *cdev; - QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) { + QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; cdev = DO_UPCAST(HDACodecDevice, qdev, qdev); if (cdev->cad == cad) { return cdev; @@ -483,10 +484,11 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st) static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running, bool output) { - DeviceState *qdev; + BusChild *kid; HDACodecDevice *cdev; - QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) { + QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) { + DeviceState *qdev = kid->child; HDACodecDeviceClass *cdc; cdev = DO_UPCAST(HDACodecDevice, qdev, qdev); @@ -1105,15 +1107,16 @@ static const MemoryRegionOps intel_hda_mmio_ops = { static void intel_hda_reset(DeviceState *dev) { + BusChild *kid; IntelHDAState *d = DO_UPCAST(IntelHDAState, pci.qdev, dev); - DeviceState *qdev; HDACodecDevice *cdev; intel_hda_regs_reset(d); d->wall_base_ns = qemu_get_clock_ns(vm_clock); /* reset codecs */ - QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) { + QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) { + DeviceState *qdev = kid->child; cdev = DO_UPCAST(HDACodecDevice, qdev, qdev); device_reset(DEVICE(cdev)); d->state_sts |= (1 << cdev->cad); diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index f022a02447..2fe141d24e 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -1677,9 +1677,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) } if (val & LSI_SCNTL1_RST) { if (!(s->sstat0 & LSI_SSTAT0_RST)) { - DeviceState *dev; + BusChild *kid; - QTAILQ_FOREACH(dev, &s->bus.qbus.children, sibling) { + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { + DeviceState *dev = kid->child; device_reset(dev); } s->sstat0 |= LSI_SSTAT0_RST; diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c index 691b864c54..17452c8c01 100644 --- a/hw/qdev-monitor.c +++ b/hw/qdev-monitor.c @@ -205,11 +205,12 @@ static void qbus_list_bus(DeviceState *dev) static void qbus_list_dev(BusState *bus) { - DeviceState *dev; + BusChild *kid; const char *sep = " "; error_printf("devices at \"%s\":", bus->name); - QTAILQ_FOREACH(dev, &bus->children, sibling) { + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev))); if (dev->id) error_printf("/\"%s\"", dev->id); @@ -232,7 +233,7 @@ static BusState *qbus_find_bus(DeviceState *dev, char *elem) static DeviceState *qbus_find_dev(BusState *bus, char *elem) { - DeviceState *dev; + BusChild *kid; /* * try to match in order: @@ -240,17 +241,20 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem) * (2) driver name * (3) driver alias, if present */ - QTAILQ_FOREACH(dev, &bus->children, sibling) { + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; if (dev->id && strcmp(dev->id, elem) == 0) { return dev; } } - QTAILQ_FOREACH(dev, &bus->children, sibling) { + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) { return dev; } } - QTAILQ_FOREACH(dev, &bus->children, sibling) { + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; DeviceClass *dc = DEVICE_GET_CLASS(dev); if (qdev_class_has_alias(dc) && @@ -264,7 +268,7 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem) static BusState *qbus_find_recursive(BusState *bus, const char *name, const char *bus_typename) { - DeviceState *dev; + BusChild *kid; BusState *child, *ret; int match = 1; @@ -279,7 +283,8 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, return bus; } - QTAILQ_FOREACH(dev, &bus->children, sibling) { + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; QLIST_FOREACH(child, &dev->child_bus, sibling) { ret = qbus_find_recursive(child, name, bus_typename); if (ret) { @@ -533,12 +538,13 @@ static void qdev_print(Monitor *mon, DeviceState *dev, int indent) static void qbus_print(Monitor *mon, BusState *bus, int indent) { - struct DeviceState *dev; + BusChild *kid; qdev_printf("bus: %s\n", bus->name); indent += 2; qdev_printf("type %s\n", object_get_typename(OBJECT(bus))); - QTAILQ_FOREACH(dev, &bus->children, sibling) { + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; qdev_print(mon, dev, indent); } } diff --git a/hw/qdev.c b/hw/qdev.c index dc46e7bd10..fc79b24103 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -60,14 +60,48 @@ bool qdev_exists(const char *name) static void qdev_property_add_legacy(DeviceState *dev, Property *prop, Error **errp); -void qdev_set_parent_bus(DeviceState *dev, BusState *bus) +static void bus_remove_child(BusState *bus, DeviceState *child) { + BusChild *kid; + + QTAILQ_FOREACH(kid, &bus->children, sibling) { + if (kid->child == child) { + char name[32]; + + snprintf(name, sizeof(name), "child[%d]", kid->index); + QTAILQ_REMOVE(&bus->children, kid, sibling); + object_property_del(OBJECT(bus), name, NULL); + g_free(kid); + return; + } + } +} + +static void bus_add_child(BusState *bus, DeviceState *child) +{ + char name[32]; + BusChild *kid = g_malloc0(sizeof(*kid)); + if (qdev_hotplug) { assert(bus->allow_hotplug); } + kid->index = bus->max_index++; + kid->child = child; + + QTAILQ_INSERT_HEAD(&bus->children, kid, sibling); + + snprintf(name, sizeof(name), "child[%d]", kid->index); + object_property_add_link(OBJECT(bus), name, + object_get_typename(OBJECT(child)), + (Object **)&kid->child, + NULL); +} + +void qdev_set_parent_bus(DeviceState *dev, BusState *bus) +{ dev->parent_bus = bus; - QTAILQ_INSERT_HEAD(&bus->children, dev, sibling); + bus_add_child(bus, dev); } /* Create a new device. This only initializes the device state structure @@ -310,7 +344,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name) int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn, qbus_walkerfn *busfn, void *opaque) { - DeviceState *dev; + BusChild *kid; int err; if (busfn) { @@ -320,8 +354,8 @@ int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn, } } - QTAILQ_FOREACH(dev, &bus->children, sibling) { - err = qdev_walk_children(dev, devfn, busfn, opaque); + QTAILQ_FOREACH(kid, &bus->children, sibling) { + err = qdev_walk_children(kid->child, devfn, busfn, opaque); if (err < 0) { return err; } @@ -355,12 +389,17 @@ int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn, DeviceState *qdev_find_recursive(BusState *bus, const char *id) { - DeviceState *dev, *ret; + BusChild *kid; + DeviceState *ret; BusState *child; - QTAILQ_FOREACH(dev, &bus->children, sibling) { - if (dev->id && strcmp(dev->id, id) == 0) + QTAILQ_FOREACH(kid, &bus->children, sibling) { + DeviceState *dev = kid->child; + + if (dev->id && strcmp(dev->id, id) == 0) { return dev; + } + QLIST_FOREACH(child, &dev->child_bus, sibling) { ret = qdev_find_recursive(child, id); if (ret) { @@ -431,9 +470,10 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam void qbus_free(BusState *bus) { - DeviceState *dev; + BusChild *kid; - while ((dev = QTAILQ_FIRST(&bus->children)) != NULL) { + while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { + DeviceState *dev = kid->child; qdev_free(dev); } if (bus->parent) { @@ -684,7 +724,9 @@ static void device_finalize(Object *obj) qemu_opts_del(dev->opts); } } - QTAILQ_REMOVE(&dev->parent_bus->children, dev, sibling); + if (dev->parent_bus) { + bus_remove_child(dev->parent_bus, dev); + } } static void device_class_base_init(ObjectClass *class, void *data) diff --git a/hw/qdev.h b/hw/qdev.h index 736271ecef..e39f82e029 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -74,7 +74,6 @@ struct DeviceState { qemu_irq *gpio_in; QLIST_HEAD(, BusState) child_bus; int num_child_bus; - QTAILQ_ENTRY(DeviceState) sibling; int instance_id_alias; int alias_required_for_version; }; @@ -100,6 +99,12 @@ struct BusClass { int (*reset)(BusState *bus); }; +typedef struct BusChild { + DeviceState *child; + int index; + QTAILQ_ENTRY(BusChild) sibling; +} BusChild; + /** * BusState: * @qom_allocated: Indicates whether the object was allocated by QOM. @@ -113,7 +118,8 @@ struct BusState { int allow_hotplug; bool qom_allocated; bool glib_allocated; - QTAILQ_HEAD(ChildrenHead, DeviceState) children; + int max_index; + QTAILQ_HEAD(ChildrenHead, BusChild) children; QLIST_ENTRY(BusState) sibling; }; diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index 2aec756da1..4d49b96f94 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -315,20 +315,20 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, ram_addr_t mem, int *vq_num) { - VirtIOS390Device *_dev; - DeviceState *dev; + BusChild *kid; int i; - QTAILQ_FOREACH(dev, &bus->bus.children, sibling) { - _dev = (VirtIOS390Device *)dev; + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; + for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) { - if (!virtio_queue_get_addr(_dev->vdev, i)) + if (!virtio_queue_get_addr(dev->vdev, i)) break; - if (virtio_queue_get_addr(_dev->vdev, i) == mem) { + if (virtio_queue_get_addr(dev->vdev, i) == mem) { if (vq_num) { *vq_num = i; } - return _dev; + return dev; } } } @@ -339,13 +339,12 @@ VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, /* Find a device by device descriptor location */ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem) { - VirtIOS390Device *_dev; - DeviceState *dev; + BusChild *kid; - QTAILQ_FOREACH(dev, &bus->bus.children, sibling) { - _dev = (VirtIOS390Device *)dev; - if (_dev->dev_offs == mem) { - return _dev; + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; + if (dev->dev_offs == mem) { + return dev; } } diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 276c794f47..dbfccdc24a 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -315,7 +315,7 @@ static void store_lun(uint8_t *outbuf, int lun) static bool scsi_target_emulate_report_luns(SCSITargetReq *r) { - DeviceState *qdev; + BusChild *kid; int i, len, n; int channel, id; bool found_lun0; @@ -330,7 +330,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) id = r->req.dev->id; found_lun0 = false; n = 0; - QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) { + QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->channel == channel && dev->id == id) { @@ -352,7 +353,8 @@ static bool scsi_target_emulate_report_luns(SCSITargetReq *r) memset(r->buf, 0, len); stl_be_p(&r->buf, n); i = found_lun0 ? 8 : 16; - QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) { + QTAILQ_FOREACH(kid, &r->req.bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->channel == channel && dev->id == id) { @@ -1487,10 +1489,11 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev) SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) { - DeviceState *qdev; + BusChild *kid; SCSIDevice *target_dev = NULL; - QTAILQ_FOREACH_REVERSE(qdev, &bus->qbus.children, ChildrenHead, sibling) { + QTAILQ_FOREACH_REVERSE(kid, &bus->qbus.children, ChildrenHead, sibling) { + DeviceState *qdev = kid->child; SCSIDevice *dev = SCSI_DEVICE(qdev); if (dev->channel == channel && dev->id == id) { diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 25b400aa47..97d417a997 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -35,17 +35,18 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, uint32_t config_addr) { - DeviceState *qdev; int devfn = (config_addr >> 8) & 0xFF; sPAPRPHBState *phb; QLIST_FOREACH(phb, &spapr->phbs, list) { + BusChild *kid; + if (phb->buid != buid) { continue; } - QTAILQ_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) { - PCIDevice *dev = (PCIDevice *)qdev; + QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) { + PCIDevice *dev = (PCIDevice *)kid->child; if (dev->devfn == devfn) { return dev; } diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index b7611ff865..c8271c626c 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -62,11 +62,11 @@ static const TypeInfo spapr_vio_bus_info = { VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) { - DeviceState *qdev; + BusChild *kid; VIOsPAPRDevice *dev = NULL; - QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { - dev = (VIOsPAPRDevice *)qdev; + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + dev = (VIOsPAPRDevice *)kid->child; if (dev->reg == reg) { return dev; } @@ -606,7 +606,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token, uint32_t nret, target_ulong rets) { VIOsPAPRBus *bus = spapr->vio_bus; - DeviceState *qdev; + BusChild *kid; VIOsPAPRDevice *dev = NULL; if (nargs != 0) { @@ -614,8 +614,8 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token, return; } - QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { - dev = (VIOsPAPRDevice *)qdev; + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + dev = (VIOsPAPRDevice *)kid->child; spapr_vio_quiesce_one(dev); } @@ -625,7 +625,7 @@ static void rtas_quiesce(sPAPREnvironment *spapr, uint32_t token, static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev) { VIOsPAPRBus *bus = DO_UPCAST(VIOsPAPRBus, bus, dev->qdev.parent_bus); - DeviceState *qdev; + BusChild *kid; VIOsPAPRDevice *other; /* @@ -633,8 +633,8 @@ static VIOsPAPRDevice *reg_conflict(VIOsPAPRDevice *dev) * using the requested address. We have to open code this because * the given dev might already be in the list. */ - QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { - other = DO_UPCAST(VIOsPAPRDevice, qdev, qdev); + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + other = DO_UPCAST(VIOsPAPRDevice, qdev, kid->child); if (other != dev && other->reg == dev->reg) { return other; @@ -840,19 +840,20 @@ static int compare_reg(const void *p1, const void *p2) int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt) { DeviceState *qdev, **qdevs; + BusChild *kid; int i, num, ret = 0; /* Count qdevs on the bus list */ num = 0; - QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { num++; } /* Copy out into an array of pointers */ qdevs = g_malloc(sizeof(qdev) * num); num = 0; - QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { - qdevs[num++] = qdev; + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + qdevs[num++] = kid->child; } /* Sort the array */ diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index c9674f36a6..f340b83237 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -160,7 +160,7 @@ static TypeInfo spapr_vty_info = { VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus) { VIOsPAPRDevice *sdev, *selected; - DeviceState *iter; + BusChild *kid; /* * To avoid the console bouncing around we want one VTY to be @@ -169,7 +169,9 @@ VIOsPAPRDevice *spapr_vty_get_default(VIOsPAPRBus *bus) */ selected = NULL; - QTAILQ_FOREACH(iter, &bus->bus.children, sibling) { + QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { + DeviceState *iter = kid->child; + /* Only look at VTY devices */ if (!object_dynamic_cast(OBJECT(iter), "spapr-vty")) { continue; diff --git a/hw/ssi.c b/hw/ssi.c index 8db99c29e4..e5f14a0cef 100644 --- a/hw/ssi.c +++ b/hw/ssi.c @@ -30,10 +30,11 @@ static int ssi_slave_init(DeviceState *dev) SSISlave *s = SSI_SLAVE(dev); SSISlaveClass *ssc = SSI_SLAVE_GET_CLASS(s); SSIBus *bus; + BusChild *kid; bus = FROM_QBUS(SSIBus, qdev_get_parent_bus(dev)); - if (QTAILQ_FIRST(&bus->qbus.children) != dev - || QTAILQ_NEXT(dev, sibling) != NULL) { + kid = QTAILQ_FIRST(&bus->qbus.children); + if (kid->child != dev || QTAILQ_NEXT(kid, sibling) != NULL) { hw_error("Too many devices on SSI bus"); } @@ -72,14 +73,15 @@ SSIBus *ssi_create_bus(DeviceState *parent, const char *name) uint32_t ssi_transfer(SSIBus *bus, uint32_t val) { - DeviceState *dev; + BusChild *kid; SSISlave *slave; SSISlaveClass *ssc; - dev = QTAILQ_FIRST(&bus->qbus.children); - if (!dev) { + + kid = QTAILQ_FIRST(&bus->qbus.children); + if (!kid) { return 0; } - slave = SSI_SLAVE(dev); + slave = SSI_SLAVE(kid->child); ssc = SSI_SLAVE_GET_CLASS(slave); return ssc->transfer(slave, val); } diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c index 5e39ce93c4..e1a767ea78 100644 --- a/hw/virtio-scsi.c +++ b/hw/virtio-scsi.c @@ -275,7 +275,7 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) { SCSIDevice *d = virtio_scsi_device_find(s, req->req.tmf->lun); SCSIRequest *r, *next; - DeviceState *qdev; + BusChild *kid; int target; /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */ @@ -346,8 +346,8 @@ static void virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req) case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET: target = req->req.tmf->lun[1]; s->resetting++; - QTAILQ_FOREACH(qdev, &s->bus.qbus.children, sibling) { - d = DO_UPCAST(SCSIDevice, qdev, qdev); + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { + d = DO_UPCAST(SCSIDevice, qdev, kid->child); if (d->channel == 0 && d->id == target) { qdev_reset_all(&d->qdev); } diff --git a/qom/object.c b/qom/object.c index d5c6ff7471..27cc651a91 100644 --- a/qom/object.c +++ b/qom/object.c @@ -689,9 +689,16 @@ void object_property_del(Object *obj, const char *name, Error **errp) { ObjectProperty *prop = object_property_find(obj, name); - QTAILQ_REMOVE(&obj->properties, prop, node); + if (prop == NULL) { + error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); + return; + } - prop->release(obj, prop->name, prop->opaque); + if (prop->release) { + prop->release(obj, name, prop->opaque); + } + + QTAILQ_REMOVE(&obj->properties, prop, node); g_free(prop->name); g_free(prop->type); From ac7d1ba6d15ff10343d2ff5ea331fa6a41174f3f Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 3 Feb 2012 13:32:19 -0600 Subject: [PATCH 20/22] qbus: Initialize in standard way MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move code to an initfn and finalizer. Replace do_qbus_create_inplace() with qbus_realize(). Signed-off-by: Anthony Liguori Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/qdev.c | 80 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index fc79b24103..38ca58175f 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -410,40 +410,35 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id) return NULL; } -/* FIXME move this logic into instance_init */ -static void do_qbus_create_inplace(BusState *bus, const char *typename, - DeviceState *parent, const char *name) +static void qbus_realize(BusState *bus) { + const char *typename = object_get_typename(OBJECT(bus)); char *buf; int i,len; - bus->parent = parent; - - if (name) { + if (bus->name) { /* use supplied name */ - bus->name = g_strdup(name); - } else if (parent && parent->id) { + } else if (bus->parent && bus->parent->id) { /* parent device has id -> use it for bus name */ - len = strlen(parent->id) + 16; + len = strlen(bus->parent->id) + 16; buf = g_malloc(len); - snprintf(buf, len, "%s.%d", parent->id, parent->num_child_bus); + snprintf(buf, len, "%s.%d", bus->parent->id, bus->parent->num_child_bus); bus->name = buf; } else { /* no id -> use lowercase bus type for bus name */ len = strlen(typename) + 16; buf = g_malloc(len); len = snprintf(buf, len, "%s.%d", typename, - parent ? parent->num_child_bus : 0); + bus->parent ? bus->parent->num_child_bus : 0); for (i = 0; i < len; i++) buf[i] = qemu_tolower(buf[i]); bus->name = buf; } - QTAILQ_INIT(&bus->children); - if (parent) { - QLIST_INSERT_HEAD(&parent->child_bus, bus, sibling); - parent->num_child_bus++; - object_property_add_child(OBJECT(parent), bus->name, OBJECT(bus), NULL); + if (bus->parent) { + QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling); + bus->parent->num_child_bus++; + object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL); } else if (bus != sysbus_get_default()) { /* TODO: once all bus devices are qdevified, only reset handler for main_system_bus should be registered here. */ @@ -455,7 +450,10 @@ void qbus_create_inplace(BusState *bus, const char *typename, DeviceState *parent, const char *name) { object_initialize(bus, typename); - do_qbus_create_inplace(bus, typename, parent, name); + + bus->parent = parent; + bus->name = name ? g_strdup(name) : NULL; + qbus_realize(bus); } BusState *qbus_create(const char *typename, DeviceState *parent, const char *name) @@ -464,26 +462,16 @@ BusState *qbus_create(const char *typename, DeviceState *parent, const char *nam bus = BUS(object_new(typename)); bus->qom_allocated = true; - do_qbus_create_inplace(bus, typename, parent, name); + + bus->parent = parent; + bus->name = name ? g_strdup(name) : NULL; + qbus_realize(bus); + return bus; } void qbus_free(BusState *bus) { - BusChild *kid; - - while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { - DeviceState *dev = kid->child; - qdev_free(dev); - } - if (bus->parent) { - QLIST_REMOVE(bus, sibling); - bus->parent->num_child_bus--; - } else { - assert(bus != sysbus_get_default()); /* main_system_bus is never freed */ - qemu_unregister_reset(qbus_reset_all_fn, bus); - } - g_free((void*)bus->name); if (bus->qom_allocated) { object_delete(OBJECT(bus)); } else { @@ -770,12 +758,40 @@ static TypeInfo device_type_info = { .class_size = sizeof(DeviceClass), }; +static void qbus_initfn(Object *obj) +{ + BusState *bus = BUS(obj); + + QTAILQ_INIT(&bus->children); +} + +static void qbus_finalize(Object *obj) +{ + BusState *bus = BUS(obj); + BusChild *kid; + + while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) { + DeviceState *dev = kid->child; + qdev_free(dev); + } + if (bus->parent) { + QLIST_REMOVE(bus, sibling); + bus->parent->num_child_bus--; + } else { + assert(bus != sysbus_get_default()); /* main_system_bus is never freed */ + qemu_unregister_reset(qbus_reset_all_fn, bus); + } + g_free((char *)bus->name); +} + static const TypeInfo bus_info = { .name = TYPE_BUS, .parent = TYPE_OBJECT, .instance_size = sizeof(BusState), .abstract = true, .class_size = sizeof(BusClass), + .instance_init = qbus_initfn, + .instance_finalize = qbus_finalize, }; static void qdev_register_types(void) From 8cb6789a31e8c5823b36d84416433c145a1e6442 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 30 Mar 2012 14:54:31 +0200 Subject: [PATCH 21/22] qdev: Remove qdev_prop_exists() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Can be replaced everywhere with object_property_find(). Signed-off-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/qdev-properties.c | 5 ----- hw/qdev.c | 2 +- hw/qdev.h | 1 - hw/scsi-bus.c | 2 +- include/qemu/object.h | 9 +++++++++ qom/object.c | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index f4b9a0e2c8..099a7aa96f 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -931,11 +931,6 @@ static Property *qdev_prop_find(DeviceState *dev, const char *name) return NULL; } -int qdev_prop_exists(DeviceState *dev, const char *name) -{ - return qdev_prop_find(dev, name) ? true : false; -} - void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, Property *prop, const char *value) { diff --git a/hw/qdev.c b/hw/qdev.c index 38ca58175f..654cbcaccf 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -323,7 +323,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) if (nd->netdev) qdev_prop_set_netdev(dev, "netdev", nd->netdev); if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && - qdev_prop_exists(dev, "vectors")) { + object_property_find(OBJECT(dev), "vectors")) { qdev_prop_set_uint32(dev, "vectors", nd->nvectors); } nd->instantiated = 1; diff --git a/hw/qdev.h b/hw/qdev.h index e39f82e029..ae1d2812bf 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -306,7 +306,6 @@ extern PropertyInfo qdev_prop_blocksize; /* Set properties between creation and init. */ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop); -int qdev_prop_exists(DeviceState *dev, const char *name); int qdev_prop_parse(DeviceState *dev, const char *name, const char *value); void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value); void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value); diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index dbfccdc24a..a4ae44b344 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -214,7 +214,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, if (bootindex >= 0) { qdev_prop_set_int32(dev, "bootindex", bootindex); } - if (qdev_prop_exists(dev, "removable")) { + if (object_property_find(OBJECT(dev), "removable")) { qdev_prop_set_bit(dev, "removable", removable); } if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { diff --git a/include/qemu/object.h b/include/qemu/object.h index b16d99be8c..8cac7da420 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -635,6 +635,15 @@ void object_property_add(Object *obj, const char *name, const char *type, void object_property_del(Object *obj, const char *name, struct Error **errp); +/** + * object_property_find: + * @obj: the object + * @name: the name of the property + * + * Look up a property for an object and return its #ObjectProperty if found. + */ +ObjectProperty *object_property_find(Object *obj, const char *name); + void object_unparent(Object *obj); /** diff --git a/qom/object.c b/qom/object.c index 27cc651a91..e072e895bb 100644 --- a/qom/object.c +++ b/qom/object.c @@ -672,7 +672,7 @@ void object_property_add(Object *obj, const char *name, const char *type, QTAILQ_INSERT_TAIL(&obj->properties, prop, node); } -static ObjectProperty *object_property_find(Object *obj, const char *name) +ObjectProperty *object_property_find(Object *obj, const char *name) { ObjectProperty *prop; From 89bfe000433a601d30729086e88519ff36b85103 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 12 Apr 2012 18:00:18 +0200 Subject: [PATCH 22/22] qom: Push error reporting to object_property_find() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids duplicated error_set(). Signed-off-by: Paolo Bonzini [AF: Also drop error_set() in object_property_del().] Signed-off-by: Andreas Färber --- hw/qdev.c | 2 +- hw/scsi-bus.c | 2 +- include/qemu/object.h | 4 +++- qom/object.c | 22 ++++++++-------------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/hw/qdev.c b/hw/qdev.c index 654cbcaccf..b20b34d11f 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -323,7 +323,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) if (nd->netdev) qdev_prop_set_netdev(dev, "netdev", nd->netdev); if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED && - object_property_find(OBJECT(dev), "vectors")) { + object_property_find(OBJECT(dev), "vectors", NULL)) { qdev_prop_set_uint32(dev, "vectors", nd->nvectors); } nd->instantiated = 1; diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index a4ae44b344..187bc903c1 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -214,7 +214,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, if (bootindex >= 0) { qdev_prop_set_int32(dev, "bootindex", bootindex); } - if (object_property_find(OBJECT(dev), "removable")) { + if (object_property_find(OBJECT(dev), "removable", NULL)) { qdev_prop_set_bit(dev, "removable", removable); } if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { diff --git a/include/qemu/object.h b/include/qemu/object.h index 8cac7da420..8b17776bb3 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -639,10 +639,12 @@ void object_property_del(Object *obj, const char *name, struct Error **errp); * object_property_find: * @obj: the object * @name: the name of the property + * @errp: returns an error if this function fails * * Look up a property for an object and return its #ObjectProperty if found. */ -ObjectProperty *object_property_find(Object *obj, const char *name); +ObjectProperty *object_property_find(Object *obj, const char *name, + struct Error **errp); void object_unparent(Object *obj); diff --git a/qom/object.c b/qom/object.c index e072e895bb..00bb3b029c 100644 --- a/qom/object.c +++ b/qom/object.c @@ -672,7 +672,8 @@ void object_property_add(Object *obj, const char *name, const char *type, QTAILQ_INSERT_TAIL(&obj->properties, prop, node); } -ObjectProperty *object_property_find(Object *obj, const char *name) +ObjectProperty *object_property_find(Object *obj, const char *name, + Error **errp) { ObjectProperty *prop; @@ -682,15 +683,14 @@ ObjectProperty *object_property_find(Object *obj, const char *name) } } + error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); return NULL; } void object_property_del(Object *obj, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name); - + ObjectProperty *prop = object_property_find(obj, name, errp); if (prop == NULL) { - error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); return; } @@ -708,10 +708,8 @@ void object_property_del(Object *obj, const char *name, Error **errp) void object_property_get(Object *obj, Visitor *v, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name); - + ObjectProperty *prop = object_property_find(obj, name, errp); if (prop == NULL) { - error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); return; } @@ -725,10 +723,8 @@ void object_property_get(Object *obj, Visitor *v, const char *name, void object_property_set(Object *obj, Visitor *v, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name); - + ObjectProperty *prop = object_property_find(obj, name, errp); if (prop == NULL) { - error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); return; } @@ -881,10 +877,8 @@ char *object_property_print(Object *obj, const char *name, const char *object_property_get_type(Object *obj, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name); - + ObjectProperty *prop = object_property_find(obj, name, errp); if (prop == NULL) { - error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name); return NULL; } @@ -1067,7 +1061,7 @@ gchar *object_get_canonical_path(Object *obj) Object *object_resolve_path_component(Object *parent, gchar *part) { - ObjectProperty *prop = object_property_find(parent, part); + ObjectProperty *prop = object_property_find(parent, part, NULL); if (prop == NULL) { return NULL; }