diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 12:24:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 12:24:44 -0400 |
commit | fc82e1d59a24cbac01c49d4eb3b28d6abc26a5f4 (patch) | |
tree | 5e01479d69e69dbbe483044b39afd2aa99d4f2b2 /drivers/base/syscore.c | |
parent | 48d5f6731837f0ec9a0e19ca763aa17d58385a98 (diff) | |
parent | bea3864fb627d110933cfb8babe048b63c4fc76e (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6: (21 commits)
PM / Hibernate: Reduce autotuned default image size
PM / Core: Introduce struct syscore_ops for core subsystems PM
PM QoS: Make pm_qos settings readable
PM / OPP: opp_find_freq_exact() documentation fix
PM: Documentation/power/states.txt: fix repetition
PM: Make system-wide PM and runtime PM treat subsystems consistently
PM: Simplify kernel/power/Kconfig
PM: Add support for device power domains
PM: Drop pm_flags that is not necessary
PM: Allow pm_runtime_suspend() to succeed during system suspend
PM: Clean up PM_TRACE dependencies and drop unnecessary Kconfig option
PM: Remove CONFIG_PM_OPS
PM: Reorder power management Kconfig options
PM: Make CONFIG_PM depend on (CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME)
PM / ACPI: Remove references to pm_flags from bus.c
PM: Do not create wakeup sysfs files for devices that cannot wake up
USB / Hub: Do not call device_set_wakeup_capable() under spinlock
PM: Use appropriate printk() priority level in trace.c
PM / Wakeup: Don't update events_check_enabled in pm_get_wakeup_count()
PM / Wakeup: Make pm_save_wakeup_count() work as documented
...
Diffstat (limited to 'drivers/base/syscore.c')
-rw-r--r-- | drivers/base/syscore.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c new file mode 100644 index 000000000000..90af2943f9e4 --- /dev/null +++ b/drivers/base/syscore.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * syscore.c - Execution of system core operations. | ||
3 | * | ||
4 | * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
5 | * | ||
6 | * This file is released under the GPLv2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/syscore_ops.h> | ||
10 | #include <linux/mutex.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | static LIST_HEAD(syscore_ops_list); | ||
14 | static DEFINE_MUTEX(syscore_ops_lock); | ||
15 | |||
16 | /** | ||
17 | * register_syscore_ops - Register a set of system core operations. | ||
18 | * @ops: System core operations to register. | ||
19 | */ | ||
20 | void register_syscore_ops(struct syscore_ops *ops) | ||
21 | { | ||
22 | mutex_lock(&syscore_ops_lock); | ||
23 | list_add_tail(&ops->node, &syscore_ops_list); | ||
24 | mutex_unlock(&syscore_ops_lock); | ||
25 | } | ||
26 | EXPORT_SYMBOL_GPL(register_syscore_ops); | ||
27 | |||
28 | /** | ||
29 | * unregister_syscore_ops - Unregister a set of system core operations. | ||
30 | * @ops: System core operations to unregister. | ||
31 | */ | ||
32 | void unregister_syscore_ops(struct syscore_ops *ops) | ||
33 | { | ||
34 | mutex_lock(&syscore_ops_lock); | ||
35 | list_del(&ops->node); | ||
36 | mutex_unlock(&syscore_ops_lock); | ||
37 | } | ||
38 | EXPORT_SYMBOL_GPL(unregister_syscore_ops); | ||
39 | |||
40 | #ifdef CONFIG_PM_SLEEP | ||
41 | /** | ||
42 | * syscore_suspend - Execute all the registered system core suspend callbacks. | ||
43 | * | ||
44 | * This function is executed with one CPU on-line and disabled interrupts. | ||
45 | */ | ||
46 | int syscore_suspend(void) | ||
47 | { | ||
48 | struct syscore_ops *ops; | ||
49 | int ret = 0; | ||
50 | |||
51 | WARN_ONCE(!irqs_disabled(), | ||
52 | "Interrupts enabled before system core suspend.\n"); | ||
53 | |||
54 | list_for_each_entry_reverse(ops, &syscore_ops_list, node) | ||
55 | if (ops->suspend) { | ||
56 | if (initcall_debug) | ||
57 | pr_info("PM: Calling %pF\n", ops->suspend); | ||
58 | ret = ops->suspend(); | ||
59 | if (ret) | ||
60 | goto err_out; | ||
61 | WARN_ONCE(!irqs_disabled(), | ||
62 | "Interrupts enabled after %pF\n", ops->suspend); | ||
63 | } | ||
64 | |||
65 | return 0; | ||
66 | |||
67 | err_out: | ||
68 | pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend); | ||
69 | |||
70 | list_for_each_entry_continue(ops, &syscore_ops_list, node) | ||
71 | if (ops->resume) | ||
72 | ops->resume(); | ||
73 | |||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * syscore_resume - Execute all the registered system core resume callbacks. | ||
79 | * | ||
80 | * This function is executed with one CPU on-line and disabled interrupts. | ||
81 | */ | ||
82 | void syscore_resume(void) | ||
83 | { | ||
84 | struct syscore_ops *ops; | ||
85 | |||
86 | WARN_ONCE(!irqs_disabled(), | ||
87 | "Interrupts enabled before system core resume.\n"); | ||
88 | |||
89 | list_for_each_entry(ops, &syscore_ops_list, node) | ||
90 | if (ops->resume) { | ||
91 | if (initcall_debug) | ||
92 | pr_info("PM: Calling %pF\n", ops->resume); | ||
93 | ops->resume(); | ||
94 | WARN_ONCE(!irqs_disabled(), | ||
95 | "Interrupts enabled after %pF\n", ops->resume); | ||
96 | } | ||
97 | } | ||
98 | #endif /* CONFIG_PM_SLEEP */ | ||
99 | |||
100 | /** | ||
101 | * syscore_shutdown - Execute all the registered system core shutdown callbacks. | ||
102 | */ | ||
103 | void syscore_shutdown(void) | ||
104 | { | ||
105 | struct syscore_ops *ops; | ||
106 | |||
107 | mutex_lock(&syscore_ops_lock); | ||
108 | |||
109 | list_for_each_entry_reverse(ops, &syscore_ops_list, node) | ||
110 | if (ops->shutdown) { | ||
111 | if (initcall_debug) | ||
112 | pr_info("PM: Calling %pF\n", ops->shutdown); | ||
113 | ops->shutdown(); | ||
114 | } | ||
115 | |||
116 | mutex_unlock(&syscore_ops_lock); | ||
117 | } | ||