From 71e5770b618a2a10d9f92eade0ea0f2c8aaca58d Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 9 Jun 2020 14:23:18 +0200 Subject: sd/pxa2xx_mmci: Fix to realize "pxa2xx-mmci" device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pxa2xx_mmci_init() creates a "pxa2xx-mmci" device, but neglects to realize it. Affects machines akita, borzoi, connex, mainstone, spitz, terrier, tosa, verdex, and z2. In theory, a device becomes real only on realize. In practice, the transition from unreal to real is a fuzzy one. The work to make a device real can be spread between realize methods (fine), instance_init methods (wrong), and board code wiring up the device (fine as long as it effectively happens on realize). Depending on what exactly is done where, a device can work even when we neglect to realize it. This one appears to work. Nevertheless, it's a clear misuse of the interface. Even when it works today (more or less by chance), it can break tomorrow. Fix by realizing it right away. Visible in "info qom-tree"; here's the change for akita: /machine (akita-machine) [...] /unattached (container) [...] + /device[5] (pxa2xx-mmci) + /pxa2xx-mmci[0] (qemu:memory-region) + /sd-bus (pxa2xx-mmci-bus) [rest of device[*] renumbered...] Fixes: 7a9468c92517e19037bfe2272f64f5dadaf9db15 Cc: Andrzej Zaborowski Cc: Peter Maydell Cc: qemu-arm@nongnu.org Signed-off-by: Markus Armbruster Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20200609122339.937862-4-armbru@redhat.com> --- hw/sd/pxa2xx_mmci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw/sd') diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index f9c50ddda5..c32df1b8f9 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -492,6 +492,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, sysbus_connect_irq(sbd, 0, irq); qdev_connect_gpio_out_named(dev, "rx-dma", 0, rx_dma); qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma); + qdev_init_nofail(dev); /* Create and plug in the sd card */ carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD); -- cgit v1.2.3 From 007d1dbf72536ec1b847a944832e4de1546af2ac Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 9 Jun 2020 14:23:38 +0200 Subject: sd: Hide the qdev-but-not-quite thing created by sd_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 260bc9d8aa "hw/sd/sd.c: QOMify" QOMified only the device itself, not its users. It kept sd_init() around for non-QOMified users. More than four years later, three such users remain: omap1 (machines cheetah, sx1, sx1-v1) and omap2 (machines n800, n810) are not QOMified, and pl181 (machines integratorcp, realview-eb, realview-eb-mpcore, realview-pb-a8 realview-pbx-a9, versatileab, versatilepb, vexpress-a15, vexpress-a9) is not QOMified properly. The issue I presently have with this: an "sd-card" device should plug into an "sd-bus" (its DeviceClass member bus_type says so), but sd_init() leaves it unplugged. This is normally a bug (I just fixed some instances), and I'd like to assert proper pluggedness to prevent regressions. However, the qdev-but-not-quite thing returned by sd_init() would fail the assertion. Meh. Make sd_init() hide it from QOM/qdev. Visible in "info qom-tree", here's the change for cheetah: /machine (cheetah-machine) [...] /unattached (container) [...] /device[5] (serial-mm) /serial (serial) /serial[0] (qemu:memory-region) - /device[6] (sd-card) - /device[7] (omap-gpio) + /device[6] (omap-gpio) [rest of device[*] renumbered...] Cc: "Philippe Mathieu-Daudé" Signed-off-by: Markus Armbruster Message-Id: <20200609122339.937862-24-armbru@redhat.com> --- hw/sd/sd.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'hw/sd') diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 3c06a0ac6d..7070a116ea 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -83,6 +83,10 @@ enum SDCardStates { struct SDState { DeviceState parent_obj; + /* If true, created by sd_init() for a non-qdevified caller */ + /* TODO purge them with fire */ + bool me_no_qdev_me_kill_mammoth_with_rocks; + /* SD Memory Card Registers */ uint32_t ocr; uint8_t scr[8]; @@ -129,6 +133,8 @@ struct SDState { bool cmd_line; }; +static void sd_realize(DeviceState *dev, Error **errp); + static const char *sd_state_name(enum SDCardStates state) { static const char *state_name[] = { @@ -590,7 +596,7 @@ static void sd_cardchange(void *opaque, bool load, Error **errp) { SDState *sd = opaque; DeviceState *dev = DEVICE(sd); - SDBus *sdbus = SD_BUS(qdev_get_parent_bus(dev)); + SDBus *sdbus; bool inserted = sd_get_inserted(sd); bool readonly = sd_get_readonly(sd); @@ -601,18 +607,16 @@ static void sd_cardchange(void *opaque, bool load, Error **errp) trace_sdcard_ejected(); } - /* The IRQ notification is for legacy non-QOM SD controller devices; - * QOMified controllers use the SDBus APIs. - */ - if (sdbus) { - sdbus_set_inserted(sdbus, inserted); + if (sd->me_no_qdev_me_kill_mammoth_with_rocks) { + qemu_set_irq(sd->inserted_cb, inserted); if (inserted) { - sdbus_set_readonly(sdbus, readonly); + qemu_set_irq(sd->readonly_cb, readonly); } } else { - qemu_set_irq(sd->inserted_cb, inserted); + sdbus = SD_BUS(qdev_get_parent_bus(dev)); + sdbus_set_inserted(sdbus, inserted); if (inserted) { - qemu_set_irq(sd->readonly_cb, readonly); + sdbus_set_readonly(sdbus, readonly); } } } @@ -697,6 +701,7 @@ SDState *sd_init(BlockBackend *blk, bool is_spi) { Object *obj; DeviceState *dev; + SDState *sd; Error *err = NULL; obj = object_new(TYPE_SD_CARD); @@ -707,13 +712,24 @@ SDState *sd_init(BlockBackend *blk, bool is_spi) return NULL; } qdev_prop_set_bit(dev, "spi", is_spi); - object_property_set_bool(obj, true, "realized", &err); + + /* + * Realizing the device properly would put it into the QOM + * composition tree even though it is not plugged into an + * appropriate bus. That's a no-no. Hide the device from + * QOM/qdev, and call its qdev realize callback directly. + */ + object_ref(obj); + object_unparent(obj); + sd_realize(dev, &err); if (err) { error_reportf_err(err, "sd_init failed: "); return NULL; } - return SD_CARD(dev); + sd = SD_CARD(dev); + sd->me_no_qdev_me_kill_mammoth_with_rocks = true; + return sd; } void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert) -- cgit v1.2.3 From 3e80f6902c13f6edb6675c0f33edcbbf0163ec32 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 10 Jun 2020 07:31:58 +0200 Subject: qdev: Convert uses of qdev_create() with Coccinelle This is the transformation explained in the commit before previous. Takes care of just one pattern that needs conversion. More to come in this series. Coccinelle script: @ depends on !(file in "hw/arm/highbank.c")@ expression bus, type_name, dev, expr; @@ - dev = qdev_create(bus, type_name); + dev = qdev_new(type_name); ... when != dev = expr - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, bus, &error_fatal); @@ expression bus, type_name, dev, expr; identifier DOWN; @@ - dev = DOWN(qdev_create(bus, type_name)); + dev = DOWN(qdev_new(type_name)); ... when != dev = expr - qdev_init_nofail(DEVICE(dev)); + qdev_realize_and_unref(DEVICE(dev), bus, &error_fatal); @@ expression bus, type_name, expr; identifier dev; @@ - DeviceState *dev = qdev_create(bus, type_name); + DeviceState *dev = qdev_new(type_name); ... when != dev = expr - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, bus, &error_fatal); @@ expression bus, type_name, dev, expr, errp; symbol true; @@ - dev = qdev_create(bus, type_name); + dev = qdev_new(type_name); ... when != dev = expr - object_property_set_bool(OBJECT(dev), true, "realized", errp); + qdev_realize_and_unref(dev, bus, errp); @@ expression bus, type_name, expr, errp; identifier dev; symbol true; @@ - DeviceState *dev = qdev_create(bus, type_name); + DeviceState *dev = qdev_new(type_name); ... when != dev = expr - object_property_set_bool(OBJECT(dev), true, "realized", errp); + qdev_realize_and_unref(dev, bus, errp); The first rule exempts hw/arm/highbank.c, because it matches along two control flow paths there, with different @type_name. Covered by the next commit's manual conversions. Missing #include "qapi/error.h" added manually. Signed-off-by: Markus Armbruster Reviewed-by: Paolo Bonzini Message-Id: <20200610053247.1583243-10-armbru@redhat.com> [Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved] --- hw/sd/milkymist-memcard.c | 4 ++-- hw/sd/pxa2xx_mmci.c | 8 ++++---- hw/sd/ssi-sd.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'hw/sd') diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 926e1af475..4cfdf7b64c 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -278,9 +278,9 @@ static void milkymist_memcard_realize(DeviceState *dev, Error **errp) /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; - carddev = qdev_create(BUS(&s->sdbus), TYPE_SD_CARD); + carddev = qdev_new(TYPE_SD_CARD); qdev_prop_set_drive(carddev, "drive", blk, &err); - object_property_set_bool(OBJECT(carddev), true, "realized", &err); + qdev_realize_and_unref(carddev, BUS(&s->sdbus), &err); if (err) { error_setg(errp, "failed to init SD card: %s", error_get_pretty(err)); return; diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index c32df1b8f9..89784407b9 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -485,23 +485,23 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, PXA2xxMMCIState *s; Error *err = NULL; - dev = qdev_create(NULL, TYPE_PXA2XX_MMCI); + dev = qdev_new(TYPE_PXA2XX_MMCI); s = PXA2XX_MMCI(dev); sbd = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sbd, 0, base); sysbus_connect_irq(sbd, 0, irq); qdev_connect_gpio_out_named(dev, "rx-dma", 0, rx_dma); qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma); - qdev_init_nofail(dev); + qdev_realize_and_unref(dev, NULL, &error_fatal); /* Create and plug in the sd card */ - carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD); + carddev = qdev_new(TYPE_SD_CARD); qdev_prop_set_drive(carddev, "drive", blk, &err); if (err) { error_reportf_err(err, "failed to init SD card: "); return NULL; } - object_property_set_bool(OBJECT(carddev), true, "realized", &err); + qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"), &err); if (err) { error_reportf_err(err, "failed to init SD card: "); return NULL; diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index 829797b597..f98a6f3ae1 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -252,7 +252,7 @@ static void ssi_sd_realize(SSISlave *d, Error **errp) /* Create and plug in the sd card */ /* FIXME use a qdev drive property instead of drive_get_next() */ dinfo = drive_get_next(IF_SD); - carddev = qdev_create(BUS(&s->sdbus), TYPE_SD_CARD); + carddev = qdev_new(TYPE_SD_CARD); if (dinfo) { qdev_prop_set_drive(carddev, "drive", blk_by_legacy_dinfo(dinfo), &err); if (err) { @@ -265,7 +265,7 @@ static void ssi_sd_realize(SSISlave *d, Error **errp) goto fail; } - object_property_set_bool(OBJECT(carddev), true, "realized", &err); + qdev_realize_and_unref(carddev, BUS(&s->sdbus), &err); if (err) { goto fail; } -- cgit v1.2.3 From 3c6ef471ee67bf5a22a9e0ecfdc45ca7d2393216 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 10 Jun 2020 07:32:34 +0200 Subject: sysbus: Convert to sysbus_realize() etc. with Coccinelle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert from qdev_realize(), qdev_realize_and_unref() with null @bus argument to sysbus_realize(), sysbus_realize_and_unref(). Coccinelle script: @@ expression dev, errp; @@ - qdev_realize(DEVICE(dev), NULL, errp); + sysbus_realize(SYS_BUS_DEVICE(dev), errp); @@ expression sysbus_dev, dev, errp; @@ + sysbus_dev = SYS_BUS_DEVICE(dev); - qdev_realize_and_unref(dev, NULL, errp); + sysbus_realize_and_unref(sysbus_dev, errp); - sysbus_dev = SYS_BUS_DEVICE(dev); @@ expression sysbus_dev, dev, errp; expression expr; @@ sysbus_dev = SYS_BUS_DEVICE(dev); ... when != dev = expr; - qdev_realize_and_unref(dev, NULL, errp); + sysbus_realize_and_unref(sysbus_dev, errp); @@ expression dev, errp; @@ - qdev_realize_and_unref(DEVICE(dev), NULL, errp); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp); @@ expression dev, errp; @@ - qdev_realize_and_unref(dev, NULL, errp); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp); Whitespace changes minimized manually. Signed-off-by: Markus Armbruster Acked-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Paolo Bonzini Message-Id: <20200610053247.1583243-46-armbru@redhat.com> [Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved] --- hw/sd/pxa2xx_mmci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/sd') diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index 89784407b9..623be70b26 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -492,7 +492,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, sysbus_connect_irq(sbd, 0, irq); qdev_connect_gpio_out_named(dev, "rx-dma", 0, rx_dma); qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma); - qdev_realize_and_unref(dev, NULL, &error_fatal); + sysbus_realize_and_unref(sbd, &error_fatal); /* Create and plug in the sd card */ carddev = qdev_new(TYPE_SD_CARD); -- cgit v1.2.3 From 7089e0cc468597556bb208ae8e3853499b746ebd Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 10 Jun 2020 07:32:39 +0200 Subject: sysbus: Convert qdev_set_parent_bus() use with Coccinelle, part 4 This is still the same transformation as in the previous commits, but here the sysbus_init_child_obj() and its matching realize in are in separate files. Fortunately, there's just one realize left to convert. Signed-off-by: Markus Armbruster Reviewed-by: Paolo Bonzini Message-Id: <20200610053247.1583243-51-armbru@redhat.com> --- hw/sd/aspeed_sdhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/sd') diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c index 6a039a1d2f..538d3bad3d 100644 --- a/hw/sd/aspeed_sdhci.c +++ b/hw/sd/aspeed_sdhci.c @@ -145,7 +145,7 @@ static void aspeed_sdhci_realize(DeviceState *dev, Error **errp) return; } - object_property_set_bool(sdhci_slot, true, "realized", &err); + sysbus_realize(sbd_slot, &err); if (err) { error_propagate(errp, err); return; -- cgit v1.2.3