Re: [PATCH] USB: code cleanup in suspend/resume path

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

 



On Tue, 3 Jan 2012, Oliver Neukum wrote:

> From 186ed6425f31636d1bb52de0f48a76dddf8e6224 Mon Sep 17 00:00:00 2001
> From: Oliver Neukum <oliver@xxxxxxxxxx>
> Date: Tue, 3 Jan 2012 12:34:31 +0100
> Subject: [PATCH] USB: code cleanup in suspend/resume path
> 
> Do the cleanup to avoid behaviorial parameters Linus
> requested.

This patch needs to be fixed up.

> Signed-off-by: Oliver Neukum <oneukum@xxxxxxx>
> ---
>  drivers/usb/core/driver.c |   54 ++++++++++++++++++++++++++++----------------
>  1 files changed, 34 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index 07f8718..9d708c3 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -974,12 +974,11 @@ void usb_rebind_intf(struct usb_interface *intf)
>  #define DO_UNBIND	0
>  #define DO_REBIND	1
>  
> -/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
> - * or rebind interfaces that have been unbound, according to @action.
> +/* Unbind drivers for @udev's interfaces that don't support suspend/resume
>   *
>   * The caller must hold @udev's device lock.
>   */
> -static void do_unbind_rebind(struct usb_device *udev, int action)
> +static void kick_unsupportive_drivers_from_interfaces(struct usb_device *udev)

Okay, I admit I combined multiple routines into one in order to save
code space.  But I don't like your choice of a new name.  How about
unbind_drivers_with_no_suspend_or_resume_method?  Still pretty bad, but
it's more precise.

Also, if you're going to do this cleanup, change usb_rebind_intf().  
Its first "delayed unbind" section is basically a copy of
usb_forced_unbind_intf() -- have it call that routine instead of
duplicating the code.

...

> +static void do_rebind(struct usb_device *udev)
> +{
> +	struct usb_host_config	*config;
> +	int			i;
> +	struct usb_interface	*intf;
> +
> +	config = udev->actconfig;
> +	if (config) {
> +		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
> +			intf = config->interface[i];
> +			if (intf->needs_binding)
> +				usb_rebind_intf(intf);
> +		}
> +	}
> +}

This is okay.  But maybe change the name to rebind_interfaces.

> @@ -1296,7 +1304,11 @@ int usb_suspend(struct device *dev, pm_message_t msg)
>  {
>  	struct usb_device	*udev = to_usb_device(dev);
>  
> -	do_unbind_rebind(udev, DO_UNBIND);
> +	kick_unsupportive_drivers_from_interfaces(udev);

Blank line before the comment, please.

> +	/* From now on we are sure all drivers support suspend/resume
> +	 * but not necessarily reset_resume()
> +	 * so we may still need to rebind upon resumption

"... may still need to unbind and rebind upon resume"

> +	 */
>  	choose_wakeup(udev, msg);
>  	return usb_suspend_both(udev, msg);
>  }
> @@ -1307,15 +1319,17 @@ int usb_resume(struct device *dev, pm_message_t msg)
>  	struct usb_device	*udev = to_usb_device(dev);
>  	int			status;
>  
> -	/* For PM complete calls, all we do is rebind interfaces */
> +	/* For PM complete calls, all we do is rebind interfaces
> +	 * if the need has arisen earlier

How about: "... all we do is rebind interfaces that need it" ?

> +	 */
>  	if (msg.event == PM_EVENT_ON) {
>  		if (udev->state != USB_STATE_NOTATTACHED)
> -			do_unbind_rebind(udev, DO_REBIND);
> +			do_rebind(udev);
>  		status = 0;
>  
>  	/* For all other calls, take the device back to full power and
>  	 * tell the PM core in case it was autosuspended previously.
> -	 * Unbind the interfaces that will need rebinding later.
> +	 * Rebind the interfaces that need it.

The original comment was correct and the new comment is wrong.  See 
below.

>  	 */
>  	} else {
>  		status = usb_resume_both(udev, msg);
> @@ -1323,7 +1337,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
>  			pm_runtime_disable(dev);
>  			pm_runtime_set_active(dev);
>  			pm_runtime_enable(dev);
> -			do_unbind_rebind(udev, DO_REBIND);
> +			do_rebind(udev);

This is what Linus was complaining about.  The action here really is an 
unbind, not a rebind, but it applies only to interfaces that have 
needs_binding set already.

"Why would an interface have needs_binding set without already being
unbound", you ask.  Well, that's what happens when a driver doesn't
support reset-resume.  usb_resume_interface() sets intf->needs_binding,
but it can't unbind the interface because it doesn't own the right set
of locks.

Thus what you really need here is yet another routine, with a name like 
unbind_drivers_because_of_reset_resume.  That routine will be just like 
unbind_drivers_with_no_suspend_or_resume_method, except that it will 
check for needs_binding set rather than looking at method pointers.

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