Skip to content

Commit f532522

Browse files
committed
Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: clocksource, acpi_pm.c: check for monotonicity clocksource, acpi_pm.c: use proper read function also in errata mode ntp: fix calculation of the next jiffie to trigger RTC sync x86: HPET: read back compare register before reading counter x86: HPET fix moronic 32/64bit thinko clockevents: broadcast fixup possible waiters HPET: make minimum reprogramming delta useful clockevents: prevent endless loop lockup clockevents: prevent multiple init/shutdown clockevents: enforce reprogram in oneshot setup clockevents: prevent endless loop in periodic broadcast handler clockevents: prevent clockevent event_handler ending up handler_noop
2 parents 4747832 + 4ab6a21 commit f532522

File tree

9 files changed

+151
-56
lines changed

9 files changed

+151
-56
lines changed

arch/x86/kernel/hpet.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,8 @@ static void hpet_legacy_clockevent_register(void)
210210
/* Calculate the min / max delta */
211211
hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
212212
&hpet_clockevent);
213-
hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30,
214-
&hpet_clockevent);
213+
/* 5 usec minimum reprogramming delta. */
214+
hpet_clockevent.min_delta_ns = 5000;
215215

216216
/*
217217
* Start hpet with the boot cpu mask and make it
@@ -270,15 +270,22 @@ static void hpet_legacy_set_mode(enum clock_event_mode mode,
270270
}
271271

272272
static int hpet_legacy_next_event(unsigned long delta,
273-
struct clock_event_device *evt)
273+
struct clock_event_device *evt)
274274
{
275-
unsigned long cnt;
275+
u32 cnt;
276276

277277
cnt = hpet_readl(HPET_COUNTER);
278-
cnt += delta;
278+
cnt += (u32) delta;
279279
hpet_writel(cnt, HPET_T0_CMP);
280280

281-
return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0;
281+
/*
282+
* We need to read back the CMP register to make sure that
283+
* what we wrote hit the chip before we compare it to the
284+
* counter.
285+
*/
286+
WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt);
287+
288+
return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
282289
}
283290

