Add parented variants of the IRQ allocation helpers under the
well-known names, taking (Object *owner, const char *name, ...) as
their first two arguments:

  qemu_allocate_irq(owner, name, handler, opaque, n)
  qemu_allocate_irqs(owner, name, handler, opaque, n)
  qemu_extend_irqs(owner, name, old, n_old, handler, opaque, n)
  qemu_irq_invert(owner, name, irq)

The new IRQ object is created via object_new_child() so it lands
under @owner with a stable path.  The array/extend variants suffix
"[*]" so callers pass a bare name and get name[0], name[1], ...

qemu_free_irq() is taught to unparent when the IRQ has a QOM parent,
so it works for both the *_orphan() and the parented allocation
paths during the transition.

The *_orphan() variants stay for now; later commits convert every
caller and delete them, at which point the /machine/unattached
fallback in qdev_connect_gpio_out_named() also goes away.

Assisted-by: Kiro
Signed-off-by: Alexander Graf <[email protected]>
---
 hw/core/irq.c         | 45 ++++++++++++++++++++++++++++++++++++++++++-
 include/hw/core/irq.h | 15 +++++++++++++++
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/hw/core/irq.c b/hw/core/irq.c
index f8fdeb7e02..ee954eaf62 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -96,6 +96,38 @@ qemu_irq qemu_allocate_irq_orphan(qemu_irq_handler handler, 
void *opaque, int n)
     return irq;
 }
 
+qemu_irq qemu_allocate_irq(Object *owner, const char *name,
+                           qemu_irq_handler handler, void *opaque, int n)
+{
+    IRQState *irq = IRQ(object_new_child(owner, name, TYPE_IRQ));
+    init_irq_fields(irq, handler, opaque, n);
+    return irq;
+}
+
+qemu_irq *qemu_extend_irqs(Object *owner, const char *name,
+                           qemu_irq *old, int n_old,
+                           qemu_irq_handler handler, void *opaque, int n)
+{
+    g_autofree char *propname = g_strdup_printf("%s[*]", name);
+    qemu_irq *s;
+    int i;
+
+    if (!old) {
+        n_old = 0;
+    }
+    s = old ? g_renew(qemu_irq, old, n + n_old) : g_new(qemu_irq, n);
+    for (i = n_old; i < n + n_old; i++) {
+        s[i] = qemu_allocate_irq(owner, propname, handler, opaque, i);
+    }
+    return s;
+}
+
+qemu_irq *qemu_allocate_irqs(Object *owner, const char *name,
+                             qemu_irq_handler handler, void *opaque, int n)
+{
+    return qemu_extend_irqs(owner, name, NULL, 0, handler, opaque, n);
+}
+
 void qemu_free_irqs(qemu_irq *s, int n)
 {
     int i;
@@ -107,7 +139,11 @@ void qemu_free_irqs(qemu_irq *s, int n)
 
 void qemu_free_irq(qemu_irq irq)
 {
-    object_unref(OBJECT(irq));
+    if (irq && OBJECT(irq)->parent) {
+        object_unparent(OBJECT(irq));
+    } else {
+        object_unref(OBJECT(irq));
+    }
 }
 
 static void qemu_notirq(void *opaque, int line, int level)
@@ -124,6 +160,13 @@ qemu_irq qemu_irq_invert_orphan(qemu_irq irq)
     return qemu_allocate_irq_orphan(qemu_notirq, irq, 0);
 }
 
+qemu_irq qemu_irq_invert(Object *owner, const char *name, qemu_irq irq)
+{
+    /* The default state for IRQs is low, so raise the output now.  */
+    qemu_irq_raise(irq);
+    return qemu_allocate_irq(owner, name, qemu_notirq, irq, 0);
+}
+
 void qemu_irq_set_observer(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
 {
     int i;
diff --git a/include/hw/core/irq.h b/include/hw/core/irq.h
index f984c02c14..5ccccd2697 100644
--- a/include/hw/core/irq.h
+++ b/include/hw/core/irq.h
@@ -85,6 +85,20 @@ qemu_irq *qemu_allocate_irqs_orphan(qemu_irq_handler 
handler, void *opaque, int
  */
 qemu_irq qemu_allocate_irq_orphan(qemu_irq_handler handler, void *opaque, int 
n);
 
+/*
+ * Same as the *_orphan() variants above, but the new IRQ objects are
+ * parented under @owner with property name @name (or @name[*] for the
+ * array/extend variants).  The reference is held by @owner; call
+ * qemu_free_irq() to unparent and free.
+ */
+qemu_irq qemu_allocate_irq(Object *owner, const char *name,
+                           qemu_irq_handler handler, void *opaque, int n);
+qemu_irq *qemu_allocate_irqs(Object *owner, const char *name,
+                             qemu_irq_handler handler, void *opaque, int n);
+qemu_irq *qemu_extend_irqs(Object *owner, const char *name,
+                           qemu_irq *old, int n_old,
+                           qemu_irq_handler handler, void *opaque, int n);
+
 /* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
  * preserved. New IRQs are assigned the argument handler and opaque data.
  */
@@ -96,6 +110,7 @@ void qemu_free_irq(qemu_irq irq);
 
 /* Returns a new IRQ with opposite polarity.  */
 qemu_irq qemu_irq_invert_orphan(qemu_irq irq);
+qemu_irq qemu_irq_invert(Object *owner, const char *name, qemu_irq irq);
 
 /* For internal use in qtest. */
 void qemu_irq_set_observer(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
-- 
2.47.1


Reply via email to