Răsfoiți Sursa

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>
Gerd Hoffmann 11 ani în urmă
părinte
comite
b791c3b38c
3 a modificat fișierele cu 22 adăugiri și 12 ștergeri
  1. 21 0
      hw/usb/core.c
  2. 0 12
      hw/usb/desc.c
  3. 1 0
      include/hw/usb.h

+ 21 - 0
hw/usb/core.c

@@ -28,6 +28,26 @@
 #include "qemu/iov.h"
 #include "qemu/iov.h"
 #include "trace.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)
 void usb_attach(USBPort *port)
 {
 {
     USBDevice *dev = port->dev;
     USBDevice *dev = port->dev;
@@ -35,6 +55,7 @@ void usb_attach(USBPort *port)
     assert(dev != NULL);
     assert(dev != NULL);
     assert(dev->attached);
     assert(dev->attached);
     assert(dev->state == USB_STATE_NOTATTACHED);
     assert(dev->state == USB_STATE_NOTATTACHED);
+    usb_pick_speed(port);
     port->ops->attach(port);
     port->ops->attach(port);
     dev->state = USB_STATE_ATTACHED;
     dev->state = USB_STATE_ATTACHED;
     usb_device_handle_attach(dev);
     usb_device_handle_attach(dev);

+ 0 - 12
hw/usb/desc.c

@@ -518,18 +518,6 @@ void usb_desc_init(USBDevice *dev)
 
 
 void usb_desc_attach(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);
     usb_desc_setdefaults(dev);
 }
 }
 
 

+ 1 - 0
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_input_packet_complete(USBDevice *dev, USBPacket *p);
 void usb_combined_packet_cancel(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_attach(USBPort *port);
 void usb_detach(USBPort *port);
 void usb_detach(USBPort *port);
 void usb_port_reset(USBPort *port);
 void usb_port_reset(USBPort *port);