aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/main.c')
-rw-r--r--kernel/power/main.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/kernel/power/main.c b/kernel/power/main.c
index e1c413120469..72419a3b1beb 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -30,7 +30,7 @@
30DEFINE_MUTEX(pm_mutex); 30DEFINE_MUTEX(pm_mutex);
31 31
32struct pm_ops *pm_ops; 32struct pm_ops *pm_ops;
33suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM; 33suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
34 34
35/** 35/**
36 * pm_set_ops - Set the global power method table. 36 * pm_set_ops - Set the global power method table.
@@ -41,9 +41,26 @@ void pm_set_ops(struct pm_ops * ops)
41{ 41{
42 mutex_lock(&pm_mutex); 42 mutex_lock(&pm_mutex);
43 pm_ops = ops; 43 pm_ops = ops;
44 if (ops && ops->pm_disk_mode != PM_DISK_INVALID) {
45 pm_disk_mode = ops->pm_disk_mode;
46 } else
47 pm_disk_mode = PM_DISK_SHUTDOWN;
44 mutex_unlock(&pm_mutex); 48 mutex_unlock(&pm_mutex);
45} 49}
46 50
51/**
52 * pm_valid_only_mem - generic memory-only valid callback
53 *
54 * pm_ops drivers that implement mem suspend only and only need
55 * to check for that in their .valid callback can use this instead
56 * of rolling their own .valid callback.
57 */
58int pm_valid_only_mem(suspend_state_t state)
59{
60 return state == PM_SUSPEND_MEM;
61}
62
63
47static inline void pm_finish(suspend_state_t state) 64static inline void pm_finish(suspend_state_t state)
48{ 65{
49 if (pm_ops->finish) 66 if (pm_ops->finish)
@@ -111,13 +128,24 @@ static int suspend_prepare(suspend_state_t state)
111 return error; 128 return error;
112} 129}
113 130
131/* default implementation */
132void __attribute__ ((weak)) arch_suspend_disable_irqs(void)
133{
134 local_irq_disable();
135}
136
137/* default implementation */
138void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
139{
140 local_irq_enable();
141}
114 142
115int suspend_enter(suspend_state_t state) 143int suspend_enter(suspend_state_t state)
116{ 144{
117 int error = 0; 145 int error = 0;
118 unsigned long flags;
119 146
120 local_irq_save(flags); 147 arch_suspend_disable_irqs();
148 BUG_ON(!irqs_disabled());
121 149
122 if ((error = device_power_down(PMSG_SUSPEND))) { 150 if ((error = device_power_down(PMSG_SUSPEND))) {
123 printk(KERN_ERR "Some devices failed to power down\n"); 151 printk(KERN_ERR "Some devices failed to power down\n");
@@ -126,7 +154,8 @@ int suspend_enter(suspend_state_t state)
126 error = pm_ops->enter(state); 154 error = pm_ops->enter(state);
127 device_power_up(); 155 device_power_up();
128 Done: 156 Done:
129 local_irq_restore(flags); 157 arch_suspend_enable_irqs();
158 BUG_ON(irqs_disabled());
130 return error; 159 return error;
131} 160}
132 161
@@ -167,7 +196,10 @@ static inline int valid_state(suspend_state_t state)
167 if (state == PM_SUSPEND_DISK) 196 if (state == PM_SUSPEND_DISK)
168 return 1; 197 return 1;
169 198
170 if (pm_ops && pm_ops->valid && !pm_ops->valid(state)) 199 /* all other states need lowlevel support and need to be
200 * valid to the lowlevel implementation, no valid callback
201 * implies that none are valid. */
202 if (!pm_ops || !pm_ops->valid || !pm_ops->valid(state))
171 return 0; 203 return 0;
172 return 1; 204 return 1;
173} 205}