The device topology structures based on buses are unidirectional: the parent device can access the child device through the BusChild within the bus, but not vice versa. For the CPU topology tree constructed on the device-bus, it is necessary for the child device to be able to access the parent device via the parent bus. To address this, introduce a pointer to the BusChild, named bus_node. This pointer also simplifies the logic of bus_remove_child(). Instead of the parent bus needing to traverse the children list to locate the corresponding BusChild, it can now directly find it using the bus_node pointer. Signed-off-by: Zhao Liu <zhao1.liu@xxxxxxxxx> --- hw/core/qdev.c | 29 ++++++++++++++--------------- include/hw/qdev-core.h | 4 ++++ include/qemu/typedefs.h | 1 + 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index db36f54d914a..4429856eaddd 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -57,25 +57,23 @@ static void bus_free_bus_child(BusChild *kid) static void bus_remove_child(BusState *bus, DeviceState *child) { - BusChild *kid; - - QTAILQ_FOREACH(kid, &bus->children, sibling) { - if (kid->child == child) { - char name[32]; + BusChild *kid = child->bus_node; + char name[32]; - snprintf(name, sizeof(name), "child[%d]", kid->index); - QTAILQ_REMOVE_RCU(&bus->children, kid, sibling); + if (!kid) { + return; + } - bus->num_children--; + snprintf(name, sizeof(name), "child[%d]", kid->index); + QTAILQ_REMOVE_RCU(&bus->children, kid, sibling); + child->bus_node = NULL; + bus->num_children--; - /* This gives back ownership of kid->child back to us. */ - object_property_del(OBJECT(bus), name); + /* This gives back ownership of kid->child back to us. */ + object_property_del(OBJECT(bus), name); - /* free the bus kid, when it is safe to do so*/ - call_rcu(kid, bus_free_bus_child, rcu); - break; - } - } + /* free the bus kid, when it is safe to do so*/ + call_rcu(kid, bus_free_bus_child, rcu); } static void bus_add_child(BusState *bus, DeviceState *child) @@ -86,6 +84,7 @@ static void bus_add_child(BusState *bus, DeviceState *child) bus->num_children++; kid->index = bus->max_index++; kid->child = child; + child->bus_node = kid; object_ref(OBJECT(kid->child)); QTAILQ_INSERT_HEAD_RCU(&bus->children, kid, sibling); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index aa97c34a4be7..85c7d462dfba 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -253,6 +253,10 @@ struct DeviceState { * @parent_bus: bus this device belongs to */ BusState *parent_bus; + /** + * @bus_node: bus node inserted in parent bus + */ + BusChild *bus_node; /** * @gpios: QLIST of named GPIOs the device provides. */ diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 9d222dc37628..aef41c4e67ce 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -32,6 +32,7 @@ typedef struct BdrvDirtyBitmapIter BdrvDirtyBitmapIter; typedef struct BlockBackend BlockBackend; typedef struct BlockBackendRootState BlockBackendRootState; typedef struct BlockDriverState BlockDriverState; +typedef struct BusChild BusChild; typedef struct BusClass BusClass; typedef struct BusState BusState; typedef struct Chardev Chardev; -- 2.34.1