mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 23:45:31 +08:00
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. Cc: <stable@kernel.org> # v3.5 Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20210715150122.1995966-1-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
57560ee95c
commit
1bf2761c83
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user