Re: [PATCH v5 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2017-01-25 Thread Robert Foss

Looks good to me.

Feel free to add my r-b.


Rob.

On 2016-12-13 02:49 AM, Baolin Wang wrote:

For some mobile devices with strict power management, we also want to suspend
the host when the slave is detached for power saving. Thus we add the host
suspend/resume functions to support this requirement.

Signed-off-by: Baolin Wang 
---
Changes since v4:
 - Remove Kconfig and just enable host suspend/resume.
 - Simplify the dwc3_host_suspend/resume() function.

Changes since v3:
 - No updates.

Changes since v2:
 - Remove pm_children_suspended() and other unused macros.

Changes since v1:
 - Add pm_runtime.h head file to avoid kbuild error.
---
 drivers/usb/dwc3/core.c |   26 +-
 drivers/usb/dwc3/core.h |7 +++
 drivers/usb/dwc3/host.c |   21 +
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..7ad4bc3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
+   pm_suspend_ignore_children(dev, true);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err1;
@@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
 static int dwc3_suspend_common(struct dwc3 *dwc)
 {
unsigned long   flags;
+   int ret;

switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(&dwc->lock, flags);
+   dwc3_gadget_suspend(dwc);
+   spin_unlock_irqrestore(&dwc->lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
@@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)

switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(&dwc->lock, flags);
+   dwc3_gadget_resume(dwc);
+   spin_unlock_irqrestore(&dwc->lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
-   /* FALLTHROUGH */
+   break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b585a30..1099168 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1158,11 +1158,18 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc)
 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
 void dwc3_host_exit(struct dwc3 *dwc);
+int dwc3_host_suspend(struct dwc3 *dwc);
+int dwc3_host_resume(struct dwc3 *dwc);
 #else
 static inline int dwc3_host_init(struct dwc3 *dwc)
 { return 0; }
 static inline void dwc3_host_exit(struct dwc3 *dwc)
 { }
+
+static inline int dwc3_host_suspend(struct dwc3 *dwc)
+{ return 0; }
+static inline int dwc3_host_resume(struct dwc3 *dwc)
+{ return 0; }
 #endif

 #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index ed82464..7959ef0 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,6 +16,7 @@
  */

 #include 
+#include 

 #include "core.h"

@@ -130,3 +131,23 @@ void dwc3_host_exit(struct dwc3 *dwc)
  dev_name(&dwc->xhci->dev));
platform_device_unregister(dwc->xhci);
 }
+
+int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   struct device *xhci = &dwc->xhci->dev;
+
+   /*
+* Note: if we get the -EBUSY, which means the xHCI children devices are
+* not in suspend state yet, the glue layer need to wait for a while and
+* try to suspend xHCI device again.
+*/
+   return pm_runtime_put_sync(xhci);
+}
+
+int dwc3_host_resume(struct dwc3 *dwc)
+{
+   struct device *xhci = &dwc->xhci->dev;
+
+   /* Resume the xHCI device synchronously. */
+   return pm_runtime_get_sync(xhci);
+}


--
To un

