]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
PM / Domains: Move syscore flag from subsys data to struct device
authorRafael J. Wysocki <rjw@sisk.pl>
Sun, 5 Aug 2012 23:46:39 +0000 (01:46 +0200)
committerRafael J. Wysocki <rjw@sisk.pl>
Mon, 3 Sep 2012 23:36:04 +0000 (01:36 +0200)
The syscore device PM flag is used to mark the devices (belonging to
a PM domain) that should never be turned off, except for the system
core (syscore) suspend/hibernation and resume stages.  That flag is
stored in the device's struct pm_subsys_data object whose address is
available from struct device.  However, in some situations it may be
convenient to set that flag before the device is added to a PM
domain, so it is better to move it directly to the "power" member of
struct device.  Then, it can be checked by the routines in
drivers/base/power/runtime.c and drivers/base/power/main.c, which is
more straightforward.

This also reduces the number of dev_gpd_data() invocations in the
generic PM domains framework, so the overhead related to the syscore
flag is slightly smaller.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Magnus Damm <damm@opensource.se>
drivers/base/power/common.c
drivers/base/power/domain.c
drivers/base/power/main.c
drivers/base/power/runtime.c
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/sh_tmu.c
include/linux/pm.h
include/linux/pm_domain.h

index 39c32529b83374c36eda18188c393930732ad99f..cf7a85134730d579074808d0c42174ab04a1e9c7 100644 (file)
@@ -83,3 +83,18 @@ int dev_pm_put_subsys_data(struct device *dev)
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
+
+/**
+ * dev_pm_syscore_device - Set/unset the given device's power.syscore flag.
+ * @dev: Device whose flag is to be modified.
+ * @val: New value of the flag.
+ */
+void dev_pm_syscore_device(struct device *dev, bool val)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->power.lock, flags);
+       dev->power.syscore = val;
+       spin_unlock_irqrestore(&dev->power.lock, flags);
+}
+EXPORT_SYMBOL_GPL(dev_pm_syscore_device);
index 15234ecd7edb0e28e585c6bab84e9ce90eca9a87..52172754ff786c9bfd17958231dcf9d623536f43 100644 (file)
@@ -436,7 +436,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
        not_suspended = 0;
        list_for_each_entry(pdd, &genpd->dev_list, list_node)
                if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
-                   || pdd->dev->power.irq_safe || to_gpd_data(pdd)->syscore))
+                   || pdd->dev->power.irq_safe || pdd->dev->power.syscore))
                        not_suspended++;
 
        if (not_suspended > genpd->in_progress)
@@ -578,9 +578,6 @@ static int pm_genpd_runtime_suspend(struct device *dev)
 
        might_sleep_if(!genpd->dev_irq_safe);
 
-       if (dev_gpd_data(dev)->syscore)
-               return -EBUSY;
-
        stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
        if (stop_ok && !stop_ok(dev))
                return -EBUSY;
@@ -983,7 +980,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
        if (IS_ERR(genpd))
                return -EINVAL;
 
