diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2011-10-07 17:17:02 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-10-07 17:17:02 -0400 |
commit | c28b56b1d46b1bbb1be33c8f2632a88b0de1ef68 (patch) | |
tree | a7caddb9f58c968f6e77f36d2d398ec06983509e /include | |
parent | d727b60659a1173eb4142a5fc521ce67c28b34e1 (diff) | |
parent | cd0ea672f58d5cfdea271c45cec0c897f2b792aa (diff) |
Merge branch 'pm-domains' into pm-for-linus
* pm-domains:
PM / Domains: Split device PM domain data into base and need_restore
ARM: mach-shmobile: sh7372 sleep warning fixes
ARM: mach-shmobile: sh7372 A3SM support
ARM: mach-shmobile: sh7372 generic suspend/resume support
PM / Domains: Preliminary support for devices with power.irq_safe set
PM: Move clock-related definitions and headers to separate file
PM / Domains: Use power.sybsys_data to reduce overhead
PM: Reference counting of power.subsys_data
PM: Introduce struct pm_subsys_data
ARM / shmobile: Make A3RV be a subdomain of A4LC on SH7372
PM / Domains: Rename argument of pm_genpd_add_subdomain()
PM / Domains: Rename GPD_STATE_WAIT_PARENT to GPD_STATE_WAIT_MASTER
PM / Domains: Allow generic PM domains to have multiple masters
PM / Domains: Add "wait for parent" status for generic PM domains
PM / Domains: Make pm_genpd_poweron() always survive parent removal
PM / Domains: Do not take parent locks to modify subdomain counters
PM / Domains: Implement subdomain counters as atomic fields
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/device.h | 5 | ||||
-rw-r--r-- | include/linux/pm.h | 20 | ||||
-rw-r--r-- | include/linux/pm_clock.h | 71 | ||||
-rw-r--r-- | include/linux/pm_domain.h | 26 | ||||
-rw-r--r-- | include/linux/pm_runtime.h | 42 |
5 files changed, 114 insertions, 50 deletions
diff --git a/include/linux/device.h b/include/linux/device.h index c20dfbfc49b4..5d200ed0071a 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -636,6 +636,11 @@ static inline void set_dev_node(struct device *dev, int node) | |||
636 | } | 636 | } |
637 | #endif | 637 | #endif |
638 | 638 | ||
639 | static inline struct pm_subsys_data *dev_to_psd(struct device *dev) | ||
640 | { | ||
641 | return dev ? dev->power.subsys_data : NULL; | ||
642 | } | ||
643 | |||
639 | static inline unsigned int dev_get_uevent_suppress(const struct device *dev) | 644 | static inline unsigned int dev_get_uevent_suppress(const struct device *dev) |
640 | { | 645 | { |
641 | return dev->kobj.uevent_suppress; | 646 | return dev->kobj.uevent_suppress; |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 18de9f893497..f497ed06ee15 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -423,6 +423,22 @@ enum rpm_request { | |||
423 | 423 | ||
424 | struct wakeup_source; | 424 | struct wakeup_source; |
425 | 425 | ||
426 | struct pm_domain_data { | ||
427 | struct list_head list_node; | ||
428 | struct device *dev; | ||
429 | }; | ||
430 | |||
431 | struct pm_subsys_data { | ||
432 | spinlock_t lock; | ||
433 | unsigned int refcount; | ||
434 | #ifdef CONFIG_PM_CLK | ||
435 | struct list_head clock_list; | ||
436 | #endif | ||
437 | #ifdef CONFIG_PM_GENERIC_DOMAINS | ||
438 | struct pm_domain_data *domain_data; | ||
439 | #endif | ||
440 | }; | ||
441 | |||
426 | struct dev_pm_info { | 442 | struct dev_pm_info { |
427 | pm_message_t power_state; | 443 | pm_message_t power_state; |
428 | unsigned int can_wakeup:1; | 444 | unsigned int can_wakeup:1; |
@@ -464,10 +480,12 @@ struct dev_pm_info { | |||
464 | unsigned long suspended_jiffies; | 480 | unsigned long suspended_jiffies; |
465 | unsigned long accounting_timestamp; | 481 | unsigned long accounting_timestamp; |
466 | #endif | 482 | #endif |
467 | void *subsys_data; /* Owned by the subsystem. */ | 483 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ |
468 | }; | 484 | }; |
469 | 485 | ||
470 | extern void update_pm_runtime_accounting(struct device *dev); | 486 | extern void update_pm_runtime_accounting(struct device *dev); |
487 | extern int dev_pm_get_subsys_data(struct device *dev); | ||
488 | extern int dev_pm_put_subsys_data(struct device *dev); | ||
471 | 489 | ||
472 | /* | 490 | /* |
473 | * Power domains provide callbacks that are executed during system suspend, | 491 | * Power domains provide callbacks that are executed during system suspend, |
diff --git a/include/linux/pm_clock.h b/include/linux/pm_clock.h new file mode 100644 index 000000000000..8348866e7b05 --- /dev/null +++ b/include/linux/pm_clock.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * pm_clock.h - Definitions and headers related to device clocks. | ||
3 | * | ||
4 | * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp. | ||
5 | * | ||
6 | * This file is released under the GPLv2. | ||
7 | */ | ||
8 | |||
9 | #ifndef _LINUX_PM_CLOCK_H | ||
10 | #define _LINUX_PM_CLOCK_H | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | #include <linux/notifier.h> | ||
14 | |||
15 | struct pm_clk_notifier_block { | ||
16 | struct notifier_block nb; | ||
17 | struct dev_pm_domain *pm_domain; | ||
18 | char *con_ids[]; | ||
19 | }; | ||
20 | |||
21 | #ifdef CONFIG_PM_CLK | ||
22 | static inline bool pm_clk_no_clocks(struct device *dev) | ||
23 | { | ||
24 | return dev && dev->power.subsys_data | ||
25 | && list_empty(&dev->power.subsys_data->clock_list); | ||
26 | } | ||
27 | |||
28 | extern void pm_clk_init(struct device *dev); | ||
29 | extern int pm_clk_create(struct device *dev); | ||
30 | extern void pm_clk_destroy(struct device *dev); | ||
31 | extern int pm_clk_add(struct device *dev, const char *con_id); | ||
32 | extern void pm_clk_remove(struct device *dev, const char *con_id); | ||
33 | extern int pm_clk_suspend(struct device *dev); | ||
34 | extern int pm_clk_resume(struct device *dev); | ||
35 | #else | ||
36 | static inline bool pm_clk_no_clocks(struct device *dev) | ||
37 | { | ||
38 | return true; | ||
39 | } | ||
40 | static inline void pm_clk_init(struct device *dev) | ||
41 | { | ||
42 | } | ||
43 | static inline int pm_clk_create(struct device *dev) | ||
44 | { | ||
45 | return -EINVAL; | ||
46 | } | ||
47 | static inline void pm_clk_destroy(struct device *dev) | ||
48 | { | ||
49 | } | ||
50 | static inline int pm_clk_add(struct device *dev, const char *con_id) | ||
51 | { | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | static inline void pm_clk_remove(struct device *dev, const char *con_id) | ||
55 | { | ||
56 | } | ||
57 | #define pm_clk_suspend NULL | ||
58 | #define pm_clk_resume NULL | ||
59 | #endif | ||
60 | |||
61 | #ifdef CONFIG_HAVE_CLK | ||
62 | extern void pm_clk_add_notifier(struct bus_type *bus, | ||
63 | struct pm_clk_notifier_block *clknb); | ||
64 | #else | ||
65 | static inline void pm_clk_add_notifier(struct bus_type *bus, | ||
66 | struct pm_clk_notifier_block *clknb) | ||
67 | { | ||
68 | } | ||
69 | #endif | ||
70 | |||
71 | #endif | ||
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index f9ec1736a116..65633e5a2bc0 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | enum gpd_status { | 14 | enum gpd_status { |
15 | GPD_STATE_ACTIVE = 0, /* PM domain is active */ | 15 | GPD_STATE_ACTIVE = 0, /* PM domain is active */ |
16 | GPD_STATE_WAIT_MASTER, /* PM domain's master is being waited for */ | ||
16 | GPD_STATE_BUSY, /* Something is happening to the PM domain */ | 17 | GPD_STATE_BUSY, /* Something is happening to the PM domain */ |
17 | GPD_STATE_REPEAT, /* Power off in progress, to be repeated */ | 18 | GPD_STATE_REPEAT, /* Power off in progress, to be repeated */ |
18 | GPD_STATE_POWER_OFF, /* PM domain is off */ | 19 | GPD_STATE_POWER_OFF, /* PM domain is off */ |
@@ -25,15 +26,14 @@ struct dev_power_governor { | |||
25 | struct generic_pm_domain { | 26 | struct generic_pm_domain { |
26 | struct dev_pm_domain domain; /* PM domain operations */ | 27 | struct dev_pm_domain domain; /* PM domain operations */ |
27 | struct list_head gpd_list_node; /* Node in the global PM domains list */ | 28 | struct list_head gpd_list_node; /* Node in the global PM domains list */ |
28 | struct list_head sd_node; /* Node in the parent's subdomain list */ | 29 | struct list_head master_links; /* Links with PM domain as a master */ |
29 | struct generic_pm_domain *parent; /* Parent PM domain */ | 30 | struct list_head slave_links; /* Links with PM domain as a slave */ |
30 | struct list_head sd_list; /* List of dubdomains */ | ||
31 | struct list_head dev_list; /* List of devices */ | 31 | struct list_head dev_list; /* List of devices */ |
32 | struct mutex lock; | 32 | struct mutex lock; |
33 | struct dev_power_governor *gov; | 33 | struct dev_power_governor *gov; |
34 | struct work_struct power_off_work; | 34 | struct work_struct power_off_work; |
35 | unsigned int in_progress; /* Number of devices being suspended now */ | 35 | unsigned int in_progress; /* Number of devices being suspended now */ |
36 | unsigned int sd_count; /* Number of subdomains with power "on" */ | 36 | atomic_t sd_count; /* Number of subdomains with power "on" */ |
37 | enum gpd_status status; /* Current state of the domain */ | 37 | enum gpd_status status; /* Current state of the domain */ |
38 | wait_queue_head_t status_wait_queue; | 38 | wait_queue_head_t status_wait_queue; |
39 | struct task_struct *poweroff_task; /* Powering off task */ | 39 | struct task_struct *poweroff_task; /* Powering off task */ |
@@ -42,6 +42,7 @@ struct generic_pm_domain { | |||
42 | unsigned int suspended_count; /* System suspend device counter */ | 42 | unsigned int suspended_count; /* System suspend device counter */ |
43 | unsigned int prepared_count; /* Suspend counter of prepared devices */ | 43 | unsigned int prepared_count; /* Suspend counter of prepared devices */ |
44 | bool suspend_power_off; /* Power status before system suspend */ | 44 | bool suspend_power_off; /* Power status before system suspend */ |
45 | bool dev_irq_safe; /* Device callbacks are IRQ-safe */ | ||
45 | int (*power_off)(struct generic_pm_domain *domain); | 46 | int (*power_off)(struct generic_pm_domain *domain); |
46 | int (*power_on)(struct generic_pm_domain *domain); | 47 | int (*power_on)(struct generic_pm_domain *domain); |
47 | int (*start_device)(struct device *dev); | 48 | int (*start_device)(struct device *dev); |
@@ -54,12 +55,23 @@ static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd) | |||
54 | return container_of(pd, struct generic_pm_domain, domain); | 55 | return container_of(pd, struct generic_pm_domain, domain); |
55 | } | 56 | } |
56 | 57 | ||
57 | struct dev_list_entry { | 58 | struct gpd_link { |
58 | struct list_head node; | 59 | struct generic_pm_domain *master; |
59 | struct device *dev; | 60 | struct list_head master_node; |
61 | struct generic_pm_domain *slave; | ||
62 | struct list_head slave_node; | ||
63 | }; | ||
64 | |||
65 | struct generic_pm_domain_data { | ||
66 | struct pm_domain_data base; | ||
60 | bool need_restore; | 67 | bool need_restore; |
61 | }; | 68 | }; |
62 | 69 | ||
70 | static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd) | ||
71 | { | ||
72 | return container_of(pdd, struct generic_pm_domain_data, base); | ||
73 | } | ||
74 | |||
63 | #ifdef CONFIG_PM_GENERIC_DOMAINS | 75 | #ifdef CONFIG_PM_GENERIC_DOMAINS |
64 | extern int pm_genpd_add_device(struct generic_pm_domain *genpd, | 76 | extern int pm_genpd_add_device(struct generic_pm_domain *genpd, |
65 | struct device *dev); | 77 | struct device *dev); |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index daac05d751b2..70b284024d9e 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h | |||
@@ -251,46 +251,4 @@ static inline void pm_runtime_dont_use_autosuspend(struct device *dev) | |||
251 | __pm_runtime_use_autosuspend(dev, false); | 251 | __pm_runtime_use_autosuspend(dev, false); |
252 | } | 252 | } |
253 | 253 | ||
254 | struct pm_clk_notifier_block { | ||
255 | struct notifier_block nb; | ||
256 | struct dev_pm_domain *pm_domain; | ||
257 | char *con_ids[]; | ||
258 | }; | ||
259 | |||
260 | #ifdef CONFIG_PM_CLK | ||
261 | extern int pm_clk_init(struct device *dev); | ||
262 | extern void pm_clk_destroy(struct device *dev); | ||
263 | extern int pm_clk_add(struct device *dev, const char *con_id); | ||
264 | extern void pm_clk_remove(struct device *dev, const char *con_id); | ||
265 | extern int pm_clk_suspend(struct device *dev); | ||
266 | extern int pm_clk_resume(struct device *dev); | ||
267 | #else | ||
268 | static inline int pm_clk_init(struct device *dev) | ||
269 | { | ||
270 | return -EINVAL; | ||
271 | } | ||
272 | static inline void pm_clk_destroy(struct device *dev) | ||
273 | { | ||
274 | } | ||
275 | static inline int pm_clk_add(struct device *dev, const char *con_id) | ||
276 | { | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | static inline void pm_clk_remove(struct device *dev, const char *con_id) | ||
280 | { | ||
281 | } | ||
282 | #define pm_clk_suspend NULL | ||
283 | #define pm_clk_resume NULL | ||
284 | #endif | ||
285 | |||
286 | #ifdef CONFIG_HAVE_CLK | ||
287 | extern void pm_clk_add_notifier(struct bus_type *bus, | ||
288 | struct pm_clk_notifier_block *clknb); | ||
289 | #else | ||
290 | static inline void pm_clk_add_notifier(struct bus_type *bus, | ||
291 | struct pm_clk_notifier_block *clknb) | ||
292 | { | ||
293 | } | ||
294 | #endif | ||
295 | |||
296 | #endif | 254 | #endif |