[PATCH 06/20] usb: hcd-pci: introduce pm-ops for platform-pci devs

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

 



usb_hcd_pci_pm_ops provides run-time functionality for the USB HCDs.
It expects that driver's data is a struct usb_hcd. This does not work
if we create the HCD device is a platform device and its parent is the
PCI device. We create the pci_dev from device and usb_hcd from parent's
driver data.
This patch is preparation to let the xhci core work under a platform
device.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
---
 drivers/usb/core/hcd-pci.c |  133 ++++++++++++++++++++++++++++++++++++++-----
 include/linux/usb/hcd.h    |    1 +
 2 files changed, 118 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index ce22f4a..01f8955 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 
@@ -358,11 +359,8 @@ static inline void powermac_set_asic(struct pci_dev *pci_dev, int enable)
 
 #endif	/* CONFIG_PPC_PMAC */
 
-static int check_root_hub_suspended(struct device *dev)
+static int _check_root_hub_suspended(struct device *dev, struct usb_hcd *hcd)
 {
-	struct pci_dev		*pci_dev = to_pci_dev(dev);
-	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
-
 	if (HCD_RH_RUNNING(hcd)) {
 		dev_warn(dev, "Root hub is not suspended\n");
 		return -EBUSY;
@@ -377,10 +375,26 @@ static int check_root_hub_suspended(struct device *dev)
 	return 0;
 }
 
-static int suspend_common(struct device *dev, bool do_wakeup)
+static int check_root_hub_suspended(struct device *dev)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+
+	return _check_root_hub_suspended(dev, hcd);
+}
+
+static int check_plat_pci_root_hub_suspended(struct device *dev)
+{
+	struct usb_hcd		*hcd = dev_get_drvdata(dev->parent);
+
+	return _check_root_hub_suspended(dev, hcd);
+}
+
+
+static int _suspend_common(struct device *dev, bool do_wakeup,
+		struct usb_hcd *hcd)
+{
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
 	int			retval;
 
 	/* Root hub suspend should have stopped all downstream traffic,
@@ -388,7 +402,7 @@ static int suspend_common(struct device *dev, bool do_wakeup)
 	 * and the stub usb_device (which we check here).  But maybe it
 	 * didn't; writing sysfs power/state files ignores such rules...
 	 */
-	retval = check_root_hub_suspended(dev);
+	retval = _check_root_hub_suspended(dev, hcd);
 	if (retval)
 		return retval;
 
@@ -432,10 +446,9 @@ static int suspend_common(struct device *dev, bool do_wakeup)
 	return retval;
 }
 
-static int resume_common(struct device *dev, int event)
+static int _resume_common(struct device *dev, int event, struct usb_hcd *hcd)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
-	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 	int			retval;
 
 	if (HCD_RH_RUNNING(hcd) ||
@@ -477,16 +490,25 @@ static int resume_common(struct device *dev, int event)
 
 static int hcd_pci_suspend(struct device *dev)
 {
-	return suspend_common(dev, device_may_wakeup(dev));
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+
+	return _suspend_common(dev, device_may_wakeup(dev), hcd);
 }
 
-static int hcd_pci_suspend_noirq(struct device *dev)
+static int hcd_plat_pci_suspend(struct device *dev)
+{
+	struct usb_hcd		*hcd = dev_get_drvdata(dev->parent);
+
+	return _suspend_common(dev, device_may_wakeup(dev), hcd);
+}
+
+static int _hcd_pci_suspend_noirq(struct device *dev, struct usb_hcd *hcd)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
-	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 	int			retval;
 
-	retval = check_root_hub_suspended(dev);
+	retval = _check_root_hub_suspended(dev, hcd);
 	if (retval)
 		return retval;
 
@@ -519,6 +541,21 @@ static int hcd_pci_suspend_noirq(struct device *dev)
 	return retval;
 }
 
+static int hcd_pci_suspend_noirq(struct device *dev)
+{
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+
+	return _hcd_pci_suspend_noirq(dev, hcd);
+}
+
+static int hcd_plat_pci_suspend_noirq(struct device *dev)
+{
+	struct usb_hcd		*hcd = dev_get_drvdata(dev->parent);
+
+	return _hcd_pci_suspend_noirq(dev, hcd);
+}
+
 static int hcd_pci_resume_noirq(struct device *dev)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
