|
@@ -25,18 +25,42 @@
|
|
/**
|
|
/**
|
|
* tick_program_event internal worker function
|
|
* tick_program_event internal worker function
|
|
*/
|
|
*/
|
|
-static int __tick_program_event(struct clock_event_device *dev,
|
|
|
|
- ktime_t expires, int force)
|
|
|
|
|
|
+int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
|
|
|
|
+ int force)
|
|
{
|
|
{
|
|
ktime_t now = ktime_get();
|
|
ktime_t now = ktime_get();
|
|
|
|
+ int i;
|
|
|
|
|
|
- while (1) {
|
|
|
|
|
|
+ for (i = 0;;) {
|
|
int ret = clockevents_program_event(dev, expires, now);
|
|
int ret = clockevents_program_event(dev, expires, now);
|
|
|
|
|
|
if (!ret || !force)
|
|
if (!ret || !force)
|
|
return ret;
|
|
return ret;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * We tried 2 times to program the device with the given
|
|
|
|
+ * min_delta_ns. If that's not working then we double it
|
|
|
|
+ * and emit a warning.
|
|
|
|
+ */
|
|
|
|
+ if (++i > 2) {
|
|
|
|
+ printk(KERN_WARNING "CE: __tick_program_event of %s is "
|
|
|
|
+ "stuck %llx %llx\n", dev->name ? dev->name : "?",
|
|
|
|
+ now.tv64, expires.tv64);
|
|
|
|
+ printk(KERN_WARNING
|
|
|
|
+ "CE: increasing min_delta_ns %ld to %ld nsec\n",
|
|
|
|
+ dev->min_delta_ns, dev->min_delta_ns << 1);
|
|
|
|
+ WARN_ON(1);
|
|
|
|
+
|
|
|
|
+ /* Double the min. delta and try again */
|
|
|
|
+ if (!dev->min_delta_ns)
|
|
|
|
+ dev->min_delta_ns = 5000;
|
|
|
|
+ else
|
|
|
|
+ dev->min_delta_ns <<= 1;
|
|
|
|
+ i = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
now = ktime_get();
|
|
now = ktime_get();
|
|
- expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
|
|
|
|
|
|
+ expires = ktime_add_ns(now, dev->min_delta_ns);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -47,7 +71,7 @@ int tick_program_event(ktime_t expires, int force)
|
|
{
|
|
{
|
|
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
|
|
struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
|
|
|
|
|
|
- return __tick_program_event(dev, expires, force);
|
|
|
|
|
|
+ return tick_dev_program_event(dev, expires, force);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -71,7 +95,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev,
|
|
{
|
|
{
|
|
newdev->event_handler = handler;
|
|
newdev->event_handler = handler;
|
|
clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
|
|
clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
|
|
- __tick_program_event(newdev, next_event, 1);
|
|
|
|
|
|
+ tick_dev_program_event(newdev, next_event, 1);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|