1 /* 2 * kernel/power/main.c - PM subsystem core functionality. 3 * 4 * Copyright (c) 2003 Patrick Mochel 5 * Copyright (c) 2003 Open Source Development Lab 6 * 7 * This file is released under the GPLv2 8 * 9 */ 10 11 #include <linux/module.h> 12 #include <linux/suspend.h> 13 #include <linux/kobject.h> 14 #include <linux/string.h> 15 #include <linux/delay.h> 16 #include <linux/errno.h> 17 #include <linux/init.h> 18 #include <linux/pm.h> 19 #include <linux/console.h> 20 #include <linux/cpu.h> 21 #include <linux/resume-trace.h> 22 #include <linux/freezer.h> 23 #include <linux/vmstat.h> 24 25 #include "power.h" 26 27 /*This is just an arbitrary number */ 28 #define FREE_PAGE_NUMBER (100) 29 30 DEFINE_MUTEX(pm_mutex); 31 32 struct pm_ops *pm_ops; 33 34 /** 35 * pm_set_ops - Set the global power method table. 36 * @ops: Pointer to ops structure. 37 */ 38 39 void pm_set_ops(struct pm_ops * ops) 40 { 41 mutex_lock(&pm_mutex); 42 pm_ops = ops; 43 mutex_unlock(&pm_mutex); 44 } 45 46 /** 47 * pm_valid_only_mem - generic memory-only valid callback 48 * 49 * pm_ops drivers that implement mem suspend only and only need 50 * to check for that in their .valid callback can use this instead 51 * of rolling their own .valid callback. 52 */ 53 int pm_valid_only_mem(suspend_state_t state) 54 { 55 return state == PM_SUSPEND_MEM; 56 } 57 58 59 static inline void pm_finish(suspend_state_t state) 60 { 61 if (pm_ops->finish) 62 pm_ops->finish(state); 63 } 64 65 /** 66 * suspend_prepare - Do prep work before entering low-power state. 67 * @state: State we're entering. 68 * 69 * This is common code that is called for each state that we're 70 * entering. Allocate a console, stop all processes, then make sure 71 * the platform can enter the requested state. 72 */ 73 74 static int suspend_prepare(suspend_state_t state) 75 { 76 int error; 77 unsigned int free_pages; 78 79 if (!pm_ops || !pm_ops->enter) 80 return -EPERM; 81 82 pm_prepare_console(); 83 84 if (freeze_processes()) { 85 error = -EAGAIN; 86 goto Thaw; 87 } 88 89 if ((free_pages = global_page_state(NR_FREE_PAGES)) 90 < FREE_PAGE_NUMBER) { 91 pr_debug("PM: free some memory\n"); 92 shrink_all_memory(FREE_PAGE_NUMBER - free_pages); 93 if (nr_free_pages() < FREE_PAGE_NUMBER) { 94 error = -ENOMEM; 95 printk(KERN_ERR "PM: No enough memory\n"); 96 goto Thaw; 97 } 98 } 99 100 suspend_console(); 101 error = device_suspend(PMSG_SUSPEND); 102 if (error) { 103 printk(KERN_ERR "Some devices failed to suspend\n"); 104 goto Resume_console; 105 } 106 if (pm_ops->prepare) { 107 if ((error = pm_ops->prepare(state))) 108 goto Resume_devices; 109 } 110 111 error = disable_nonboot_cpus(); 112 if (!error) 113 return 0; 114 115 enable_nonboot_cpus(); 116 pm_finish(state); 117 Resume_devices: 118 device_resume(); 119 Resume_console: 120 resume_console(); 121 Thaw: 122 thaw_processes(); 123 pm_restore_console(); 124 return error; 125 } 126 127 /* default implementation */ 128 void __attribute__ ((weak)) arch_suspend_disable_irqs(void) 129 { 130 local_irq_disable(); 131 } 132 133 /* default implementation */ 134 void __attribute__ ((weak)) arch_suspend_enable_irqs(void) 135 { 136 local_irq_enable(); 137 } 138 139 int suspend_enter(suspend_state_t state) 140 { 141 int error = 0; 142 143 arch_suspend_disable_irqs(); 144 BUG_ON(!irqs_disabled()); 145 146 if ((error = device_power_down(PMSG_SUSPEND))) { 147 printk(KERN_ERR "Some devices failed to power down\n"); 148 goto Done; 149 } 150 error = pm_ops->enter(state); 151 device_power_up(); 152 Done: 153 arch_suspend_enable_irqs(); 154 BUG_ON(irqs_disabled()); 155 return error; 156 } 157 158 159 /** 160 * suspend_finish - Do final work before exiting suspend sequence. 161 * @state: State we're coming out of. 162 * 163 * Call platform code to clean up, restart processes, and free the 164 * console that we've allocated. This is not called for suspend-to-disk. 165 */ 166 167 static void suspend_finish(suspend_state_t state) 168 { 169 enable_nonboot_cpus(); 170 pm_finish(state); 171 device_resume(); 172 resume_console(); 173 thaw_processes(); 174 pm_restore_console(); 175 } 176 177 178 179 180 static const char * const pm_states[PM_SUSPEND_MAX] = { 181 [PM_SUSPEND_STANDBY] = "standby", 182 [PM_SUSPEND_MEM] = "mem", 183 }; 184 185 static inline int valid_state(suspend_state_t state) 186 { 187 /* All states need lowlevel support and need to be valid 188 * to the lowlevel implementation, no valid callback 189 * implies that none are valid. */ 190 if (!pm_ops || !pm_ops->valid || !pm_ops->valid(state)) 191 return 0; 192 return 1; 193 } 194 195 196 /** 197 * enter_state - Do common work of entering low-power state. 198 * @state: pm_state structure for state we're entering. 199 * 200 * Make sure we're the only ones trying to enter a sleep state. Fail 201 * if someone has beat us to it, since we don't want anything weird to 202 * happen when we wake up. 203 * Then, do the setup for suspend, enter the state, and cleaup (after 204 * we've woken up). 205 */ 206 207 static int enter_state(suspend_state_t state) 208 { 209 int error; 210 211 if (!valid_state(state)) 212 return -ENODEV; 213 if (!mutex_trylock(&pm_mutex)) 214 return -EBUSY; 215 216 pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); 217 if ((error = suspend_prepare(state))) 218 goto Unlock; 219 220 pr_debug("PM: Entering %s sleep\n", pm_states[state]); 221 error = suspend_enter(state); 222 223 pr_debug("PM: Finishing wakeup.\n"); 224 suspend_finish(state); 225 Unlock: 226 mutex_unlock(&pm_mutex); 227 return error; 228 } 229 230 231 /** 232 * pm_suspend - Externally visible function for suspending system. 233 * @state: Enumerated value of state to enter. 234 * 235 * Determine whether or not value is within range, get state 236 * structure, and enter (above). 237 */ 238 239 int pm_suspend(suspend_state_t state) 240 { 241 if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX) 242 return enter_state(state); 243 return -EINVAL; 244 } 245 246 EXPORT_SYMBOL(pm_suspend); 247 248 decl_subsys(power,NULL,NULL); 249 250 251 /** 252 * state - control system power state. 253 * 254 * show() returns what states are supported, which is hard-coded to 255 * 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and 256 * 'disk' (Suspend-to-Disk). 257 * 258 * store() accepts one of those strings, translates it into the 259 * proper enumerated value, and initiates a suspend transition. 260 */ 261 262 static ssize_t state_show(struct kset *kset, char *buf) 263 { 264 int i; 265 char * s = buf; 266 267 for (i = 0; i < PM_SUSPEND_MAX; i++) { 268 if (pm_states[i] && valid_state(i)) 269 s += sprintf(s,"%s ", pm_states[i]); 270 } 271 #ifdef CONFIG_SOFTWARE_SUSPEND 272 s += sprintf(s, "%s\n", "disk"); 273 #else 274 if (s != buf) 275 /* convert the last space to a newline */ 276 *(s-1) = '\n'; 277 #endif 278 return (s - buf); 279 } 280 281 static ssize_t state_store(struct kset *kset, const char *buf, size_t n) 282 { 283 suspend_state_t state = PM_SUSPEND_STANDBY; 284 const char * const *s; 285 char *p; 286 int error; 287 int len; 288 289 p = memchr(buf, '\n', n); 290 len = p ? p - buf : n; 291 292 /* First, check if we are requested to hibernate */ 293 if (len == 4 && !strncmp(buf, "disk", len)) { 294 error = hibernate(); 295 return error ? error : n; 296 } 297 298 for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { 299 if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) 300 break; 301 } 302 if (state < PM_SUSPEND_MAX && *s) 303 error = enter_state(state); 304 else 305 error = -EINVAL; 306 return error ? error : n; 307 } 308 309 power_attr(state); 310 311 #ifdef CONFIG_PM_TRACE 312 int pm_trace_enabled; 313 314 static ssize_t pm_trace_show(struct kset *kset, char *buf) 315 { 316 return sprintf(buf, "%d\n", pm_trace_enabled); 317 } 318 319 static ssize_t 320 pm_trace_store(struct kset *kset, const char *buf, size_t n) 321 { 322 int val; 323 324 if (sscanf(buf, "%d", &val) == 1) { 325 pm_trace_enabled = !!val; 326 return n; 327 } 328 return -EINVAL; 329 } 330 331 power_attr(pm_trace); 332 333 static struct attribute * g[] = { 334 &state_attr.attr, 335 &pm_trace_attr.attr, 336 NULL, 337 }; 338 #else 339 static struct attribute * g[] = { 340 &state_attr.attr, 341 NULL, 342 }; 343 #endif /* CONFIG_PM_TRACE */ 344 345 static struct attribute_group attr_group = { 346 .attrs = g, 347 }; 348 349 350 static int __init pm_init(void) 351 { 352 int error = subsystem_register(&power_subsys); 353 if (!error) 354 error = sysfs_create_group(&power_subsys.kobj,&attr_group); 355 return error; 356 } 357 358 core_initcall(pm_init); 359