@@ -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);
@@ -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.
*/
@@ -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;
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@intel.com> --- hw/core/qdev.c | 29 ++++++++++++++--------------- include/hw/qdev-core.h | 4 ++++ include/qemu/typedefs.h | 1 + 3 files changed, 19 insertions(+), 15 deletions(-)