diff options
| -rw-r--r-- | arch/x86/kernel/setup.c | 3 | ||||
| -rw-r--r-- | include/linux/jiffies.h | 15 | ||||
| -rw-r--r-- | kernel/time/jiffies.c | 32 |
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 | 54 | extern 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 | |||
| 99 | struct clocksource refined_jiffies; | ||
| 100 | |||
| 101 | int 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 | } | ||
