lkml.org 
[lkml]   [2021]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 122/167] usb: hub: Fix link power management max exit latency (MEL) calculations
    Date
    From: Mathias Nyman <mathias.nyman@linux.intel.com>

    commit 1bf2761c837571a66ec290fb66c90413821ffda2 upstream.

    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>
    ---
    drivers/usb/core/hub.c | 52 ++++++++++++++++++++++++++-----------------------
    1 file changed, 28 insertions(+), 24 deletions(-)

    --- a/drivers/usb/core/hub.c
    +++ b/drivers/usb/core/hub.c
    @@ -47,6 +47,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
    @@ -181,8 +182,9 @@ int usb_device_supports_lpm(struct usb_d
    }

    /*
    - * 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,
    @@ -192,35 +194,37 @@ static void usb_set_lpm_mel(struct usb_d
    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;
    }

    \
     
     \ /
      Last update: 2021-07-26 18:24    [W:4.613 / U:0.104 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site