diff mbox series

[v2] USB: core: Disable LPM only for non-suspended ports

Message ID 20241205091215.41348-1-kaihengf@nvidia.com (mailing list archive)
State Superseded
Headers show
Series [v2] USB: core: Disable LPM only for non-suspended ports | expand

Commit Message

Kai-Heng Feng Dec. 5, 2024, 9:12 a.m. UTC
There's USB error when tegra board is shutting down:
[  180.919315] usb 2-3: Failed to set U1 timeout to 0x0,error code -113
[  180.919995] usb 2-3: Failed to set U1 timeout to 0xa,error code -113
[  180.920512] usb 2-3: Failed to set U2 timeout to 0x4,error code -113
[  186.157172] tegra-xusb 3610000.usb: xHCI host controller not responding, assume dead
[  186.157858] tegra-xusb 3610000.usb: HC died; cleaning up
[  186.317280] tegra-xusb 3610000.usb: Timeout while waiting for evaluate context command

The issue is caused by disabling LPM on already suspended ports.

For USB2 LPM, the LPM is already disabled during port suspend. For USB3
LPM, port won't transit to U1/U2 when it's already suspended in U3,
hence disabling LPM is only needed for ports that are not suspended.

Cc: Wayne Chang <waynec@nvidia.com>
Cc: stable@vger.kernel.org
Fixes: d920a2ed8620 ("usb: Disable USB3 LPM at shutdown")
Signed-off-by: Kai-Heng Feng <kaihengf@nvidia.com>
---
v2:
 Add "Cc: stable@vger.kernel.org"

 drivers/usb/core/port.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

Comments