-       if (genpd->suspend_power_off || dev_gpd_data(dev)->syscore
+       if (genpd->suspend_power_off
            || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
                return 0;
 
@@ -1016,7 +1013,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
        if (IS_ERR(genpd))
                return -EINVAL;
 
-       if (genpd->suspend_power_off || dev_gpd_data(dev)->syscore
+       if (genpd->suspend_power_off
            || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
                return 0;
 
@@ -1136,8 +1133,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
        if (IS_ERR(genpd))
                return -EINVAL;
 
-       return genpd->suspend_power_off || dev_gpd_data(dev)->syscore ?
-               0 : genpd_stop_dev(genpd, dev);
+       return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev);
 }
 
 /**
@@ -1157,8 +1153,7 @@ static int pm_genpd_thaw_noirq(struct device *dev)
        if (IS_ERR(genpd))
                return -EINVAL;
 
-       return genpd->suspend_power_off || dev_gpd_data(dev)->syscore ?
-               0 : genpd_start_dev(genpd, dev);
+       return genpd->suspend_power_off ? 0 : genpd_start_dev(genpd, dev);
 }
 
 /**
@@ -1253,7 +1248,7 @@ static int pm_genpd_restore_noirq(struct device *dev)
 
        pm_genpd_sync_poweron(genpd);
 
-       return dev_gpd_data(dev)->syscore ? 0 : genpd_start_dev(genpd, dev);
+       return genpd_start_dev(genpd, dev);
 }
 
 /**
@@ -1525,26 +1520,6 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
        return ret;
 }
 
-/**
- * pm_genpd_dev_syscore - Set/unset the "syscore" flag for a given device.
- * @dev: Device to set/unset the flag for.
- * @val: The new value of the device's "syscore" flag.
- */
-void pm_genpd_dev_syscore(struct device *dev, bool val)
-{
-       struct pm_subsys_data *psd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->power.lock, flags);
-
-       psd = dev_to_psd(dev);
-       if (psd && psd->domain_data)
-               to_gpd_data(psd->domain_data)->syscore = val;
-
-       spin_unlock_irqrestore(&dev->power.lock, flags);
-}
-EXPORT_SYMBOL_GPL(pm_genpd_dev_syscore);
-
 /**
  * pm_genpd_dev_need_restore - Set/unset the device's "need restore" flag.
  * @dev: Device to set/unset the flag for.
index 7bd1fe400549c5b2192aa17751cd1ca9b99e35cd..57f5814c2732783d7c4f06c756728465f185fa2c 100644 (file)
@@ -405,6 +405,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
        TRACE_DEVICE(dev);
        TRACE_RESUME(0);
 
+       if (dev->power.syscore)
+               goto Out;
+
        if (dev->pm_domain) {
                info = "noirq power domain ";
                callback = pm_noirq_op(&dev->pm_domain->ops, state);
@@ -426,6 +429,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 
        error = dpm_run_callback(callback, dev, state, info);
 
+ Out:
        TRACE_RESUME(error);
        return error;
 }
@@ -483,6 +487,9 @@ static int device_resume_early(struct device *dev, pm_message_t state)
        TRACE_DEVICE(dev);
        TRACE_RESUME(0);
 
+       if (dev->power.syscore)
+               goto Out;
+
        if (dev->pm_domain) {
                info = "early power domain ";
                callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -504,6 +511,7 @@ static int device_resume_early(struct device *dev, pm_message_t state)
 
        error = dpm_run_callback(callback, dev, state, info);
 
+ Out:
        TRACE_RESUME(error);
        return error;
 }
@@ -567,6 +575,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
        TRACE_DEVICE(dev);
        TRACE_RESUME(0);
 
+       if (dev->power.syscore)
+               goto Complete;
+
        dpm_wait(dev->parent, async);
        device_lock(dev);
 
@@ -629,6 +640,8 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 
  Unlock:
        device_unlock(dev);
+
+ Complete:
        complete_all(&dev->power.completion);
 
        TRACE_RESUME(error);
@@ -719,6 +732,9 @@ static void device_complete(struct device *dev, pm_message_t state)
        void (*callback)(struct device *) = NULL;
        char *info = NULL;
 
+       if (dev->power.syscore)
+               return;
+
        device_lock(dev);
 
        if (dev->pm_domain) {
@@ -831,6 +847,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
        pm_callback_t callback = NULL;
        char *info = NULL;
 
+       if (dev->power.syscore)
+               return 0;
+
        if (dev->pm_domain) {
                info = "noirq power domain ";
                callback = pm_noirq_op(&dev->pm_domain->ops, state);
@@ -914,6 +933,9 @@ static int device_suspend_late(struct device *dev, pm_message_t state)
        pm_callback_t callback = NULL;
        char *info = NULL;
 
+       if (dev->power.syscore)
+               return 0;
+
        if (dev->pm_domain) {
                info = "late power domain ";
                callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -1050,6 +1072,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
                goto Complete;
        }
 
+       if (dev->power.syscore)
+               goto Complete;
+
        device_lock(dev);
 
        if (dev->pm_domain) {
@@ -1206,6 +1231,9 @@ static int device_prepare(struct device *dev, pm_message_t state)
        char *info = NULL;
        int error = 0;
 
+       if (dev->power.syscore)
+               return 0;
+
        device_lock(dev);
 
        dev->power.wakeup_path = device_may_wakeup(dev);
index 7d9c1cb1c39a7760081bae4d518efd8acf835902..bd1de3980919ca8dfa7670e15145b1ce796f9c1a 100644 (file)
@@ -134,7 +134,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
 
        if (dev->power.runtime_error)
                retval = -EINVAL;
-       else if (dev->power.disable_depth > 0)
+       else if (dev->power.disable_depth > 0 || dev->power.syscore)
                retval = -EACCES;
        else if (atomic_read(&dev->power.usage_count) > 0)
                retval = -EAGAIN;
index c6fbb9f719115cf71ff66f08da513853988c9efb..a515605bf8f54f0e90c8aa3c8ada23474289ac5e 100644 (file)
@@ -717,7 +717,7 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)
                struct sh_timer_config *cfg = pdev->dev.platform_data;
 
                if (cfg->clocksource_rating || cfg->clockevent_rating)
-                       pm_genpd_dev_syscore(&pdev->dev, true);
+                       dev_pm_syscore_device(&pdev->dev, true);
        }
 
        if (p) {
index 278c18abb2ae55c1346c69fc772f6d7970c4196e..1a95cad968199d29a9f3c06b85a840ddf752d238 100644 (file)
@@ -323,7 +323,7 @@ static int __devinit sh_mtu2_probe(struct platform_device *pdev)
                struct sh_timer_config *cfg = pdev->dev.platform_data;
 
                if (cfg->clockevent_rating)
-                       pm_genpd_dev_syscore(&pdev->dev, true);
+                       dev_pm_syscore_device(&pdev->dev, true);
        }
 
        if (p) {
index 5319689c579c9d891a6abcbe0e10fde05fb4607b..81b0239718ee2bc0d80dccf803546a6db24964ab 100644 (file)
@@ -453,7 +453,7 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)
                struct sh_timer_config *cfg = pdev->dev.platform_data;
 
                if (cfg->clocksource_rating || cfg->clockevent_rating)
-                       pm_genpd_dev_syscore(&pdev->dev, true);
+                       dev_pm_syscore_device(&pdev->dev, true);
        }
 
        if (p) {
index 716517af1543b0fa55ec57f6a834f53f222023f6..b79a0dd3bc6dcf8032dbc33f06bbbd54b35f71bb 100644 (file)
@@ -43,8 +43,12 @@ struct device;
 
 #ifdef CONFIG_PM
 extern const char power_group_name[];          /* = "power" */
+
+extern void dev_pm_syscore_device(struct device *dev, bool val);
 #else
 #define power_group_name       NULL
+
+static inline void dev_pm_syscore_device(struct device *dev, bool val) {}
 #endif
 
 typedef struct pm_message {
@@ -511,6 +515,7 @@ struct dev_pm_info {
        bool                    is_suspended:1; /* Ditto */
        bool                    ignore_children:1;
        bool                    early_init:1;   /* Owned by the PM core */
+       bool                    syscore:1;
        spinlock_t              lock;
 #ifdef CONFIG_PM_SLEEP
        struct list_head        entry;
index dab0938603faa433e5ce43ca82d8ccbf0e16e61c..08adf8e5a80e9c34ccb1ea9de19efe8bf992ea0d 100644 (file)
@@ -114,7 +114,6 @@ struct generic_pm_domain_data {
        struct mutex lock;
        unsigned int refcount;
        bool need_restore;
-       bool syscore;
 };
 
 #ifdef CONFIG_PM_GENERIC_DOMAINS
@@ -153,7 +152,6 @@ static inline int pm_genpd_of_add_device(struct device_node *genpd_node,
 
 extern int pm_genpd_remove_device(struct generic_pm_domain *genpd,
                                  struct device *dev);
-extern void pm_genpd_dev_syscore(struct device *dev, bool val);
 extern void pm_genpd_dev_need_restore(struct device *dev, bool val);
 extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
                                  struct generic_pm_domain *new_subdomain);
@@ -199,7 +197,6 @@ static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 {
        return -ENOSYS;
 }
-static inline void pm_genpd_dev_syscore(struct device *dev, bool val) {}
 static inline void pm_genpd_dev_need_restore(struct device *dev, bool val) {}
 static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
                                         struct generic_pm_domain *new_sd)