diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2014-05-23 16:20:54 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2014-06-02 16:29:00 +0200 |
commit | b791c3b38c7969cb9f4acda8229e19fd865a1c08 (patch) | |
tree | 2c239c2e37373914733ad011c50fd4a29c4c6f4a | |
parent | 322fd1f4f7c884c75749398bf48e01bd4b226e9f (diff) | |
download | qemu-b791c3b38c7969cb9f4acda8229e19fd865a1c08.zip |
usb: add usb_pick_speed
We can pick the usb port speed in generic code, by looking at the port
and device speed masks and looking for the fastest match. So add a
function to do exactly that, and drop the speed setting code from
usb_desc_attach as it isn't needed any more.
This way we can set the device speed before calling port->ops->attach,
which fixes some xhci hotplug issues.
https://bugzilla.redhat.com/show_bug.cgi?id=1046873
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r-- | hw/usb/core.c | 21 | ||||
-rw-r--r-- | hw/usb/desc.c | 12 | ||||
-rw-r--r-- | include/hw/usb.h | 1 |
3 files changed, 22 insertions, 12 deletions
diff --git a/hw/usb/core.c b/hw/usb/core.c index 67ba7d6018..cf34755bba 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -28,6 +28,26 @@ #include "qemu/iov.h" #include "trace.h" +void usb_pick_speed(USBPort *port) +{ + static const int speeds[] = { + USB_SPEED_SUPER, + USB_SPEED_HIGH, + USB_SPEED_FULL, + USB_SPEED_LOW, + }; + USBDevice *udev = port->dev; + int i; + + for (i = 0; i < ARRAY_SIZE(speeds); i++) { + if ((udev->speedmask & (1 << speeds[i])) && + (port->speedmask & (1 << speeds[i]))) { + udev->speed = speeds[i]; + return; + } + } +} + void usb_attach(USBPort *port) { USBDevice *dev = port->dev; @@ -35,6 +55,7 @@ void usb_attach(USBPort *port) assert(dev != NULL); assert(dev->attached); assert(dev->state == USB_STATE_NOTATTACHED); + usb_pick_speed(port); port->ops->attach(port); dev->state = USB_STATE_ATTACHED; usb_device_handle_attach(dev); diff --git a/hw/usb/desc.c b/hw/usb/desc.c index ab48691363..b82c397ef9 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -518,18 +518,6 @@ void usb_desc_init(USBDevice *dev) void usb_desc_attach(USBDevice *dev) { - const USBDesc *desc = usb_device_get_usb_desc(dev); - - assert(desc != NULL); - if (desc->super && (dev->port->speedmask & USB_SPEED_MASK_SUPER)) { - dev->speed = USB_SPEED_SUPER; - } else if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) { - dev->speed = USB_SPEED_HIGH; - } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) { - dev->speed = USB_SPEED_FULL; - } else { - return; - } usb_desc_setdefaults(dev); } diff --git a/include/hw/usb.h b/include/hw/usb.h index 1919bdc09d..8bcab48d29 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -458,6 +458,7 @@ void usb_ep_combine_input_packets(USBEndpoint *ep); void usb_combined_input_packet_complete(USBDevice *dev, USBPacket *p); void usb_combined_packet_cancel(USBDevice *dev, USBPacket *p); +void usb_pick_speed(USBPort *port); void usb_attach(USBPort *port); void usb_detach(USBPort *port); void usb_port_reset(USBPort *port); |