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 24 #include "power.h" 25 26 /*This is just an arbitrary number */ 27 #define FREE_PAGE_NUMBER (100) 28 29 DEFINE_MUTEX(pm_mutex); 30 31 struct pm_ops *pm_ops; 32 suspend_disk_method_t pm_disk_mode = PM_DISK_PLATFORM; 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 /** 48 * suspend_prepare - Do prep work before entering low-power state. 49 * @state: State we're entering. 50 * 51 * This is common code that is called for each state that we're 52 * entering. Allocate a console, stop all processes, then make sure 53 * the platform can enter the requested state. 54 */ 55 56 static int suspend_prepare(suspend_state_t state) 57 { 58 int error; 59 unsigned int free_pages; 60 61 if (!pm_ops || !pm_ops->enter) 62 return -EPERM; 63 64 pm_prepare_console(); 65 66 error = disable_nonboot_cpus(); 67 if (error) 68 goto Enable_cpu; 69 70 if (freeze_processes()) { 71 error = -EAGAIN; 72 goto Thaw; 73 } 74 75 if ((free_pages = nr_free_pages()) < FREE_PAGE_NUMBER) { 76 pr_debug("PM: free some memory\n"); 77 shrink_all_memory(FREE_PAGE_NUMBER - free_pages); 78 if (nr_free_pages() < FREE_PAGE_NUMBER) { 79 error = -ENOMEM; 80 printk(KERN_ERR "PM: No enough memory\n"); 81 goto Thaw; 82 } 83 } 84 85 if (pm_ops->prepare) { 86 if ((error = pm_ops->prepare(state))) 87 goto Thaw; 88 } 89 90 suspend_console(); 91 if ((error = device_suspend(PMSG_SUSPEND))) { 92 printk(KERN_ERR "Some devices failed to suspend\n"); 93 goto Finish; 94 } 95 return 0; 96 Finish: 97 if (pm_ops->finish) 98 pm_ops->finish(state); 99 Thaw: 100 thaw_processes(); 101 Enable_cpu: 102 enable_nonboot_cpus(); 103 pm_restore_console(); 104 return error; 105 } 106 107 108 int suspend_enter(suspend_state_t state) 109 { 110 int error = 0; 111 unsigned long flags; 112 113 local_irq_save(flags); 114 115 if ((error = device_power_down(PMSG_SUSPEND))) { 116 printk(KERN_ERR "Some devices failed to power down\n"); 117 goto Done; 118 } 119 error = pm_ops->enter(state); 120 device_power_up(); 121 Done: 122 local_irq_restore(flags); 123 return error; 124 } 125 126 127 /** 128 * suspend_finish - Do final work before exiting suspend sequence. 129 * @state: State we're coming out of. 130 * 131 * Call platform code to clean up, restart processes, and free the 132 * console that we've allocated. This is not called for suspend-to-disk. 133 */ 134 135 static void suspend_finish(suspend_state_t state) 136 { 137 device_resume(); 138 resume_console(); 139 thaw_processes(); 140 enable_nonboot_cpus(); 141 if (pm_ops && pm_ops->finish) 142 pm_ops->finish(state); 143 pm_restore_console(); 144 } 145 146 147 148 149 static const char * const pm_states[PM_SUSPEND_MAX] = { 150 [PM_SUSPEND_STANDBY] = "standby", 151 [PM_SUSPEND_MEM] = "mem", 152 #ifdef CONFIG_SOFTWARE_SUSPEND 153 [PM_SUSPEND_DISK] = "disk", 154 #endif 155 }; 156 157 static inline int valid_state(suspend_state_t state) 158 { 159 /* Suspend-to-disk does not really need low-level support. 160 * It can work with reboot if needed. */ 161 if (state == PM_SUSPEND_DISK) 162 return 1; 163 164 if (pm_ops && pm_ops->valid && !pm_ops->valid(state)) 165 return 0; 166 return 1; 167 } 168 169 170 /** 171 * enter_state - Do common work of entering low-power state. 172 * @state: pm_state structure for state we're entering. 173 * 174 * Make sure we're the only ones trying to enter a sleep state. Fail 175 * if someone has beat us to it, since we don't want anything weird to 176 * happen when we wake up. 177 * Then, do the setup for suspend, enter the state, and cleaup (after 178 * we've woken up). 179 */ 180 181 static int enter_state(suspend_state_t state) 182 { 183 int error; 184 185 if (!valid_state(state)) 186 return -ENODEV; 187 if (!mutex_trylock(&pm_mutex)) 188 return -EBUSY; 189 190 if (state == PM_SUSPEND_DISK) { 191 error = pm_suspend_disk(); 192 goto Unlock; 193 } 194 195 pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); 196 if ((error = suspend_prepare(state))) 197 goto Unlock; 198 199 pr_debug("PM: Entering %s sleep\n", pm_states[state]); 200 error = suspend_enter(state); 201 202 pr_debug("PM: Finishing wakeup.\n"); 203 suspend_finish(state); 204 Unlock: 205 mutex_unlock(&pm_mutex); 206 return error; 207 } 208 209 /* 210 * This is main interface to the outside world. It needs to be 211 * called from process context. 212 */ 213 int software_suspend(void) 214 { 215 return enter_state(PM_SUSPEND_DISK); 216 } 217 218 219 /** 220 * pm_suspend - Externally visible function for suspending system. 221 * @state: Enumarted value of state to enter. 222 * 223 * Determine whether or not value is within range, get state 224 * structure, and enter (above). 225 */ 226 227 int pm_suspend(suspend_state_t state) 228 { 229 if (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX) 230 return enter_state(state); 231 return -EINVAL; 232 } 233 234 EXPORT_SYMBOL(pm_suspend); 235 236 decl_subsys(power,NULL,NULL); 237 238 239 /** 240 * state - control system power state. 241 * 242 * show() returns what states are supported, which is hard-coded to 243 * 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and 244 * 'disk' (Suspend-to-Disk). 245 * 246 * store() accepts one of those strings, translates it into the 247 * proper enumerated value, and initiates a suspend transition. 248 */ 249 250 static ssize_t state_show(struct subsystem * subsys, char * buf) 251 { 252 int i; 253 char * s = buf; 254 255 for (i = 0; i < PM_SUSPEND_MAX; i++) { 256 if (pm_states[i] && valid_state(i)) 257 s += sprintf(s,"%s ", pm_states[i]); 258 } 259 s += sprintf(s,"\n"); 260 return (s - buf); 261 } 262 263 static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n) 264 { 265 suspend_state_t state = PM_SUSPEND_STANDBY; 266 const char * const *s; 267 char *p; 268 int error; 269 int len; 270 271 p = memchr(buf, '\n', n); 272 len = p ? p - buf : n; 273 274 for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { 275 if (*s && !strncmp(buf, *s, len)) 276 break; 277 } 278 if (state < PM_SUSPEND_MAX && *s) 279 error = enter_state(state); 280 else 281 error = -EINVAL; 282 return error ? error : n; 283 } 284 285 power_attr(state); 286 287 #ifdef CONFIG_PM_TRACE 288 int pm_trace_enabled; 289 290 static ssize_t pm_trace_show(struct subsystem * subsys, char * buf) 291 { 292 return sprintf(buf, "%d\n", pm_trace_enabled); 293 } 294 295 static ssize_t 296 pm_trace_store(struct subsystem * subsys, const char * buf, size_t n) 297 { 298 int val; 299 300 if (sscanf(buf, "%d", &val) == 1) { 301 pm_trace_enabled = !!val; 302 return n; 303 } 304 return -EINVAL; 305 } 306 307 power_attr(pm_trace); 308 309 static struct attribute * g[] = { 310 &state_attr.attr, 311 &pm_trace_attr.attr, 312 NULL, 313 }; 314 #else 315 static struct attribute * g[] = { 316 &state_attr.attr, 317 NULL, 318 }; 319 #endif /* CONFIG_PM_TRACE */ 320 321 static struct attribute_group attr_group = { 322 .attrs = g, 323 }; 324 325 326 static int __init pm_init(void) 327 { 328 int error = subsystem_register(&power_subsys); 329 if (!error) 330 error = sysfs_create_group(&power_subsys.kset.kobj,&attr_group); 331 return error; 332 } 333 334 core_initcall(pm_init); 335