Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM: Reduce code duplication between main.c and user.c

The SNAPSHOT_S2RAM ioctl code is outdated and it should not duplicate the
suspend code in kernel/power/main.c. Fix that.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Cc: Nigel Cunningham <nigel@nigel.suspend2.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Rafael J. Wysocki and committed by
Linus Torvalds
6c961dfb ccd4b65a

+62 -78
+55 -44
kernel/power/main.c
··· 65 65 66 66 /** 67 67 * suspend_prepare - Do prep work before entering low-power state. 68 - * @state: State we're entering. 69 68 * 70 - * This is common code that is called for each state that we're 71 - * entering. Allocate a console, stop all processes, then make sure 72 - * the platform can enter the requested state. 69 + * This is common code that is called for each state that we're entering. 70 + * Run suspend notifiers, allocate a console and stop all processes. 73 71 */ 74 - 75 - static int suspend_prepare(suspend_state_t state) 72 + static int suspend_prepare(void) 76 73 { 77 74 int error; 78 75 unsigned int free_pages; ··· 88 91 goto Thaw; 89 92 } 90 93 91 - if ((free_pages = global_page_state(NR_FREE_PAGES)) 92 - < FREE_PAGE_NUMBER) { 94 + free_pages = global_page_state(NR_FREE_PAGES); 95 + if (free_pages < FREE_PAGE_NUMBER) { 93 96 pr_debug("PM: free some memory\n"); 94 97 shrink_all_memory(FREE_PAGE_NUMBER - free_pages); 95 98 if (nr_free_pages() < FREE_PAGE_NUMBER) { 96 99 error = -ENOMEM; 97 100 printk(KERN_ERR "PM: No enough memory\n"); 98 - goto Thaw; 99 101 } 100 102 } 101 - 102 - if (pm_ops->set_target) { 103 - error = pm_ops->set_target(state); 104 - if (error) 105 - goto Thaw; 106 - } 107 - suspend_console(); 108 - error = device_suspend(PMSG_SUSPEND); 109 - if (error) { 110 - printk(KERN_ERR "Some devices failed to suspend\n"); 111 - goto Resume_console; 112 - } 113 - if (pm_ops->prepare) { 114 - if ((error = pm_ops->prepare(state))) 115 - goto Resume_devices; 116 - } 117 - 118 - error = disable_nonboot_cpus(); 119 103 if (!error) 120 104 return 0; 121 105 122 - enable_nonboot_cpus(); 123 - pm_finish(state); 124 - Resume_devices: 125 - device_resume(); 126 - Resume_console: 127 - resume_console(); 128 106 Thaw: 129 107 thaw_processes(); 130 108 pm_restore_console(); ··· 120 148 local_irq_enable(); 121 149 } 122 150 151 + /** 152 + * suspend_enter - enter the desired system sleep state. 153 + * @state: state to enter 154 + * 155 + * This function should be called after devices have been suspended. 156 + */ 123 157 int suspend_enter(suspend_state_t state) 124 158 { 125 159 int error = 0; ··· 145 167 return error; 146 168 } 147 169 170 + /** 171 + * suspend_devices_and_enter - suspend devices and enter the desired system sleep 172 + * state. 173 + * @state: state to enter 174 + */ 175 + int suspend_devices_and_enter(suspend_state_t state) 176 + { 177 + int error; 178 + 179 + if (!pm_ops) 180 + return -ENOSYS; 181 + 182 + if (pm_ops->set_target) { 183 + error = pm_ops->set_target(state); 184 + if (error) 185 + return error; 186 + } 187 + suspend_console(); 188 + error = device_suspend(PMSG_SUSPEND); 189 + if (error) { 190 + printk(KERN_ERR "Some devices failed to suspend\n"); 191 + goto Resume_console; 192 + } 193 + if (pm_ops->prepare) { 194 + error = pm_ops->prepare(state); 195 + if (error) 196 + goto Resume_devices; 197 + } 198 + error = disable_nonboot_cpus(); 199 + if (!error) 200 + suspend_enter(state); 201 + 202 + enable_nonboot_cpus(); 203 + pm_finish(state); 204 + Resume_devices: 205 + device_resume(); 206 + Resume_console: 207 + resume_console(); 208 + return error; 209 + } 148 210 149 211 /** 150 212 * suspend_finish - Do final work before exiting suspend sequence. 151 - * @state: State we're coming out of. 152 213 * 153 214 * Call platform code to clean up, restart processes, and free the 154 215 * console that we've allocated. This is not called for suspend-to-disk. 155 216 */ 156 - 157 - static void suspend_finish(suspend_state_t state) 217 + static void suspend_finish(void) 158 218 { 159 - enable_nonboot_cpus(); 160 - pm_finish(state); 161 - device_resume(); 162 - resume_console(); 163 219 thaw_processes(); 164 220 pm_restore_console(); 165 221 pm_notifier_call_chain(PM_POST_SUSPEND); ··· 228 216 * Then, do the setup for suspend, enter the state, and cleaup (after 229 217 * we've woken up). 230 218 */ 231 - 232 219 static int enter_state(suspend_state_t state) 233 220 { 234 221 int error; ··· 238 227 return -EBUSY; 239 228 240 229 pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); 241 - if ((error = suspend_prepare(state))) 230 + if ((error = suspend_prepare())) 242 231 goto Unlock; 243 232 244 233 pr_debug("PM: Entering %s sleep\n", pm_states[state]); 245 - error = suspend_enter(state); 234 + error = suspend_devices_and_enter(state); 246 235 247 236 pr_debug("PM: Finishing wakeup.\n"); 248 - suspend_finish(state); 237 + suspend_finish(); 249 238 Unlock: 250 239 mutex_unlock(&pm_mutex); 251 240 return error;
+2 -1
kernel/power/power.h
··· 170 170 extern int swsusp_read(unsigned int *flags_p); 171 171 extern int swsusp_write(unsigned int flags); 172 172 extern void swsusp_close(void); 173 - extern int suspend_enter(suspend_state_t state); 174 173 175 174 struct timeval; 176 175 /* kernel/power/swsusp.c */ ··· 177 178 unsigned int, char *); 178 179 179 180 /* kernel/power/main.c */ 181 + extern int suspend_enter(suspend_state_t state); 182 + extern int suspend_devices_and_enter(suspend_state_t state); 180 183 extern struct blocking_notifier_head pm_chain_head; 181 184 182 185 static inline int pm_notifier_call_chain(unsigned long val)
+5 -33
kernel/power/user.c
··· 255 255 break; 256 256 257 257 case SNAPSHOT_S2RAM: 258 - if (!pm_ops) { 259 - error = -ENOSYS; 260 - break; 261 - } 262 - 263 258 if (!data->frozen) { 264 259 error = -EPERM; 265 260 break; 266 261 } 267 - 268 262 if (!mutex_trylock(&pm_mutex)) { 269 263 error = -EBUSY; 270 264 break; 271 265 } 272 - 273 - if (pm_ops->prepare) { 274 - error = pm_ops->prepare(PM_SUSPEND_MEM); 275 - if (error) 276 - goto OutS3; 277 - } 278 - 279 - /* Put devices to sleep */ 280 - suspend_console(); 281 - error = device_suspend(PMSG_SUSPEND); 282 - if (error) { 283 - printk(KERN_ERR "Failed to suspend some devices.\n"); 284 - } else { 285 - error = disable_nonboot_cpus(); 286 - if (!error) { 287 - /* Enter S3, system is already frozen */ 288 - suspend_enter(PM_SUSPEND_MEM); 289 - enable_nonboot_cpus(); 290 - } 291 - /* Wake up devices */ 292 - device_resume(); 293 - } 294 - resume_console(); 295 - if (pm_ops->finish) 296 - pm_ops->finish(PM_SUSPEND_MEM); 297 - 298 - OutS3: 266 + /* 267 + * Tasks are frozen and the notifiers have been called with 268 + * PM_HIBERNATION_PREPARE 269 + */ 270 + error = suspend_devices_and_enter(PM_SUSPEND_MEM); 299 271 mutex_unlock(&pm_mutex); 300 272 break; 301 273