[RFC PATCH 4/5] usb: add runtime pm support for usb port device

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

 



When pm qos flags is changing, the pm core will keep device not
in RPM_SUSPEND via pm_runtime_get_sync/put(dev). When the flags are
changed, this will affect usb device status. If NO_POWER_OFF flag was
set when the device was power off, it would need to be resumed and
suspended again without power off. If NO_POWER_OFF flag was cleared
when the device was suspended without power off, it would need to be
resumed and suspended again with power off inorder to save more power.

This patch is to add runtime pm callback for usb port device. In the callback,
usb device attached to the port will be resumed and suspended.

Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx>
---
 drivers/usb/core/hub.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f0e1b29..3ba6a96 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1264,9 +1264,55 @@ static void usb_hub_remove_port_device(struct usb_hub *hub,
 	device_unregister(&hub->ports[port1 - 1]->dev);
 }
 
+static int usb_port_runtime_suspend(struct device *dev)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+	int ret;
+
+	if (!port_dev->child)
+		return 0;
+
+	ret = pm_runtime_suspend(&port_dev->child->dev);
+	if (ret == 1 || ret == 0 || ret == -EBUSY)
+		return 0;
+	else
+		return ret;
+}
+
+static int usb_port_runtime_resume(struct device *dev)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+	int ret;
+
+	if (!port_dev->child)
+		return 0;
+
+	ret = pm_runtime_resume(&port_dev->child->dev);
+	if (ret == 1 || ret == 0)
+		return 0;
+	else
+		return ret;
+}
+
+static int usb_port_runtime_idle(struct device *dev)
+{
+	struct usb_port *port_dev = to_usb_port(dev);
+
+	return pm_runtime_suspend(&port_dev->dev);
+}
+
+static const struct dev_pm_ops usb_port_pm_ops = {
+#ifdef CONFIG_USB_SUSPEND
+.runtime_suspend =	usb_port_runtime_suspend,
+.runtime_resume =	usb_port_runtime_resume,
+.runtime_idle =		usb_port_runtime_idle,
+#endif
+};
+
 struct device_type usb_port_device_type = {
 	.name =		"usb_port",
 	.release =	usb_port_device_release,
+	.pm = &usb_port_pm_ops,
 };
 
 static int usb_hub_create_port_device(struct usb_hub *hub,
@@ -1291,6 +1337,8 @@ static int usb_hub_create_port_device(struct usb_hub *hub,
 	if (retval)
 		goto error_register;
 
+	pm_runtime_enable(&port_dev->dev);
+
 	retval = dev_pm_qos_expose_flags(&port_dev->dev,
 			PM_QOS_FLAG_NO_POWER_OFF);
 	if (retval)
-- 
1.7.9.5

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