From b235a71f52f60d42dd69c4ac2e41fa5a5861cf85 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Thu, 25 Sep 2014 22:17:08 -0700 Subject: [PATCH 01/47] qdev: gpio: Don't allow name share between I and O MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only allow a GPIO name to be one or the other. Inputs and outputs are functionally different and should be in different namespaces. Prepares support for the QOMification of IRQs as Links or Child objects. The alternative is to munge names .e.g. with "-in" or "-out" suffixes when giving QOM names. But that reduces clarity and if there are cases out there where users want I and O with same name they can manually add their own suffixes. Reviewed-by: Alexander Graf Signed-off-by: Peter Crosthwaite Signed-off-by: Andreas Färber --- hw/core/qdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index fcb16383a1..976e20861a 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -339,6 +339,7 @@ void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, { NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + assert(gpio_list->num_out == 0 || !name); gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler, dev, n); gpio_list->num_in += n; @@ -354,6 +355,7 @@ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, { NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + assert(gpio_list->num_in == 0 || !name); assert(gpio_list->num_out == 0); gpio_list->num_out = n; gpio_list->out = pins; From a69bef1cf12159233b0ba193bd9dc9b173cea453 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Thu, 25 Sep 2014 22:17:41 -0700 Subject: [PATCH 02/47] qdev: gpio: Register GPIO inputs as child objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To the device that contains them. This will allow for referencing a GPIO input from it's canonical path (exciting for dynamic machine generation!) Reviewed-by: Alexander Graf Signed-off-by: Peter Crosthwaite Signed-off-by: Andreas Färber --- hw/core/qdev.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 976e20861a..a140c79757 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -337,11 +337,20 @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev, void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, const char *name, int n) { + int i; NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + char *propname = g_strdup_printf("%s[*]", name ? name : "unnamed-gpio-in"); assert(gpio_list->num_out == 0 || !name); gpio_list->in = qemu_extend_irqs(gpio_list->in, gpio_list->num_in, handler, dev, n); + + for (i = gpio_list->num_in; i < gpio_list->num_in + n; i++) { + object_property_add_child(OBJECT(dev), propname, + OBJECT(gpio_list->in[i]), &error_abort); + } + g_free(propname); + gpio_list->num_in += n; } From 688b057aece53003f9d5a1dadc8961482dc2d948 Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Thu, 25 Sep 2014 22:18:14 -0700 Subject: [PATCH 03/47] qdev: gpio: Register GPIO outputs as QOM links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Within the object that contains the GPIO output. This allows for connecting GPIO outputs via setting of a Link property. Also clear the link value to zero. This catch-alls the case where a device improperly inits a gpio_out (malloc instead of malloc0). Reviewed-by: Alexander Graf Signed-off-by: Peter Crosthwaite Signed-off-by: Andreas Färber --- hw/core/qdev.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index a140c79757..2b42d5b58c 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -362,12 +362,24 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n) void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, const char *name, int n) { + int i; NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + char *propname = g_strdup_printf("%s[*]", name ? name : "unnamed-gpio-out"); assert(gpio_list->num_in == 0 || !name); assert(gpio_list->num_out == 0); gpio_list->num_out = n; gpio_list->out = pins; + + for (i = 0; i < n; ++i) { + memset(&pins[i], 0, sizeof(*pins)); + object_property_add_link(OBJECT(dev), propname, TYPE_IRQ, + (Object **)&pins[i], + object_property_allow_set_link, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &error_abort); + } + g_free(propname); } void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n) From 3a53009fa044a554dbdeacf30a6b8ea3eb02fe63 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Sat, 27 Sep 2014 13:13:55 +0800 Subject: [PATCH 04/47] qom: Add error handler for object_property_print() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid the caller of object_property_print() leaking string argument's memory, such as qdev_print_props() when encounter errors. Reviewed-by: Paolo Bonzini Signed-off-by: Gonglei Signed-off-by: Andreas Färber --- qom/object.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/qom/object.c b/qom/object.c index da0919a3dd..21135e1a08 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1010,11 +1010,19 @@ char *object_property_print(Object *obj, const char *name, bool human, Error **errp) { StringOutputVisitor *mo; - char *string; + char *string = NULL; + Error *local_err = NULL; mo = string_output_visitor_new(human); - object_property_get(obj, string_output_get_visitor(mo), name, errp); + object_property_get(obj, string_output_get_visitor(mo), name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto out; + } + string = string_output_get_string(mo); + +out: string_output_visitor_cleanup(mo); return string; } From 8ae9a9ef4e610a58d0748f5aa7dd144b08e09039 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Sat, 27 Sep 2014 13:13:56 +0800 Subject: [PATCH 05/47] qom: Add error handler for object alias property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit object_property_add_alias() is called at some places at present. And its parameter errp may not NULL, such as object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread", &error_abort); This patch add error handler for security. Cc: Stefan Hajnoczi Cc: Michael S. Tsirkin Cc: Markus Armbruster Reviewed-by: Paolo Bonzini Signed-off-by: Gonglei Signed-off-by: Andreas Färber --- qom/object.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/qom/object.c b/qom/object.c index 21135e1a08..575291f109 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1642,6 +1642,7 @@ void object_property_add_alias(Object *obj, const char *name, ObjectProperty *op; ObjectProperty *target_prop; gchar *prop_type; + Error *local_err = NULL; target_prop = object_property_find(target_obj, target_name, errp); if (!target_prop) { @@ -1663,9 +1664,15 @@ void object_property_add_alias(Object *obj, const char *name, property_get_alias, property_set_alias, property_release_alias, - prop, errp); + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + goto out; + } op->resolve = property_resolve_alias; +out: g_free(prop_type); } From ac2c4946ccc62e0c3eabd93206134f9e98db75c9 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:06 +0000 Subject: [PATCH 06/47] tests: virtio-scsi: Check if hot-plug/unplug works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- tests/virtio-scsi-test.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c index 3230908b98..41f9602e44 100644 --- a/tests/virtio-scsi-test.c +++ b/tests/virtio-scsi-test.c @@ -17,14 +17,43 @@ static void pci_nop(void) { } +static void hotplug(void) +{ + QDict *response; + + response = qmp("{\"execute\": \"device_add\"," + " \"arguments\": {" + " \"driver\": \"scsi-hd\"," + " \"id\": \"scsi-hd\"," + " \"drive\": \"drv1\"" + "}}"); + + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + response = qmp("{\"execute\": \"device_del\"," + " \"arguments\": {" + " \"id\": \"scsi-hd\"" + "}}"); + + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + g_assert(qdict_haskey(response, "event")); + g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); + QDECREF(response); +} + int main(int argc, char **argv) { int ret; g_test_init(&argc, &argv, NULL); qtest_add_func("/virtio/scsi/pci/nop", pci_nop); + qtest_add_func("/virtio/scsi/pci/hotplug", hotplug); qtest_start("-drive id=drv0,if=none,file=/dev/null " + "-drive id=drv1,if=none,file=/dev/null " "-device virtio-scsi-pci,id=vscsi0 " "-device scsi-hd,bus=vscsi0.0,drive=drv0"); ret = g_test_run(); From 823a9987c99da3d2ee6249730f6cf5c4dcdc15cc Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:07 +0000 Subject: [PATCH 07/47] tests: virtio-serial: Check if hot-plug/unplug works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- tests/virtio-serial-test.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/virtio-serial-test.c b/tests/virtio-serial-test.c index e7438751ea..bf030a6162 100644 --- a/tests/virtio-serial-test.c +++ b/tests/virtio-serial-test.c @@ -17,12 +17,39 @@ static void pci_nop(void) { } +static void hotplug(void) +{ + QDict *response; + + response = qmp("{\"execute\": \"device_add\"," + " \"arguments\": {" + " \"driver\": \"virtserialport\"," + " \"id\": \"hp-port\"" + "}}"); + + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + response = qmp("{\"execute\": \"device_del\"," + " \"arguments\": {" + " \"id\": \"hp-port\"" + "}}"); + + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + g_assert(qdict_haskey(response, "event")); + g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); + QDECREF(response); +} + int main(int argc, char **argv) { int ret; g_test_init(&argc, &argv, NULL); qtest_add_func("/virtio/serial/pci/nop", pci_nop); + qtest_add_func("/virtio/serial/pci/hotplug", hotplug); qtest_start("-device virtio-serial-pci"); ret = g_test_run(); From 2f8b2767203a73814b3c3c386e3ed74cd0b5a32e Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:08 +0000 Subject: [PATCH 08/47] libqos: Add qpci_plug_device_test() and qpci_unplug_acpi_device_test() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Functions will be used for testing hot(un)plug of PCI devices. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- tests/libqos/pci-pc.c | 49 +++++++++++++++++++++++++++++++++++++++++++ tests/libqos/pci.h | 3 +++ 2 files changed, 52 insertions(+) diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c index 0609294af0..6dba0db00a 100644 --- a/tests/libqos/pci-pc.c +++ b/tests/libqos/pci-pc.c @@ -20,6 +20,9 @@ #include +#define ACPI_PCIHP_ADDR 0xae00 +#define PCI_EJ_BASE 0x0008 + typedef struct QPCIBusPC { QPCIBus bus; @@ -247,3 +250,49 @@ void qpci_free_pc(QPCIBus *bus) g_free(s); } + +void qpci_plug_device_test(const char *driver, const char *id, + uint8_t slot, const char *opts) +{ + QDict *response; + char *cmd; + + cmd = g_strdup_printf("{'execute': 'device_add'," + " 'arguments': {" + " 'driver': '%s'," + " 'addr': '%d'," + " %s%s" + " 'id': '%s'" + "}}", driver, slot, + opts ? opts : "", opts ? "," : "", + id); + response = qmp(cmd); + g_free(cmd); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); +} + +void qpci_unplug_acpi_device_test(const char *id, uint8_t slot) +{ + QDict *response; + char *cmd; + + cmd = g_strdup_printf("{'execute': 'device_del'," + " 'arguments': {" + " 'id': '%s'" + "}}", id); + response = qmp(cmd); + g_free(cmd); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + outb(ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot); + + response = qmp(""); + g_assert(response); + g_assert(qdict_haskey(response, "event")); + g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); + QDECREF(response); +} diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h index d51eb9e219..dfaee9ec37 100644 --- a/tests/libqos/pci.h +++ b/tests/libqos/pci.h @@ -87,4 +87,7 @@ void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value); void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr); void qpci_iounmap(QPCIDevice *dev, void *data); +void qpci_plug_device_test(const char *driver, const char *id, + uint8_t slot, const char *opts); +void qpci_unplug_acpi_device_test(const char *id, uint8_t slot); #endif From d1f3fc24f8c0fd193929eb4303d2768241d18a95 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:09 +0000 Subject: [PATCH 09/47] tests: virtio-rng: Check if hot-plug/unplug works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- tests/Makefile | 2 +- tests/virtio-rng-test.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index ffa8312eb5..49d653230f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -325,7 +325,7 @@ tests/wdt_ib700-test$(EXESUF): tests/wdt_ib700-test.o tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o $(libqos-virtio-obj-y) tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o -tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o +tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o $(libqos-pc-obj-y) tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o diff --git a/tests/virtio-rng-test.c b/tests/virtio-rng-test.c index 402c2060da..41c1cdb1aa 100644 --- a/tests/virtio-rng-test.c +++ b/tests/virtio-rng-test.c @@ -11,18 +11,28 @@ #include #include "libqtest.h" #include "qemu/osdep.h" +#include "libqos/pci.h" + +#define PCI_SLOT_HP 0x06 /* Tests only initialization so far. TODO: Replace with functional tests */ static void pci_nop(void) { } +static void hotplug(void) +{ + qpci_plug_device_test("virtio-rng-pci", "rng1", PCI_SLOT_HP, NULL); + qpci_unplug_acpi_device_test("rng1", PCI_SLOT_HP); +} + int main(int argc, char **argv) { int ret; g_test_init(&argc, &argv, NULL); qtest_add_func("/virtio/rng/pci/nop", pci_nop); + qtest_add_func("/virtio/rng/pci/hotplug", hotplug); qtest_start("-device virtio-rng-pci"); ret = g_test_run(); From 9224709b7bde6d6a81fad4c1aa2c2479cf840a60 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:10 +0000 Subject: [PATCH 10/47] tests: virtio-net: Check if hot-plug/unplug works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- tests/Makefile | 2 +- tests/virtio-net-test.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index 49d653230f..1bc8b10a61 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -324,7 +324,7 @@ tests/ne2000-test$(EXESUF): tests/ne2000-test.o tests/wdt_ib700-test$(EXESUF): tests/wdt_ib700-test.o tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o $(libqos-virtio-obj-y) -tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o +tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o $(libqos-pc-obj-y) tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o $(libqos-pc-obj-y) tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c index df99343238..ea7478c278 100644 --- a/tests/virtio-net-test.c +++ b/tests/virtio-net-test.c @@ -11,18 +11,28 @@ #include #include "libqtest.h" #include "qemu/osdep.h" +#include "libqos/pci.h" + +#define PCI_SLOT_HP 0x06 /* Tests only initialization so far. TODO: Replace with functional tests */ static void pci_nop(void) { } +static void hotplug(void) +{ + qpci_plug_device_test("virtio-net-pci", "net1", PCI_SLOT_HP, NULL); + qpci_unplug_acpi_device_test("net1", PCI_SLOT_HP); +} + int main(int argc, char **argv) { int ret; g_test_init(&argc, &argv, NULL); qtest_add_func("/virtio/net/pci/nop", pci_nop); + qtest_add_func("/virtio/net/pci/hotplug", hotplug); qtest_start("-device virtio-net-pci"); ret = g_test_run(); From aaf36070510cd95f8d77ec208fda8a555b507a1d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:11 +0000 Subject: [PATCH 11/47] tests: virtio-blk: Check if hot-plug/unplug works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- tests/virtio-blk-test.c | 49 ++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 5ce6e79757..ead3911e28 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -45,6 +45,8 @@ #define PCI_SLOT 0x04 #define PCI_FN 0x00 +#define PCI_SLOT_HP 0x06 + typedef struct QVirtioBlkReq { uint32_t type; uint32_t ioprio; @@ -55,7 +57,7 @@ typedef struct QVirtioBlkReq { static QPCIBus *test_start(void) { - char cmdline[100]; + char *cmdline; char tmp_path[] = "/tmp/qtest.XXXXXX"; int fd, ret; @@ -66,11 +68,14 @@ static QPCIBus *test_start(void) g_assert_cmpint(ret, ==, 0); close(fd); - snprintf(cmdline, 100, "-drive if=none,id=drive0,file=%s " - "-device virtio-blk-pci,drive=drive0,addr=%x.%x", - tmp_path, PCI_SLOT, PCI_FN); + cmdline = g_strdup_printf("-drive if=none,id=drive0,file=%s " + "-drive if=none,id=drive1,file=/dev/null " + "-device virtio-blk-pci,id=drv0,drive=drive0," + "addr=%x.%x", + tmp_path, PCI_SLOT, PCI_FN); qtest_start(cmdline); unlink(tmp_path); + g_free(cmdline); return qpci_init_pc(); } @@ -80,14 +85,14 @@ static void test_end(void) qtest_end(); } -static QVirtioPCIDevice *virtio_blk_init(QPCIBus *bus) +static QVirtioPCIDevice *virtio_blk_init(QPCIBus *bus, int slot) { QVirtioPCIDevice *dev; dev = qvirtio_pci_device_find(bus, QVIRTIO_BLK_DEVICE_ID); g_assert(dev != NULL); g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_BLK_DEVICE_ID); - g_assert_cmphex(dev->pdev->devfn, ==, ((PCI_SLOT << 3) | PCI_FN)); + g_assert_cmphex(dev->pdev->devfn, ==, ((slot << 3) | PCI_FN)); qvirtio_pci_device_enable(dev); qvirtio_reset(&qvirtio_pci, &dev->vdev); @@ -147,7 +152,7 @@ static void pci_basic(void) bus = test_start(); - dev = virtio_blk_init(bus); + dev = virtio_blk_init(bus, PCI_SLOT); /* MSI-X is not enabled */ addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; @@ -293,7 +298,7 @@ static void pci_indirect(void) bus = test_start(); - dev = virtio_blk_init(bus); + dev = virtio_blk_init(bus, PCI_SLOT); /* MSI-X is not enabled */ addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; @@ -384,7 +389,7 @@ static void pci_config(void) bus = test_start(); - dev = virtio_blk_init(bus); + dev = virtio_blk_init(bus, PCI_SLOT); /* MSI-X is not enabled */ addr = dev->addr + QVIRTIO_DEVICE_SPECIFIC_NO_MSIX; @@ -425,7 +430,7 @@ static void pci_msix(void) bus = test_start(); alloc = pc_alloc_init(); - dev = virtio_blk_init(bus); + dev = virtio_blk_init(bus, PCI_SLOT); qpci_msix_enable(dev->pdev); qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0); @@ -534,7 +539,7 @@ static void pci_idx(void) bus = test_start(); alloc = pc_alloc_init(); - dev = virtio_blk_init(bus); + dev = virtio_blk_init(bus, PCI_SLOT); qpci_msix_enable(dev->pdev); qvirtio_pci_set_msix_configuration_vector(dev, alloc, 0); @@ -637,6 +642,27 @@ static void pci_idx(void) test_end(); } +static void hotplug(void) +{ + QPCIBus *bus; + QVirtioPCIDevice *dev; + + bus = test_start(); + + /* plug secondary disk */ + qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP, + "'drive': 'drive1'"); + + dev = virtio_blk_init(bus, PCI_SLOT_HP); + g_assert(dev); + qvirtio_pci_device_disable(dev); + g_free(dev); + + /* unplug secondary disk */ + qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP); + test_end(); +} + int main(int argc, char **argv) { int ret; @@ -648,6 +674,7 @@ int main(int argc, char **argv) g_test_add_func("/virtio/blk/pci/config", pci_config); g_test_add_func("/virtio/blk/pci/msix", pci_msix); g_test_add_func("/virtio/blk/pci/idx", pci_idx); + g_test_add_func("/virtio/blk/pci/hotplug", hotplug); ret = g_test_run(); From b0354ec59640a23c3be544d904400e38be8ff51d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:12 +0000 Subject: [PATCH 12/47] tests: usb: Move uhci port test code to libqos/usb.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move code necessary for testing uhci port into library so it could be used by other USB tests. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- tests/Makefile | 3 ++- tests/libqos/usb.c | 37 +++++++++++++++++++++++++++++++++++++ tests/libqos/usb.h | 14 ++++++++++++++ tests/usb-hcd-ehci-test.c | 36 +++++------------------------------- 4 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 tests/libqos/usb.c create mode 100644 tests/libqos/usb.h diff --git a/tests/Makefile b/tests/Makefile index 1bc8b10a61..d2294abf74 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -301,6 +301,7 @@ libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o libqos-pc-obj-y += tests/libqos/malloc-pc.o libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o libqos-virtio-obj-y = $(libqos-obj-y) $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o +libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o tests/rtc-test$(EXESUF): tests/rtc-test.o tests/m48t59-test$(EXESUF): tests/m48t59-test.o @@ -345,7 +346,7 @@ tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o -tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-pc-obj-y) +tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y) tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o diff --git a/tests/libqos/usb.c b/tests/libqos/usb.c new file mode 100644 index 0000000000..54865b4759 --- /dev/null +++ b/tests/libqos/usb.c @@ -0,0 +1,37 @@ +/* + * common code shared by usb tests + * + * Copyright (c) 2014 Red Hat, Inc + * + * Authors: + * Gerd Hoffmann + * John Snow + * Igor Mammedov + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include +#include +#include "libqtest.h" +#include "qemu/osdep.h" +#include "hw/usb/uhci-regs.h" +#include "libqos/usb.h" + +void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar) +{ + hc->dev = qpci_device_find(pcibus, devfn); + g_assert(hc->dev != NULL); + qpci_device_enable(hc->dev); + hc->base = qpci_iomap(hc->dev, bar, NULL); + g_assert(hc->base != NULL); +} + +void uhci_port_test(struct qhc *hc, int port, uint16_t expect) +{ + void *addr = hc->base + 0x10 + 2 * port; + uint16_t value = qpci_io_readw(hc->dev, addr); + uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1); + + g_assert((value & mask) == (expect & mask)); +} diff --git a/tests/libqos/usb.h b/tests/libqos/usb.h new file mode 100644 index 0000000000..7fcd669ac4 --- /dev/null +++ b/tests/libqos/usb.h @@ -0,0 +1,14 @@ +#ifndef LIBQOS_USB_H +#define LIBQOS_USB_H + +#include "libqos/pci-pc.h" + +struct qhc { + QPCIDevice *dev; + void *base; +}; + +void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, + uint32_t devfn, int bar); +void uhci_port_test(struct qhc *hc, int port, uint16_t expect); +#endif diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c index c990492835..69f852230d 100644 --- a/tests/usb-hcd-ehci-test.c +++ b/tests/usb-hcd-ehci-test.c @@ -15,11 +15,7 @@ #include "qemu/osdep.h" #include "hw/usb/uhci-regs.h" #include "hw/usb/ehci-regs.h" - -struct qhc { - QPCIDevice *dev; - void *base; -}; +#include "libqos/usb.h" static QPCIBus *pcibus; static struct qhc uhci1; @@ -29,15 +25,6 @@ static struct qhc ehci1; /* helpers */ -static void pci_init_one(struct qhc *hc, uint32_t devfn, int bar) -{ - hc->dev = qpci_device_find(pcibus, devfn); - g_assert(hc->dev != NULL); - qpci_device_enable(hc->dev); - hc->base = qpci_iomap(hc->dev, bar, NULL); - g_assert(hc->base != NULL); -} - #if 0 static void uhci_port_update(struct qhc *hc, int port, uint16_t set, uint16_t clear) @@ -52,19 +39,6 @@ static void uhci_port_update(struct qhc *hc, int port, } #endif -static void uhci_port_test(struct qhc *hc, int port, uint16_t expect) -{ - void *addr = hc->base + 0x10 + 2 * port; - uint16_t value = qpci_io_readw(hc->dev, addr); - uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1); - -#if 0 - fprintf(stderr, "%s: %d, have 0x%04x, want 0x%04x\n", - __func__, port, value & mask, expect & mask); -#endif - g_assert((value & mask) == (expect & mask)); -} - static void ehci_port_test(struct qhc *hc, int port, uint32_t expect) { void *addr = hc->base + 0x64 + 4 * port; @@ -88,10 +62,10 @@ static void pci_init(void) pcibus = qpci_init_pc(); g_assert(pcibus != NULL); - pci_init_one(&uhci1, QPCI_DEVFN(0x1d, 0), 4); - pci_init_one(&uhci2, QPCI_DEVFN(0x1d, 1), 4); - pci_init_one(&uhci3, QPCI_DEVFN(0x1d, 2), 4); - pci_init_one(&ehci1, QPCI_DEVFN(0x1d, 7), 0); + qusb_pci_init_one(pcibus, &uhci1, QPCI_DEVFN(0x1d, 0), 4); + qusb_pci_init_one(pcibus, &uhci2, QPCI_DEVFN(0x1d, 1), 4); + qusb_pci_init_one(pcibus, &uhci3, QPCI_DEVFN(0x1d, 2), 4); + qusb_pci_init_one(pcibus, &ehci1, QPCI_DEVFN(0x1d, 7), 0); } static void pci_uhci_port_1(void) From fbd942c993001f5276fcd1f25a56405fdd968472 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:13 +0000 Subject: [PATCH 13/47] tests: usb: add port test to uhci unit test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- tests/Makefile | 2 +- tests/usb-hcd-uhci-test.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index d2294abf74..6d143880e1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -345,7 +345,7 @@ tests/es1370-test$(EXESUF): tests/es1370-test.o tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o -tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o +tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y) tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y) tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 94e858f4c6..68047b8006 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -11,13 +11,23 @@ #include #include "libqtest.h" #include "qemu/osdep.h" +#include "libqos/usb.h" +#include "hw/usb/uhci-regs.h" static void test_uhci_init(void) { - qtest_start("-device piix3-usb-uhci,id=uhci"); +} - qtest_end(); +static void test_port_1(void) +{ + QPCIBus *pcibus; + struct qhc uhci; + + pcibus = qpci_init_pc(); + g_assert(pcibus != NULL); + qusb_pci_init_one(pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4); + uhci_port_test(&uhci, 0, UHCI_PORT_CCS); } @@ -28,8 +38,12 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); qtest_add_func("/uhci/pci/init", test_uhci_init); + qtest_add_func("/uhci/pci/port1", test_port_1); + qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0" + " -device usb-tablet,bus=uhci.0,port=1"); ret = g_test_run(); + qtest_end(); return ret; } From b3937683147481fba3406a01da4ce15f0b2deb21 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:14 +0000 Subject: [PATCH 14/47] tests: usb: Generic usb device hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use usb-tablet as a hotplugged usb device. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- tests/Makefile | 4 ++-- tests/libqos/usb.c | 34 ++++++++++++++++++++++++++++++++++ tests/libqos/usb.h | 3 +++ tests/usb-hcd-ehci-test.c | 14 ++++++++++++++ tests/usb-hcd-ohci-test.c | 10 ++++++++-- tests/usb-hcd-uhci-test.c | 20 ++++++++++++++++++-- tests/usb-hcd-xhci-test.c | 11 ++++++++--- 7 files changed, 87 insertions(+), 9 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 6d143880e1..95deff0e2f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -344,10 +344,10 @@ tests/ac97-test$(EXESUF): tests/ac97-test.o tests/es1370-test$(EXESUF): tests/es1370-test.o tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o -tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o +tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y) tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y) tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y) -tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o +tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y) tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub.a diff --git a/tests/libqos/usb.c b/tests/libqos/usb.c index 54865b4759..41d89b8487 100644 --- a/tests/libqos/usb.c +++ b/tests/libqos/usb.c @@ -35,3 +35,37 @@ void uhci_port_test(struct qhc *hc, int port, uint16_t expect) g_assert((value & mask) == (expect & mask)); } + +void usb_test_hotplug(const char *hcd_id, const int port, + void (*port_check)(void)) +{ + QDict *response; + char *cmd; + + cmd = g_strdup_printf("{'execute': 'device_add'," + " 'arguments': {" + " 'driver': 'usb-tablet'," + " 'port': '%d'," + " 'bus': '%s.0'," + " 'id': 'usbdev%d'" + "}}", port, hcd_id, port); + response = qmp(cmd); + g_free(cmd); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + if (port_check) { + port_check(); + } + + cmd = g_strdup_printf("{'execute': 'device_del'," + " 'arguments': {" + " 'id': 'usbdev%d'" + "}}", port); + response = qmp(cmd); + g_free(cmd); + g_assert(response); + g_assert(qdict_haskey(response, "event")); + g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); +} diff --git a/tests/libqos/usb.h b/tests/libqos/usb.h index 7fcd669ac4..8fe56872b7 100644 --- a/tests/libqos/usb.h +++ b/tests/libqos/usb.h @@ -11,4 +11,7 @@ struct qhc { void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar); void uhci_port_test(struct qhc *hc, int port, uint16_t expect); + +void usb_test_hotplug(const char *bus_name, const int port, + void (*port_check)(void)); #endif diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c index 69f852230d..75073bf24e 100644 --- a/tests/usb-hcd-ehci-test.c +++ b/tests/usb-hcd-ehci-test.c @@ -128,6 +128,19 @@ static void pci_ehci_port_2(void) } } +static void pci_ehci_port_3_hotplug(void) +{ + /* check for presence of hotplugged usb-tablet */ + g_assert(pcibus != NULL); + ehci_port_test(&ehci1, 2, PORTSC_PPOWER | PORTSC_CONNECT); +} + +static void pci_ehci_port_hotplug(void) +{ + usb_test_hotplug("ich9-ehci-1", 3, pci_ehci_port_3_hotplug); +} + + int main(int argc, char **argv) { int ret; @@ -139,6 +152,7 @@ int main(int argc, char **argv) qtest_add_func("/ehci/pci/ehci-config", pci_ehci_config); qtest_add_func("/ehci/pci/uhci-port-2", pci_uhci_port_2); qtest_add_func("/ehci/pci/ehci-port-2", pci_ehci_port_2); + qtest_add_func("/ehci/pci/ehci-port-3-hotplug", pci_ehci_port_hotplug); qtest_start("-machine q35 -device ich9-usb-ehci1,bus=pcie.0,addr=1d.7," "multifunction=on,id=ich9-ehci-1 " diff --git a/tests/usb-hcd-ohci-test.c b/tests/usb-hcd-ohci-test.c index fbc3ffeebd..1160bde840 100644 --- a/tests/usb-hcd-ohci-test.c +++ b/tests/usb-hcd-ohci-test.c @@ -11,15 +11,18 @@ #include #include "libqtest.h" #include "qemu/osdep.h" +#include "libqos/usb.h" static void test_ohci_init(void) { - qtest_start("-device pci-ohci,id=ohci"); - qtest_end(); } +static void test_ohci_hotplug(void) +{ + usb_test_hotplug("ohci", 1, NULL); +} int main(int argc, char **argv) { @@ -28,8 +31,11 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); qtest_add_func("/ohci/pci/init", test_ohci_init); + qtest_add_func("/ohci/pci/hotplug", test_ohci_hotplug); + qtest_start("-device pci-ohci,id=ohci"); ret = g_test_run(); + qtest_end(); return ret; } diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 68047b8006..da96f98de6 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -19,17 +19,32 @@ static void test_uhci_init(void) { } -static void test_port_1(void) +static void test_port(int port) { QPCIBus *pcibus; struct qhc uhci; + g_assert(port > 0); pcibus = qpci_init_pc(); g_assert(pcibus != NULL); qusb_pci_init_one(pcibus, &uhci, QPCI_DEVFN(0x1d, 0), 4); - uhci_port_test(&uhci, 0, UHCI_PORT_CCS); + uhci_port_test(&uhci, port - 1, UHCI_PORT_CCS); } +static void test_port_1(void) +{ + test_port(1); +} + +static void test_port_2(void) +{ + test_port(2); +} + +static void test_uhci_hotplug(void) +{ + usb_test_hotplug("uhci", 2, test_port_2); +} int main(int argc, char **argv) { @@ -39,6 +54,7 @@ int main(int argc, char **argv) qtest_add_func("/uhci/pci/init", test_uhci_init); qtest_add_func("/uhci/pci/port1", test_port_1); + qtest_add_func("/uhci/pci/hotplug", test_uhci_hotplug); qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0" " -device usb-tablet,bus=uhci.0,port=1"); diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c index 743e9798cd..d16963d3f7 100644 --- a/tests/usb-hcd-xhci-test.c +++ b/tests/usb-hcd-xhci-test.c @@ -11,15 +11,17 @@ #include #include "libqtest.h" #include "qemu/osdep.h" +#include "libqos/usb.h" static void test_xhci_init(void) { - qtest_start("-device nec-usb-xhci,id=xhci"); - - qtest_end(); } +static void test_xhci_hotplug(void) +{ + usb_test_hotplug("xhci", 1, NULL); +} int main(int argc, char **argv) { @@ -28,8 +30,11 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); qtest_add_func("/xhci/pci/init", test_xhci_init); + qtest_add_func("/xhci/pci/hotplug", test_xhci_hotplug); + qtest_start("-device nec-usb-xhci,id=xhci"); ret = g_test_run(); + qtest_end(); return ret; } From b6ca82feedbf341af42ffaf6241a850443d853ae Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:15 +0000 Subject: [PATCH 15/47] tests: usb: usb-storage hotplug test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit usb-storage is different from usual usb devices in that it uses a child SCSI bus for underlying storage. This commit verifies that the SCSI bus is hotpluggable, as hotplug operation wouldn't succeed without it. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- tests/usb-hcd-uhci-test.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index da96f98de6..8cf2c5bcaa 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -46,6 +46,35 @@ static void test_uhci_hotplug(void) usb_test_hotplug("uhci", 2, test_port_2); } +static void test_usb_storage_hotplug(void) +{ + QDict *response; + + response = qmp("{'execute': 'device_add'," + " 'arguments': {" + " 'driver': 'usb-storage'," + " 'drive': 'drive0'," + " 'id': 'usbdev0'" + "}}"); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + response = qmp("{'execute': 'device_del'," + " 'arguments': {" + " 'id': 'usbdev0'" + "}}"); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + response = qmp(""); + g_assert(response); + g_assert(qdict_haskey(response, "event")); + g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); + QDECREF(response); +} + int main(int argc, char **argv) { int ret; @@ -55,8 +84,10 @@ int main(int argc, char **argv) qtest_add_func("/uhci/pci/init", test_uhci_init); qtest_add_func("/uhci/pci/port1", test_port_1); qtest_add_func("/uhci/pci/hotplug", test_uhci_hotplug); + qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug); qtest_start("-device piix3-usb-uhci,id=uhci,addr=1d.0" + " -drive id=drive0,if=none,file=/dev/null" " -device usb-tablet,bus=uhci.0,port=1"); ret = g_test_run(); qtest_end(); From 49cec38591d6fef833cf12873fb4ff9748d0f08b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:16 +0000 Subject: [PATCH 16/47] tests: usb: usb-uas hotplug test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit checks that it's possible to hotplug usb-uas HBA and then if it's possible to hot(un)plug scsi-disk to it. Thest basically covers hot(un)plug on dummy HBAs without means of hot(un)plug notification of the guest. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- tests/usb-hcd-xhci-test.c | 61 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c index d16963d3f7..b1a7dec5bb 100644 --- a/tests/usb-hcd-xhci-test.c +++ b/tests/usb-hcd-xhci-test.c @@ -23,6 +23,63 @@ static void test_xhci_hotplug(void) usb_test_hotplug("xhci", 1, NULL); } +static void test_usb_uas_hotplug(void) +{ + QDict *response; + + response = qmp("{'execute': 'device_add'," + " 'arguments': {" + " 'driver': 'usb-uas'," + " 'id': 'uas'" + "}}"); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + response = qmp("{'execute': 'device_add'," + " 'arguments': {" + " 'driver': 'scsi-hd'," + " 'drive': 'drive0'," + " 'id': 'scsi-hd'" + "}}"); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + /* TODO: + UAS HBA driver in libqos, to check that + added disk is visible after BUS rescan + */ + + response = qmp("{'execute': 'device_del'," + " 'arguments': {" + " 'id': 'scsi-hd'" + "}}"); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + response = qmp(""); + g_assert(qdict_haskey(response, "event")); + g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); + QDECREF(response); + + + response = qmp("{'execute': 'device_del'," + " 'arguments': {" + " 'id': 'uas'" + "}}"); + g_assert(response); + g_assert(!qdict_haskey(response, "error")); + QDECREF(response); + + response = qmp(""); + g_assert(response); + g_assert(qdict_haskey(response, "event")); + g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); + QDECREF(response); +} + int main(int argc, char **argv) { int ret; @@ -31,8 +88,10 @@ int main(int argc, char **argv) qtest_add_func("/xhci/pci/init", test_xhci_init); qtest_add_func("/xhci/pci/hotplug", test_xhci_hotplug); + qtest_add_func("/xhci/pci/hotplug/usb-uas", test_usb_uas_hotplug); - qtest_start("-device nec-usb-xhci,id=xhci"); + qtest_start("-device nec-usb-xhci,id=xhci" + " -drive id=drive0,if=none,file=/dev/null"); ret = g_test_run(); qtest_end(); From 39b888bd88296b178082b5a2e4c6e82fcbd877f8 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:17 +0000 Subject: [PATCH 17/47] Access BusState::allow_hotplug using wraper qbus_is_hotpluggable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It would allow to transparently switch detection whether Bus is hotpluggable from allow_hotplug field to hotplug_handler link and to drop allow_hotplug field once all users are converted to hotplug handler API. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/core/qdev.c | 6 +++--- hw/i386/acpi-build.c | 2 +- hw/pci/pci-hotplug-old.c | 4 ++-- include/hw/qdev-core.h | 5 +++++ qdev-monitor.c | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 2b42d5b58c..df97003289 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -86,7 +86,7 @@ static void bus_add_child(BusState *bus, DeviceState *child) BusChild *kid = g_malloc0(sizeof(*kid)); if (qdev_hotplug) { - assert(bus->allow_hotplug); + assert(qbus_is_hotpluggable(bus)); } kid->index = bus->max_index++; @@ -213,7 +213,7 @@ void qdev_unplug(DeviceState *dev, Error **errp) { DeviceClass *dc = DEVICE_GET_CLASS(dev); - if (dev->parent_bus && !dev->parent_bus->allow_hotplug) { + if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) { error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name); return; } @@ -948,7 +948,7 @@ static bool device_get_hotpluggable(Object *obj, Error **errp) DeviceState *dev = DEVICE(obj); return dc->hotpluggable && (dev->parent_bus == NULL || - dev->parent_bus->allow_hotplug); + qbus_is_hotpluggable(dev->parent_bus)); } static bool device_get_hotplugged(Object *obj, Error **err) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index a3133211a8..00be4bb12a 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -774,7 +774,7 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque) unsigned *bsel_alloc = opaque; unsigned *bus_bsel; - if (bus->qbus.allow_hotplug) { + if (qbus_is_hotpluggable(BUS(bus))) { bus_bsel = g_malloc(sizeof *bus_bsel); *bus_bsel = (*bsel_alloc)++; diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index d87c469096..6ab28b703c 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -77,7 +77,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); return NULL; } - if (!((BusState*)bus)->allow_hotplug) { + if (!qbus_is_hotpluggable(BUS(bus))) { monitor_printf(mon, "PCI bus doesn't support hotplug\n"); return NULL; } @@ -227,7 +227,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); return NULL; } - if (!((BusState*)bus)->allow_hotplug) { + if (!qbus_is_hotpluggable(BUS(bus))) { monitor_printf(mon, "PCI bus doesn't support hotplug\n"); return NULL; } diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 178fee2ef6..48a96d28ff 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -368,4 +368,9 @@ static inline void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, QDEV_HOTPLUG_HANDLER_PROPERTY, errp); bus->allow_hotplug = 1; } + +static inline bool qbus_is_hotpluggable(BusState *bus) +{ + return bus->allow_hotplug || bus->hotplug_handler; +} #endif diff --git a/qdev-monitor.c b/qdev-monitor.c index 5ec66067f5..f6db461476 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -515,7 +515,7 @@ DeviceState *qdev_device_add(QemuOpts *opts) return NULL; } } - if (qdev_hotplug && bus && !bus->allow_hotplug) { + if (qdev_hotplug && bus && !qbus_is_hotpluggable(bus)) { qerror_report(QERR_BUS_NO_HOTPLUG, bus->name); return NULL; } From ce9835e00df65bf5beb6c094c0865d8e60018310 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:18 +0000 Subject: [PATCH 18/47] qdev: do not allow to instantiate non hotpluggable device with device_add MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will allow explicitly mark device as not hotpluggable and avoid its creation with following error at realize time and destroying it afterwards anyway. Instead of it will error out even before instance of device is created. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- qdev-monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index f6db461476..c72145127e 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -487,7 +487,8 @@ DeviceState *qdev_device_add(QemuOpts *opts) } dc = DEVICE_CLASS(oc); - if (dc->cannot_instantiate_with_device_add_yet) { + if (dc->cannot_instantiate_with_device_add_yet || + (qdev_hotplug && !dc->hotpluggable)) { qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "pluggable device type"); return NULL; From 14d5a28fb6bb8ac6505ad1faca2690df56fef326 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:19 +0000 Subject: [PATCH 19/47] qdev: HotplugHandler: Rename unplug callback to unplug_request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'HotplugHandler.unplug' callback is currently used as async call to issue unplug request for device that implements it. Renaming 'unplug' callback to 'unplug_request' should help to avoid confusion about what callback does and would allow to introduce 'unplug' callback that would perform actual device removal when guest is ready for it. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/acpi/piix4.c | 6 +++--- hw/core/hotplug.c | 10 +++++----- hw/core/qdev.c | 3 ++- hw/isa/lpc_ich9.c | 6 +++--- hw/pci-bridge/pci_bridge_dev.c | 2 +- hw/pci/pcie.c | 4 ++-- hw/pci/pcie_port.c | 2 +- hw/pci/shpc.c | 4 ++-- include/hw/hotplug.h | 16 +++++++++------- include/hw/pci/pcie.h | 4 ++-- include/hw/pci/shpc.h | 4 ++-- 11 files changed, 32 insertions(+), 29 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index b72b34e5c9..0bfa814f71 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -354,8 +354,8 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev, } } -static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) +static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { PIIX4PMState *s = PIIX4_PM(hotplug_dev); @@ -615,7 +615,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) dc->cannot_instantiate_with_device_add_yet = true; dc->hotpluggable = false; hc->plug = piix4_device_plug_cb; - hc->unplug = piix4_device_unplug_cb; + hc->unplug_request = piix4_device_unplug_request_cb; adevc->ospm_status = piix4_ospm_status; } diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c index 5573d9d2d9..2ec4736593 100644 --- a/hw/core/hotplug.c +++ b/hw/core/hotplug.c @@ -23,14 +23,14 @@ void hotplug_handler_plug(HotplugHandler *plug_handler, } } -void hotplug_handler_unplug(HotplugHandler *plug_handler, - DeviceState *plugged_dev, - Error **errp) +void hotplug_handler_unplug_request(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp) { HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler); - if (hdc->unplug) { - hdc->unplug(plug_handler, plugged_dev, errp); + if (hdc->unplug_request) { + hdc->unplug_request(plug_handler, plugged_dev, errp); } } diff --git a/hw/core/qdev.c b/hw/core/qdev.c index df97003289..87ed438475 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -227,7 +227,8 @@ void qdev_unplug(DeviceState *dev, Error **errp) qdev_hot_removed = true; if (dev->parent_bus && dev->parent_bus->hotplug_handler) { - hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp); + hotplug_handler_unplug_request(dev->parent_bus->hotplug_handler, + dev, errp); } else { assert(dc->unplug != NULL); if (dc->unplug(dev) < 0) { /* legacy handler */ diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 177023bcaf..530b074551 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -607,8 +607,8 @@ static void ich9_device_plug_cb(HotplugHandler *hotplug_dev, ich9_pm_device_plug_cb(&lpc->pm, dev, errp); } -static void ich9_device_unplug_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) +static void ich9_device_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { error_setg(errp, "acpi: device unplug request for not supported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -676,7 +676,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) */ dc->cannot_instantiate_with_device_add_yet = true; hc->plug = ich9_device_plug_cb; - hc->unplug = ich9_device_unplug_cb; + hc->unplug_request = ich9_device_unplug_request_cb; adevc->ospm_status = ich9_pm_ospm_status; } diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 92799d08ef..252ea5eb53 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -150,7 +150,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) dc->vmsd = &pci_bridge_dev_vmstate; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); hc->plug = shpc_device_hotplug_cb; - hc->unplug = shpc_device_hot_unplug_cb; + hc->unplug_request = shpc_device_hot_unplug_request_cb; } static const TypeInfo pci_bridge_dev_info = { diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 1babddff4d..b64a004631 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -262,8 +262,8 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP); } -void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +void pcie_cap_slot_hot_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { uint8_t *exp_cap; diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c index fa24877955..40ca8d5d17 100644 --- a/hw/pci/pcie_port.c +++ b/hw/pci/pcie_port.c @@ -154,7 +154,7 @@ static void pcie_slot_class_init(ObjectClass *oc, void *data) dc->props = pcie_slot_props; hc->plug = pcie_cap_slot_hotplug_cb; - hc->unplug = pcie_cap_slot_hot_unplug_cb; + hc->unplug_request = pcie_cap_slot_hot_unplug_request_cb; } static const TypeInfo pcie_slot_type_info = { diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 1fcb8c4d85..65b2f5103f 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -549,8 +549,8 @@ void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, shpc_interrupt_update(pci_hotplug_dev); } -void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { Error *local_err = NULL; PCIDevice *pci_hotplug_dev = PCI_DEVICE(hotplug_dev); diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h index a6533cb0b1..e397d0819a 100644 --- a/include/hw/hotplug.h +++ b/include/hw/hotplug.h @@ -47,7 +47,9 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler, * * @parent: Opaque parent interface. * @plug: plug callback. - * @unplug: unplug callback. + * @unplug_request: unplug request callback. + * Used as a means to initiate device unplug for devices that + * require asynchronous unplug handling. */ typedef struct HotplugHandlerClass { /* */ @@ -55,7 +57,7 @@ typedef struct HotplugHandlerClass { /* */ hotplug_fn plug; - hotplug_fn unplug; + hotplug_fn unplug_request; } HotplugHandlerClass; /** @@ -68,11 +70,11 @@ void hotplug_handler_plug(HotplugHandler *plug_handler, Error **errp); /** - * hotplug_handler_unplug: + * hotplug_handler_unplug_request: * - * Call #HotplugHandlerClass.unplug callback of @plug_handler. + * Calls #HotplugHandlerClass.unplug_request callback of @plug_handler. */ -void hotplug_handler_unplug(HotplugHandler *plug_handler, - DeviceState *plugged_dev, - Error **errp); +void hotplug_handler_unplug_request(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp); #endif diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h index d139d588f6..b48a7a2c5a 100644 --- a/include/hw/pci/pcie.h +++ b/include/hw/pci/pcie.h @@ -128,6 +128,6 @@ extern const VMStateDescription vmstate_pcie_device; void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); -void pcie_cap_slot_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp); +void pcie_cap_slot_hot_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); #endif /* QEMU_PCIE_H */ diff --git a/include/hw/pci/shpc.h b/include/hw/pci/shpc.h index eef1a1ad6e..025bc5b268 100644 --- a/include/hw/pci/shpc.h +++ b/include/hw/pci/shpc.h @@ -46,8 +46,8 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int len); void shpc_device_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); -void shpc_device_hot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp); +void shpc_device_hot_unplug_request_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); extern VMStateInfo shpc_vmstate_info; #define SHPC_VMSTATE(_field, _type) \ From 181a2c63236966b3c80eef131bac33a355a492da Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:20 +0000 Subject: [PATCH 20/47] qdev: HotplugHandler: Provide unplug callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is to be called for actual device removal and will allow to separate request and removal handling phases of x86-CPU devices and also it's a handler to be called for synchronously removable devices. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/core/hotplug.c | 11 +++++++++++ hw/core/qdev.c | 13 +++++++++++-- include/hw/hotplug.h | 12 ++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/hw/core/hotplug.c b/hw/core/hotplug.c index 2ec4736593..4e01074557 100644 --- a/hw/core/hotplug.c +++ b/hw/core/hotplug.c @@ -34,6 +34,17 @@ void hotplug_handler_unplug_request(HotplugHandler *plug_handler, } } +void hotplug_handler_unplug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp) +{ + HotplugHandlerClass *hdc = HOTPLUG_HANDLER_GET_CLASS(plug_handler); + + if (hdc->unplug) { + hdc->unplug(plug_handler, plugged_dev, errp); + } +} + static const TypeInfo hotplug_handler_info = { .name = TYPE_HOTPLUG_HANDLER, .parent = TYPE_INTERFACE, diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 87ed438475..6479194498 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -227,8 +227,17 @@ void qdev_unplug(DeviceState *dev, Error **errp) qdev_hot_removed = true; if (dev->parent_bus && dev->parent_bus->hotplug_handler) { - hotplug_handler_unplug_request(dev->parent_bus->hotplug_handler, - dev, errp); + HotplugHandlerClass *hdc; + + /* If device supports async unplug just request it to be done, + * otherwise just remove it synchronously */ + hdc = HOTPLUG_HANDLER_GET_CLASS(dev->parent_bus->hotplug_handler); + if (hdc->unplug_request) { + hotplug_handler_unplug_request(dev->parent_bus->hotplug_handler, + dev, errp); + } else { + hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp); + } } else { assert(dc->unplug != NULL); if (dc->unplug(dev) < 0) { /* legacy handler */ diff --git a/include/hw/hotplug.h b/include/hw/hotplug.h index e397d0819a..050d2f0530 100644 --- a/include/hw/hotplug.h +++ b/include/hw/hotplug.h @@ -50,6 +50,9 @@ typedef void (*hotplug_fn)(HotplugHandler *plug_handler, * @unplug_request: unplug request callback. * Used as a means to initiate device unplug for devices that * require asynchronous unplug handling. + * @unplug: unplug callback. + * Used for device removal with devices that implement + * asynchronous and synchronous (suprise) removal. */ typedef struct HotplugHandlerClass { /* */ @@ -58,6 +61,7 @@ typedef struct HotplugHandlerClass { /* */ hotplug_fn plug; hotplug_fn unplug_request; + hotplug_fn unplug; } HotplugHandlerClass; /** @@ -77,4 +81,12 @@ void hotplug_handler_plug(HotplugHandler *plug_handler, void hotplug_handler_unplug_request(HotplugHandler *plug_handler, DeviceState *plugged_dev, Error **errp); +/** + * hotplug_handler_unplug: + * + * Calls #HotplugHandlerClass.unplug callback of @plug_handler. + */ +void hotplug_handler_unplug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, + Error **errp); #endif From 014176f914ab8e41a88225e8f26569ef0e0bf223 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:21 +0000 Subject: [PATCH 21/47] qdev: Add simple/generic unplug callback for HotplugHandler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will be used in shallow conversion from legacy hotplug mechanism and eventually replace all the uses of old mechanism DeviceClass::unplug = qdev_simple_unplug_cb() Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/core/qdev.c | 5 +++++ include/hw/qdev-core.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 6479194498..9f18520219 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -286,6 +286,11 @@ int qdev_simple_unplug_cb(DeviceState *dev) return 0; } +void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + qdev_simple_unplug_cb(dev); +} /* Like qdev_init(), but terminate program via error_report() instead of returning an error value. This is okay during machine creation. diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 48a96d28ff..ba812c5f9e 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -265,6 +265,8 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version); void qdev_unplug(DeviceState *dev, Error **errp); int qdev_simple_unplug_cb(DeviceState *dev); +void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp); void qdev_machine_creation_done(void); bool qdev_machine_modified(void); From 431bbb26cbd0e9862c48320deaaf83aa9aacd6ce Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:22 +0000 Subject: [PATCH 22/47] qdev: Add wrapper to set BUS as HotplugHandler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be used for conversion of SCSI and USB devices, and would allow to make every HBA/USB host switch to HotplugHandler API without touching each controller explicitly. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/core/qdev.c | 19 +++++++++++++++++++ include/hw/qdev-core.h | 11 ++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 9f18520219..b1da409eeb 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -112,6 +112,25 @@ void qdev_set_parent_bus(DeviceState *dev, BusState *bus) bus_add_child(bus, dev); } +static void qbus_set_hotplug_handler_internal(BusState *bus, Object *handler, + Error **errp) +{ + + object_property_set_link(OBJECT(bus), OBJECT(handler), + QDEV_HOTPLUG_HANDLER_PROPERTY, errp); + bus->allow_hotplug = 1; +} + +void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, Error **errp) +{ + qbus_set_hotplug_handler_internal(bus, OBJECT(handler), errp); +} + +void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp) +{ + qbus_set_hotplug_handler_internal(bus, OBJECT(bus), errp); +} + /* Create a new device. This only initializes the device state structure and allows properties to be set. qdev_init should be called to initialize the actual device emulation. */ diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index ba812c5f9e..48e9579a88 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -363,13 +363,10 @@ extern int qdev_hotplug; char *qdev_get_dev_path(DeviceState *dev); -static inline void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, - Error **errp) -{ - object_property_set_link(OBJECT(bus), OBJECT(handler), - QDEV_HOTPLUG_HANDLER_PROPERTY, errp); - bus->allow_hotplug = 1; -} +void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, + Error **errp); + +void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp); static inline bool qbus_is_hotpluggable(BusState *bus) { From e378acb4047fbec4f89031dbba7fb7851042f6ee Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:23 +0000 Subject: [PATCH 23/47] qdev: Drop hotplug check from bus_add_child() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check is too restrictive and does not allow to add children to just created bus during hotplug when the bus is part of composite device. Removing check from bus_add_child() doesn't affect devices creatable with device_add/del commands since they have a similar builtin check and patch will allow to create complex composite devices during hotplug. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/core/qdev.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index b1da409eeb..6439a23273 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -85,10 +85,6 @@ static void bus_add_child(BusState *bus, DeviceState *child) char name[32]; BusChild *kid = g_malloc0(sizeof(*kid)); - if (qdev_hotplug) { - assert(qbus_is_hotpluggable(bus)); - } - kid->index = bus->max_index++; kid->child = child; object_ref(OBJECT(kid->child)); From c32e36f6ab847e0726542a822606a3525f959ff4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:24 +0000 Subject: [PATCH 24/47] target-i386: ICC bus: Drop BusState::allow_hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since bus_add_child() no longer cares if BUS is hotpluggable or not, there is no need in setting allow_hotplug field. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/cpu/icc_bus.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c index 7f44c59b25..9575fd6a42 100644 --- a/hw/cpu/icc_bus.c +++ b/hw/cpu/icc_bus.c @@ -24,18 +24,10 @@ /* icc-bridge implementation */ -static void icc_bus_init(Object *obj) -{ - BusState *b = BUS(obj); - - b->allow_hotplug = true; -} - static const TypeInfo icc_bus_info = { .name = TYPE_ICC_BUS, .parent = TYPE_BUS, .instance_size = sizeof(ICCBus), - .instance_init = icc_bus_init, }; From 7f17a917150abb38221d32a35398527b3e9a87cb Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:25 +0000 Subject: [PATCH 25/47] virtio-pci: Drop BusState::allow_hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit virtio-pci-bus is an internal object of composite virtio-pci device and it doesn't participate in -device/device_add hotplug flow, and since it's not required by bus_add_child() that BUS must be hotpluggable to be able to add child at runtime, it's possible to drop not needed 'allow_hotplug' field. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/virtio/virtio-pci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 390f8244f3..10abd657aa 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1542,13 +1542,10 @@ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, VirtIOPCIProxy *dev) { DeviceState *qdev = DEVICE(dev); - BusState *qbus; char virtio_bus_name[] = "virtio-bus"; qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev, virtio_bus_name); - qbus = BUS(bus); - qbus->allow_hotplug = 1; } static void virtio_pci_bus_class_init(ObjectClass *klass, void *data) From 0ddef15b0432fbcb65429e17b32231e18aa103c9 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:26 +0000 Subject: [PATCH 26/47] virtio-serial: Convert to hotplug-handler API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/char/virtio-serial-bus.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 3931085983..c6870f19e1 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -904,6 +904,12 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) } port->elem.out_num = 0; +} + +static void virtser_port_device_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); QTAILQ_INSERT_TAIL(&port->vser->ports, port, next); port->ivq = port->vser->ivqs[port->id]; @@ -912,7 +918,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) add_port(port->vser, port->id); /* Send an update to the guest about this new port added */ - virtio_notify_config(vdev); + virtio_notify_config(VIRTIO_DEVICE(hotplug_dev)); } static void virtser_port_device_unrealize(DeviceState *dev, Error **errp) @@ -935,7 +941,6 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOSerial *vser = VIRTIO_SERIAL(dev); - BusState *bus; uint32_t i, max_supported_ports; if (!vser->serial.max_virtserial_ports) { @@ -957,8 +962,7 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) /* Spawn a new virtio-serial bus on which the ports will ride as devices */ qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS, dev, vdev->bus_name); - bus = BUS(&vser->bus); - bus->allow_hotplug = 1; + qbus_set_hotplug_handler(BUS(&vser->bus), DEVICE(vser), errp); vser->bus.vser = vser; QTAILQ_INIT(&vser->ports); @@ -1021,7 +1025,6 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data) k->bus_type = TYPE_VIRTIO_SERIAL_BUS; k->realize = virtser_port_device_realize; k->unrealize = virtser_port_device_unrealize; - k->unplug = qdev_simple_unplug_cb; k->props = virtser_props; } @@ -1064,6 +1067,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); QLIST_INIT(&vserdevices.devices); @@ -1077,6 +1081,8 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data) vdc->reset = vser_reset; vdc->save = virtio_serial_save_device; vdc->load = virtio_serial_load_device; + hc->plug = virtser_port_device_plug; + hc->unplug = qdev_simple_device_unplug_cb; } static const TypeInfo virtio_device_info = { @@ -1084,6 +1090,10 @@ static const TypeInfo virtio_device_info = { .parent = TYPE_VIRTIO_DEVICE, .instance_size = sizeof(VirtIOSerial), .class_init = virtio_serial_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void virtio_serial_register_types(void) From 2f4f60351782c22744ae7c7de6afcefbe66f28a4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:27 +0000 Subject: [PATCH 27/47] virtio-mmio: Drop useless bus->allow_hotplug = 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bus by default is not hotpluggable. virtio-mmio-bus and its parent types do not set allow_hotplug anywhere explicitly, so remove not needed field access and wrapper along with it. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/virtio/virtio-mmio.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 18c6e5b55c..2450c13747 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -89,9 +89,6 @@ typedef struct { VirtioBusState bus; } VirtIOMMIOProxy; -static void virtio_mmio_bus_new(VirtioBusState *bus, size_t bus_size, - VirtIOMMIOProxy *dev); - static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size) { VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque; @@ -362,7 +359,8 @@ static void virtio_mmio_realizefn(DeviceState *d, Error **errp) VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); SysBusDevice *sbd = SYS_BUS_DEVICE(d); - virtio_mmio_bus_new(&proxy->bus, sizeof(proxy->bus), proxy); + qbus_create_inplace(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS, + d, NULL); sysbus_init_irq(sbd, &proxy->irq); memory_region_init_io(&proxy->iomem, OBJECT(d), &virtio_mem_ops, proxy, TYPE_VIRTIO_MMIO, 0x200); @@ -393,17 +391,6 @@ static const TypeInfo virtio_mmio_info = { /* virtio-mmio-bus. */ -static void virtio_mmio_bus_new(VirtioBusState *bus, size_t bus_size, - VirtIOMMIOProxy *dev) -{ - DeviceState *qdev = DEVICE(dev); - BusState *qbus; - - qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_MMIO_BUS, qdev, NULL); - qbus = BUS(bus); - qbus->allow_hotplug = 0; -} - static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data) { BusClass *bus_class = BUS_CLASS(klass); From 492bcf8f711cfd1f1056b0a7cff768a6a5f387ee Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:28 +0000 Subject: [PATCH 28/47] s390x: Drop not used allow_hotplug in event-facility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s390-sclp-event-facility creates s390-sclp-events-bus and immediately sets its allow_hotplug field to 0, which is NOP since it's already 0 by default. Also since BUS is not hotpluggable, it's not possible to call SCLP_EVENT{ DeviceClass::unplug } callback from qdev_unplug() making this unreachable code, so drop it as well. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Cornelia Huck Signed-off-by: Andreas Färber --- hw/s390x/event-facility.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 597db34019..78da718362 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -333,7 +333,6 @@ static int init_event_facility(SCLPEventFacility *event_facility) /* Spawn a new bus for SCLP events */ qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus), TYPE_SCLP_EVENTS_BUS, sdev, NULL); - event_facility->sbus.qbus.allow_hotplug = 0; quiesce = qdev_create(&event_facility->sbus.qbus, "sclpquiesce"); if (!quiesce) { @@ -408,7 +407,6 @@ static void event_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->bus_type = TYPE_SCLP_EVENTS_BUS; - dc->unplug = qdev_simple_unplug_cb; dc->realize = event_realize; dc->unrealize = event_unrealize; } From e98f8c36222d2d6574a137ebb452fb35c59ad697 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 12:37:30 +0000 Subject: [PATCH 29/47] s390x: Convert s390-virtio to hotplug handler API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beside of conversion, patch drops present unplug handling, effectively disabling hot-unplug of s390-virtio devices. Signed-off-by: Igor Mammedov Reviewed-by: Cornelia Huck Signed-off-by: Andreas Färber --- hw/s390x/s390-virtio-bus.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index f451ca1ed3..5a9e52b777 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -102,7 +102,7 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; /* Enable hotplugging */ - _bus->allow_hotplug = 1; + qbus_set_hotplug_handler(_bus, dev, &error_abort); /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */ *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE; @@ -600,7 +600,6 @@ static void virtio_s390_device_class_init(ObjectClass *klass, void *data) dc->init = s390_virtio_busdev_init; dc->bus_type = TYPE_S390_VIRTIO_BUS; - dc->unplug = qdev_simple_unplug_cb; dc->reset = s390_virtio_busdev_reset; } @@ -681,6 +680,10 @@ static const TypeInfo s390_virtio_bridge_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SysBusDevice), .class_init = s390_virtio_bridge_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; /* virtio-s390-bus */ @@ -689,13 +692,10 @@ static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size, VirtIOS390Device *dev) { DeviceState *qdev = DEVICE(dev); - BusState *qbus; char virtio_bus_name[] = "virtio-bus"; qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_S390_BUS, qdev, virtio_bus_name); - qbus = BUS(bus); - qbus->allow_hotplug = 1; } static void virtio_s390_bus_class_init(ObjectClass *klass, void *data) From 277bc95ed31c2db08c5e3662e1dcebaf27cb5150 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:30 +0000 Subject: [PATCH 30/47] s390x: Convert virtio-ccw to hotplug handler API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/s390x/virtio-ccw.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 18ba29fa14..4438b6fc74 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -230,7 +230,7 @@ VirtualCssBus *virtual_css_bus_init(void) cbus = VIRTUAL_CSS_BUS(bus); /* Enable hotplugging */ - bus->allow_hotplug = 1; + qbus_set_hotplug_handler(bus, dev, &error_abort); return cbus; } @@ -1590,7 +1590,8 @@ static int virtio_ccw_busdev_exit(DeviceState *dev) return _info->exit(_dev); } -static int virtio_ccw_busdev_unplug(DeviceState *dev) +static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) { VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; SubchDev *sch = _dev->sch; @@ -1609,7 +1610,6 @@ static int virtio_ccw_busdev_unplug(DeviceState *dev) css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0); object_unparent(OBJECT(dev)); - return 0; } static Property virtio_ccw_properties[] = { @@ -1624,9 +1624,7 @@ static void virtio_ccw_device_class_init(ObjectClass *klass, void *data) dc->props = virtio_ccw_properties; dc->init = virtio_ccw_busdev_init; dc->exit = virtio_ccw_busdev_exit; - dc->unplug = virtio_ccw_busdev_unplug; dc->bus_type = TYPE_VIRTUAL_CSS_BUS; - } static const TypeInfo virtio_ccw_device_info = { @@ -1650,8 +1648,10 @@ static int virtual_css_bridge_init(SysBusDevice *dev) static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); k->init = virtual_css_bridge_init; + hc->unplug = virtio_ccw_busdev_unplug; } static const TypeInfo virtual_css_bridge_info = { @@ -1659,6 +1659,10 @@ static const TypeInfo virtual_css_bridge_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SysBusDevice), .class_init = virtual_css_bridge_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; /* virtio-ccw-bus */ @@ -1667,13 +1671,10 @@ static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, VirtioCcwDevice *dev) { DeviceState *qdev = DEVICE(dev); - BusState *qbus; char virtio_bus_name[] = "virtio-bus"; qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_CCW_BUS, qdev, virtio_bus_name); - qbus = BUS(bus); - qbus->allow_hotplug = 1; } static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data) From bddd763a4e43213ba4e003ee2f8afb4f1222ec88 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:31 +0000 Subject: [PATCH 31/47] scsi: Set SCSI BUS itself as default HotplugHandler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That would allow to handle SCSI device unplug on HBAs without dedicated hot(un)plug handlers and avoid making such HBAs explicitly hotpluggable. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/scsi/scsi-bus.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 0f3e0395f5..c454331ee1 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -23,9 +23,11 @@ static Property scsi_props[] = { static void scsi_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); k->get_dev_path = scsibus_get_dev_path; k->get_fw_dev_path = scsibus_get_fw_dev_path; + hc->unplug = qdev_simple_device_unplug_cb; } static const TypeInfo scsi_bus_info = { @@ -33,6 +35,10 @@ static const TypeInfo scsi_bus_info = { .parent = TYPE_BUS, .instance_size = sizeof(SCSIBus), .class_init = scsi_bus_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static int next_scsi_bus; @@ -92,7 +98,7 @@ void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host, qbus_create_inplace(bus, bus_size, TYPE_SCSI_BUS, host, bus_name); bus->busnr = next_scsi_bus++; bus->info = info; - bus->qbus.allow_hotplug = 1; + qbus_set_bus_hotplug_handler(BUS(bus), &error_abort); } static void scsi_dma_restart_bh(void *opaque) From 91c8daad4b66cebe5cecc799c988bed215cd791c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:32 +0000 Subject: [PATCH 32/47] scsi: Convert pvscsi HBA to hotplug handler API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/scsi/vmw_pvscsi.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index 5734d19789..d3a92fbabf 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -524,17 +524,20 @@ pvscsi_send_msg(PVSCSIState *s, SCSIDevice *dev, uint32_t msg_type) } static void -pvscsi_hotplug(SCSIBus *bus, SCSIDevice *dev) +pvscsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - PVSCSIState *s = container_of(bus, PVSCSIState, bus); - pvscsi_send_msg(s, dev, PVSCSI_MSG_DEV_ADDED); + PVSCSIState *s = PVSCSI(hotplug_dev); + + pvscsi_send_msg(s, SCSI_DEVICE(dev), PVSCSI_MSG_DEV_ADDED); } static void -pvscsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev) +pvscsi_hot_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - PVSCSIState *s = container_of(bus, PVSCSIState, bus); - pvscsi_send_msg(s, dev, PVSCSI_MSG_DEV_REMOVED); + PVSCSIState *s = PVSCSI(hotplug_dev); + + pvscsi_send_msg(s, SCSI_DEVICE(dev), PVSCSI_MSG_DEV_REMOVED); + qdev_simple_device_unplug_cb(hotplug_dev, dev, errp); } static void @@ -1057,8 +1060,6 @@ static const struct SCSIBusInfo pvscsi_scsi_info = { .get_sg_list = pvscsi_get_sg_list, .complete = pvscsi_command_complete, .cancel = pvscsi_request_cancelled, - .hotplug = pvscsi_hotplug, - .hot_unplug = pvscsi_hot_unplug, }; static int @@ -1092,6 +1093,8 @@ pvscsi_init(PCIDevice *pci_dev) scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(pci_dev), &pvscsi_scsi_info, NULL); + /* override default SCSI bus hotplug-handler, with pvscsi's one */ + qbus_set_hotplug_handler(BUS(&s->bus), DEVICE(s), &error_abort); pvscsi_reset_state(s); return 0; @@ -1187,6 +1190,7 @@ static void pvscsi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); k->init = pvscsi_init; k->exit = pvscsi_uninit; @@ -1199,6 +1203,8 @@ static void pvscsi_class_init(ObjectClass *klass, void *data) dc->props = pvscsi_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); k->config_write = pvscsi_write_config; + hc->unplug = pvscsi_hot_unplug; + hc->plug = pvscsi_hotplug; } static const TypeInfo pvscsi_info = { @@ -1206,6 +1212,10 @@ static const TypeInfo pvscsi_info = { .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PVSCSIState), .class_init = pvscsi_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void From 02206e5275ee1e34b2adf177c05aadec56af4bf8 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:33 +0000 Subject: [PATCH 33/47] scsi: Convert virtio-scsi HBA to hotplug handler API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/scsi/virtio-scsi.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 6c02fe2b9a..8547ea0475 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -737,26 +737,29 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense) } } -static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev) +static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) { - VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); - VirtIODevice *vdev = VIRTIO_DEVICE(s); + VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { - virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, + virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), + VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } } -static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev) +static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) { - VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus); - VirtIODevice *vdev = VIRTIO_DEVICE(s); + VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { - virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET, + virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), + VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); } + qdev_simple_device_unplug_cb(hotplug_dev, dev, errp); } static struct SCSIBusInfo virtio_scsi_scsi_info = { @@ -768,8 +771,6 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = { .complete = virtio_scsi_command_complete, .cancel = virtio_scsi_request_cancelled, .change = virtio_scsi_change, - .hotplug = virtio_scsi_hotplug, - .hot_unplug = virtio_scsi_hot_unplug, .parse_cdb = virtio_scsi_parse_cdb, .get_sg_list = virtio_scsi_get_sg_list, .save_request = virtio_scsi_save_request, @@ -853,6 +854,8 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp) scsi_bus_new(&s->bus, sizeof(s->bus), dev, &virtio_scsi_scsi_info, vdev->bus_name); + /* override default SCSI bus hotplug-handler, with virtio-scsi's one */ + qbus_set_hotplug_handler(BUS(&s->bus), dev, &error_abort); if (!dev->hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus, &err); @@ -915,6 +918,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); dc->props = virtio_scsi_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); @@ -923,6 +927,8 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data) vdc->set_config = virtio_scsi_set_config; vdc->get_features = virtio_scsi_get_features; vdc->reset = virtio_scsi_reset; + hc->plug = virtio_scsi_hotplug; + hc->unplug = virtio_scsi_hotunplug; } static const TypeInfo virtio_scsi_common_info = { @@ -939,6 +945,10 @@ static const TypeInfo virtio_scsi_info = { .instance_size = sizeof(VirtIOSCSI), .instance_init = virtio_scsi_instance_init, .class_init = virtio_scsi_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void virtio_register_types(void) From 10bdcd565992e17f0b4f04e0b28793b169e51a26 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:34 +0000 Subject: [PATCH 34/47] scsi: Cleanup not used anymore SCSIBusInfo{hotplug, hot_unplug} fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SCSI subsytem was converted to hotplug handler API and doesn't use SCSIBusInfo{hotplug, hot_unplug} fields and related callbacks anymore. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/scsi/scsi-bus.c | 16 ---------------- include/hw/scsi/scsi.h | 2 -- 2 files changed, 18 deletions(-) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index c454331ee1..d33030e6e9 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -208,10 +208,6 @@ static void scsi_qdev_realize(DeviceState *qdev, Error **errp) } dev->vmsentry = qemu_add_vm_change_state_handler(scsi_dma_restart_cb, dev); - - if (bus->info->hotplug) { - bus->info->hotplug(bus, dev); - } } static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp) @@ -1943,17 +1939,6 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size) return 0; } -static int scsi_qdev_unplug(DeviceState *qdev) -{ - SCSIDevice *dev = SCSI_DEVICE(qdev); - SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); - - if (bus->info->hot_unplug) { - bus->info->hot_unplug(bus, dev); - } - return qdev_simple_unplug_cb(qdev); -} - static const VMStateInfo vmstate_info_scsi_requests = { .name = "scsi-requests", .get = get_scsi_requests, @@ -2017,7 +2002,6 @@ static void scsi_device_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_STORAGE, k->categories); k->bus_type = TYPE_SCSI_BUS; k->realize = scsi_qdev_realize; - k->unplug = scsi_qdev_unplug; k->unrealize = scsi_qdev_unrealize; k->props = scsi_props; } diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index b61bedb28c..caaa3201ce 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -146,8 +146,6 @@ struct SCSIBusInfo { void (*transfer_data)(SCSIRequest *req, uint32_t arg); void (*complete)(SCSIRequest *req, uint32_t arg, size_t resid); void (*cancel)(SCSIRequest *req); - void (*hotplug)(SCSIBus *bus, SCSIDevice *dev); - void (*hot_unplug)(SCSIBus *bus, SCSIDevice *dev); void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense); QEMUSGList *(*get_sg_list)(SCSIRequest *req); From e9fd12aa0dd734f1e3725d93a0afa8721fab3bd2 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:35 +0000 Subject: [PATCH 35/47] usb-bot: Mark device as non hotpluggable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit usb-bot creates SCSI bus and immediately makes it non hotpluggable which was making not possible to hotplug usb-bot since QEMU would abort at bus_add_child(scsi-hd) time when usb-bot is realized. Mark usb-bot as not hotpluggable so that attempt to hotplug it would error out even before it gets to device initialization point. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/usb/dev-storage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index bd7cc53e07..a2075074a5 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -770,9 +770,11 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data) static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data) { USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); uc->realize = usb_msd_realize_bot; usb_msd_class_initfn_common(klass); + dc->hotpluggable = false; } static const TypeInfo msd_info = { From af01492755b82ccaf0d15014477b34ba3ea643fc Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:36 +0000 Subject: [PATCH 36/47] usb-bot: Drop not needed "allow_hotplug = 0" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop useless hack that disables hotplug on bus by setting "allow_hotplug = 0". Even if bus is hotpluggable, It won't be possible to add another SCSI device to bus since its realization will fail early with error "no free target" in scsi_qdev_realize() method. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/usb/dev-storage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index a2075074a5..bccaa3fbf4 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -653,7 +653,6 @@ static void usb_msd_realize_bot(USBDevice *dev, Error **errp) usb_desc_init(dev); scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), &usb_msd_scsi_info_bot, NULL); - s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); } From 77de4a09c6d3d1e4fabcc0eb6cfdb9ea5a1616d5 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:37 +0000 Subject: [PATCH 37/47] usb-storage: Drop not needed "allow_hotplug = 0" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop useless hack that disables hotplug on bus, after backend storage was added to it, by setting "allow_hotplug = 0". Even if bus is hotpluggable, it won't be possible to add another SCSI device to bus since its realize will fail early with error "no free target" in scsi_qdev_realize() method. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/usb/dev-storage.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index bccaa3fbf4..b005783fdf 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -632,7 +632,6 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) error_propagate(errp, err); return; } - s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); if (bdrv_key_required(bs)) { From 138d587afbf17dc6ef42106f0dd0de9ae707b81c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:38 +0000 Subject: [PATCH 38/47] usb: Convert usb-ccid to hotplug handler API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/usb/dev-smartcard-reader.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index d37ed02d2e..78ce681671 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1312,8 +1312,8 @@ static void ccid_realize(USBDevice *dev, Error **errp) usb_desc_init(dev); qbus_create_inplace(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev), NULL); + qbus_set_hotplug_handler(BUS(&s->bus), DEVICE(dev), &error_abort); s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); - s->bus.qbus.allow_hotplug = 1; s->card = NULL; s->migration_state = MIGRATION_NONE; s->migration_target_ip = 0; @@ -1439,6 +1439,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); uc->realize = ccid_realize; uc->product_desc = "QEMU USB CCID"; @@ -1451,6 +1452,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data) dc->vmsd = &ccid_vmstate; dc->props = ccid_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + hc->unplug = qdev_simple_device_unplug_cb; } static const TypeInfo ccid_info = { @@ -1458,6 +1460,10 @@ static const TypeInfo ccid_info = { .parent = TYPE_USB_DEVICE, .instance_size = sizeof(USBCCIDState), .class_init = ccid_class_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void ccid_card_class_init(ObjectClass *klass, void *data) From 5f4d917376fef99fe7f2e978b404cddc41727fa4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:39 +0000 Subject: [PATCH 39/47] usb: Convert usb devices to hotplug handler API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/usb/bus.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/usb/bus.c b/hw/usb/bus.c index da1eba9fbd..986b2d8da8 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -24,10 +24,12 @@ static Property usb_props[] = { static void usb_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); k->print_dev = usb_bus_dev_print; k->get_dev_path = usb_get_dev_path; k->get_fw_dev_path = usb_get_fw_dev_path; + hc->unplug = qdev_simple_device_unplug_cb; } static const TypeInfo usb_bus_info = { @@ -35,6 +37,10 @@ static const TypeInfo usb_bus_info = { .parent = TYPE_BUS, .instance_size = sizeof(USBBus), .class_init = usb_bus_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static int next_usb_bus = 0; @@ -79,9 +85,9 @@ void usb_bus_new(USBBus *bus, size_t bus_size, USBBusOps *ops, DeviceState *host) { qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL); + qbus_set_bus_hotplug_handler(BUS(bus), &error_abort); bus->ops = ops; bus->busnr = next_usb_bus++; - bus->qbus.allow_hotplug = 1; /* Yes, we can */ QTAILQ_INIT(&bus->free); QTAILQ_INIT(&bus->used); QTAILQ_INSERT_TAIL(&busses, bus, next); @@ -701,7 +707,6 @@ static void usb_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->bus_type = TYPE_USB_BUS; - k->unplug = qdev_simple_unplug_cb; k->realize = usb_qdev_realize; k->unrealize = usb_qdev_unrealize; k->props = usb_props; From 2d9a982f37cc7c427d655a828c5ffa3cc5753863 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:40 +0000 Subject: [PATCH 40/47] qdev: Drop legacy hotplug fields/methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It removes not needed anymore BusState::allow_hotplug field and DeviceClass::unplug callback. Signed-off-by: Igor Mammedov Reviewed-by: Paolo Bonzini Signed-off-by: Andreas Färber --- hw/core/qdev.c | 16 +++------------- include/hw/qdev-core.h | 5 +---- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 6439a23273..3e58dd0309 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -114,7 +114,6 @@ static void qbus_set_hotplug_handler_internal(BusState *bus, Object *handler, object_property_set_link(OBJECT(bus), OBJECT(handler), QDEV_HOTPLUG_HANDLER_PROPERTY, errp); - bus->allow_hotplug = 1; } void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler, Error **errp) @@ -254,10 +253,7 @@ void qdev_unplug(DeviceState *dev, Error **errp) hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp); } } else { - assert(dc->unplug != NULL); - if (dc->unplug(dev) < 0) { /* legacy handler */ - error_set(errp, QERR_UNDEFINED_ERROR); - } + assert(0); } } @@ -294,17 +290,11 @@ void qbus_reset_all_fn(void *opaque) } /* can be used as ->unplug() callback for the simple cases */ -int qdev_simple_unplug_cb(DeviceState *dev) -{ - /* just zap it */ - object_unparent(OBJECT(dev)); - return 0; -} - void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - qdev_simple_unplug_cb(dev); + /* just zap it */ + object_unparent(OBJECT(dev)); } /* Like qdev_init(), but terminate program via error_report() instead of diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 48e9579a88..01d7db47e0 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -126,7 +126,6 @@ typedef struct DeviceClass { /* Private to qdev / bus. */ qdev_initfn init; /* TODO remove, once users are converted to realize */ - qdev_event unplug; qdev_event exit; /* TODO remove, once users are converted to unrealize */ const char *bus_type; } DeviceClass; @@ -210,7 +209,6 @@ struct BusState { Object obj; DeviceState *parent; const char *name; - int allow_hotplug; HotplugHandler *hotplug_handler; int max_index; bool realized; @@ -264,7 +262,6 @@ void qdev_init_nofail(DeviceState *dev); void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, int required_for_version); void qdev_unplug(DeviceState *dev, Error **errp); -int qdev_simple_unplug_cb(DeviceState *dev); void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); void qdev_machine_creation_done(void); @@ -370,6 +367,6 @@ void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp); static inline bool qbus_is_hotpluggable(BusState *bus) { - return bus->allow_hotplug || bus->hotplug_handler; + return bus->hotplug_handler; } #endif From 7716b8ca7479dec146062c97453dd38e505a5ab4 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 26 Sep 2014 09:28:41 +0000 Subject: [PATCH 41/47] qdev: HotplugHandler: Add support for unplugging BUS-less devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- hw/core/qdev.c | 59 ++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 3e58dd0309..7685e0728b 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -223,9 +223,28 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, dev->alias_required_for_version = required_for_version; } +static HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) +{ + HotplugHandler *hotplug_ctrl = NULL; + + if (dev->parent_bus && dev->parent_bus->hotplug_handler) { + hotplug_ctrl = dev->parent_bus->hotplug_handler; + } else if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) { + MachineState *machine = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(machine); + + if (mc->get_hotplug_handler) { + hotplug_ctrl = mc->get_hotplug_handler(machine, dev); + } + } + return hotplug_ctrl; +} + void qdev_unplug(DeviceState *dev, Error **errp) { DeviceClass *dc = DEVICE_GET_CLASS(dev); + HotplugHandler *hotplug_ctrl; + HotplugHandlerClass *hdc; if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) { error_set(errp, QERR_BUS_NO_HOTPLUG, dev->parent_bus->name); @@ -240,20 +259,18 @@ void qdev_unplug(DeviceState *dev, Error **errp) qdev_hot_removed = true; - if (dev->parent_bus && dev->parent_bus->hotplug_handler) { - HotplugHandlerClass *hdc; + hotplug_ctrl = qdev_get_hotplug_handler(dev); + /* hotpluggable device MUST have HotplugHandler, if it doesn't + * then something is very wrong with it */ + g_assert(hotplug_ctrl); - /* If device supports async unplug just request it to be done, - * otherwise just remove it synchronously */ - hdc = HOTPLUG_HANDLER_GET_CLASS(dev->parent_bus->hotplug_handler); - if (hdc->unplug_request) { - hotplug_handler_unplug_request(dev->parent_bus->hotplug_handler, - dev, errp); - } else { - hotplug_handler_unplug(dev->parent_bus->hotplug_handler, dev, errp); - } + /* If device supports async unplug just request it to be done, + * otherwise just remove it synchronously */ + hdc = HOTPLUG_HANDLER_GET_CLASS(hotplug_ctrl); + if (hdc->unplug_request) { + hotplug_handler_unplug_request(hotplug_ctrl, dev, errp); } else { - assert(0); + hotplug_handler_unplug(hotplug_ctrl, dev, errp); } } @@ -854,6 +871,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) { DeviceState *dev = DEVICE(obj); DeviceClass *dc = DEVICE_GET_CLASS(dev); + HotplugHandler *hotplug_ctrl; BusState *bus; Error *local_err = NULL; @@ -881,20 +899,9 @@ static void device_set_realized(Object *obj, bool value, Error **errp) goto fail; } - if (dev->parent_bus && dev->parent_bus->hotplug_handler) { - hotplug_handler_plug(dev->parent_bus->hotplug_handler, - dev, &local_err); - } else if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) { - HotplugHandler *hotplug_ctrl; - MachineState *machine = MACHINE(qdev_get_machine()); - MachineClass *mc = MACHINE_GET_CLASS(machine); - - if (mc->get_hotplug_handler) { - hotplug_ctrl = mc->get_hotplug_handler(machine, dev); - if (hotplug_ctrl) { - hotplug_handler_plug(hotplug_ctrl, dev, &local_err); - } - } + hotplug_ctrl = qdev_get_hotplug_handler(dev); + if (hotplug_ctrl) { + hotplug_handler_plug(hotplug_ctrl, dev, &local_err); } if (local_err != NULL) { From b6cc36abb20a54a30fbd7d0ae98066df6c5adabc Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 2 Oct 2014 10:08:45 +0000 Subject: [PATCH 42/47] qdev: device_del: Search for to be unplugged device in 'peripheral' container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit device_add puts every device with 'id' inside of 'peripheral' container using id's value as the last component name. Use it by replacing recursive search on sysbus with path lookup in 'peripheral' container, which could handle both BUS and BUS-less device cases. Signed-off-by: Igor Mammedov Signed-off-by: Andreas Färber --- qdev-monitor.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/qdev-monitor.c b/qdev-monitor.c index c72145127e..754437b777 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -686,15 +686,20 @@ int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data) void qmp_device_del(const char *id, Error **errp) { - DeviceState *dev; + Object *obj; + char *root_path = object_get_canonical_path(qdev_get_peripheral()); + char *path = g_strdup_printf("%s/%s", root_path, id); - dev = qdev_find_recursive(sysbus_get_default(), id); - if (!dev) { + g_free(root_path); + obj = object_resolve_path_type(path, TYPE_DEVICE, NULL); + g_free(path); + + if (!obj) { error_set(errp, QERR_DEVICE_NOT_FOUND, id); return; } - qdev_unplug(dev, errp); + qdev_unplug(DEVICE(obj), errp); } void qdev_machine_init(void) From 51b2e8c331c1e3de5463bd7fe13676c2a9ec52fe Mon Sep 17 00:00:00 2001 From: Gonglei Date: Tue, 7 Oct 2014 14:33:20 +0800 Subject: [PATCH 43/47] qdev: Add description field in PropertyInfo struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The descriptions can serve as documentation in the code, and they can be used to provide better help. Cc: Markus Armbruster Signed-off-by: Gonglei Signed-off-by: Paolo Bonzini Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/core/qdev-properties-system.c | 4 ++++ hw/core/qdev-properties.c | 8 ++++++++ include/hw/qdev-core.h | 1 + target-ppc/translate_init.c | 1 + 4 files changed, 14 insertions(+) diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 84caa1d694..55b6636106 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -113,6 +113,7 @@ static void set_drive(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_drive = { .name = "str", .legacy_name = "drive", + .description = "ID of a drive to use as a backend", .get = get_drive, .set = set_drive, .release = release_drive, @@ -170,6 +171,7 @@ static void set_chr(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_chr = { .name = "str", .legacy_name = "chr", + .description = "ID of a chardev to use as a backend", .get = get_chr, .set = set_chr, .release = release_chr, @@ -249,6 +251,7 @@ static void set_netdev(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_netdev = { .name = "str", .legacy_name = "netdev", + .description = "ID of a netdev to use as a backend", .get = get_netdev, .set = set_netdev, }; @@ -329,6 +332,7 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_vlan = { .name = "int32", .legacy_name = "vlan", + .description = "Integer VLAN id to connect to", .print = print_vlan, .get = get_vlan, .set = set_vlan, diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 66556d3bf9..5fc711eb5c 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -121,6 +121,7 @@ static void prop_set_bit(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_bit = { .name = "bool", .legacy_name = "on/off", + .description = "on/off", .get = prop_get_bit, .set = prop_set_bit, }; @@ -456,6 +457,7 @@ inval: PropertyInfo qdev_prop_macaddr = { .name = "str", .legacy_name = "macaddr", + .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", .get = get_mac, .set = set_mac, }; @@ -478,6 +480,8 @@ QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); PropertyInfo qdev_prop_bios_chs_trans = { .name = "BiosAtaTranslation", .legacy_name = "bios-chs-trans", + .description = "Logical CHS translation algorithm, " + "auto/none/lba/large/rechs", .enum_table = BiosAtaTranslation_lookup, .get = get_enum, .set = set_enum, @@ -552,6 +556,7 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, PropertyInfo qdev_prop_pci_devfn = { .name = "int32", .legacy_name = "pci-devfn", + .description = "Slot and optional function number, example: 06.0 or 06", .print = print_pci_devfn, .get = get_int32, .set = set_pci_devfn, @@ -599,6 +604,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_blocksize = { .name = "uint16", .legacy_name = "blocksize", + .description = "A power of two between 512 and 32768", .get = get_uint16, .set = set_blocksize, }; @@ -707,6 +713,8 @@ inval: PropertyInfo qdev_prop_pci_host_devaddr = { .name = "str", .legacy_name = "pci-host-devaddr", + .description = "Address (bus/device/function) of " + "the host device, example: 04:10.0", .get = get_pci_host_devaddr, .set = set_pci_host_devaddr, }; diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 01d7db47e0..c30e50268f 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -231,6 +231,7 @@ struct Property { struct PropertyInfo { const char *name; const char *legacy_name; + const char *description; const char **enum_table; int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); ObjectPropertyAccessor *get; diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 65b840da03..0312e04778 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8045,6 +8045,7 @@ static void powerpc_set_compat(Object *obj, Visitor *v, static PropertyInfo powerpc_compat_propinfo = { .name = "str", .legacy_name = "powerpc-server-compat", + .description = "compatibility mode, power6/power7/power8", .get = powerpc_get_compat, .set = powerpc_set_compat, }; From 8074264203db3351a4017ea0371c2c5eeb86df82 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Tue, 7 Oct 2014 14:33:21 +0800 Subject: [PATCH 44/47] qom: Add description field in ObjectProperty struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The descriptions can serve as documentation in the code, and they can be used to provide better help. Copy property descriptions when copying alias properties. Cc: Markus Armbruster Signed-off-by: Gonglei Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- include/qom/object.h | 14 ++++++++++++++ qom/object.c | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/qom/object.h b/include/qom/object.h index 8a05a81a99..89c3092967 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -338,6 +338,7 @@ typedef struct ObjectProperty { gchar *name; gchar *type; + gchar *description; ObjectPropertyAccessor *get; ObjectPropertyAccessor *set; ObjectPropertyResolve *resolve; @@ -1274,6 +1275,19 @@ void object_property_add_alias(Object *obj, const char *name, Object *target_obj, const char *target_name, Error **errp); +/** + * object_property_set_description: + * @obj: the object owning the property + * @name: the name of the property + * @description: the description of the property on the object + * @errp: if an error occurs, a pointer to an area to store the error + * + * Set an object property's description. + * + */ +void object_property_set_description(Object *obj, const char *name, + const char *description, Error **errp); + /** * object_child_foreach: * @obj: the object whose children will be navigated diff --git a/qom/object.c b/qom/object.c index 575291f109..a751367e61 100644 --- a/qom/object.c +++ b/qom/object.c @@ -369,6 +369,7 @@ static void object_property_del_all(Object *obj) g_free(prop->name); g_free(prop->type); + g_free(prop->description); g_free(prop); } } @@ -803,6 +804,7 @@ void object_property_del(Object *obj, const char *name, Error **errp) g_free(prop->name); g_free(prop->type); + g_free(prop->description); g_free(prop); } @@ -1672,10 +1674,28 @@ void object_property_add_alias(Object *obj, const char *name, } op->resolve = property_resolve_alias; + object_property_set_description(obj, name, + target_prop->description, + &error_abort); + out: g_free(prop_type); } +void object_property_set_description(Object *obj, const char *name, + const char *description, Error **errp) +{ + ObjectProperty *op; + + op = object_property_find(obj, name, errp); + if (!op) { + return; + } + + g_free(op->description); + op->description = g_strdup(description); +} + static void object_instance_init(Object *obj) { object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); From b8c9cd5c8cf2a105dab8ac3e5799e3b27bfda9d5 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Tue, 7 Oct 2014 14:33:22 +0800 Subject: [PATCH 45/47] qdev: Set the object property's description to the qdev property's. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set all static qdev properties' descriptions to object property's description. Cc: Markus Armbruster Signed-off-by: Gonglei Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/core/qdev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 7685e0728b..a1e9247772 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -826,6 +826,11 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, error_propagate(errp, local_err); return; } + + object_property_set_description(obj, prop->name, + prop->info->description, + &error_abort); + if (prop->qtype == QTYPE_NONE) { return; } From 07d09c58dbbb9e3c6f6d06e5a27b23531f84a6f6 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Tue, 7 Oct 2014 14:33:23 +0800 Subject: [PATCH 46/47] qmp: Print descriptions of object properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new "description" field to DevicePropertyInfo. The descriptions can serve as documentation in the code, and they can be used to provide better help. For example: $./qemu-system-x86_64 -device virtio-blk-pci,? Before this patch: virtio-blk-pci.iothread=link virtio-blk-pci.x-data-plane=bool virtio-blk-pci.scsi=bool virtio-blk-pci.config-wce=bool virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 virtio-blk-pci.logical_block_size=uint16 virtio-blk-pci.drive=str virtio-blk-pci.virtio-backend=child virtio-blk-pci.command_serr_enable=on/off virtio-blk-pci.multifunction=on/off virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=pci-devfn virtio-blk-pci.event_idx=on/off virtio-blk-pci.indirect_desc=on/off virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=on/off virtio-blk-pci.class=uint32 After: virtio-blk-pci.iothread=link virtio-blk-pci.x-data-plane=bool (on/off) virtio-blk-pci.scsi=bool (on/off) virtio-blk-pci.config-wce=bool (on/off) virtio-blk-pci.serial=str virtio-blk-pci.secs=uint32 virtio-blk-pci.heads=uint32 virtio-blk-pci.cyls=uint32 virtio-blk-pci.discard_granularity=uint32 virtio-blk-pci.bootindex=int32 virtio-blk-pci.opt_io_size=uint32 virtio-blk-pci.min_io_size=uint16 virtio-blk-pci.physical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.logical_block_size=uint16 (A power of two between 512 and 32768) virtio-blk-pci.drive=str (ID of a drive to use as a backend) virtio-blk-pci.virtio-backend=child virtio-blk-pci.command_serr_enable=bool (on/off) virtio-blk-pci.multifunction=bool (on/off) virtio-blk-pci.rombar=uint32 virtio-blk-pci.romfile=str virtio-blk-pci.addr=int32 (Slot and optional function number, example: 06.0 or 06) virtio-blk-pci.event_idx=bool (on/off) virtio-blk-pci.indirect_desc=bool (on/off) virtio-blk-pci.vectors=uint32 virtio-blk-pci.ioeventfd=bool (on/off) virtio-blk-pci.class=uint32 Cc: Markus Armbruster Signed-off-by: Gonglei Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Reviewed-by: Eric Blake Signed-off-by: Andreas Färber --- qapi-schema.json | 4 +++- qdev-monitor.c | 7 ++++++- qmp.c | 13 ++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/qapi-schema.json b/qapi-schema.json index 4f0d7e3250..24379ab3af 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1615,11 +1615,13 @@ # # @name: the name of the property # @type: the typename of the property +# @description: #optional if specified, the description of the property. +# (since 2.2) # # Since: 1.2 ## { 'type': 'DevicePropertyInfo', - 'data': { 'name': 'str', 'type': 'str' } } + 'data': { 'name': 'str', 'type': 'str', '*description': 'str' } } ## # @device-list-properties: diff --git a/qdev-monitor.c b/qdev-monitor.c index 754437b777..fac7d179fe 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -213,9 +213,14 @@ int qdev_device_help(QemuOpts *opts) } for (prop = prop_list; prop; prop = prop->next) { - error_printf("%s.%s=%s\n", driver, + error_printf("%s.%s=%s", driver, prop->value->name, prop->value->type); + if (prop->value->has_description) { + error_printf(" (%s)\n", prop->value->description); + } else { + error_printf("\n"); + } } qapi_free_DevicePropertyInfoList(prop_list); diff --git a/qmp.c b/qmp.c index c6767c4df3..0b4f131936 100644 --- a/qmp.c +++ b/qmp.c @@ -442,7 +442,8 @@ ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, */ static DevicePropertyInfo *make_device_property_info(ObjectClass *klass, const char *name, - const char *default_type) + const char *default_type, + const char *description) { DevicePropertyInfo *info; Property *prop; @@ -465,7 +466,9 @@ static DevicePropertyInfo *make_device_property_info(ObjectClass *klass, info = g_malloc0(sizeof(*info)); info->name = g_strdup(prop->name); - info->type = g_strdup(prop->info->legacy_name ?: prop->info->name); + info->type = g_strdup(prop->info->name); + info->has_description = !!prop->info->description; + info->description = g_strdup(prop->info->description); return info; } klass = object_class_get_parent(klass); @@ -475,6 +478,9 @@ static DevicePropertyInfo *make_device_property_info(ObjectClass *klass, info = g_malloc0(sizeof(*info)); info->name = g_strdup(name); info->type = g_strdup(default_type); + info->has_description = !!description; + info->description = g_strdup(description); + return info; } @@ -521,7 +527,8 @@ DevicePropertyInfoList *qmp_device_list_properties(const char *typename, continue; } - info = make_device_property_info(klass, prop->name, prop->type); + info = make_device_property_info(klass, prop->name, prop->type, + prop->description); if (!info) { continue; } From 18b91a3e082e7111455fd69ab43181831f8e0169 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Tue, 7 Oct 2014 14:33:24 +0800 Subject: [PATCH 47/47] qdev: Drop legacy_name from qdev properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The legacy_name is useless now, better help information is provided by description field of property. Cc: Markus Armbruster Signed-off-by: Gonglei Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Andreas Färber --- hw/core/qdev-properties-system.c | 4 ---- hw/core/qdev-properties.c | 6 ------ include/hw/qdev-core.h | 1 - target-ppc/translate_init.c | 1 - 4 files changed, 12 deletions(-) diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 55b6636106..f2bd954be5 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -112,7 +112,6 @@ static void set_drive(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_drive = { .name = "str", - .legacy_name = "drive", .description = "ID of a drive to use as a backend", .get = get_drive, .set = set_drive, @@ -170,7 +169,6 @@ static void set_chr(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_chr = { .name = "str", - .legacy_name = "chr", .description = "ID of a chardev to use as a backend", .get = get_chr, .set = set_chr, @@ -250,7 +248,6 @@ static void set_netdev(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_netdev = { .name = "str", - .legacy_name = "netdev", .description = "ID of a netdev to use as a backend", .get = get_netdev, .set = set_netdev, @@ -331,7 +328,6 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_vlan = { .name = "int32", - .legacy_name = "vlan", .description = "Integer VLAN id to connect to", .print = print_vlan, .get = get_vlan, diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 5fc711eb5c..2ed995f2b7 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -120,7 +120,6 @@ static void prop_set_bit(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_bit = { .name = "bool", - .legacy_name = "on/off", .description = "on/off", .get = prop_get_bit, .set = prop_set_bit, @@ -456,7 +455,6 @@ inval: PropertyInfo qdev_prop_macaddr = { .name = "str", - .legacy_name = "macaddr", .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", .get = get_mac, .set = set_mac, @@ -479,7 +477,6 @@ QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); PropertyInfo qdev_prop_bios_chs_trans = { .name = "BiosAtaTranslation", - .legacy_name = "bios-chs-trans", .description = "Logical CHS translation algorithm, " "auto/none/lba/large/rechs", .enum_table = BiosAtaTranslation_lookup, @@ -555,7 +552,6 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, PropertyInfo qdev_prop_pci_devfn = { .name = "int32", - .legacy_name = "pci-devfn", .description = "Slot and optional function number, example: 06.0 or 06", .print = print_pci_devfn, .get = get_int32, @@ -603,7 +599,6 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque, PropertyInfo qdev_prop_blocksize = { .name = "uint16", - .legacy_name = "blocksize", .description = "A power of two between 512 and 32768", .get = get_uint16, .set = set_blocksize, @@ -712,7 +707,6 @@ inval: PropertyInfo qdev_prop_pci_host_devaddr = { .name = "str", - .legacy_name = "pci-host-devaddr", .description = "Address (bus/device/function) of " "the host device, example: 04:10.0", .get = get_pci_host_devaddr, diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index c30e50268f..1fca75c591 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -230,7 +230,6 @@ struct Property { struct PropertyInfo { const char *name; - const char *legacy_name; const char *description; const char **enum_table; int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len); diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 0312e04778..33fb4cc9c3 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8044,7 +8044,6 @@ static void powerpc_set_compat(Object *obj, Visitor *v, static PropertyInfo powerpc_compat_propinfo = { .name = "str", - .legacy_name = "powerpc-server-compat", .description = "compatibility mode, power6/power7/power8", .get = powerpc_get_compat, .set = powerpc_set_compat,