@@ -532,12 +569,32 @@ static int hcd_pci_resume_noirq(struct device *dev)
 
 static int hcd_pci_resume(struct device *dev)
 {
-	return resume_common(dev, PM_EVENT_RESUME);
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+
+	return _resume_common(dev, PM_EVENT_RESUME, hcd);
+}
+
+static int hcd_plat_pci_resume(struct device *dev)
+{
+	struct usb_hcd		*hcd = dev_get_drvdata(dev->parent);
+
+	return _resume_common(dev, PM_EVENT_RESUME, hcd);
 }
 
 static int hcd_pci_restore(struct device *dev)
 {
-	return resume_common(dev, PM_EVENT_RESTORE);
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+
+	return _resume_common(dev, PM_EVENT_RESTORE, hcd);
+}
+
+static int hcd_plat_pci_restore(struct device *dev)
+{
+	struct usb_hcd		*hcd = dev_get_drvdata(dev->parent);
+
+	return _resume_common(dev, PM_EVENT_RESTORE, hcd);
 }
 
 #else
@@ -548,35 +605,61 @@ static int hcd_pci_restore(struct device *dev)
 #define hcd_pci_resume		NULL
 #define hcd_pci_restore		NULL
 
+#define hcd_plat_pci_suspend		NULL
+#define hcd_plat_pci_suspend_noirq	NULL
+#define hcd_plat_pci_resume_noirq	NULL
+#define hcd_plat_pci_resume		NULL
+#define hcd_plat_pci_restore		NULL
+
 #endif	/* CONFIG_PM_SLEEP */
 
 #ifdef	CONFIG_PM_RUNTIME
 
 static int hcd_pci_runtime_suspend(struct device *dev)
 {
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 	int	retval;
 
-	retval = suspend_common(dev, true);
+	retval = _suspend_common(dev, true, hcd);
 	if (retval == 0)
 		powermac_set_asic(to_pci_dev(dev), 0);
 	dev_dbg(dev, "hcd_pci_runtime_suspend: %d\n", retval);
 	return retval;
 }
 
+static int hcd_plat_pci_runtime_suspend(struct device *dev)
+{
+	struct usb_hcd		*hcd = dev_get_drvdata(dev->parent);
+
+	return _suspend_common(dev, true, hcd);
+}
+
 static int hcd_pci_runtime_resume(struct device *dev)
 {
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 	int	retval;
 
 	powermac_set_asic(to_pci_dev(dev), 1);
-	retval = resume_common(dev, PM_EVENT_AUTO_RESUME);
+	retval = _resume_common(dev, PM_EVENT_AUTO_RESUME, hcd);
 	dev_dbg(dev, "hcd_pci_runtime_resume: %d\n", retval);
 	return retval;
 }
 
+static int hcd_plat_pci_runtime_resume(struct device *dev)
+{
+	struct usb_hcd		*hcd = dev_get_drvdata(dev->parent);
+
+	return _resume_common(dev, PM_EVENT_AUTO_RESUME, hcd);
+}
+
 #else
 
 #define hcd_pci_runtime_suspend	NULL
 #define hcd_pci_runtime_resume	NULL
+#define hcd_plat_pci_runtime_suspend	NULL
+#define hcd_plat_pci_runtime_resume	NULL
 
 #endif	/* CONFIG_PM_RUNTIME */
 
@@ -598,4 +681,22 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = {
 };
 EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops);
 
+const struct dev_pm_ops usb_hcd_plat_pci_pm_ops = {
+	.suspend	= hcd_plat_pci_suspend,
+	.suspend_noirq	= hcd_plat_pci_suspend_noirq,
+	.resume_noirq	= hcd_pci_resume_noirq,
+	.resume		= hcd_plat_pci_resume,
+	.freeze		= check_plat_pci_root_hub_suspended,
+	.freeze_noirq	= check_plat_pci_root_hub_suspended,
+	.thaw_noirq	= NULL,
+	.thaw		= NULL,
+	.poweroff	= hcd_plat_pci_suspend,
+	.poweroff_noirq	= hcd_plat_pci_suspend_noirq,
+	.restore_noirq	= hcd_pci_resume_noirq,
+	.restore	= hcd_plat_pci_restore,
+	.runtime_suspend = hcd_plat_pci_runtime_suspend,
+	.runtime_resume	= hcd_plat_pci_runtime_resume,
+};
+EXPORT_SYMBOL_GPL(usb_hcd_plat_pci_pm_ops);
+
 #endif	/* CONFIG_PM */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 0097136..61181a4 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -396,6 +396,7 @@ extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
 
 #ifdef CONFIG_PM_SLEEP
 extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
+extern const struct dev_pm_ops usb_hcd_plat_pci_pm_ops;
 #endif
 #endif /* CONFIG_PCI */
 
-- 
1.7.4.4

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