aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/setup.c3
-rw-r--r--include/linux/jiffies.h15
-rw-r--r--kernel/time/jiffies.c32
3 files changed, 36 insertions, 14 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index f4b9b80e1b95..4062f15bfbdd 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -68,6 +68,7 @@
68#include <linux/percpu.h> 68#include <linux/percpu.h>
69#include <linux/crash_dump.h> 69#include <linux/crash_dump.h>
70#include <linux/tboot.h> 70#include <linux/tboot.h>
71#include <linux/jiffies.h>
71 72
72#include <video/edid.h> 73#include <video/edid.h>
73 74
@@ -1034,6 +1035,8 @@ void __init setup_arch(char **cmdline_p)
1034 mcheck_init(); 1035 mcheck_init();
1035 1036
1036 arch_init_ideal_nops(); 1037 arch_init_ideal_nops();
1038
1039 register_refined_jiffies(CLOCK_TICK_RATE);
1037} 1040}
1038 1041
1039#ifdef CONFIG_X86_32 1042#ifdef CONFIG_X86_32
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 4a7e3864e80d..388edb54bfb6 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -51,21 +51,10 @@
51#define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ 51#define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \
52 + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) 52 + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN))
53 53
54#ifdef CLOCK_TICK_RATE 54extern int register_refined_jiffies(long clock_tick_rate);
55/* LATCH is used in the interval timer and ftape setup. */
56# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
57
58/*
59 * HZ is the requested value. However the CLOCK_TICK_RATE may not allow
60 * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy)
61 */
62# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8))
63#else
64# define SHIFTED_HZ (HZ << 8)
65#endif
66 55
67/* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */ 56/* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */
68#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8)) 57#define TICK_NSEC ((NSEC_PER_SEC+HZ/2)/HZ)
69 58
70/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ 59/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
71#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) 60#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index 46da0537c10b..6629bf7b5285 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -37,7 +37,7 @@
37 * requested HZ value. It is also not recommended 37 * requested HZ value. It is also not recommended
38 * for "tick-less" systems. 38 * for "tick-less" systems.
39 */ 39 */
40#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/SHIFTED_HZ)) 40#define NSEC_PER_JIFFY ((NSEC_PER_SEC+HZ/2)/HZ)
41 41
42/* Since jiffies uses a simple NSEC_PER_JIFFY multiplier 42/* Since jiffies uses a simple NSEC_PER_JIFFY multiplier
43 * conversion, the .shift value could be zero. However 43 * conversion, the .shift value could be zero. However
@@ -95,3 +95,33 @@ struct clocksource * __init __weak clocksource_default_clock(void)
95{ 95{
96 return &clocksource_jiffies; 96 return &clocksource_jiffies;
97} 97}
98
99struct clocksource refined_jiffies;
100
101int register_refined_jiffies(long cycles_per_second)
102{
103 u64 nsec_per_tick, shift_hz;
104 long cycles_per_tick;
105
106
107
108 refined_jiffies = clocksource_jiffies;
109 refined_jiffies.name = "refined-jiffies";
110 refined_jiffies.rating++;
111
112 /* Calc cycles per tick */
113 cycles_per_tick = (cycles_per_second + HZ/2)/HZ;
114 /* shift_hz stores hz<<8 for extra accuracy */
115 shift_hz = (u64)cycles_per_second << 8;
116 shift_hz += cycles_per_tick/2;
117 do_div(shift_hz, cycles_per_tick);
118 /* Calculate nsec_per_tick using shift_hz */
119 nsec_per_tick = (u64)NSEC_PER_SEC << 8;
120 nsec_per_tick += (u32)shift_hz/2;
121 do_div(nsec_per_tick, (u32)shift_hz);
122
123 refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT;
124
125 clocksource_register(&refined_jiffies);
126 return 0;
127}