Re: [PATCH v5 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2017-01-16 Thread Baolin Wang
Hi,

On 16 January 2017 at 18:28, Felipe Balbi  wrote:
>
> Hi,
>
> Baolin Wang  writes:
>> For some mobile devices with strict power management, we also want to suspend
>> the host when the slave is detached for power saving. Thus we add the host
>> suspend/resume functions to support this requirement.
>>
>> Signed-off-by: Baolin Wang 
>> ---
>> Changes since v4:
>>  - Remove Kconfig and just enable host suspend/resume.
>>  - Simplify the dwc3_host_suspend/resume() function.
>>
>> Changes since v3:
>>  - No updates.
>>
>> Changes since v2:
>>  - Remove pm_children_suspended() and other unused macros.
>>
>> Changes since v1:
>>  - Add pm_runtime.h head file to avoid kbuild error.
>> ---
>>  drivers/usb/dwc3/core.c |   26 +-
>>  drivers/usb/dwc3/core.h |7 +++
>>  drivers/usb/dwc3/host.c |   21 +
>>  3 files changed, 53 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 9a4a5e4..7ad4bc3 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
>>   pm_runtime_use_autosuspend(dev);
>>   pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
>>   pm_runtime_enable(dev);
>> + pm_suspend_ignore_children(dev, true);
>>   ret = pm_runtime_get_sync(dev);
>>   if (ret < 0)
>>   goto err1;
>> @@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
>>  static int dwc3_suspend_common(struct dwc3 *dwc)
>>  {
>>   unsigned long   flags;
>> + int ret;
>>
>>   switch (dwc->dr_mode) {
>>   case USB_DR_MODE_PERIPHERAL:
>> + spin_lock_irqsave(&dwc->lock, flags);
>> + dwc3_gadget_suspend(dwc);
>> + spin_unlock_irqrestore(&dwc->lock, flags);
>> + break;
>>   case USB_DR_MODE_OTG:
>> + ret = dwc3_host_suspend(dwc);
>> + if (ret)
>> + return ret;
>> +
>>   spin_lock_irqsave(&dwc->lock, flags);
>>   dwc3_gadget_suspend(dwc);
>>   spin_unlock_irqrestore(&dwc->lock, flags);
>>   break;
>>   case USB_DR_MODE_HOST:
>> + ret = dwc3_host_suspend(dwc);
>> + if (ret)
>> + return ret;
>>   default:
>>   /* do nothing */
>>   break;
>> @@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
>>
>>   switch (dwc->dr_mode) {
>>   case USB_DR_MODE_PERIPHERAL:
>> + spin_lock_irqsave(&dwc->lock, flags);
>> + dwc3_gadget_resume(dwc);
>> + spin_unlock_irqrestore(&dwc->lock, flags);
>> + break;
>>   case USB_DR_MODE_OTG:
>> + ret = dwc3_host_resume(dwc);
>> + if (ret)
>> + return ret;
>> +
>>   spin_lock_irqsave(&dwc->lock, flags);
>>   dwc3_gadget_resume(dwc);
>>   spin_unlock_irqrestore(&dwc->lock, flags);
>> - /* FALLTHROUGH */
>> + break;
>>   case USB_DR_MODE_HOST:
>> + ret = dwc3_host_resume(dwc);
>> + if (ret)
>> + return ret;
>>   default:
>>   /* do nothing */
>>   break;
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index b585a30..1099168 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -1158,11 +1158,18 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc)
>>  #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || 
>> IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
>>  int dwc3_host_init(struct dwc3 *dwc);
>>  void dwc3_host_exit(struct dwc3 *dwc);
>> +int dwc3_host_suspend(struct dwc3 *dwc);
>> +int dwc3_host_resume(struct dwc3 *dwc);
>>  #else
>>  static inline int dwc3_host_init(struct dwc3 *dwc)
>>  { return 0; }
>>  static inline void dwc3_host_exit(struct dwc3 *dwc)
>>  { }
>> +
>> +static inline int dwc3_host_suspend(struct dwc3 *dwc)
>> +{ return 0; }
>> +static inline int dwc3_host_resume(struct dwc3 *dwc)
>> +{ return 0; }
>>  #endif
>>
>>  #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || 
>> IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
>> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
>> index ed82464..7959ef0 100644
>> --- a/drivers/usb/dwc3/host.c
>> +++ b/drivers/usb/dwc3/host.c
>> @@ -16,6 +16,7 @@
>>   */
>>
>>  #include 
>> +#include 
>>
>>  #include "core.h"
>>
>> @@ -130,3 +131,23 @@ void dwc3_host_exit(struct dwc3 *dwc)
>> dev_name(&dwc->xhci->dev));
>>   platform_device_unregister(dwc->xhci);
>>  }
>> +
>> +int dwc3_host_suspend(struct dwc3 *dwc)
>> +{
>> + struct device *xhci = &dwc->xhci->dev;
>> +
>> + /*
>> +  * Note: if we get the -EBUSY, which means the xHCI children devices 
>> are
>> +  * not in suspend state yet, the glue layer need to wait for a while 
>> and
>> +  * try

Re: [PATCH v5 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2017-01-16 Thread Felipe Balbi

Hi,

Baolin Wang  writes:
> For some mobile devices with strict power management, we also want to suspend
> the host when the slave is detached for power saving. Thus we add the host
> suspend/resume functions to support this requirement.
>
> Signed-off-by: Baolin Wang 
> ---
> Changes since v4:
>  - Remove Kconfig and just enable host suspend/resume.
>  - Simplify the dwc3_host_suspend/resume() function.
>
> Changes since v3:
>  - No updates.
>
> Changes since v2:
>  - Remove pm_children_suspended() and other unused macros.
>
> Changes since v1:
>  - Add pm_runtime.h head file to avoid kbuild error.
> ---
>  drivers/usb/dwc3/core.c |   26 +-
>  drivers/usb/dwc3/core.h |7 +++
>  drivers/usb/dwc3/host.c |   21 +
>  3 files changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 9a4a5e4..7ad4bc3 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
>   pm_runtime_use_autosuspend(dev);
>   pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
>   pm_runtime_enable(dev);
> + pm_suspend_ignore_children(dev, true);
>   ret = pm_runtime_get_sync(dev);
>   if (ret < 0)
>   goto err1;
> @@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
>  static int dwc3_suspend_common(struct dwc3 *dwc)
>  {
>   unsigned long   flags;
> + int ret;
>  
>   switch (dwc->dr_mode) {
>   case USB_DR_MODE_PERIPHERAL:
> + spin_lock_irqsave(&dwc->lock, flags);
> + dwc3_gadget_suspend(dwc);
> + spin_unlock_irqrestore(&dwc->lock, flags);
> + break;
>   case USB_DR_MODE_OTG:
> + ret = dwc3_host_suspend(dwc);
> + if (ret)
> + return ret;
> +
>   spin_lock_irqsave(&dwc->lock, flags);
>   dwc3_gadget_suspend(dwc);
>   spin_unlock_irqrestore(&dwc->lock, flags);
>   break;
>   case USB_DR_MODE_HOST:
> + ret = dwc3_host_suspend(dwc);
> + if (ret)
> + return ret;
>   default:
>   /* do nothing */
>   break;
> @@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
>  
>   switch (dwc->dr_mode) {
>   case USB_DR_MODE_PERIPHERAL:
> + spin_lock_irqsave(&dwc->lock, flags);
> + dwc3_gadget_resume(dwc);
> + spin_unlock_irqrestore(&dwc->lock, flags);
> + break;
>   case USB_DR_MODE_OTG:
> + ret = dwc3_host_resume(dwc);
> + if (ret)
> + return ret;
> +
>   spin_lock_irqsave(&dwc->lock, flags);
>   dwc3_gadget_resume(dwc);
>   spin_unlock_irqrestore(&dwc->lock, flags);
> - /* FALLTHROUGH */
> + break;
>   case USB_DR_MODE_HOST:
> + ret = dwc3_host_resume(dwc);
> + if (ret)
> + return ret;
>   default:
>   /* do nothing */
>   break;
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index b585a30..1099168 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1158,11 +1158,18 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc)
>  #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
>  int dwc3_host_init(struct dwc3 *dwc);
>  void dwc3_host_exit(struct dwc3 *dwc);
> +int dwc3_host_suspend(struct dwc3 *dwc);
> +int dwc3_host_resume(struct dwc3 *dwc);
>  #else
>  static inline int dwc3_host_init(struct dwc3 *dwc)
>  { return 0; }
>  static inline void dwc3_host_exit(struct dwc3 *dwc)
>  { }
> +
> +static inline int dwc3_host_suspend(struct dwc3 *dwc)
> +{ return 0; }
> +static inline int dwc3_host_resume(struct dwc3 *dwc)
> +{ return 0; }
>  #endif
>  
>  #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || 
> IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
> index ed82464..7959ef0 100644
> --- a/drivers/usb/dwc3/host.c
> +++ b/drivers/usb/dwc3/host.c
> @@ -16,6 +16,7 @@
>   */
>  
>  #include 
> +#include 
>  
>  #include "core.h"
>  
> @@ -130,3 +131,23 @@ void dwc3_host_exit(struct dwc3 *dwc)
> dev_name(&dwc->xhci->dev));
>   platform_device_unregister(dwc->xhci);
>  }
> +
> +int dwc3_host_suspend(struct dwc3 *dwc)
> +{
> + struct device *xhci = &dwc->xhci->dev;
> +
> + /*
> +  * Note: if we get the -EBUSY, which means the xHCI children devices are
> +  * not in suspend state yet, the glue layer need to wait for a while and
> +  * try to suspend xHCI device again.
> +  */
> + return pm_runtime_put_sync(xhci);
> +}
> +
> +int dwc3_host_resume(struct dwc3 *dwc)
> +{
> + struct device *xhci = &dwc->xhci->dev;
> +
> +

[PATCH v5 2/2] usb: dwc3: core: Support the dwc3 host suspend/resume

2016-12-12 Thread Baolin Wang
For some mobile devices with strict power management, we also want to suspend
the host when the slave is detached for power saving. Thus we add the host
suspend/resume functions to support this requirement.

Signed-off-by: Baolin Wang 
---
Changes since v4:
 - Remove Kconfig and just enable host suspend/resume.
 - Simplify the dwc3_host_suspend/resume() function.

Changes since v3:
 - No updates.

Changes since v2:
 - Remove pm_children_suspended() and other unused macros.

Changes since v1:
 - Add pm_runtime.h head file to avoid kbuild error.
---
 drivers/usb/dwc3/core.c |   26 +-
 drivers/usb/dwc3/core.h |7 +++
 drivers/usb/dwc3/host.c |   21 +
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9a4a5e4..7ad4bc3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1091,6 +1091,7 @@ static int dwc3_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY);
pm_runtime_enable(dev);
+   pm_suspend_ignore_children(dev, true);
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err1;
@@ -1215,15 +1216,27 @@ static int dwc3_remove(struct platform_device *pdev)
 static int dwc3_suspend_common(struct dwc3 *dwc)
 {
unsigned long   flags;
+   int ret;
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(&dwc->lock, flags);
+   dwc3_gadget_suspend(dwc);
+   spin_unlock_irqrestore(&dwc->lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_suspend(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_suspend(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
@@ -1245,12 +1258,23 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
+   spin_lock_irqsave(&dwc->lock, flags);
+   dwc3_gadget_resume(dwc);
+   spin_unlock_irqrestore(&dwc->lock, flags);
+   break;
case USB_DR_MODE_OTG:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
+
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_resume(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
-   /* FALLTHROUGH */
+   break;
case USB_DR_MODE_HOST:
+   ret = dwc3_host_resume(dwc);
+   if (ret)
+   return ret;
default:
/* do nothing */
break;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b585a30..1099168 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1158,11 +1158,18 @@ static inline bool dwc3_is_usb31(struct dwc3 *dwc)
 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 int dwc3_host_init(struct dwc3 *dwc);
 void dwc3_host_exit(struct dwc3 *dwc);
+int dwc3_host_suspend(struct dwc3 *dwc);
+int dwc3_host_resume(struct dwc3 *dwc);
 #else
 static inline int dwc3_host_init(struct dwc3 *dwc)
 { return 0; }
 static inline void dwc3_host_exit(struct dwc3 *dwc)
 { }
+
+static inline int dwc3_host_suspend(struct dwc3 *dwc)
+{ return 0; }
+static inline int dwc3_host_resume(struct dwc3 *dwc)
+{ return 0; }
 #endif
 
 #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index ed82464..7959ef0 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -16,6 +16,7 @@
  */
 
 #include 
+#include 
 
 #include "core.h"
 
@@ -130,3 +131,23 @@ void dwc3_host_exit(struct dwc3 *dwc)
  dev_name(&dwc->xhci->dev));
platform_device_unregister(dwc->xhci);
 }
+
+int dwc3_host_suspend(struct dwc3 *dwc)
+{
+   struct device *xhci = &dwc->xhci->dev;
+
+   /*
+* Note: if we get the -EBUSY, which means the xHCI children devices are
+* not in suspend state yet, the glue layer need to wait for a while and
+* try to suspend xHCI device again.
+*/
+   return pm_runtime_put_sync(xhci);
+}
+
+int dwc3_host_resume(struct dwc3 *dwc)
+{
+   struct device *xhci = &dwc->xhci->dev;
+
+   /* Resume the xHCI device synchronously. */
+   return pm_runtime_get_sync(xhci);
+}
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a