diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/time.c | 12 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 25 |
2 files changed, 22 insertions, 15 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 061e81138dc2..8ca485676780 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -244,7 +244,7 @@ int sysctl_hz_timer = 1; | |||
244 | */ | 244 | */ |
245 | static inline void stop_hz_timer(void) | 245 | static inline void stop_hz_timer(void) |
246 | { | 246 | { |
247 | __u64 timer; | 247 | __u64 timer, todval; |
248 | 248 | ||
249 | if (sysctl_hz_timer != 0) | 249 | if (sysctl_hz_timer != 0) |
250 | return; | 250 | return; |
@@ -265,8 +265,14 @@ static inline void stop_hz_timer(void) | |||
265 | * for the next event. | 265 | * for the next event. |
266 | */ | 266 | */ |
267 | timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; | 267 | timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; |
268 | timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; | 268 | todval = -1ULL; |
269 | asm volatile ("SCKC %0" : : "m" (timer)); | 269 | /* Be careful about overflows. */ |
270 | if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) { | ||
271 | timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; | ||
272 | if (timer >= jiffies_timer_cc) | ||
273 | todval = timer; | ||
274 | } | ||
275 | asm volatile ("SCKC %0" : : "m" (todval)); | ||
270 | } | 276 | } |
271 | 277 | ||
272 | /* | 278 | /* |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index bb6cf02418a2..fa0726507b3d 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -122,12 +122,17 @@ static void start_cpu_timer(void) | |||
122 | struct vtimer_queue *vt_list; | 122 | struct vtimer_queue *vt_list; |
123 | 123 | ||
124 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); | 124 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); |
125 | set_vtimer(vt_list->idle); | 125 | |
126 | /* CPU timer interrupt is pending, don't reprogramm it */ | ||
127 | if (vt_list->idle & 1LL<<63) | ||
128 | return; | ||
129 | |||
130 | if (!list_empty(&vt_list->list)) | ||
131 | set_vtimer(vt_list->idle); | ||
126 | } | 132 | } |
127 | 133 | ||
128 | static void stop_cpu_timer(void) | 134 | static void stop_cpu_timer(void) |
129 | { | 135 | { |
130 | __u64 done; | ||
131 | struct vtimer_queue *vt_list; | 136 | struct vtimer_queue *vt_list; |
132 | 137 | ||
133 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); | 138 | vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); |
@@ -138,21 +143,17 @@ static void stop_cpu_timer(void) | |||
138 | goto fire; | 143 | goto fire; |
139 | } | 144 | } |
140 | 145 | ||
141 | /* store progress */ | 146 | /* store the actual expire value */ |
142 | asm volatile ("STPT %0" : "=m" (done)); | 147 | asm volatile ("STPT %0" : "=m" (vt_list->idle)); |
143 | 148 | ||
144 | /* | 149 | /* |
145 | * If done is negative we do not stop the CPU timer | 150 | * If the CPU timer is negative we don't reprogramm |
146 | * because we will get instantly an interrupt that | 151 | * it because we will get instantly an interrupt. |
147 | * will start the CPU timer again. | ||
148 | */ | 152 | */ |
149 | if (done & 1LL<<63) | 153 | if (vt_list->idle & 1LL<<63) |
150 | return; | 154 | return; |
151 | else | ||
152 | vt_list->offset += vt_list->to_expire - done; | ||
153 | 155 | ||
154 | /* save the actual expire value */ | 156 | vt_list->offset += vt_list->to_expire - vt_list->idle; |
155 | vt_list->idle = done; | ||
156 | 157 | ||
157 | /* | 158 | /* |
158 | * We cannot halt the CPU timer, we just write a value that | 159 | * We cannot halt the CPU timer, we just write a value that |