Re: [PATCH v2] USB: Force disconnect Huawei 4G modem during suspend

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 13 Oct 2017, Daniel Drake wrote:

> When going into S3 suspend, the Acer TravelMate P648-M and P648-G3
> laptops immediately wake up 3-4 seconds later for no obvious reason.
> 
> Unbinding the integrated Huawei 4G LTE modem before suspend avoids
> the issue, even though we are not using the modem at all (checked
> from rescue.target/runlevel1). The problem also occurs when the option
> and cdc-ether modem drivers aren't loaded; it reproduces just with the
> base usb driver. Under Windows the system can suspend fine.
> 
> Seeking a better fix, we've tried a lot of things, including:
>  - Check that the device's power/wakeup is disabled
>  - Check that remote wakeup is off at the USB level
>  - All the quirks in drivers/usb/core/quirks.c e.g. USB_QUIRK_RESET_RESUME,
>    USB_QUIRK_RESET, USB_QUIRK_IGNORE_REMOTE_WAKEUP, USB_QUIRK_NO_LPM.
> 
> but none of that makes any difference.
> 
> There are no errors in the logs showing any suspend/resume-related issues.
> When the system wakes up due to the modem, log-wise it appears to be a
> normal resume.
> 
> Introduce a quirk to disable the port during suspend when the modem is
> detected.

> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index eb87a259d55c..7c048afc9bfd 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -1461,6 +1461,7 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
>  int usb_suspend(struct device *dev, pm_message_t msg)
>  {
>  	struct usb_device	*udev = to_usb_device(dev);
> +	int r;
>  
>  	unbind_no_pm_drivers_interfaces(udev);
>  
> @@ -1469,7 +1470,14 @@ int usb_suspend(struct device *dev, pm_message_t msg)
>  	 * so we may still need to unbind and rebind upon resume
>  	 */
>  	choose_wakeup(udev, msg);
> -	return usb_suspend_both(udev, msg);
> +	r = usb_suspend_both(udev, msg);
> +	if (r)
> +		return r;
> +
> +	if (udev->quirks & USB_QUIRK_DISCONNECT_SUSPEND)
> +		r = usb_port_disable(udev);
> +
> +	return r;

Here it's probably best to ignore the return value.  Even if 
usb_port_disable failed, you want the system suspend to move forward -- 
even if the system spontaneously wakes up a second later.

>  }
>  
>  /* The device lock is held by the PM core */
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index b5c733613823..9662eaa9c44d 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -4180,6 +4180,19 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
>  	return ret;
>  }
>  
> +/*
> + * usb_port_disable - disable a usb device's upstream port
> + * @udev: device to disable
> + * Context: must be able to sleep; device not locked; pm locks held

Actually the device _is_ locked when this routine gets called.  And the 
PM locks are not held.

> + *
> + * Disables a USB device that isn't in active use.
> + */
> +int usb_port_disable(struct usb_device *udev)
> +{
> +	struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
> +
> +	return hub_port_disable(hub, udev->portnum, 1);
> +}

You probably want the last argument to be 0, not 1.  The 1 will cause
the device to be marked as disconnected, so when the system wakes up it
will think that a new device has been plugged in rather than the old
device having been attached all along.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux