diff options
-rw-r--r-- | drivers/acpi/battery.c | 2 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 19 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 106 | ||||
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | include/linux/tick.h | 6 | ||||
-rw-r--r-- | kernel/freezer.c | 2 | ||||
-rw-r--r-- | kernel/power/process.c | 11 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 9 |
8 files changed, 31 insertions, 125 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 082b4dd252a8..d405fbad406a 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -117,6 +117,7 @@ struct acpi_battery { | |||
117 | struct acpi_device *device; | 117 | struct acpi_device *device; |
118 | struct notifier_block pm_nb; | 118 | struct notifier_block pm_nb; |
119 | unsigned long update_time; | 119 | unsigned long update_time; |
120 | int revision; | ||
120 | int rate_now; | 121 | int rate_now; |
121 | int capacity_now; | 122 | int capacity_now; |
122 | int voltage_now; | 123 | int voltage_now; |
@@ -359,6 +360,7 @@ static struct acpi_offsets info_offsets[] = { | |||
359 | }; | 360 | }; |
360 | 361 | ||
361 | static struct acpi_offsets extended_info_offsets[] = { | 362 | static struct acpi_offsets extended_info_offsets[] = { |
363 | {offsetof(struct acpi_battery, revision), 0}, | ||
362 | {offsetof(struct acpi_battery, power_unit), 0}, | 364 | {offsetof(struct acpi_battery, power_unit), 0}, |
363 | {offsetof(struct acpi_battery, design_capacity), 0}, | 365 | {offsetof(struct acpi_battery, design_capacity), 0}, |
364 | {offsetof(struct acpi_battery, full_charge_capacity), 0}, | 366 | {offsetof(struct acpi_battery, full_charge_capacity), 0}, |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a4ad7339588d..f0a5e2b0eb8a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -1177,14 +1177,11 @@ static int __cpufreq_remove_dev(struct device *dev, | |||
1177 | __func__, cpu_dev->id, cpu); | 1177 | __func__, cpu_dev->id, cpu); |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | if ((cpus == 1) && (cpufreq_driver->target)) | ||
1181 | __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); | ||
1182 | |||
1183 | pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); | ||
1184 | cpufreq_cpu_put(data); | ||
1185 | |||
1186 | /* If cpu is last user of policy, free policy */ | 1180 | /* If cpu is last user of policy, free policy */ |
1187 | if (cpus == 1) { | 1181 | if (cpus == 1) { |
1182 | if (cpufreq_driver->target) | ||
1183 | __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); | ||
1184 | |||
1188 | lock_policy_rwsem_read(cpu); | 1185 | lock_policy_rwsem_read(cpu); |
1189 | kobj = &data->kobj; | 1186 | kobj = &data->kobj; |
1190 | cmp = &data->kobj_unregister; | 1187 | cmp = &data->kobj_unregister; |
@@ -1205,9 +1202,13 @@ static int __cpufreq_remove_dev(struct device *dev, | |||
1205 | free_cpumask_var(data->related_cpus); | 1202 | free_cpumask_var(data->related_cpus); |
1206 | free_cpumask_var(data->cpus); | 1203 | free_cpumask_var(data->cpus); |
1207 | kfree(data); | 1204 | kfree(data); |
1208 | } else if (cpufreq_driver->target) { | 1205 | } else { |
1209 | __cpufreq_governor(data, CPUFREQ_GOV_START); | 1206 | pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); |
1210 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); | 1207 | cpufreq_cpu_put(data); |
1208 | if (cpufreq_driver->target) { | ||
1209 | __cpufreq_governor(data, CPUFREQ_GOV_START); | ||
1210 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); | ||
1211 | } | ||
1211 | } | 1212 | } |
1212 | 1213 | ||
1213 | per_cpu(cpufreq_policy_cpu, cpu) = -1; | 1214 | per_cpu(cpufreq_policy_cpu, cpu) = -1; |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index fe343a06b7da..bc580b67a652 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -28,13 +28,6 @@ | |||
28 | #define MAX_INTERESTING 50000 | 28 | #define MAX_INTERESTING 50000 |
29 | #define STDDEV_THRESH 400 | 29 | #define STDDEV_THRESH 400 |
30 | 30 | ||
31 | /* 60 * 60 > STDDEV_THRESH * INTERVALS = 400 * 8 */ | ||
32 | #define MAX_DEVIATION 60 | ||
33 | |||
34 | static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer); | ||
35 | static DEFINE_PER_CPU(int, hrtimer_status); | ||
36 | /* menu hrtimer mode */ | ||
37 | enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL}; | ||
38 | 31 | ||
39 | /* | 32 | /* |
40 | * Concepts and ideas behind the menu governor | 33 | * Concepts and ideas behind the menu governor |
@@ -116,13 +109,6 @@ enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL}; | |||
116 | * | 109 | * |
117 | */ | 110 | */ |
118 | 111 | ||
119 | /* | ||
120 | * The C-state residency is so long that is is worthwhile to exit | ||
121 | * from the shallow C-state and re-enter into a deeper C-state. | ||
122 | */ | ||
123 | static unsigned int perfect_cstate_ms __read_mostly = 30; | ||
124 | module_param(perfect_cstate_ms, uint, 0000); | ||
125 | |||
126 | struct menu_device { | 112 | struct menu_device { |
127 | int last_state_idx; | 113 | int last_state_idx; |
128 | int needs_update; | 114 | int needs_update; |
@@ -205,52 +191,17 @@ static u64 div_round64(u64 dividend, u32 divisor) | |||
205 | return div_u64(dividend + (divisor / 2), divisor); | 191 | return div_u64(dividend + (divisor / 2), divisor); |
206 | } | 192 | } |
207 | 193 | ||
208 | /* Cancel the hrtimer if it is not triggered yet */ | ||
209 | void menu_hrtimer_cancel(void) | ||
210 | { | ||
211 | int cpu = smp_processor_id(); | ||
212 | struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu); | ||
213 | |||
214 | /* The timer is still not time out*/ | ||
215 | if (per_cpu(hrtimer_status, cpu)) { | ||
216 | hrtimer_cancel(hrtmr); | ||
217 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; | ||
218 | } | ||
219 | } | ||
220 | EXPORT_SYMBOL_GPL(menu_hrtimer_cancel); | ||
221 | |||
222 | /* Call back for hrtimer is triggered */ | ||
223 | static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer) | ||
224 | { | ||
225 | int cpu = smp_processor_id(); | ||
226 | struct menu_device *data = &per_cpu(menu_devices, cpu); | ||
227 | |||
228 | /* In general case, the expected residency is much larger than | ||
229 | * deepest C-state target residency, but prediction logic still | ||
230 | * predicts a small predicted residency, so the prediction | ||
231 | * history is totally broken if the timer is triggered. | ||
232 | * So reset the correction factor. | ||
233 | */ | ||
234 | if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL) | ||
235 | data->correction_factor[data->bucket] = RESOLUTION * DECAY; | ||
236 | |||
237 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; | ||
238 | |||
239 | return HRTIMER_NORESTART; | ||
240 | } | ||
241 | |||
242 | /* | 194 | /* |
243 | * Try detecting repeating patterns by keeping track of the last 8 | 195 | * Try detecting repeating patterns by keeping track of the last 8 |
244 | * intervals, and checking if the standard deviation of that set | 196 | * intervals, and checking if the standard deviation of that set |
245 | * of points is below a threshold. If it is... then use the | 197 | * of points is below a threshold. If it is... then use the |
246 | * average of these 8 points as the estimated value. | 198 | * average of these 8 points as the estimated value. |
247 | */ | 199 | */ |
248 | static u32 get_typical_interval(struct menu_device *data) | 200 | static void get_typical_interval(struct menu_device *data) |
249 | { | 201 | { |
250 | int i = 0, divisor = 0; | 202 | int i = 0, divisor = 0; |
251 | uint64_t max = 0, avg = 0, stddev = 0; | 203 | uint64_t max = 0, avg = 0, stddev = 0; |
252 | int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */ | 204 | int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */ |
253 | unsigned int ret = 0; | ||
254 | 205 | ||
255 | again: | 206 | again: |
256 | 207 | ||
@@ -291,16 +242,13 @@ again: | |||
291 | if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3)) | 242 | if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3)) |
292 | || stddev <= 20) { | 243 | || stddev <= 20) { |
293 | data->predicted_us = avg; | 244 | data->predicted_us = avg; |
294 | ret = 1; | 245 | return; |
295 | return ret; | ||
296 | 246 | ||
297 | } else if ((divisor * 4) > INTERVALS * 3) { | 247 | } else if ((divisor * 4) > INTERVALS * 3) { |
298 | /* Exclude the max interval */ | 248 | /* Exclude the max interval */ |
299 | thresh = max - 1; | 249 | thresh = max - 1; |
300 | goto again; | 250 | goto again; |
301 | } | 251 | } |
302 | |||
303 | return ret; | ||
304 | } | 252 | } |
305 | 253 | ||
306 | /** | 254 | /** |
@@ -315,9 +263,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
315 | int i; | 263 | int i; |
316 | int multiplier; | 264 | int multiplier; |
317 | struct timespec t; | 265 | struct timespec t; |
318 | int repeat = 0, low_predicted = 0; | ||
319 | int cpu = smp_processor_id(); | ||
320 | struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu); | ||
321 | 266 | ||
322 | if (data->needs_update) { | 267 | if (data->needs_update) { |
323 | menu_update(drv, dev); | 268 | menu_update(drv, dev); |
@@ -352,7 +297,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
352 | data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], | 297 | data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], |
353 | RESOLUTION * DECAY); | 298 | RESOLUTION * DECAY); |
354 | 299 | ||
355 | repeat = get_typical_interval(data); | 300 | get_typical_interval(data); |
356 | 301 | ||
357 | /* | 302 | /* |
358 | * We want to default to C1 (hlt), not to busy polling | 303 | * We want to default to C1 (hlt), not to busy polling |
@@ -373,10 +318,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
373 | 318 | ||
374 | if (s->disabled || su->disable) | 319 | if (s->disabled || su->disable) |
375 | continue; | 320 | continue; |
376 | if (s->target_residency > data->predicted_us) { | 321 | if (s->target_residency > data->predicted_us) |
377 | low_predicted = 1; | ||
378 | continue; | 322 | continue; |
379 | } | ||
380 | if (s->exit_latency > latency_req) | 323 | if (s->exit_latency > latency_req) |
381 | continue; | 324 | continue; |
382 | if (s->exit_latency * multiplier > data->predicted_us) | 325 | if (s->exit_latency * multiplier > data->predicted_us) |
@@ -386,44 +329,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
386 | data->exit_us = s->exit_latency; | 329 | data->exit_us = s->exit_latency; |
387 | } | 330 | } |
388 | 331 | ||
389 | /* not deepest C-state chosen for low predicted residency */ | ||
390 | if (low_predicted) { | ||
391 | unsigned int timer_us = 0; | ||
392 | unsigned int perfect_us = 0; | ||
393 | |||
394 | /* | ||
395 | * Set a timer to detect whether this sleep is much | ||
396 | * longer than repeat mode predicted. If the timer | ||
397 | * triggers, the code will evaluate whether to put | ||
398 | * the CPU into a deeper C-state. | ||
399 | * The timer is cancelled on CPU wakeup. | ||
400 | */ | ||
401 | timer_us = 2 * (data->predicted_us + MAX_DEVIATION); | ||
402 | |||
403 | perfect_us = perfect_cstate_ms * 1000; | ||
404 | |||
405 | if (repeat && (4 * timer_us < data->expected_us)) { | ||
406 | RCU_NONIDLE(hrtimer_start(hrtmr, | ||
407 | ns_to_ktime(1000 * timer_us), | ||
408 | HRTIMER_MODE_REL_PINNED)); | ||
409 | /* In repeat case, menu hrtimer is started */ | ||
410 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT; | ||
411 | } else if (perfect_us < data->expected_us) { | ||
412 | /* | ||
413 | * The next timer is long. This could be because | ||
414 | * we did not make a useful prediction. | ||
415 | * In that case, it makes sense to re-enter | ||
416 | * into a deeper C-state after some time. | ||
417 | */ | ||
418 | RCU_NONIDLE(hrtimer_start(hrtmr, | ||
419 | ns_to_ktime(1000 * timer_us), | ||
420 | HRTIMER_MODE_REL_PINNED)); | ||
421 | /* In general case, menu hrtimer is started */ | ||
422 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL; | ||
423 | } | ||
424 | |||
425 | } | ||
426 | |||
427 | return data->last_state_idx; | 332 | return data->last_state_idx; |
428 | } | 333 | } |
429 | 334 | ||
@@ -514,9 +419,6 @@ static int menu_enable_device(struct cpuidle_driver *drv, | |||
514 | struct cpuidle_device *dev) | 419 | struct cpuidle_device *dev) |
515 | { | 420 | { |
516 | struct menu_device *data = &per_cpu(menu_devices, dev->cpu); | 421 | struct menu_device *data = &per_cpu(menu_devices, dev->cpu); |
517 | struct hrtimer *t = &per_cpu(menu_hrtimer, dev->cpu); | ||
518 | hrtimer_init(t, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
519 | t->function = menu_hrtimer_notify; | ||
520 | 422 | ||
521 | memset(data, 0, sizeof(struct menu_device)); | 423 | memset(data, 0, sizeof(struct menu_device)); |
522 | 424 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 50d04b92ceda..d722490da030 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1628,6 +1628,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, | |||
1628 | #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ | 1628 | #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ |
1629 | #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ | 1629 | #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ |
1630 | #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ | 1630 | #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ |
1631 | #define PF_SUSPEND_TASK 0x80000000 /* this thread called freeze_processes and should not be frozen */ | ||
1631 | 1632 | ||
1632 | /* | 1633 | /* |
1633 | * Only the _current_ task can read/write to tsk->flags, but other | 1634 | * Only the _current_ task can read/write to tsk->flags, but other |
diff --git a/include/linux/tick.h b/include/linux/tick.h index 9180f4b85e6d..62bd8b72873c 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h | |||
@@ -174,10 +174,4 @@ static inline void tick_nohz_task_switch(struct task_struct *tsk) { } | |||
174 | #endif | 174 | #endif |
175 | 175 | ||
176 | 176 | ||
177 | # ifdef CONFIG_CPU_IDLE_GOV_MENU | ||
178 | extern void menu_hrtimer_cancel(void); | ||
179 | # else | ||
180 | static inline void menu_hrtimer_cancel(void) {} | ||
181 | # endif /* CONFIG_CPU_IDLE_GOV_MENU */ | ||
182 | |||
183 | #endif | 177 | #endif |
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 | ||