|
@@ -38,6 +38,9 @@
|
|
|
#define USB_VENDOR_GENESYS_LOGIC 0x05e3
|
|
|
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
|
|
|
|
|
|
+#define USB_TP_TRANSMISSION_DELAY 40 /* ns */
|
|
|
+#define USB_TP_TRANSMISSION_DELAY_MAX 65535 /* ns */
|
|
|
+
|
|
|
/* Protect struct usb_device->state and ->children members
|
|
|
* Note: Both are also protected by ->dev.sem, except that ->state can
|
|
|
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
|
|
@@ -1350,6 +1353,20 @@ static int hub_configure(struct usb_hub *hub,
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Accumulate wHubDelay + 40ns for every hub in the tree of devices.
|
|
|
+ * The resulting value will be used for SetIsochDelay() request.
|
|
|
+ */
|
|
|
+ if (hub_is_superspeed(hdev) || hub_is_superspeedplus(hdev)) {
|
|
|
+ u32 delay = __le16_to_cpu(hub->descriptor->u.ss.wHubDelay);
|
|
|
+
|
|
|
+ if (hdev->parent)
|
|
|
+ delay += hdev->parent->hub_delay;
|
|
|
+
|
|
|
+ delay += USB_TP_TRANSMISSION_DELAY;
|
|
|
+ hdev->hub_delay = min_t(u32, delay, USB_TP_TRANSMISSION_DELAY_MAX);
|
|
|
+ }
|
|
|
+
|
|
|
maxchild = hub->descriptor->bNbrPorts;
|
|
|
dev_info(hub_dev, "%d port%s detected\n", maxchild,
|
|
|
(maxchild == 1) ? "" : "s");
|
|
@@ -4597,7 +4614,20 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
|
|
|
if (retval >= 0)
|
|
|
retval = -EMSGSIZE;
|
|
|
} else {
|
|
|
+ u32 delay;
|
|
|
+
|
|
|
retval = 0;
|
|
|
+
|
|
|
+ delay = udev->parent->hub_delay;
|
|
|
+ udev->hub_delay = min_t(u32, delay,
|
|
|
+ USB_TP_TRANSMISSION_DELAY_MAX);
|
|
|
+ retval = usb_set_isoch_delay(udev);
|
|
|
+ if (retval) {
|
|
|
+ dev_dbg(&udev->dev,
|
|
|
+ "Failed set isoch delay, error %d\n",
|
|
|
+ retval);
|
|
|
+ retval = 0;
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
}
|