diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-08-05 19:45:11 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-09-03 19:36:03 -0400 |
commit | bed2b42d9f0b411f384c5619870ab0fea5dd116b (patch) | |
tree | abdfe3a877b5751411ba10d6bf1a57040c56bf73 | |
parent | e91c11b1a7f876c6f056d872eb210734150a1795 (diff) |
PM / Runtime: Allow helpers to be called by early platform drivers
Runtime PM helper functions, like pm_runtime_get_sync(), cannot be
called by early platform device drivers, because the devices' power
management locks are not initialized at that time. This is quite
inconvenient, so modify early_platform_add_devices() to initialize
the devices power management locks as appropriate and make sure that
they won't be initialized more than once if an early platform
device is going to be used as a regular one later.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
-rw-r--r-- | drivers/base/platform.c | 2 | ||||
-rw-r--r-- | drivers/base/power/power.h | 18 | ||||
-rw-r--r-- | include/linux/pm.h | 1 |
3 files changed, 19 insertions, 2 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index a1a722502587..d51514b79efe 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
23 | 23 | ||
24 | #include "base.h" | 24 | #include "base.h" |
25 | #include "power/power.h" | ||
25 | 26 | ||
26 | #define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ | 27 | #define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ |
27 | driver)) | 28 | driver)) |
@@ -948,6 +949,7 @@ void __init early_platform_add_devices(struct platform_device **devs, int num) | |||
948 | dev = &devs[i]->dev; | 949 | dev = &devs[i]->dev; |
949 | 950 | ||
950 | if (!dev->devres_head.next) { | 951 | if (!dev->devres_head.next) { |
952 | pm_runtime_early_init(dev); | ||
951 | INIT_LIST_HEAD(&dev->devres_head); | 953 | INIT_LIST_HEAD(&dev->devres_head); |
952 | list_add_tail(&dev->devres_head, | 954 | list_add_tail(&dev->devres_head, |
953 | &early_platform_device_list); | 955 | &early_platform_device_list); |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 8a0dcc7f98f9..0dbfdf4419af 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -2,17 +2,31 @@ | |||
2 | 2 | ||
3 | static inline void device_pm_init_common(struct device *dev) | 3 | static inline void device_pm_init_common(struct device *dev) |
4 | { | 4 | { |
5 | spin_lock_init(&dev->power.lock); | 5 | if (!dev->power.early_init) { |
6 | dev->power.power_state = PMSG_INVALID; | 6 | spin_lock_init(&dev->power.lock); |
7 | dev->power.power_state = PMSG_INVALID; | ||
8 | dev->power.early_init = true; | ||
9 | } | ||
7 | } | 10 | } |
8 | 11 | ||
9 | #ifdef CONFIG_PM_RUNTIME | 12 | #ifdef CONFIG_PM_RUNTIME |
10 | 13 | ||
14 | static inline void pm_runtime_early_init(struct device *dev) | ||
15 | { | ||
16 | dev->power.disable_depth = 1; | ||
17 | device_pm_init_common(dev); | ||
18 | } | ||
19 | |||
11 | extern void pm_runtime_init(struct device *dev); | 20 | extern void pm_runtime_init(struct device *dev); |
12 | extern void pm_runtime_remove(struct device *dev); | 21 | extern void pm_runtime_remove(struct device *dev); |
13 | 22 | ||
14 | #else /* !CONFIG_PM_RUNTIME */ | 23 | #else /* !CONFIG_PM_RUNTIME */ |
15 | 24 | ||
25 | static inline void pm_runtime_early_init(struct device *dev) | ||
26 | { | ||
27 | device_pm_init_common(dev); | ||
28 | } | ||
29 | |||
16 | static inline void pm_runtime_init(struct device *dev) {} | 30 | static inline void pm_runtime_init(struct device *dev) {} |
17 | static inline void pm_runtime_remove(struct device *dev) {} | 31 | static inline void pm_runtime_remove(struct device *dev) {} |
18 | 32 | ||
diff --git a/include/linux/pm.h b/include/linux/pm.h index f067e60a3832..716517af1543 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -510,6 +510,7 @@ struct dev_pm_info { | |||
510 | bool is_prepared:1; /* Owned by the PM core */ | 510 | bool is_prepared:1; /* Owned by the PM core */ |
511 | bool is_suspended:1; /* Ditto */ | 511 | bool is_suspended:1; /* Ditto */ |
512 | bool ignore_children:1; | 512 | bool ignore_children:1; |
513 | bool early_init:1; /* Owned by the PM core */ | ||
513 | spinlock_t lock; | 514 | spinlock_t lock; |
514 | #ifdef CONFIG_PM_SLEEP | 515 | #ifdef CONFIG_PM_SLEEP |
515 | struct list_head entry; | 516 | struct list_head entry; |