[RFC PATCH v2 116/137] hw/core: Parent GPIO input IRQs and embedded IRQState via QOM

Alexander Graf <[email protected]>
Newsgroups org.nongnu.qemu-arm,org.nongnu.qemu-devel,org.nongnu.qemu-riscv
Message-ID <[email protected]>
qdev_init_gpio_in_named_with_opaque() now uses qemu_extend_irqs()
directly, so the input IRQ objects are parented under the device via
object_new_child() and the manual object_property_add_child() loop
goes away.  device_finalize() no longer needs to free the IRQ objects
explicitly since child<> property destruction does that; only the
qemu_irq* array itself needs g_free().

Convert the six users of qemu_init_irq()/qemu_init_irqs() (which
initialize an IRQState embedded in a device struct) to
qemu_init_irq_child() so those IRQs also get a QOM parent.

qdev_connect_gpio_out_named() now asserts that its input pin has a
parent instead of falling back to /machine/unattached; every
qemu_irq that reaches it is parented after this and the preceding
commits.

AI-used-for: code (refactoring)
Signed-off-by: Alexander Graf <[email protected]>
---
 hw/core/gpio.c    | 24 ++++--------------------
 hw/core/qdev.c    |  3 ++-
 hw/ipack/ipack.c  | 11 +++++++++--
 hw/isa/vt82c686.c |  3 ++-
 hw/net/imx_fec.c  |  2 +-
 hw/net/lan9118.c  |  2 +-
 hw/ppc/pegasos.c  |  3 ++-
 hw/sh4/r2d.c      |  5 ++++-
 8 files changed, 25 insertions(+), 28 deletions(-)

diff --git a/hw/core/gpio.c b/hw/core/gpio.c
index ef8ef8f25a..f76d604520 100644
--- a/hw/core/gpio.c
+++ b/hw/core/gpio.c
@@ -45,24 +45,12 @@ void qdev_init_gpio_in_named_with_opaque(DeviceState *dev,
                                          void *opaque,
                                          const char *name, int n)
 {
-    int i;
     NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name);
 
     assert(gpio_list->num_out == 0 || !name);
-    gpio_list->in = qemu_extend_irqs_orphan(gpio_list->in, gpio_list->num_in, handler,
-                                     opaque, n);
-
-    if (!name) {
-        name = "unnamed-gpio-in";
-    }
-    for (i = gpio_list->num_in; i < gpio_list->num_in + n; i++) {
-        gchar *propname = g_strdup_printf("%s[%u]", name, i);
-
-        object_property_add_child(OBJECT(dev), propname,
-                                  OBJECT(gpio_list->in[i]));
-        g_free(propname);
-    }
-
+    gpio_list->in = qemu_extend_irqs(OBJECT(dev), name ?: "unnamed-gpio-in",
+                                     gpio_list->in, gpio_list->num_in,
+                                     handler, opaque, n);
     gpio_list->num_in += n;
 }
 
