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