]> Pileus Git - ~andy/linux/blobdiff - arch/arm/mach-omap2/omap_device.c
ARM: OMAP2+: omap_device: add fail hook for runtime_pm when bad data is detected
[~andy/linux] / arch / arm / mach-omap2 / omap_device.c
index b69dd9abb50aeb0003998b24d7df9063a6a41cb1..e0a398cf28d80a409e25055c19ad44baef25d7fc 100644 (file)
@@ -183,6 +183,10 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 odbfd_exit1:
        kfree(hwmods);
 odbfd_exit:
+       /* if data/we are at fault.. load up a fail handler */
+       if (ret)
+               pdev->dev.pm_domain = &omap_device_fail_pm_domain;
+
        return ret;
 }
 
@@ -604,6 +608,19 @@ static int _od_runtime_resume(struct device *dev)
 
        return pm_generic_runtime_resume(dev);
 }
+
+static int _od_fail_runtime_suspend(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
+static int _od_fail_runtime_resume(struct device *dev)
+{
+       dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
+       return -ENODEV;
+}
+
 #endif
 
 #ifdef CONFIG_SUSPEND
@@ -621,6 +638,7 @@ static int _od_suspend_noirq(struct device *dev)
 
        if (!ret && !pm_runtime_status_suspended(dev)) {
                if (pm_generic_runtime_suspend(dev) == 0) {
+                       pm_runtime_set_suspended(dev);
                        omap_device_idle(pdev);
                        od->flags |= OMAP_DEVICE_SUSPENDED;
                }
@@ -634,10 +652,18 @@ static int _od_resume_noirq(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct omap_device *od = to_omap_device(pdev);
 
-       if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
-           !pm_runtime_status_suspended(dev)) {
+       if (od->flags & OMAP_DEVICE_SUSPENDED) {
                od->flags &= ~OMAP_DEVICE_SUSPENDED;
                omap_device_enable(pdev);
+               /*
+                * XXX: we run before core runtime pm has resumed itself. At
+                * this point in time, we just restore the runtime pm state and
+                * considering symmetric operations in resume, we donot expect
+                * to fail. If we failed, something changed in core runtime_pm
+                * framework OR some device driver messed things up, hence, WARN
+                */
+               WARN(pm_runtime_set_active(dev),
+                    "Could not set %s runtime state active\n", dev_name(dev));
                pm_generic_runtime_resume(dev);
        }
 
@@ -648,6 +674,13 @@ static int _od_resume_noirq(struct device *dev)
 #define _od_resume_noirq NULL
 #endif
 
+struct dev_pm_domain omap_device_fail_pm_domain = {
+       .ops = {
+               SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend,
+                                  _od_fail_runtime_resume, NULL)
+       }
+};
+
 struct dev_pm_domain omap_device_pm_domain = {
        .ops = {
                SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,