@@ -119,11 +107,7 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
 {
     char *propname = g_strdup_printf("%s[%d]",
                                      name ? name : "unnamed-gpio-out", n);
-    if (input_pin && !OBJECT(input_pin)->parent) {
-        /* We need a name for object_property_set_link to work */
-        object_property_add_child(machine_get_container("unattached"),
-                                  "non-qdev-gpio[*]", OBJECT(input_pin));
-    }
+    g_assert(!input_pin || OBJECT(input_pin)->parent);
     object_property_set_link(OBJECT(dev), propname,
                              OBJECT(input_pin), &error_abort);
     g_free(propname);
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 89bc1e30c0..9a68fb426e 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -698,7 +698,8 @@ static void device_finalize(Object *obj)
 
     QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
         QLIST_REMOVE(ngl, node);
-        qemu_free_irqs(ngl->in, ngl->num_in);
+        /* IRQs are child<> properties of dev; freed via child destruction */
+        g_free(ngl->in);
         g_free(ngl->name);
         g_free(ngl);
         /* ngl->out irqs are owned by the other end and should not be freed
diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c
index f2e5524fa8..dad0d486df 100644
--- a/hw/ipack/ipack.c
+++ b/hw/ipack/ipack.c
@@ -55,18 +55,25 @@ static void ipack_device_realize(DeviceState *dev, Error **errp)
     }
     bus->free_slot = idev->slot + 1;
 
-    qemu_init_irqs(idev->irq, ARRAY_SIZE(idev->irq), bus->set_irq, idev);
+    for (int i = 0; i < ARRAY_SIZE(idev->irq); i++) {
+        qemu_init_irq_child(OBJECT(idev), "irq[*]", &idev->irq[i],
+                            bus->set_irq, idev, i);
+    }
 
     k->realize(dev, errp);
 }
 
 static void ipack_device_unrealize(DeviceState *dev)
 {
+    IPackDevice *idev = IPACK_DEVICE(dev);
     IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
 
     if (k->unrealize) {
         k->unrealize(dev);
-        return;
+    }
+
+    for (int i = 0; i < ARRAY_SIZE(idev->irq); i++) {
+        object_unparent(OBJECT(&idev->irq[i]));
     }
 }
 
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 2337c3115b..f93bf49754 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -722,7 +722,8 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
 
     qdev_init_gpio_out_named(dev, &s->cpu_intr, "intr", 1);
     qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS);
-    qemu_init_irq(&s->i8259_irq, via_isa_request_i8259_irq, s, 0);
+    qemu_init_irq_child(OBJECT(s), "i8259-irq", &s->i8259_irq,
+                        via_isa_request_i8259_irq, s, 0);
     isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d),
                           errp);
 
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index c177b7ff2b..38e0f64462 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1205,7 +1205,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
     sysbus_init_irq(sbd, &s->irq[0]);
     sysbus_init_irq(sbd, &s->irq[1]);
 
-    qemu_init_irq(&s->mii_irq, imx_phy_update_irq, s, 0);
+    qemu_init_irq_child(OBJECT(s), "mii-irq", &s->mii_irq, imx_phy_update_irq, s, 0);
     object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
     if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
         return;
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 91c3533702..2003280fc4 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1274,7 +1274,7 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
     const MemoryRegionOps *mem_ops =
             s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
 
-    qemu_init_irq(&s->mii_irq, lan9118_update_irq, s, 0);
+    qemu_init_irq_child(OBJECT(s), "mii-irq", &s->mii_irq, lan9118_update_irq, s, 0);
     object_initialize_child(OBJECT(s), "mii", &s->mii, TYPE_LAN9118_PHY);
     if (!sysbus_realize_and_unref(SYS_BUS_DEVICE(&s->mii), errp)) {
         return;
diff --git a/hw/ppc/pegasos.c b/hw/ppc/pegasos.c
index 426a54d8ee..845b6355e9 100644
--- a/hw/ppc/pegasos.c
+++ b/hw/ppc/pegasos.c
@@ -134,7 +134,8 @@ static void pegasos2_setup_pci_irq(PegasosMachineState *pm)
                                                    TYPE_OR_IRQ, &error_fatal,
                                                    "num-lines", "2", NULL);
                 qdev_realize(DEVICE(ori), NULL, &error_fatal);
-                qemu_init_irq(&pm->pci_irqs[i], pegasos2_pci_irq, pm, i);
+                qemu_init_irq_child(OBJECT(pm), "pci-irq[*]", &pm->pci_irqs[i],
+                                    pegasos2_pci_irq, pm, i);
                 qdev_connect_gpio_out(DEVICE(ori), 0, &pm->pci_irqs[i]);
                 pm->mv_pirq[i] = qdev_get_gpio_in_named(pm->nb, "gpp", 12 + i);
                 pm->via_pirq[i] = qdev_get_gpio_in_named(pm->sb, "pirq", i);
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 8deda6e5f4..21e804f3d9 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -200,7 +200,10 @@ static r2d_fpga_t *r2d_fpga_init(Object *owner,
     memory_region_init_io(&s->iomem, owner, &r2d_fpga_ops, s, "r2d-fpga", 0x40);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    qemu_init_irqs(s->irq, NR_IRQS, r2d_fpga_irq_set, s);
+    for (int i = 0; i < NR_IRQS; i++) {
+        qemu_init_irq_child(owner, "fpga-irq[*]", &s->irq[i],
+                            r2d_fpga_irq_set, s, i);
+    }
 
     return s;
 }
-- 
2.47.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.