Hi Tianyu,

This patch looks fine, however, this doesn't apply against Greg's
usb-linus branch.  Can you please fix and resubmit?

Thanks,
Sarah Sharp

On Thu, Jan 17, 2013 at 03:47:51PM +0800, Lan Tianyu wrote:
> Usb3.0 device defines function remote wakeup which is only for interface
> recipient rather than device recipient. This is different with usb2.0 device's
> remote wakeup feature which is defined for device recipient. According usb3.0
> spec 9.4.5, the function remote wakeup can be modified by the SetFeature()
> requests using the FUNCTION_SUSPEND feature selector. This patch is to use
> correct way to disable usb3.0 device's function remote wakeup after suspend
> error and resuming.
> 
> Signed-off-by: Lan Tianyu <tianyu....@intel.com>
> ---
>  drivers/usb/core/hub.c       |   71 
> +++++++++++++++++++++++++++++++-----------
>  include/uapi/linux/usb/ch9.h |    6 ++++
>  2 files changed, 59 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 0ef512a..08c9c04 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -2852,6 +2852,24 @@ void usb_enable_ltm(struct usb_device *udev)
>  }
>  EXPORT_SYMBOL_GPL(usb_enable_ltm);
>  
> +/*
> + * usb_disable_function_remotewakeup - disable usb3.0
> + * device's function remote wakeup
> + * @udev: target device
> + *
> + * Assume there's only one function on the USB 3.0
> + * device and disable remote wake for the first
> + * interface. FIXME if the interface association
> + * descriptor shows there's more than one function.
> + */
> +static int usb_disable_function_remotewakeup(struct usb_device *udev)
> +{
> +     return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
> +                             USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
> +                             USB_INTRF_FUNC_SUSPEND, 0, NULL, 0,
> +                             USB_CTRL_SET_TIMEOUT);
> +}
> +
>  #ifdef       CONFIG_USB_SUSPEND
>  
>  /*
> @@ -2968,12 +2986,19 @@ int usb_port_suspend(struct usb_device *udev, 
> pm_message_t msg)
>               dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
>                               port1, status);
>               /* paranoia:  "should not happen" */
> -             if (udev->do_remote_wakeup)
> -                     (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
> -                             USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
> -                             USB_DEVICE_REMOTE_WAKEUP, 0,
> -                             NULL, 0,
> -                             USB_CTRL_SET_TIMEOUT);
> +             if (udev->do_remote_wakeup) {
> +                     if (!hub_is_superspeed(hub->hdev)) {
> +                             (void) usb_control_msg(udev,
> +                                             usb_sndctrlpipe(udev, 0),
> +                                             USB_REQ_CLEAR_FEATURE,
> +                                             USB_RECIP_DEVICE,
> +                                             USB_DEVICE_REMOTE_WAKEUP, 0,
> +                                             NULL, 0,
> +                                             USB_CTRL_SET_TIMEOUT);
> +                     } else
> +                             (void) usb_disable_function_remotewakeup(udev);
> +
> +             }
>  
>               /* Try to enable USB2 hardware LPM again */
>               if (udev->usb2_hw_lpm_capable == 1)
> @@ -3059,20 +3084,30 @@ static int finish_port_resume(struct usb_device *udev)
>               dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
>                               status);
>       } else if (udev->actconfig) {
> -             le16_to_cpus(&devstatus);
> -             if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
> -                     status = usb_control_msg(udev,
> -                                     usb_sndctrlpipe(udev, 0),
> -                                     USB_REQ_CLEAR_FEATURE,
> +             if (!hub_is_superspeed(udev->parent)) {
> +                     le16_to_cpus(&devstatus);
> +                     if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
> +                             status = usb_control_msg(udev,
> +                                             usb_sndctrlpipe(udev, 0),
> +                                             USB_REQ_CLEAR_FEATURE,
>                                               USB_RECIP_DEVICE,
> -                                     USB_DEVICE_REMOTE_WAKEUP, 0,
> -                                     NULL, 0,
> -                                     USB_CTRL_SET_TIMEOUT);
> -                     if (status)
> -                             dev_dbg(&udev->dev,
> -                                     "disable remote wakeup, status %d\n",
> -                                     status);
> +                                             USB_DEVICE_REMOTE_WAKEUP, 0,
> +                                             NULL, 0,
> +                                             USB_CTRL_SET_TIMEOUT);
> +             } else {
> +                     status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
> +                                     &devstatus);
> +                     le16_to_cpus(&devstatus);
> +                     if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
> +                                     | USB_INTRF_STAT_FUNC_RW))
> +                             status =
> +                                     usb_disable_function_remotewakeup(udev);
>               }
> +
> +             if (status)
> +                     dev_dbg(&udev->dev,
> +                             "disable remote wakeup, status %d\n",
> +                             status);
>               status = 0;
>       }
>       return status;
> diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
> index 5059847..f738e25 100644
> --- a/include/uapi/linux/usb/ch9.h
> +++ b/include/uapi/linux/usb/ch9.h
> @@ -152,6 +152,12 @@
>  #define USB_INTRF_FUNC_SUSPEND_LP    (1 << (8 + 0))
>  #define USB_INTRF_FUNC_SUSPEND_RW    (1 << (8 + 1))
>  
> +/*
> + * Interface status, Figure 9-5 USB 3.0 spec
> + */
> +#define USB_INTRF_STAT_FUNC_RW_CAP     1
> +#define USB_INTRF_STAT_FUNC_RW         2
> +
>  #define USB_ENDPOINT_HALT            0       /* IN/OUT will STALL */
>  
>  /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
> -- 
> 1.7.9.5
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to