diff options
Diffstat (limited to 'kernel/timer.c')
-rw-r--r-- | kernel/timer.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/kernel/timer.c b/kernel/timer.c index 2a87430a58d4..05809c2e2fd6 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -374,6 +374,7 @@ int del_timer_sync(struct timer_list *timer) | |||
374 | int ret = try_to_del_timer_sync(timer); | 374 | int ret = try_to_del_timer_sync(timer); |
375 | if (ret >= 0) | 375 | if (ret >= 0) |
376 | return ret; | 376 | return ret; |
377 | cpu_relax(); | ||
377 | } | 378 | } |
378 | } | 379 | } |
379 | 380 | ||
@@ -968,6 +969,7 @@ void __init timekeeping_init(void) | |||
968 | } | 969 | } |
969 | 970 | ||
970 | 971 | ||
972 | static int timekeeping_suspended; | ||
971 | /* | 973 | /* |
972 | * timekeeping_resume - Resumes the generic timekeeping subsystem. | 974 | * timekeeping_resume - Resumes the generic timekeeping subsystem. |
973 | * @dev: unused | 975 | * @dev: unused |
@@ -983,6 +985,18 @@ static int timekeeping_resume(struct sys_device *dev) | |||
983 | write_seqlock_irqsave(&xtime_lock, flags); | 985 | write_seqlock_irqsave(&xtime_lock, flags); |
984 | /* restart the last cycle value */ | 986 | /* restart the last cycle value */ |
985 | clock->cycle_last = clocksource_read(clock); | 987 | clock->cycle_last = clocksource_read(clock); |
988 | clock->error = 0; | ||
989 | timekeeping_suspended = 0; | ||
990 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
991 | return 0; | ||
992 | } | ||
993 | |||
994 | static int timekeeping_suspend(struct sys_device *dev, pm_message_t state) | ||
995 | { | ||
996 | unsigned long flags; | ||
997 | |||
998 | write_seqlock_irqsave(&xtime_lock, flags); | ||
999 | timekeeping_suspended = 1; | ||
986 | write_sequnlock_irqrestore(&xtime_lock, flags); | 1000 | write_sequnlock_irqrestore(&xtime_lock, flags); |
987 | return 0; | 1001 | return 0; |
988 | } | 1002 | } |
@@ -990,6 +1004,7 @@ static int timekeeping_resume(struct sys_device *dev) | |||
990 | /* sysfs resume/suspend bits for timekeeping */ | 1004 | /* sysfs resume/suspend bits for timekeeping */ |
991 | static struct sysdev_class timekeeping_sysclass = { | 1005 | static struct sysdev_class timekeeping_sysclass = { |
992 | .resume = timekeeping_resume, | 1006 | .resume = timekeeping_resume, |
1007 | .suspend = timekeeping_suspend, | ||
993 | set_kset_name("timekeeping"), | 1008 | set_kset_name("timekeeping"), |
994 | }; | 1009 | }; |
995 | 1010 | ||
@@ -1100,13 +1115,16 @@ static void update_wall_time(void) | |||
1100 | { | 1115 | { |
1101 | cycle_t offset; | 1116 | cycle_t offset; |
1102 | 1117 | ||
1103 | clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift; | 1118 | /* Make sure we're fully resumed: */ |
1119 | if (unlikely(timekeeping_suspended)) | ||
1120 | return; | ||
1104 | 1121 | ||
1105 | #ifdef CONFIG_GENERIC_TIME | 1122 | #ifdef CONFIG_GENERIC_TIME |
1106 | offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask; | 1123 | offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask; |
1107 | #else | 1124 | #else |
1108 | offset = clock->cycle_interval; | 1125 | offset = clock->cycle_interval; |
1109 | #endif | 1126 | #endif |
1127 | clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift; | ||
1110 | 1128 | ||
1111 | /* normally this loop will run just once, however in the | 1129 | /* normally this loop will run just once, however in the |
1112 | * case of lost or late ticks, it will accumulate correctly. | 1130 | * case of lost or late ticks, it will accumulate correctly. |