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

Merge tag 'pm-fixes-for-3.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Power management fixes for 3.3-rc3

Three power management regression fixes, one for a recent regression introcuded
by the freezer changes during the 3.3 merge window and two for regressions
in cpuidle (resulting from PM QoS changes) and in the hibernate user space
interface, both introduced during the 3.2 development cycle.

They include:

* Two hibernate (s2disk) regression fixes from Srivatsa S. Bhat (for
regressions introduced during the 3.3 merge window and during the 3.2
development cycle).

* A cpuidle fix from Venki Pallipadi for a regression resulting from PM QoS
changes during the 3.2 development cycle causing cpuidle to work incorrectly
for CONFIG_PM unset.

* tag 'pm-fixes-for-3.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM / QoS: CPU C-state breakage with PM Qos change
PM / Freezer: Thaw only kernel threads if freezing of kernel threads fails
PM / Hibernate: Thaw kernel threads in SNAPSHOT_CREATE_IMAGE ioctl path

+44 -7
+13 -1
include/linux/pm_qos.h
··· 110 110 { return; } 111 111 112 112 static inline int pm_qos_request(int pm_qos_class) 113 - { return 0; } 113 + { 114 + switch (pm_qos_class) { 115 + case PM_QOS_CPU_DMA_LATENCY: 116 + return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; 117 + case PM_QOS_NETWORK_LATENCY: 118 + return PM_QOS_NETWORK_LAT_DEFAULT_VALUE; 119 + case PM_QOS_NETWORK_THROUGHPUT: 120 + return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE; 121 + default: 122 + return PM_QOS_DEFAULT_VALUE; 123 + } 124 + } 125 + 114 126 static inline int pm_qos_add_notifier(int pm_qos_class, 115 127 struct notifier_block *notifier) 116 128 { return 0; }
+22 -2
kernel/power/power.h
··· 231 231 #ifdef CONFIG_SUSPEND_FREEZER 232 232 static inline int suspend_freeze_processes(void) 233 233 { 234 - int error = freeze_processes(); 235 - return error ? : freeze_kernel_threads(); 234 + int error; 235 + 236 + error = freeze_processes(); 237 + 238 + /* 239 + * freeze_processes() automatically thaws every task if freezing 240 + * fails. So we need not do anything extra upon error. 241 + */ 242 + if (error) 243 + goto Finish; 244 + 245 + error = freeze_kernel_threads(); 246 + 247 + /* 248 + * freeze_kernel_threads() thaws only kernel threads upon freezing 249 + * failure. So we have to thaw the userspace tasks ourselves. 250 + */ 251 + if (error) 252 + thaw_processes(); 253 + 254 + Finish: 255 + return error; 236 256 } 237 257 238 258 static inline void suspend_thaw_processes(void)
+5 -2
kernel/power/process.c
··· 143 143 /** 144 144 * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. 145 145 * 146 - * On success, returns 0. On failure, -errno and system is fully thawed. 146 + * On success, returns 0. On failure, -errno and only the kernel threads are 147 + * thawed, so as to give a chance to the caller to do additional cleanups 148 + * (if any) before thawing the userspace tasks. So, it is the responsibility 149 + * of the caller to thaw the userspace tasks, when the time is right. 147 150 */ 148 151 int freeze_kernel_threads(void) 149 152 { ··· 162 159 BUG_ON(in_atomic()); 163 160 164 161 if (error) 165 - thaw_processes(); 162 + thaw_kernel_threads(); 166 163 return error; 167 164 } 168 165
+4 -2
kernel/power/user.c
··· 249 249 } 250 250 pm_restore_gfp_mask(); 251 251 error = hibernation_snapshot(data->platform_support); 252 - if (!error) { 252 + if (error) { 253 + thaw_kernel_threads(); 254 + } else { 253 255 error = put_user(in_suspend, (int __user *)arg); 254 256 if (!error && !freezer_test_done) 255 257 data->ready = 1; 256 258 if (freezer_test_done) { 257 259 freezer_test_done = false; 258 - thaw_processes(); 260 + thaw_kernel_threads(); 259 261 } 260 262 } 261 263 break;