diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 2 | ||||
-rw-r--r-- | kernel/power/disk.c | 13 | ||||
-rw-r--r-- | kernel/power/main.c | 5 | ||||
-rw-r--r-- | kernel/sched_clock.c | 84 | ||||
-rw-r--r-- | kernel/sched_rt.c | 13 | ||||
-rw-r--r-- | kernel/smp.c | 10 |
6 files changed, 63 insertions, 64 deletions
diff --git a/kernel/module.c b/kernel/module.c index 08864d257eb0..9db11911e04b 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1799,7 +1799,7 @@ static void *module_alloc_update_bounds(unsigned long size) | |||
1799 | 1799 | ||
1800 | /* Allocate and load the module: note that size of section 0 is always | 1800 | /* Allocate and load the module: note that size of section 0 is always |
1801 | zero, and we rely on this for optional sections. */ | 1801 | zero, and we rely on this for optional sections. */ |
1802 | static struct module *load_module(void __user *umod, | 1802 | static noinline struct module *load_module(void __user *umod, |
1803 | unsigned long len, | 1803 | unsigned long len, |
1804 | const char __user *uargs) | 1804 | const char __user *uargs) |
1805 | { | 1805 | { |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index f011e0870b52..bbd85c60f741 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/console.h> | 21 | #include <linux/console.h> |
22 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
23 | #include <linux/freezer.h> | 23 | #include <linux/freezer.h> |
24 | #include <linux/ftrace.h> | ||
24 | 25 | ||
25 | #include "power.h" | 26 | #include "power.h" |
26 | 27 | ||
@@ -255,7 +256,7 @@ static int create_image(int platform_mode) | |||
255 | 256 | ||
256 | int hibernation_snapshot(int platform_mode) | 257 | int hibernation_snapshot(int platform_mode) |
257 | { | 258 | { |
258 | int error; | 259 | int error, ftrace_save; |
259 | 260 | ||
260 | /* Free memory before shutting down devices. */ | 261 | /* Free memory before shutting down devices. */ |
261 | error = swsusp_shrink_memory(); | 262 | error = swsusp_shrink_memory(); |
@@ -267,6 +268,7 @@ int hibernation_snapshot(int platform_mode) | |||
267 | goto Close; | 268 | goto Close; |
268 | 269 | ||
269 | suspend_console(); | 270 | suspend_console(); |
271 | ftrace_save = __ftrace_enabled_save(); | ||
270 | error = device_suspend(PMSG_FREEZE); | 272 | error = device_suspend(PMSG_FREEZE); |
271 | if (error) | 273 | if (error) |
272 | goto Recover_platform; | 274 | goto Recover_platform; |
@@ -296,6 +298,7 @@ int hibernation_snapshot(int platform_mode) | |||
296 | Resume_devices: | 298 | Resume_devices: |
297 | device_resume(in_suspend ? | 299 | device_resume(in_suspend ? |
298 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); | 300 | (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); |
301 | __ftrace_enabled_restore(ftrace_save); | ||
299 | resume_console(); | 302 | resume_console(); |
300 | Close: | 303 | Close: |
301 | platform_end(platform_mode); | 304 | platform_end(platform_mode); |
@@ -366,10 +369,11 @@ static int resume_target_kernel(void) | |||
366 | 369 | ||
367 | int hibernation_restore(int platform_mode) | 370 | int hibernation_restore(int platform_mode) |
368 | { | 371 | { |
369 | int error; | 372 | int error, ftrace_save; |
370 | 373 | ||
371 | pm_prepare_console(); | 374 | pm_prepare_console(); |
372 | suspend_console(); | 375 | suspend_console(); |
376 | ftrace_save = __ftrace_enabled_save(); | ||
373 | error = device_suspend(PMSG_QUIESCE); | 377 | error = device_suspend(PMSG_QUIESCE); |
374 | if (error) | 378 | if (error) |
375 | goto Finish; | 379 | goto Finish; |
@@ -384,6 +388,7 @@ int hibernation_restore(int platform_mode) | |||
384 | platform_restore_cleanup(platform_mode); | 388 | platform_restore_cleanup(platform_mode); |
385 | device_resume(PMSG_RECOVER); | 389 | device_resume(PMSG_RECOVER); |
386 | Finish: | 390 | Finish: |
391 | __ftrace_enabled_restore(ftrace_save); | ||
387 | resume_console(); | 392 | resume_console(); |
388 | pm_restore_console(); | 393 | pm_restore_console(); |
389 | return error; | 394 | return error; |
@@ -396,7 +401,7 @@ int hibernation_restore(int platform_mode) | |||
396 | 401 | ||
397 | int hibernation_platform_enter(void) | 402 | int hibernation_platform_enter(void) |
398 | { | 403 | { |
399 | int error; | 404 | int error, ftrace_save; |
400 | 405 | ||
401 | if (!hibernation_ops) | 406 | if (!hibernation_ops) |
402 | return -ENOSYS; | 407 | return -ENOSYS; |
@@ -411,6 +416,7 @@ int hibernation_platform_enter(void) | |||
411 | goto Close; | 416 | goto Close; |
412 | 417 | ||
413 | suspend_console(); | 418 | suspend_console(); |
419 | ftrace_save = __ftrace_enabled_save(); | ||
414 | error = device_suspend(PMSG_HIBERNATE); | 420 | error = device_suspend(PMSG_HIBERNATE); |
415 | if (error) { | 421 | if (error) { |
416 | if (hibernation_ops->recover) | 422 | if (hibernation_ops->recover) |
@@ -445,6 +451,7 @@ int hibernation_platform_enter(void) | |||
445 | hibernation_ops->finish(); | 451 | hibernation_ops->finish(); |
446 | Resume_devices: | 452 | Resume_devices: |
447 | device_resume(PMSG_RESTORE); | 453 | device_resume(PMSG_RESTORE); |
454 | __ftrace_enabled_restore(ftrace_save); | ||
448 | resume_console(); | 455 | resume_console(); |
449 | Close: | 456 | Close: |
450 | hibernation_ops->end(); | 457 | hibernation_ops->end(); |
diff --git a/kernel/power/main.c b/kernel/power/main.c index 0b7476f5d2a6..540b16b68565 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/freezer.h> | 21 | #include <linux/freezer.h> |
22 | #include <linux/vmstat.h> | 22 | #include <linux/vmstat.h> |
23 | #include <linux/syscalls.h> | 23 | #include <linux/syscalls.h> |
24 | #include <linux/ftrace.h> | ||
24 | 25 | ||
25 | #include "power.h" | 26 | #include "power.h" |
26 | 27 | ||
@@ -310,7 +311,7 @@ static int suspend_enter(suspend_state_t state) | |||
310 | */ | 311 | */ |
311 | int suspend_devices_and_enter(suspend_state_t state) | 312 | int suspend_devices_and_enter(suspend_state_t state) |
312 | { | 313 | { |
313 | int error; | 314 | int error, ftrace_save; |
314 | 315 | ||
315 | if (!suspend_ops) | 316 | if (!suspend_ops) |
316 | return -ENOSYS; | 317 | return -ENOSYS; |
@@ -321,6 +322,7 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
321 | goto Close; | 322 | goto Close; |
322 | } | 323 | } |
323 | suspend_console(); | 324 | suspend_console(); |
325 | ftrace_save = __ftrace_enabled_save(); | ||
324 | suspend_test_start(); | 326 | suspend_test_start(); |
325 | error = device_suspend(PMSG_SUSPEND); | 327 | error = device_suspend(PMSG_SUSPEND); |
326 | if (error) { | 328 | if (error) { |
@@ -352,6 +354,7 @@ int suspend_devices_and_enter(suspend_state_t state) | |||
352 | suspend_test_start(); | 354 | suspend_test_start(); |
353 | device_resume(PMSG_RESUME); | 355 | device_resume(PMSG_RESUME); |
354 | suspend_test_finish("resume devices"); | 356 | suspend_test_finish("resume devices"); |
357 | __ftrace_enabled_restore(ftrace_save); | ||
355 | resume_console(); | 358 | resume_console(); |
356 | Close: | 359 | Close: |
357 | if (suspend_ops->end) | 360 | if (suspend_ops->end) |
diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c index 204991a0bfa7..e8ab096ddfe3 100644 --- a/kernel/sched_clock.c +++ b/kernel/sched_clock.c | |||
@@ -12,19 +12,17 @@ | |||
12 | * | 12 | * |
13 | * Create a semi stable clock from a mixture of other events, including: | 13 | * Create a semi stable clock from a mixture of other events, including: |
14 | * - gtod | 14 | * - gtod |
15 | * - jiffies | ||
16 | * - sched_clock() | 15 | * - sched_clock() |
17 | * - explicit idle events | 16 | * - explicit idle events |
18 | * | 17 | * |
19 | * We use gtod as base and the unstable clock deltas. The deltas are filtered, | 18 | * We use gtod as base and the unstable clock deltas. The deltas are filtered, |
20 | * making it monotonic and keeping it within an expected window. This window | 19 | * making it monotonic and keeping it within an expected window. |
21 | * is set up using jiffies. | ||
22 | * | 20 | * |
23 | * Furthermore, explicit sleep and wakeup hooks allow us to account for time | 21 | * Furthermore, explicit sleep and wakeup hooks allow us to account for time |
24 | * that is otherwise invisible (TSC gets stopped). | 22 | * that is otherwise invisible (TSC gets stopped). |
25 | * | 23 | * |
26 | * The clock: sched_clock_cpu() is monotonic per cpu, and should be somewhat | 24 | * The clock: sched_clock_cpu() is monotonic per cpu, and should be somewhat |
27 | * consistent between cpus (never more than 1 jiffies difference). | 25 | * consistent between cpus (never more than 2 jiffies difference). |
28 | */ | 26 | */ |
29 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
30 | #include <linux/percpu.h> | 28 | #include <linux/percpu.h> |
@@ -54,7 +52,6 @@ struct sched_clock_data { | |||
54 | */ | 52 | */ |
55 | raw_spinlock_t lock; | 53 | raw_spinlock_t lock; |
56 | 54 | ||
57 | unsigned long tick_jiffies; | ||
58 | u64 tick_raw; | 55 | u64 tick_raw; |
59 | u64 tick_gtod; | 56 | u64 tick_gtod; |
60 | u64 clock; | 57 | u64 clock; |
@@ -75,14 +72,12 @@ static inline struct sched_clock_data *cpu_sdc(int cpu) | |||
75 | void sched_clock_init(void) | 72 | void sched_clock_init(void) |
76 | { | 73 | { |
77 | u64 ktime_now = ktime_to_ns(ktime_get()); | 74 | u64 ktime_now = ktime_to_ns(ktime_get()); |
78 | unsigned long now_jiffies = jiffies; | ||
79 | int cpu; | 75 | int cpu; |
80 | 76 | ||
81 | for_each_possible_cpu(cpu) { | 77 | for_each_possible_cpu(cpu) { |
82 | struct sched_clock_data *scd = cpu_sdc(cpu); | 78 | struct sched_clock_data *scd = cpu_sdc(cpu); |
83 | 79 | ||
84 | scd->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; | 80 | scd->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; |
85 | scd->tick_jiffies = now_jiffies; | ||
86 | scd->tick_raw = 0; | 81 | scd->tick_raw = 0; |
87 | scd->tick_gtod = ktime_now; | 82 | scd->tick_gtod = ktime_now; |
88 | scd->clock = ktime_now; | 83 | scd->clock = ktime_now; |
@@ -92,46 +87,51 @@ void sched_clock_init(void) | |||
92 | } | 87 | } |
93 | 88 | ||
94 | /* | 89 | /* |
90 | * min,max except they take wrapping into account | ||
91 | */ | ||
92 | |||
93 | static inline u64 wrap_min(u64 x, u64 y) | ||
94 | { | ||
95 | return (s64)(x - y) < 0 ? x : y; | ||
96 | } | ||
97 | |||
98 | static inline u64 wrap_max(u64 x, u64 y) | ||
99 | { | ||
100 | return (s64)(x - y) > 0 ? x : y; | ||
101 | } | ||
102 | |||
103 | /* | ||
95 | * update the percpu scd from the raw @now value | 104 | * update the percpu scd from the raw @now value |
96 | * | 105 | * |
97 | * - filter out backward motion | 106 | * - filter out backward motion |
98 | * - use jiffies to generate a min,max window to clip the raw values | 107 | * - use the GTOD tick value to create a window to filter crazy TSC values |
99 | */ | 108 | */ |
100 | static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now) | 109 | static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now) |
101 | { | 110 | { |
102 | unsigned long now_jiffies = jiffies; | ||
103 | long delta_jiffies = now_jiffies - scd->tick_jiffies; | ||
104 | u64 clock = scd->clock; | ||
105 | u64 min_clock, max_clock; | ||
106 | s64 delta = now - scd->tick_raw; | 111 | s64 delta = now - scd->tick_raw; |
112 | u64 clock, min_clock, max_clock; | ||
107 | 113 | ||
108 | WARN_ON_ONCE(!irqs_disabled()); | 114 | WARN_ON_ONCE(!irqs_disabled()); |
109 | min_clock = scd->tick_gtod + delta_jiffies * TICK_NSEC; | ||
110 | 115 | ||
111 | if (unlikely(delta < 0)) { | 116 | if (unlikely(delta < 0)) |
112 | clock++; | 117 | delta = 0; |
113 | goto out; | ||
114 | } | ||
115 | 118 | ||
116 | max_clock = min_clock + TICK_NSEC; | 119 | /* |
120 | * scd->clock = clamp(scd->tick_gtod + delta, | ||
121 | * max(scd->tick_gtod, scd->clock), | ||
122 | * scd->tick_gtod + TICK_NSEC); | ||
123 | */ | ||
117 | 124 | ||
118 | if (unlikely(clock + delta > max_clock)) { | 125 | clock = scd->tick_gtod + delta; |
119 | if (clock < max_clock) | 126 | min_clock = wrap_max(scd->tick_gtod, scd->clock); |
120 | clock = max_clock; | 127 | max_clock = scd->tick_gtod + TICK_NSEC; |
121 | else | ||
122 | clock++; | ||
123 | } else { | ||
124 | clock += delta; | ||
125 | } | ||
126 | 128 | ||
127 | out: | 129 | clock = wrap_max(clock, min_clock); |
128 | if (unlikely(clock < min_clock)) | 130 | clock = wrap_min(clock, max_clock); |
129 | clock = min_clock; | ||
130 | 131 | ||
131 | scd->tick_jiffies = now_jiffies; | ||
132 | scd->clock = clock; | 132 | scd->clock = clock; |
133 | 133 | ||
134 | return clock; | 134 | return scd->clock; |
135 | } | 135 | } |
136 | 136 | ||
137 | static void lock_double_clock(struct sched_clock_data *data1, | 137 | static void lock_double_clock(struct sched_clock_data *data1, |
@@ -171,7 +171,7 @@ u64 sched_clock_cpu(int cpu) | |||
171 | * larger time as the latest time for both | 171 | * larger time as the latest time for both |
172 | * runqueues. (this creates monotonic movement) | 172 | * runqueues. (this creates monotonic movement) |
173 | */ | 173 | */ |
174 | if (likely(remote_clock < this_clock)) { | 174 | if (likely((s64)(remote_clock - this_clock) < 0)) { |
175 | clock = this_clock; | 175 | clock = this_clock; |
176 | scd->clock = clock; | 176 | scd->clock = clock; |
177 | } else { | 177 | } else { |
@@ -207,14 +207,9 @@ void sched_clock_tick(void) | |||
207 | now = sched_clock(); | 207 | now = sched_clock(); |
208 | 208 | ||
209 | __raw_spin_lock(&scd->lock); | 209 | __raw_spin_lock(&scd->lock); |
210 | __update_sched_clock(scd, now); | ||
211 | /* | ||
212 | * update tick_gtod after __update_sched_clock() because that will | ||
213 | * already observe 1 new jiffy; adding a new tick_gtod to that would | ||
214 | * increase the clock 2 jiffies. | ||
215 | */ | ||
216 | scd->tick_raw = now; | 210 | scd->tick_raw = now; |
217 | scd->tick_gtod = now_gtod; | 211 | scd->tick_gtod = now_gtod; |
212 | __update_sched_clock(scd, now); | ||
218 | __raw_spin_unlock(&scd->lock); | 213 | __raw_spin_unlock(&scd->lock); |
219 | } | 214 | } |
220 | 215 | ||
@@ -232,18 +227,7 @@ EXPORT_SYMBOL_GPL(sched_clock_idle_sleep_event); | |||
232 | */ | 227 | */ |
233 | void sched_clock_idle_wakeup_event(u64 delta_ns) | 228 | void sched_clock_idle_wakeup_event(u64 delta_ns) |
234 | { | 229 | { |
235 | struct sched_clock_data *scd = this_scd(); | 230 | sched_clock_tick(); |
236 | |||
237 | /* | ||
238 | * Override the previous timestamp and ignore all | ||
239 | * sched_clock() deltas that occured while we idled, | ||
240 | * and use the PM-provided delta_ns to advance the | ||
241 | * rq clock: | ||
242 | */ | ||
243 | __raw_spin_lock(&scd->lock); | ||
244 | scd->clock += delta_ns; | ||
245 | __raw_spin_unlock(&scd->lock); | ||
246 | |||
247 | touch_softlockup_watchdog(); | 231 | touch_softlockup_watchdog(); |
248 | } | 232 | } |
249 | EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event); | 233 | EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event); |
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 998ba54b4543..552310798dad 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c | |||
@@ -199,6 +199,8 @@ static inline struct rt_rq *group_rt_rq(struct sched_rt_entity *rt_se) | |||
199 | 199 | ||
200 | static inline void sched_rt_rq_enqueue(struct rt_rq *rt_rq) | 200 | static inline void sched_rt_rq_enqueue(struct rt_rq *rt_rq) |
201 | { | 201 | { |
202 | if (rt_rq->rt_nr_running) | ||
203 | resched_task(rq_of_rt_rq(rt_rq)->curr); | ||
202 | } | 204 | } |
203 | 205 | ||
204 | static inline void sched_rt_rq_dequeue(struct rt_rq *rt_rq) | 206 | static inline void sched_rt_rq_dequeue(struct rt_rq *rt_rq) |
@@ -438,9 +440,6 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq) | |||
438 | { | 440 | { |
439 | u64 runtime = sched_rt_runtime(rt_rq); | 441 | u64 runtime = sched_rt_runtime(rt_rq); |
440 | 442 | ||
441 | if (runtime == RUNTIME_INF) | ||
442 | return 0; | ||
443 | |||
444 | if (rt_rq->rt_throttled) | 443 | if (rt_rq->rt_throttled) |
445 | return rt_rq_throttled(rt_rq); | 444 | return rt_rq_throttled(rt_rq); |
446 | 445 | ||
@@ -491,9 +490,11 @@ static void update_curr_rt(struct rq *rq) | |||
491 | rt_rq = rt_rq_of_se(rt_se); | 490 | rt_rq = rt_rq_of_se(rt_se); |
492 | 491 | ||
493 | spin_lock(&rt_rq->rt_runtime_lock); | 492 | spin_lock(&rt_rq->rt_runtime_lock); |
494 | rt_rq->rt_time += delta_exec; | 493 | if (sched_rt_runtime(rt_rq) != RUNTIME_INF) { |
495 | if (sched_rt_runtime_exceeded(rt_rq)) | 494 | rt_rq->rt_time += delta_exec; |
496 | resched_task(curr); | 495 | if (sched_rt_runtime_exceeded(rt_rq)) |
496 | resched_task(curr); | ||
497 | } | ||
497 | spin_unlock(&rt_rq->rt_runtime_lock); | 498 | spin_unlock(&rt_rq->rt_runtime_lock); |
498 | } | 499 | } |
499 | } | 500 | } |
diff --git a/kernel/smp.c b/kernel/smp.c index 782e2b93e465..f362a8553777 100644 --- a/kernel/smp.c +++ b/kernel/smp.c | |||
@@ -210,8 +210,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
210 | { | 210 | { |
211 | struct call_single_data d; | 211 | struct call_single_data d; |
212 | unsigned long flags; | 212 | unsigned long flags; |
213 | /* prevent preemption and reschedule on another processor */ | 213 | /* prevent preemption and reschedule on another processor, |
214 | as well as CPU removal */ | ||
214 | int me = get_cpu(); | 215 | int me = get_cpu(); |
216 | int err = 0; | ||
215 | 217 | ||
216 | /* Can deadlock when called with interrupts disabled */ | 218 | /* Can deadlock when called with interrupts disabled */ |
217 | WARN_ON(irqs_disabled()); | 219 | WARN_ON(irqs_disabled()); |
@@ -220,7 +222,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
220 | local_irq_save(flags); | 222 | local_irq_save(flags); |
221 | func(info); | 223 | func(info); |
222 | local_irq_restore(flags); | 224 | local_irq_restore(flags); |
223 | } else { | 225 | } else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) { |
224 | struct call_single_data *data = NULL; | 226 | struct call_single_data *data = NULL; |
225 | 227 | ||
226 | if (!wait) { | 228 | if (!wait) { |
@@ -236,10 +238,12 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
236 | data->func = func; | 238 | data->func = func; |
237 | data->info = info; | 239 | data->info = info; |
238 | generic_exec_single(cpu, data); | 240 | generic_exec_single(cpu, data); |
241 | } else { | ||
242 | err = -ENXIO; /* CPU not online */ | ||
239 | } | 243 | } |
240 | 244 | ||
241 | put_cpu(); | 245 | put_cpu(); |
242 | return 0; | 246 | return err; |
243 | } | 247 | } |
244 | EXPORT_SYMBOL(smp_call_function_single); | 248 | EXPORT_SYMBOL(smp_call_function_single); |
245 | 249 | ||