diff options
author | Markus Armbruster <armbru@redhat.com> | 2015-02-04 13:28:11 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2015-02-18 10:53:10 +0100 |
commit | bd8b92d5c8387c2c94f06665514c05000169fafd (patch) | |
tree | 24d264faa965445785c9cdb09a43dc8ccbfcebf1 | |
parent | 06f22eb78f3eb557c667f5d0a46099e43a2aeb0d (diff) | |
download | hqemu-bd8b92d5c8387c2c94f06665514c05000169fafd.zip hqemu-bd8b92d5c8387c2c94f06665514c05000169fafd.tar.gz |
usb: Suppress bogus error when automatic usb-hub creation fails
USBDevice's realize method usb_qdev_realize() automatically creates a
usb-hub when only one port is left. Creating devices in realize
methods is questionable, but works.
If usb-hub creation fails, an error is reported to stderr, but the
failure is otherwise ignored. We then create the actual device using
the last port, which may well succeed.
Example:
$ qemu -nodefaults -S -display none -machine usb=on -monitor stdio
QEMU 2.2.50 monitor - type 'help' for more information
(qemu) device_add usb-mouse
[Repeat 36 times]
(qemu) info usb
Device 0.0, Port 1, Speed 12 Mb/s, Product QEMU USB Mouse
Device 0.0, Port 2, Speed 12 Mb/s, Product QEMU USB Hub
Device 0.0, Port 2.1, Speed 12 Mb/s, Product QEMU USB Mouse
[More mice and hubs omitted...]
Device 0.0, Port 2.8.8.8.8.7, Speed 12 Mb/s, Product QEMU USB Mouse
(qemu) device_add usb-mouse
usb hub chain too deep
Failed to initialize USB device 'usb-hub'
(qemu) info usb
[...]
Device 0.0, Port 2.8.8.8.8.7, Speed 12 Mb/s, Product QEMU USB Mouse
Device 0.0, Port 2.8.8.8.8.8, Speed 12 Mb/s, Product QEMU USB Mouse
Despite the "Failed" message, the command actually succeeded.
In QMP, it's worse. When adding the 37th mouse via QMP, the command
fails with
{"error": {"class": "GenericError", "desc": "usb hub chain too deep"}}
Additionally, "Failed to initialize USB device 'usb-hub'" is reported
on stderr. Despite the command failure, the device was created. This
is wrong.
Fix by avoiding qdev_init() for usb-hub creation, so we can ignore
errors cleanly.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r-- | hw/usb/bus.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/hw/usb/bus.c b/hw/usb/bus.c index 3e85afe..5abfac0 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -315,19 +315,40 @@ USBDevice *usb_create(USBBus *bus, const char *name) return USB_DEVICE(dev); } -USBDevice *usb_create_simple(USBBus *bus, const char *name) +static USBDevice *usb_try_create_simple(USBBus *bus, const char *name, + Error **errp) { - USBDevice *dev = usb_create(bus, name); - int rc; + Error *err = NULL; + USBDevice *dev; - rc = qdev_init(&dev->qdev); - if (rc < 0) { - error_report("Failed to initialize USB device '%s'", name); + dev = USB_DEVICE(qdev_try_create(&bus->qbus, name)); + if (!dev) { + error_setg(errp, "Failed to create USB device '%s'", name); + return NULL; + } + object_property_set_bool(OBJECT(dev), true, "realized", &err); + if (err) { + error_setg(errp, "Failed to initialize USB device '%s': %s", + name, error_get_pretty(err)); + error_free(err); + object_unparent(OBJECT(dev)); return NULL; } return dev; } +USBDevice *usb_create_simple(USBBus *bus, const char *name) +{ + Error *err = NULL; + USBDevice *dev = usb_try_create_simple(bus, name, &err); + + if (!dev) { + error_report("%s", error_get_pretty(err)); + error_free(err); + } + return dev; +} + static void usb_fill_port(USBPort *port, void *opaque, int index, USBPortOps *ops, int speedmask) { @@ -419,7 +440,7 @@ void usb_claim_port(USBDevice *dev, Error **errp) } else { if (bus->nfree == 1 && strcmp(object_get_typename(OBJECT(dev)), "usb-hub") != 0) { /* Create a new hub and chain it on */ - usb_create_simple(bus, "usb-hub"); + usb_try_create_simple(bus, "usb-hub", NULL); } if (bus->nfree == 0) { error_setg(errp, "tried to attach usb device %s to a bus " |