Alan Stern Dec. 5, 2024, 3:06 p.m. UTC | #1
On Thu, Dec 05, 2024 at 05:12:15PM +0800, Kai-Heng Feng wrote:
> There's USB error when tegra board is shutting down:
> [  180.919315] usb 2-3: Failed to set U1 timeout to 0x0,error code -113
> [  180.919995] usb 2-3: Failed to set U1 timeout to 0xa,error code -113
> [  180.920512] usb 2-3: Failed to set U2 timeout to 0x4,error code -113
> [  186.157172] tegra-xusb 3610000.usb: xHCI host controller not responding, assume dead
> [  186.157858] tegra-xusb 3610000.usb: HC died; cleaning up
> [  186.317280] tegra-xusb 3610000.usb: Timeout while waiting for evaluate context command
> 
> The issue is caused by disabling LPM on already suspended ports.
> 
> For USB2 LPM, the LPM is already disabled during port suspend. For USB3
> LPM, port won't transit to U1/U2 when it's already suspended in U3,
> hence disabling LPM is only needed for ports that are not suspended.
> 
> Cc: Wayne Chang <waynec@nvidia.com>
> Cc: stable@vger.kernel.org
> Fixes: d920a2ed8620 ("usb: Disable USB3 LPM at shutdown")
> Signed-off-by: Kai-Heng Feng <kaihengf@nvidia.com>
> ---
> v2:
>  Add "Cc: stable@vger.kernel.org"
> 
>  drivers/usb/core/port.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> index e7da2fca11a4..d50b9e004e76 100644
> --- a/drivers/usb/core/port.c
> +++ b/drivers/usb/core/port.c
> @@ -452,10 +452,11 @@ static int usb_port_runtime_suspend(struct device *dev)
>  static void usb_port_shutdown(struct device *dev)
>  {
>  	struct usb_port *port_dev = to_usb_port(dev);
> +	struct usb_device *udev = port_dev->child;
>  
> -	if (port_dev->child) {
> -		usb_disable_usb2_hardware_lpm(port_dev->child);
> -		usb_unlocked_disable_lpm(port_dev->child);
> +	if (udev && !pm_runtime_suspended(&udev->dev)) {

Instead of testing !pm_runtime_suspended(&udev->dev), it would be better 
to test udev->port_is_suspended.  This field records the actual status 
of the device's upstream port, whereas in some circumstances 
pm_runtime_suspended() will return true when the port is in U0.

Alan Stern

> +		usb_disable_usb2_hardware_lpm(udev);
> +		usb_unlocked_disable_lpm(udev);
>  	}
>  }
>  
> -- 
> 2.47.0
Kai-Heng Feng Dec. 6, 2024, 7:38 a.m. UTC | #2
On 2024/12/5 11:06 PM, Alan Stern wrote:
> External email: Use caution opening links or attachments
> 
> 
> On Thu, Dec 05, 2024 at 05:12:15PM +0800, Kai-Heng Feng wrote:
>> There's USB error when tegra board is shutting down:
>> [  180.919315] usb 2-3: Failed to set U1 timeout to 0x0,error code -113
>> [  180.919995] usb 2-3: Failed to set U1 timeout to 0xa,error code -113
>> [  180.920512] usb 2-3: Failed to set U2 timeout to 0x4,error code -113
>> [  186.157172] tegra-xusb 3610000.usb: xHCI host controller not responding, assume dead
>> [  186.157858] tegra-xusb 3610000.usb: HC died; cleaning up
>> [  186.317280] tegra-xusb 3610000.usb: Timeout while waiting for evaluate context command
>>
>> The issue is caused by disabling LPM on already suspended ports.
>>
>> For USB2 LPM, the LPM is already disabled during port suspend. For USB3
>> LPM, port won't transit to U1/U2 when it's already suspended in U3,
>> hence disabling LPM is only needed for ports that are not suspended.
>>
>> Cc: Wayne Chang <waynec@nvidia.com>
>> Cc: stable@vger.kernel.org
>> Fixes: d920a2ed8620 ("usb: Disable USB3 LPM at shutdown")
>> Signed-off-by: Kai-Heng Feng <kaihengf@nvidia.com>
>> ---
>> v2:
>>   Add "Cc: stable@vger.kernel.org"
>>
>>   drivers/usb/core/port.c | 7 ++++---
>>   1 file changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
>> index e7da2fca11a4..d50b9e004e76 100644
>> --- a/drivers/usb/core/port.c
>> +++ b/drivers/usb/core/port.c
>> @@ -452,10 +452,11 @@ static int usb_port_runtime_suspend(struct device *dev)
>>   static void usb_port_shutdown(struct device *dev)
>>   {
>>        struct usb_port *port_dev = to_usb_port(dev);
>> +     struct usb_device *udev = port_dev->child;
>>
>> -     if (port_dev->child) {
>> -             usb_disable_usb2_hardware_lpm(port_dev->child);
>> -             usb_unlocked_disable_lpm(port_dev->child);
>> +     if (udev && !pm_runtime_suspended(&udev->dev)) {
> 
> Instead of testing !pm_runtime_suspended(&udev->dev), it would be better
> to test udev->port_is_suspended.  This field records the actual status
> of the device's upstream port, whereas in some circumstances
> pm_runtime_suspended() will return true when the port is in U0.

Thanks for the tip. This indeed is a better approach. Will send another revision.

Kai-Heng


> 
> Alan Stern
> 
>> +             usb_disable_usb2_hardware_lpm(udev);
>> +             usb_unlocked_disable_lpm(udev);
>>        }
>>   }
>>
>> --
>> 2.47.0
diff mbox series

Patch

diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index e7da2fca11a4..d50b9e004e76 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -452,10 +452,11 @@  static int usb_port_runtime_suspend(struct device *dev)
 static void usb_port_shutdown(struct device *dev)
 {
 	struct usb_port *port_dev = to_usb_port(dev);
+	struct usb_device *udev = port_dev->child;
 
-	if (port_dev->child) {
-		usb_disable_usb2_hardware_lpm(port_dev->child);
-		usb_unlocked_disable_lpm(port_dev->child);
+	if (udev && !pm_runtime_suspended(&udev->dev)) {
+		usb_disable_usb2_hardware_lpm(udev);
+		usb_unlocked_disable_lpm(udev);
 	}
 }