FAILED: patch "[PATCH] usb: hub: Fix link power management max exit latency (MEL)" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1bf2761c837571a66ec290fb66c90413821ffda2 Mon Sep 17 00:00:00 2001
From: Mathias Nyman <[email protected]>
Date: Thu, 15 Jul 2021 18:01:21 +0300
Subject: [PATCH] usb: hub: Fix link power management max exit latency (MEL)
calculations
Maximum Exit Latency (MEL) value is used by host to know how much in advance it needs to start waking up a U1/U2 suspended link in order to service a periodic transfer in time.
Current MEL calculation only includes the time to wake up the path from U1/U2 to U0. This is called tMEL1 in USB 3.1 section C 1.5.2
Total MEL = tMEL1 + tMEL2 +tMEL3 + tMEL4 which should additinally include:
- tMEL2 which is the time it takes for PING message to reach device
- tMEL3 time for device to process the PING and submit a PING_RESPONSE
- tMEL4 time for PING_RESPONSE to traverse back upstream to host.
Add the missing tMEL2, tMEL3 and tMEL4 to MEL calculation.
drivers/usb/core/hub.c +28 -24
@@ -48,6 +48,7 @@#define USB_TP_TRANSMISSION_DELAY 40/* ns */ #define USB_TP_TRANSMISSION_DELAY_MAX 65535/* ns */ +#define USB_PING_RESPONSE_TIME 400/* ns */ /* Protect struct usb_device->state and ->children members * Note: Both are also protected by ->dev.sem, except that ->state can
@@ -182,8 +183,9 @@ int usb_device_supports_lpm(struct usb_device *udev) }/* -* Set the Maximum Exit Latency (MEL) for the host to initiate a transition from -* either U1 or U2. +* Set the Maximum Exit Latency (MEL) for the host to wakup up the path from +* U1/U2, send a PING to the device and receive a PING_RESPONSE. +* See USB 3.1 section C.1.5.2 */ static void usb_set_lpm_mel(struct usb_device *udev, struct usb3_lpm_parameters *udev_lpm_params,
@@ -193,35 +195,37 @@ static void usb_set_lpm_mel(struct usb_device *udev, unsigned int hub_exit_latency) {unsigned int total_mel; -unsigned int device_mel; -unsigned int hub_mel;/* -* Calculate the time it takes to transition all links from the roothub -* to the parent hub into U0. The parent hub must then decode the -* packet (hub header decode latency) to figure out which port it was -* bound for. -* -* The Hub Header decode latency is expressed in 0.1us intervals (0x1 -* means 0.1us). Multiply that by 100 to get nanoseconds. +* tMEL1. time to transition path from host to device into U0. +* MEL for parent already contains the delay up to parent, so only add +* the exit latency for the last link (pick the slower exit latency), +* and the hub header decode latency. See USB 3.1 section C 2.2.1 +* Store MEL in nanoseconds */ total_mel = hub_lpm_params->mel + - (hub->descriptor->u.ss.bHubHdrDecLat *100 ); +max (udev_exit_latency, hub_exit_latency) *1000 + + hub->descriptor->u.ss.bHubHdrDecLat *100 ;/* -* How long will it take to transition the downstream hub's port into -* U0? The greater of either the hub exit latency or the device exit -* latency. -* -* The BOS U1/U2 exit latencies are expressed in 1us intervals. -* Multiply that by 1000 to get nanoseconds. +* tMEL2. Time to submit PING packet. Sum of tTPTransmissionDelay for +* each link + wHubDelay for each hub. Add only for last link. +* tMEL4, the time for PING_RESPONSE to traverse upstream is similar. +* Multiply by 2 to include it as well. */ - device_mel = udev_exit_latency *1000 ; - hub_mel = hub_exit_latency *1000 ; -if (device_mel > hub_mel) - total_mel += device_mel; -else - total_mel += hub_mel; + total_mel += (__le16_to_cpu (hub->descriptor->u.ss.wHubDelay) + +USB_TP_TRANSMISSION_DELAY ) *2 ; + +/* +* tMEL3, tPingResponse. Time taken by device to generate PING_RESPONSE +* after receiving PING. Also add 2100ns as stated in USB 3.1 C 1.5.2.4 +* to cover the delay if the PING_RESPONSE is queued behind a Max Packet +* Size DP. +* Note these delays should be added only once for the entire path, so +* add them to the MEL of the device connected to the roothub. +*/ +if (!hub->hdev->parent) + total_mel +=USB_PING_RESPONSE_TIME +2100 ; udev_lpm_params->mel = total_mel; }