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
