__u32 ticks, xticks;
/* Calculate how many ticks have passed. */
- if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer)
+ if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
+ /*
+ * We have to program the clock comparator even if
+ * no tick has passed. That happens if e.g. an i/o
+ * interrupt wakes up an idle processor that has
+ * switched off its hz timer.
+ */
+ tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
+ asm volatile ("SCKC %0" : : "m" (tmp));
return;
+ }
tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */
ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
*/
static inline void stop_hz_timer(void)
{
- __u64 timer;
+ __u64 timer, todval;
if (sysctl_hz_timer != 0)
return;
* for the next event.
*/
timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
- timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
- asm volatile ("SCKC %0" : : "m" (timer));
+ todval = -1ULL;
+ /* Be careful about overflows. */
+ if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
+ timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
+ if (timer >= jiffies_timer_cc)
+ todval = timer;
+ }
+ asm volatile ("SCKC %0" : : "m" (todval));
}
/*