284291
/*

drivers/clocksource/acpi_pm.c

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/errno.h>
2222
#include <linux/init.h>
2323
#include <linux/pci.h>
24+
#include <linux/delay.h>
2425
#include <asm/io.h>
2526

2627
/*
@@ -151,13 +152,13 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
151152
*/
152153
static int verify_pmtmr_rate(void)
153154
{
154-
u32 value1, value2;
155+
cycle_t value1, value2;
155156
unsigned long count, delta;
156157

157158
mach_prepare_counter();
158-
value1 = read_pmtmr();
159+
value1 = clocksource_acpi_pm.read();
159160
mach_countup(&count);
160-
value2 = read_pmtmr();
161+
value2 = clocksource_acpi_pm.read();
161162
delta = (value2 - value1) & ACPI_PM_MASK;
162163

163164
/* Check that the PMTMR delta is within 5% of what we expect */
@@ -175,10 +176,13 @@ static int verify_pmtmr_rate(void)
175176
#define verify_pmtmr_rate() (0)
176177
#endif
177178

179+
/* Number of monotonicity checks to perform during initialization */
180+
#define ACPI_PM_MONOTONICITY_CHECKS 10
181+
178182
static int __init init_acpi_pm_clocksource(void)
179183
{
180-
u32 value1, value2;
181-
unsigned int i;
184+
cycle_t value1, value2;
185+
unsigned int i, j, good = 0;
182186

183187
if (!pmtmr_ioport)
184188
return -ENODEV;
@@ -187,24 +191,32 @@ static int __init init_acpi_pm_clocksource(void)
187191
clocksource_acpi_pm.shift);
188192

189193
/* "verify" this timing source: */
190-
value1 = read_pmtmr();
191-
for (i = 0; i < 10000; i++) {
192-
value2 = read_pmtmr();
193-
if (value2 == value1)
194-
continue;
195-
if (value2 > value1)
196-
goto pm_good;
197-
if ((value2 < value1) && ((value2) < 0xFFF))
198-
goto pm_good;
199-
printk(KERN_INFO "PM-Timer had inconsistent results:"
200-
" 0x%#x, 0x%#x - aborting.\n", value1, value2);
201-
return -EINVAL;
194+
for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
195+
value1 = clocksource_acpi_pm.read();
196+
for (i = 0; i < 10000; i++) {
197+
value2 = clocksource_acpi_pm.read();
198+
if (value2 == value1)
199+
continue;
200+
if (value2 > value1)
201+
good++;
202+
break;
203+
if ((value2 < value1) && ((value2) < 0xFFF))
204+
good++;
205+
break;
206+
printk(KERN_INFO "PM-Timer had inconsistent results:"
207+
" 0x%#llx, 0x%#llx - aborting.\n",
208+
value1, value2);
209+
return -EINVAL;
210+
}
211+
udelay(300 * i);
212+
}
213+
214+
if (good != ACPI_PM_MONOTONICITY_CHECKS) {
215+
printk(KERN_INFO "PM-Timer failed consistency check "
216+
" (0x%#llx) - aborting.\n", value1);
217+
return -ENODEV;
202218
}
203-
printk(KERN_INFO "PM-Timer had no reasonable result:"
204-
" 0x%#x - aborting.\n", value1);
205-
return -ENODEV;
206219

207-
pm_good:
208220
if (verify_pmtmr_rate() != 0)
209221
return -ENODEV;
210222

include/linux/clockchips.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ extern int clockevents_register_notifier(struct notifier_block *nb);
127127
extern int clockevents_program_event(struct clock_event_device *dev,
128128
ktime_t expires, ktime_t now);
129129

130+
extern void clockevents_handle_noop(struct clock_event_device *dev);
131+
130132
#ifdef CONFIG_GENERIC_CLOCKEVENTS
131133
extern void clockevents_notify(unsigned long reason, void *arg);
132134
#else

kernel/time/clockevents.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ void clockevents_register_device(struct clock_event_device *dev)
177177
/*
178178
* Noop handler when we shut down an event device
179179
*/
180-
static void clockevents_handle_noop(struct clock_event_device *dev)
180+
void clockevents_handle_noop(struct clock_event_device *dev)
181181
{
182182
}
183183

@@ -199,7 +199,6 @@ void clockevents_exchange_device(struct clock_event_device *old,
199199
* released list and do a notify add later.
200200
*/
201201
if (old) {
202-
old->event_handler = clockevents_handle_noop;
203202
clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
204203
list_del(&old->list);
205204
list_add(&old->list, &clockevents_released);

kernel/time/ntp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static void sync_cmos_clock(unsigned long dummy)
245245
if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
246246
fail = update_persistent_clock(now);
247247

248-
next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;
248+
next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
249249
if (next.tv_nsec <= 0)
250250
next.tv_nsec += NSEC_PER_SEC;
251251

kernel/time/tick-broadcast.c

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ static void tick_do_periodic_broadcast(void)
175175
*/
176176
static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
177177
{
178+
ktime_t next;
179+
178180
tick_do_periodic_broadcast();
179181

180182
/*
@@ -185,10 +187,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
185187

186188
/*
187189
* Setup the next period for devices, which do not have
188-
* periodic mode:
190+
* periodic mode. We read dev->next_event first and add to it
191+
* when the event alrady expired. clockevents_program_event()
192+
* sets dev->next_event only when the event is really
193+
* programmed to the device.
189194
*/
190-
for (;;) {
191-
ktime_t next = ktime_add(dev->next_event, tick_period);
195+
for (next = dev->next_event; ;) {
196+
next = ktime_add(next, tick_period);
192197

193198
if (!clockevents_program_event(dev, next, ktime_get()))
194199
return;
@@ -205,7 +210,7 @@ static void tick_do_broadcast_on_off(void *why)
205210
struct clock_event_device *bc, *dev;
206211
struct tick_device *td;
207212
unsigned long flags, *reason = why;
208-
int cpu;
213+
int cpu, bc_stopped;
209214

210215
spin_lock_irqsave(&tick_broadcast_lock, flags);
211216

@@ -223,6 +228,8 @@ static void tick_do_broadcast_on_off(void *why)
223228
if (!tick_device_is_functional(dev))
224229
goto out;
225230

231+
bc_stopped = cpus_empty(tick_broadcast_mask);
232+
226233
switch (*reason) {
227234
case CLOCK_EVT_NOTIFY_BROADCAST_ON:
228235
case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
@@ -245,9 +252,10 @@ static void tick_do_broadcast_on_off(void *why)
245252
break;
246253
}
247254

248-
if (cpus_empty(tick_broadcast_mask))
249-
clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
250-
else {
255+
if (cpus_empty(tick_broadcast_mask)) {
256+
if (!bc_stopped)
257+
clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
258+
} else if (bc_stopped) {
251259
if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
252260
tick_broadcast_start_periodic(bc);
253261
else
@@ -364,16 +372,8 @@ cpumask_t *tick_get_broadcast_oneshot_mask(void)
364372
static int tick_broadcast_set_event(ktime_t expires, int force)
365373
{
366374
struct clock_event_device *bc = tick_broadcast_device.evtdev;
367-
ktime_t now = ktime_get();
368-
int res;
369-
370-
for(;;) {
371-
res = clockevents_program_event(bc, expires, now);
372-
if (!res || !force)
373-
return res;
374-
now = ktime_get();
375-
expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
376-
}
375+
376+
return tick_dev_program_event(bc, expires, force);
377377
}
378378

379379
int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
@@ -491,14 +491,52 @@ static void tick_broadcast_clear_oneshot(int cpu)
491491
cpu_clear(cpu, tick_broadcast_oneshot_mask);
492492
}
493493

494+
static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
495+
{
496+
struct tick_device *td;
497+
int cpu;
498+
499+
for_each_cpu_mask_nr(cpu, *mask) {
500+
td = &per_cpu(tick_cpu_device, cpu);
501+
if (td->evtdev)
502+
td->evtdev->next_event = expires;
503+
}
504+
}
505+
494506
/**
495507
* tick_broadcast_setup_oneshot - setup the broadcast device
496508
*/
497509
void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
498510
{
499-
bc->event_handler = tick_handle_oneshot_broadcast;
500-
clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
501-
bc->next_event.tv64 = KTIME_MAX;
511+
/* Set it up only once ! */
512+
if (bc->event_handler != tick_handle_oneshot_broadcast) {
513+
int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
514+
int cpu = smp_processor_id();
515+
cpumask_t mask;
516+
517+
bc->event_handler = tick_handle_oneshot_broadcast;
518+
clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
519+
520+
/* Take the do_timer update */
521+
tick_do_timer_cpu = cpu;
522+
523+
/*
524+
* We must be careful here. There might be other CPUs
525+
* waiting for periodic broadcast. We need to set the
526+
* oneshot_mask bits for those and program the
527+
* broadcast device to fire.
528+
*/
529+
mask = tick_broadcast_mask;
530+
cpu_clear(cpu, mask);
531+
cpus_or(tick_broadcast_oneshot_mask,
532+
tick_broadcast_oneshot_mask, mask);
533+
534+
if (was_periodic && !cpus_empty(mask)) {
535+
tick_broadcast_init_next_event(&mask, tick_next_period);
536+
tick_broadcast_set_event(tick_next_period, 1);
537+
} else
538+
bc->next_event.tv64 = KTIME_MAX;
539+
}
502540
}
503541

504542
/*

kernel/time/tick-common.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ static void tick_setup_device(struct tick_device *td,
161161
} else {
162162
handler = td->evtdev->event_handler;
163163
next_event = td->evtdev->next_event;
164+
td->evtdev->event_handler = clockevents_handle_noop;
164165
}
165166

166167
td->evtdev = newdev;

kernel/time/tick-internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ extern void tick_handle_periodic(struct clock_event_device *dev);
1717
extern void tick_setup_oneshot(struct clock_event_device *newdev,
1818
void (*handler)(struct clock_event_device *),
1919
ktime_t nextevt);
20+
extern int tick_dev_program_event(struct clock_event_device *dev,
21+
ktime_t expires, int force);
2022
extern int tick_program_event(ktime_t expires, int force);
2123
extern void tick_oneshot_notify(void);
2224
extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));

kernel/time/tick-oneshot.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,57 @@
2323
#include "tick-internal.h"
2424

2525
/**
26-
* tick_program_event
26+
* tick_program_event internal worker function
2727
*/
28-
int tick_program_event(ktime_t expires, int force)
28+
int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
29+
int force)
2930
{
30-
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
3131
ktime_t now = ktime_get();
32+
int i;
3233

33-
while (1) {
34+
for (i = 0;;) {
3435
int ret = clockevents_program_event(dev, expires, now);
3536

3637
if (!ret || !force)
3738
return ret;
39+
40+
/*
41+
* We tried 2 times to program the device with the given
42+
* min_delta_ns. If that's not working then we double it
43+
* and emit a warning.
44+
*/
45+
if (++i > 2) {
46+
printk(KERN_WARNING "CE: __tick_program_event of %s is "
47+
"stuck %llx %llx\n", dev->name ? dev->name : "?",
48+
now.tv64, expires.tv64);
49+
printk(KERN_WARNING
50+
"CE: increasing min_delta_ns %ld to %ld nsec\n",
51+
dev->min_delta_ns, dev->min_delta_ns << 1);
52+
WARN_ON(1);
53+
54+
/* Double the min. delta and try again */
55+
if (!dev->min_delta_ns)
56+
dev->min_delta_ns = 5000;
57+
else
58+
dev->min_delta_ns <<= 1;
59+
i = 0;
60+
}
61+
3862
now = ktime_get();
39-
expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
63+
expires = ktime_add_ns(now, dev->min_delta_ns);
4064
}
4165
}
4266

67+
/**
68+
* tick_program_event
69+
*/
70+
int tick_program_event(ktime_t expires, int force)
71+
{
72+
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
73+
74+
return tick_dev_program_event(dev, expires, force);
75+
}
76+
4377
/**
4478
* tick_resume_onshot - resume oneshot mode
4579
*/
@@ -61,7 +95,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev,
6195
{
6296
newdev->event_handler = handler;
6397
clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
64-
clockevents_program_event(newdev, next_event, ktime_get());
98+
tick_dev_program_event(newdev, next_event, 1);
6599
}
66100

67101
/**

0 commit comments

Comments
 (0)