diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index fd4b13b131f8..383319bae3f7 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <linux/sched/sysctl.h> | 47 | #include <linux/sched/sysctl.h> |
| 48 | #include <linux/sched/rt.h> | 48 | #include <linux/sched/rt.h> |
| 49 | #include <linux/timer.h> | 49 | #include <linux/timer.h> |
| 50 | #include <linux/freezer.h> | ||
| 50 | 51 | ||
| 51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
| 52 | 53 | ||
| @@ -721,17 +722,20 @@ static int hrtimer_switch_to_hres(void) | |||
| 721 | return 1; | 722 | return 1; |
| 722 | } | 723 | } |
| 723 | 724 | ||
| 725 | static void clock_was_set_work(struct work_struct *work) | ||
| 726 | { | ||
| 727 | clock_was_set(); | ||
| 728 | } | ||
| 729 | |||
| 730 | static DECLARE_WORK(hrtimer_work, clock_was_set_work); | ||
| 731 | |||
| 724 | /* | 732 | /* |
| 725 | * Called from timekeeping code to reprogramm the hrtimer interrupt | 733 | * Called from timekeeping and resume code to reprogramm the hrtimer |
| 726 | * device. If called from the timer interrupt context we defer it to | 734 | * interrupt device on all cpus. |
| 727 | * softirq context. | ||
| 728 | */ | 735 | */ |
| 729 | void clock_was_set_delayed(void) | 736 | void clock_was_set_delayed(void) |
| 730 | { | 737 | { |
| 731 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | 738 | schedule_work(&hrtimer_work); |
| 732 | |||
| 733 | cpu_base->clock_was_set = 1; | ||
| 734 | __raise_softirq_irqoff(HRTIMER_SOFTIRQ); | ||
| 735 | } | 739 | } |
| 736 | 740 | ||
| 737 | #else | 741 | #else |
| @@ -773,15 +777,19 @@ void clock_was_set(void) | |||
| 773 | 777 | ||
| 774 | /* | 778 | /* |
| 775 | * During resume we might have to reprogram the high resolution timer | 779 | * During resume we might have to reprogram the high resolution timer |
| 776 | * interrupt (on the local CPU): | 780 | * interrupt on all online CPUs. However, all other CPUs will be |
| 781 | * stopped with IRQs interrupts disabled so the clock_was_set() call | ||
| 782 | * must be deferred. | ||
| 777 | */ | 783 | */ |
| 778 | void hrtimers_resume(void) | 784 | void hrtimers_resume(void) |
| 779 | { | 785 | { |
| 780 | WARN_ONCE(!irqs_disabled(), | 786 | WARN_ONCE(!irqs_disabled(), |
| 781 | KERN_INFO "hrtimers_resume() called with IRQs enabled!"); | 787 | KERN_INFO "hrtimers_resume() called with IRQs enabled!"); |
| 782 | 788 | ||
| 789 | /* Retrigger on the local CPU */ | ||
| 783 | retrigger_next_event(NULL); | 790 | retrigger_next_event(NULL); |
| 784 | timerfd_clock_was_set(); | 791 | /* And schedule a retrigger for all others */ |
| 792 | clock_was_set_delayed(); | ||
| 785 | } | 793 | } |
| 786 | 794 | ||
| 787 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) | 795 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) |
| @@ -1432,13 +1440,6 @@ void hrtimer_peek_ahead_timers(void) | |||
| 1432 | 1440 | ||
| 1433 | static void run_hrtimer_softirq(struct softirq_action *h) | 1441 | static void run_hrtimer_softirq(struct softirq_action *h) |
| 1434 | { | 1442 | { |
| 1435 | struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); | ||
| 1436 | |||
| 1437 | if (cpu_base->clock_was_set) { | ||
| 1438 | cpu_base->clock_was_set = 0; | ||
| 1439 | clock_was_set(); | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | hrtimer_peek_ahead_timers(); | 1443 | hrtimer_peek_ahead_timers(); |
| 1443 | } | 1444 | } |
| 1444 | 1445 | ||
| @@ -1545,7 +1546,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod | |||
| 1545 | t->task = NULL; | 1546 | t->task = NULL; |
| 1546 | 1547 | ||
| 1547 | if (likely(t->task)) | 1548 | if (likely(t->task)) |
| 1548 | schedule(); | 1549 | freezable_schedule(); |
| 1549 | 1550 | ||
| 1550 | hrtimer_cancel(&t->timer); | 1551 | hrtimer_cancel(&t->timer); |
| 1551 | mode = HRTIMER_MODE_ABS; | 1552 | mode = HRTIMER_MODE_ABS; |
| @@ -1658,7 +1659,7 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, | |||
| 1658 | /* | 1659 | /* |
| 1659 | * Functions related to boot-time initialization: | 1660 | * Functions related to boot-time initialization: |
| 1660 | */ | 1661 | */ |
| 1661 | static void __cpuinit init_hrtimers_cpu(int cpu) | 1662 | static void init_hrtimers_cpu(int cpu) |
| 1662 | { | 1663 | { |
| 1663 | struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu); | 1664 | struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu); |
| 1664 | int i; | 1665 | int i; |
| @@ -1739,7 +1740,7 @@ static void migrate_hrtimers(int scpu) | |||
| 1739 | 1740 | ||
| 1740 | #endif /* CONFIG_HOTPLUG_CPU */ | 1741 | #endif /* CONFIG_HOTPLUG_CPU */ |
| 1741 | 1742 | ||
| 1742 | static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, | 1743 | static int hrtimer_cpu_notify(struct notifier_block *self, |
| 1743 | unsigned long action, void *hcpu) | 1744 | unsigned long action, void *hcpu) |
| 1744 | { | 1745 | { |
| 1745 | int scpu = (long)hcpu; | 1746 | int scpu = (long)hcpu; |
| @@ -1772,7 +1773,7 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, | |||
| 1772 | return NOTIFY_OK; | 1773 | return NOTIFY_OK; |
| 1773 | } | 1774 | } |
| 1774 | 1775 | ||
| 1775 | static struct notifier_block __cpuinitdata hrtimers_nb = { | 1776 | static struct notifier_block hrtimers_nb = { |
| 1776 | .notifier_call = hrtimer_cpu_notify, | 1777 | .notifier_call = hrtimer_cpu_notify, |
| 1777 | }; | 1778 | }; |
| 1778 | 1779 | ||
