Commit d7e81c269db899b800e0963dc4aceece1f82a680

Authored by John Stultz
Committed by Thomas Gleixner
1 parent 29f87b793d

clocksource: Add clocksource_register_hz/khz interface

How to pick good mult/shift pairs has always been difficult to
describe to folks writing clocksource drivers, since it requires
careful tradeoffs in adjustment accuracy vs overflow limits.

Now, with the clocks_calc_mult_shift function, its much
easier. However, not many clocksources have converted to using that
function, and there is still the issue of the max interval length
assumption being made by each clocksource driver independently.

So this patch simplifies the registration process by having
clocksources be registered with a hz/khz value and the registration
function taking care of setting mult/shift.

This should take most of the confusion out of writing a clocksource
driver.

Additionally it also keeps the shift size tradeoff (more accuracy vs
longer possible nohz times) centralized so the timekeeping core can
keep track of the assumptions being made.

[ tglx: Coding style and comments fixed ]

Signed-off-by: John Stultz <johnstul@us.ibm.com>
LKML-Reference: <1273280858-30143-1-git-send-email-johnstul@us.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Showing 2 changed files with 66 additions and 1 deletions Side-by-side Diff

include/linux/clocksource.h
... ... @@ -273,7 +273,6 @@
273 273 }
274 274  
275 275  
276   -/* used to install a new clocksource */
277 276 extern int clocksource_register(struct clocksource*);
278 277 extern void clocksource_unregister(struct clocksource*);
279 278 extern void clocksource_touch_watchdog(void);
... ... @@ -286,6 +285,24 @@
286 285  
287 286 extern void
288 287 clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec);
  288 +
  289 +/*
  290 + * Don't call __clocksource_register_scale directly, use
  291 + * clocksource_register_hz/khz
  292 + */
  293 +extern int
  294 +__clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq);
  295 +
  296 +static inline int clocksource_register_hz(struct clocksource *cs, u32 hz)
  297 +{
  298 + return __clocksource_register_scale(cs, 1, hz);
  299 +}
  300 +
  301 +static inline int clocksource_register_khz(struct clocksource *cs, u32 khz)
  302 +{
  303 + return __clocksource_register_scale(cs, 1000, khz);
  304 +}
  305 +
289 306  
290 307 static inline void
291 308 clocksource_calc_mult_shift(struct clocksource *cs, u32 freq, u32 minsec)
kernel/time/clocksource.c
... ... @@ -625,6 +625,54 @@
625 625 list_add(&cs->list, entry);
626 626 }
627 627  
  628 +
  629 +/*
  630 + * Maximum time we expect to go between ticks. This includes idle
  631 + * tickless time. It provides the trade off between selecting a
  632 + * mult/shift pair that is very precise but can only handle a short
  633 + * period of time, vs. a mult/shift pair that can handle long periods
  634 + * of time but isn't as precise.
  635 + *
  636 + * This is a subsystem constant, and actual hardware limitations
  637 + * may override it (ie: clocksources that wrap every 3 seconds).
  638 + */
  639 +#define MAX_UPDATE_LENGTH 5 /* Seconds */
  640 +
  641 +/**
  642 + * __clocksource_register_scale - Used to install new clocksources
  643 + * @t: clocksource to be registered
  644 + * @scale: Scale factor multiplied against freq to get clocksource hz
  645 + * @freq: clocksource frequency (cycles per second) divided by scale
  646 + *
  647 + * Returns -EBUSY if registration fails, zero otherwise.
  648 + *
  649 + * This *SHOULD NOT* be called directly! Please use the
  650 + * clocksource_register_hz() or clocksource_register_khz helper functions.
  651 + */
  652 +int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
  653 +{
  654 +
  655 + /*
  656 + * Ideally we want to use some of the limits used in
  657 + * clocksource_max_deferment, to provide a more informed
  658 + * MAX_UPDATE_LENGTH. But for now this just gets the
  659 + * register interface working properly.
  660 + */
  661 + clocks_calc_mult_shift(&cs->mult, &cs->shift, freq,
  662 + NSEC_PER_SEC/scale,
  663 + MAX_UPDATE_LENGTH*scale);
  664 + cs->max_idle_ns = clocksource_max_deferment(cs);
  665 +
  666 + mutex_lock(&clocksource_mutex);
  667 + clocksource_enqueue(cs);
  668 + clocksource_select();
  669 + clocksource_enqueue_watchdog(cs);
  670 + mutex_unlock(&clocksource_mutex);
  671 + return 0;
  672 +}
  673 +EXPORT_SYMBOL_GPL(__clocksource_register_scale);
  674 +
  675 +
628 676 /**
629 677 * clocksource_register - Used to install new clocksources
630 678 * @t: clocksource to be registered