PM: Allow wakeup events to abort freezing of tasks

If there is a wakeup event during the freezing of tasks, suspend or
hibernation will fail anyway. Since try_to_freeze_tasks() can take
up to 20 seconds to complete or fail, aborting it as soon as a wakeup
event is detected improves the worst case wakeup latency.

Based on a patch from Arve Hjønnevåg.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>

+11 -2
+2
include/linux/suspend.h
··· 308 308 } 309 309 310 310 #define pm_notifier(fn, pri) do { (void)(fn); } while (0) 311 + 312 + static inline bool pm_check_wakeup_events(void) { return true; } 311 313 #endif /* !CONFIG_PM_SLEEP */ 312 314 313 315 extern struct mutex pm_mutex;
+9 -2
kernel/power/process.c
··· 40 40 struct timeval start, end; 41 41 u64 elapsed_csecs64; 42 42 unsigned int elapsed_csecs; 43 + bool wakeup = false; 43 44 44 45 do_gettimeofday(&start); 45 46 ··· 79 78 if (!todo || time_after(jiffies, end_time)) 80 79 break; 81 80 81 + if (!pm_check_wakeup_events()) { 82 + wakeup = true; 83 + break; 84 + } 85 + 82 86 /* 83 87 * We need to retry, but first give the freezing tasks some 84 88 * time to enter the regrigerator. ··· 103 97 * but it cleans up leftover PF_FREEZE requests. 104 98 */ 105 99 printk("\n"); 106 - printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds " 100 + printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds " 107 101 "(%d tasks refusing to freeze, wq_busy=%d):\n", 102 + wakeup ? "aborted" : "failed", 108 103 elapsed_csecs / 100, elapsed_csecs % 100, 109 104 todo - wq_busy, wq_busy); 110 105 ··· 114 107 read_lock(&tasklist_lock); 115 108 do_each_thread(g, p) { 116 109 task_lock(p); 117 - if (freezing(p) && !freezer_should_skip(p)) 110 + if (!wakeup && freezing(p) && !freezer_should_skip(p)) 118 111 sched_show_task(p); 119 112 cancel_freezing(p); 120 113 task_unlock(p);