RE: USB port power-off and system suspend

2013-03-25 Thread Alan Stern
On Sat, 23 Mar 2013, Lan, Tianyu wrote:

 On 2013/3/23 1:35, Alan Stern wrote: Tianyu:
  
  Did you ever test the port power-off mechanism with system suspend?
  Right now it doesn't seem like it would work, because it relies on
  runtime PM to turn off the port power, and runtime PM doesn't operate
  normally during a system suspend.
  
  Alan Stern
  
 
 Hi Alan:
   You are right. Current the port power-off can't work during
 system suspend. I have already worked on a patch of adding usb
 port system pm support. But there is a still problem that how to
 control power off mechanism from kernel side. Before, we have a solution
 for runtime pm that increase/decrease port dev's usage count.
   http://marc.info/?l=linux-usbm=135772122031446w=2
 But now, we have another user, System pm. So I think we should find
 a solution to cover these two cases. Maybe add a new pm qos request
 for NO_POWER_OFF flag? I'd like to see your opinion. 

Yes, I think you need to copy the test that's in usb_port_suspend.  
Better yet, move that test to a separate function in port.c and call it 
from both places.

 I have a patch that can work and it still needs to add some condition
 checks in the usb_port_system_suspend(). Dev's system wakeup disable
 and persist enable.

...

 +static int usb_port_system_suspend(struct device *dev)
 +{
 + struct usb_port *port_dev = to_usb_port(dev);
 + int retval;
 +
 + if (port_dev-child)
 + device_pm_wait_for_dev(dev, port_dev-child-dev);
 +
 + retval = usb_port_runtime_suspend(dev);
 + if (retval  0  retval != -EAGAIN)
 + return retval;
 +
 + return 0;

This should always return 0.  Ignore any errors from 
usb_port_runtime_suspend.

 +}
 +
 +static int usb_port_system_resume(struct device *dev)
 +{
 + return usb_port_runtime_resume(dev);
 +}
 +

These new functions should be protected by #ifdef CONFIG_PM_SLEEP.

  static const struct dev_pm_ops usb_port_pm_ops = {
 + .suspend =  usb_port_system_suspend,
 + .resume =   usb_port_system_resume,

And the same goes for these entries.  The runtime routines now need to 
be protected by CONFIG_PM, since they can be used if either PM_RUNTIME 
or PM_SLEEP is enabled.

Alan Stern

--
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


RE: USB port power-off and system suspend

2013-03-23 Thread Lan, Tianyu
On 2013/3/23 1:35, Alan Stern wrote: Tianyu:
 
 Did you ever test the port power-off mechanism with system suspend?
 Right now it doesn't seem like it would work, because it relies on
 runtime PM to turn off the port power, and runtime PM doesn't operate
 normally during a system suspend.
 
 Alan Stern
 

Hi Alan:
You are right. Current the port power-off can't work during
system suspend. I have already worked on a patch of adding usb
port system pm support. But there is a still problem that how to
control power off mechanism from kernel side. Before, we have a solution
for runtime pm that increase/decrease port dev's usage count.
http://marc.info/?l=linux-usbm=135772122031446w=2
But now, we have another user, System pm. So I think we should find
a solution to cover these two cases. Maybe add a new pm qos request
for NO_POWER_OFF flag? I'd like to see your opinion. 

I have a patch that can work and it still needs to add some condition
checks in the usb_port_system_suspend(). Dev's system wakeup disable
and persist enable.
 
From c3abd373707910672d6fd2e96da78879b3e22417 Mon Sep 17 00:00:00 2001
From: Lan Tianyu tianyu@intel.com
Date: Tue, 26 Feb 2013 11:12:09 +0800
Subject: [PATCH] usb: Add usb port system pm support

This patch is to add usb port system pm support. Add
usb port's system suspend/resume callbacks and call
usb_port_runtime_resume/suspend() to power off these
ports without pm qos NO_POWER_OFF flag setting.

During system pm, usb port should be powered off after
dev being suspended and powered on before dev being
resumed. Usb ports and devs enable async suspend. In
order to keeping the order, call device_pm_wait_for_dev()
in the usb_port_system_suspend() and usb_port_resume().

Usb_port_system_suspend() ignores EAGAIN from usb_port_runtime_suspend().
EAGAIN is caused by pm qos NO_POWER_OFF setting. This is
not an error for usb port system pm.
---
 drivers/usb/core/hub.c  |4 
 drivers/usb/core/port.c |   31 +++
 2 files changed, 35 insertions(+)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 53c1555..8868f15 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3162,6 +3162,10 @@ int usb_port_resume(struct usb_device *udev, 
pm_message_t msg)
int status;
u16 portchange, portstatus;
 
+   /* Wait for usb port system resume finishing */
+   if (!PMSG_IS_AUTO(msg))
+   device_pm_wait_for_dev(udev-dev, port_dev-dev);
+
if (port_dev-did_runtime_put) {
status = pm_runtime_get_sync(port_dev-dev);
port_dev-did_runtime_put = false;
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 797f9d5..e5c6ec5 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -84,6 +84,9 @@ static int usb_port_runtime_resume(struct device *dev)
if (!hub)
return -EINVAL;
 
+   if (port_dev-power_is_on)
+   return 0;
+
usb_autopm_get_interface(intf);
set_bit(port1, hub-busy_bits);
 
@@ -127,6 +130,9 @@ static int usb_port_runtime_suspend(struct device *dev)
== PM_QOS_FLAGS_ALL)
return -EAGAIN;
 
+   if (!port_dev-power_is_on)
+   return 0;
+
usb_autopm_get_interface(intf);
set_bit(port1, hub-busy_bits);
retval = usb_hub_set_port_power(hdev, port1, false);
@@ -136,9 +142,34 @@ static int usb_port_runtime_suspend(struct device *dev)
usb_autopm_put_interface(intf);
return retval;
 }
+#else
+static int usb_port_runtime_suspend(struct device *dev) { return 0; }
+static int usb_port_runtime_resume(struct device *dev) { return 0; }
 #endif
 
+static int usb_port_system_suspend(struct device *dev)
+{
+   struct usb_port *port_dev = to_usb_port(dev);
+   int retval;
+
+   if (port_dev-child)
+   device_pm_wait_for_dev(dev, port_dev-child-dev);
+
+   retval = usb_port_runtime_suspend(dev);
+   if (retval  0  retval != -EAGAIN)
+   return retval;
+
+   return 0;
+}
+
+static int usb_port_system_resume(struct device *dev)
+{
+   return usb_port_runtime_resume(dev);
+}
+
 static const struct dev_pm_ops usb_port_pm_ops = {
+   .suspend =  usb_port_system_suspend,
+   .resume =   usb_port_system_resume,
 #ifdef CONFIG_USB_SUSPEND
.runtime_suspend =  usb_port_runtime_suspend,
.runtime_resume =   usb_port_runtime_resume,
-- 
1.7.10.4



-- 
Best Regards
Tianyu Lan
linux kernel enabling team
--
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