diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-02 15:21:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-02 15:21:32 -0400 |
commit | 1fe0135b9e135ecef4eb2144027a74c3de6bf874 (patch) | |
tree | 995bd5805ac6228a85d58eba69d6eeb0a54a5ead /kernel | |
parent | 64ccccf8525fee499625b517c0faadf784c79e93 (diff) | |
parent | 2b44c4db2e2f1765d35163a861d301038e0c8a75 (diff) |
Merge tag 'pm+acpi-3.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki:
- Revert two cpuidle commits added during the 3.8 development cycle
that turn out to have introduced a significant performance regression
as requested by Jeremy Eder.
- The recent patches that made the freezer less heavy-weight introduced
a regression causing user-space-driven hibernation using the ioctl()
interface to block indefinitely when the hibernate process executes
try_to_freeze(). Fix from Colin Cross addresses this by adding a
process flag to mark the hibernate/suspend process to inform the
freezer that that process should be ignored.
- One of the recent cpufreq reverts uncovered a problem in the core
causing the cpufreq driver module refcount to become negative after a
system suspend-resume cycle. Fix from Rafael J Wysocki.
- The evaluation of the ACPI battery _BIX method has never worked
correctly, because the commit that added support for it forgot to
take the "Revision" field in the return package into account. As a
result, the reading of battery info doesn't work at all on some
systems, which is addressed by a fix from Lan Tianyu.
* tag 'pm+acpi-3.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
freezer: set PF_SUSPEND_TASK flag on tasks that call freeze_processes
ACPI / battery: Fix parsing _BIX return value
cpufreq: Fix cpufreq driver module refcount balance after suspend/resume
Revert "cpuidle: Quickly notice prediction failure for repeat mode"
Revert "cpuidle: Quickly notice prediction failure in general case"
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/freezer.c | 2 | ||||
-rw-r--r-- | kernel/power/process.c | 11 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 9 |
3 files changed, 14 insertions, 8 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c index 8b2afc1c9df0..b462fa197517 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c | |||
@@ -33,7 +33,7 @@ static DEFINE_SPINLOCK(freezer_lock); | |||
33 | */ | 33 | */ |
34 | bool freezing_slow_path(struct task_struct *p) | 34 | bool freezing_slow_path(struct task_struct *p) |
35 | { | 35 | { |
36 | if (p->flags & PF_NOFREEZE) | 36 | if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK)) |
37 | return false; | 37 | return false; |
38 | 38 | ||
39 | if (pm_nosig_freezing || cgroup_freezing(p)) | 39 | if (pm_nosig_freezing || cgroup_freezing(p)) |
diff --git a/kernel/power/process.c b/kernel/power/process.c index fc0df8486449..06ec8869dbf1 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -109,6 +109,8 @@ static int try_to_freeze_tasks(bool user_only) | |||
109 | 109 | ||
110 | /** | 110 | /** |
111 | * freeze_processes - Signal user space processes to enter the refrigerator. | 111 | * freeze_processes - Signal user space processes to enter the refrigerator. |
112 | * The current thread will not be frozen. The same process that calls | ||
113 | * freeze_processes must later call thaw_processes. | ||
112 | * | 114 | * |
113 | * On success, returns 0. On failure, -errno and system is fully thawed. | 115 | * On success, returns 0. On failure, -errno and system is fully thawed. |
114 | */ | 116 | */ |
@@ -120,6 +122,9 @@ int freeze_processes(void) | |||
120 | if (error) | 122 | if (error) |
121 | return error; | 123 | return error; |
122 | 124 | ||
125 | /* Make sure this task doesn't get frozen */ | ||
126 | current->flags |= PF_SUSPEND_TASK; | ||
127 | |||
123 | if (!pm_freezing) | 128 | if (!pm_freezing) |
124 | atomic_inc(&system_freezing_cnt); | 129 | atomic_inc(&system_freezing_cnt); |
125 | 130 | ||
@@ -168,6 +173,7 @@ int freeze_kernel_threads(void) | |||
168 | void thaw_processes(void) | 173 | void thaw_processes(void) |
169 | { | 174 | { |
170 | struct task_struct *g, *p; | 175 | struct task_struct *g, *p; |
176 | struct task_struct *curr = current; | ||
171 | 177 | ||
172 | if (pm_freezing) | 178 | if (pm_freezing) |
173 | atomic_dec(&system_freezing_cnt); | 179 | atomic_dec(&system_freezing_cnt); |
@@ -182,10 +188,15 @@ void thaw_processes(void) | |||
182 | 188 | ||
183 | read_lock(&tasklist_lock); | 189 | read_lock(&tasklist_lock); |
184 | do_each_thread(g, p) { | 190 | do_each_thread(g, p) { |
191 | /* No other threads should have PF_SUSPEND_TASK set */ | ||
192 | WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK)); | ||
185 | __thaw_task(p); | 193 | __thaw_task(p); |
186 | } while_each_thread(g, p); | 194 | } while_each_thread(g, p); |
187 | read_unlock(&tasklist_lock); | 195 | read_unlock(&tasklist_lock); |
188 | 196 | ||
197 | WARN_ON(!(curr->flags & PF_SUSPEND_TASK)); | ||
198 | curr->flags &= ~PF_SUSPEND_TASK; | ||
199 | |||
189 | usermodehelper_enable(); | 200 | usermodehelper_enable(); |
190 | 201 | ||
191 | schedule(); | 202 | schedule(); |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index e80183f4a6c4..e77edc97e036 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -827,13 +827,10 @@ void tick_nohz_irq_exit(void) | |||
827 | { | 827 | { |
828 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); | 828 | struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); |
829 | 829 | ||
830 | if (ts->inidle) { | 830 | if (ts->inidle) |
831 | /* Cancel the timer because CPU already waken up from the C-states*/ | ||
832 | menu_hrtimer_cancel(); | ||
833 | __tick_nohz_idle_enter(ts); | 831 | __tick_nohz_idle_enter(ts); |
834 | } else { | 832 | else |
835 | tick_nohz_full_stop_tick(ts); | 833 | tick_nohz_full_stop_tick(ts); |
836 | } | ||
837 | } | 834 | } |
838 | 835 | ||
839 | /** | 836 | /** |
@@ -931,8 +928,6 @@ void tick_nohz_idle_exit(void) | |||
931 | 928 | ||
932 | ts->inidle = 0; | 929 | ts->inidle = 0; |
933 | 930 | ||
934 | /* Cancel the timer because CPU already waken up from the C-states*/ | ||
935 | menu_hrtimer_cancel(); | ||
936 | if (ts->idle_active || ts->tick_stopped) | 931 | if (ts->idle_active || ts->tick_stopped) |
937 | now = ktime_get(); | 932 | now = ktime_get(); |
938 | 933 | ||