aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/hrtimer.h2
-rw-r--r--include/linux/tick.h3
-rw-r--r--kernel/hrtimer.c4
-rw-r--r--kernel/time/clocksource.c18
-rw-r--r--kernel/time/tick-oneshot.c17
5 files changed, 33 insertions, 11 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 58021b0c396d..0d2f7c8a33d6 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -305,7 +305,7 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)
305 305
306extern ktime_t ktime_get(void); 306extern ktime_t ktime_get(void);
307extern ktime_t ktime_get_real(void); 307extern ktime_t ktime_get_real(void);
308extern int hrtimer_hres_active(void); 308
309 309
310DECLARE_PER_CPU(struct tick_device, tick_cpu_device); 310DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
311 311
diff --git a/include/linux/tick.h b/include/linux/tick.h
index 469b82d88b3b..0482229c07db 100644
--- a/include/linux/tick.h
+++ b/include/linux/tick.h
@@ -97,10 +97,12 @@ extern void tick_clock_notify(void);
97extern int tick_check_oneshot_change(int allow_nohz); 97extern int tick_check_oneshot_change(int allow_nohz);
98extern struct tick_sched *tick_get_tick_sched(int cpu); 98extern struct tick_sched *tick_get_tick_sched(int cpu);
99extern void tick_check_idle(int cpu); 99extern void tick_check_idle(int cpu);
100extern int tick_oneshot_mode_active(void);
100# else 101# else
101static inline void tick_clock_notify(void) { } 102static inline void tick_clock_notify(void) { }
102static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } 103static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
103static inline void tick_check_idle(int cpu) { } 104static inline void tick_check_idle(int cpu) { }
105static inline int tick_oneshot_mode_active(void) { return 0; }
104# endif 106# endif
105 107
106#else /* CONFIG_GENERIC_CLOCKEVENTS */ 108#else /* CONFIG_GENERIC_CLOCKEVENTS */
@@ -109,6 +111,7 @@ static inline void tick_cancel_sched_timer(int cpu) { }
109static inline void tick_clock_notify(void) { } 111static inline void tick_clock_notify(void) { }
110static inline int tick_check_oneshot_change(int allow_nohz) { return 0; } 112static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
111static inline void tick_check_idle(int cpu) { } 113static inline void tick_check_idle(int cpu) { }
114static inline int tick_oneshot_mode_active(void) { return 0; }
112#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ 115#endif /* !CONFIG_GENERIC_CLOCKEVENTS */
113 116
114# ifdef CONFIG_NO_HZ 117# ifdef CONFIG_NO_HZ
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 1a70c18cdffe..cb8a15c19583 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -476,7 +476,7 @@ static inline int hrtimer_is_hres_enabled(void)
476/* 476/*
477 * Is the high resolution mode active ? 477 * Is the high resolution mode active ?
478 */ 478 */
479int hrtimer_hres_active(void) 479static inline int hrtimer_hres_active(void)
480{ 480{
481 return __get_cpu_var(hrtimer_bases).hres_active; 481 return __get_cpu_var(hrtimer_bases).hres_active;
482} 482}
@@ -704,7 +704,7 @@ static int hrtimer_switch_to_hres(void)
704 704
705#else 705#else
706 706
707int hrtimer_hres_active(void) { return 0; } 707static inline int hrtimer_hres_active(void) { return 0; }
708static inline int hrtimer_is_hres_enabled(void) { return 0; } 708static inline int hrtimer_is_hres_enabled(void) { return 0; }
709static inline int hrtimer_switch_to_hres(void) { return 0; } 709static inline int hrtimer_switch_to_hres(void) { return 0; }
710static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { } 710static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 18b9f5da4ee9..592bf584d1d2 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -30,7 +30,6 @@
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */ 31#include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */
32#include <linux/tick.h> 32#include <linux/tick.h>
33#include <linux/hrtimer.h>
34 33
35void timecounter_init(struct timecounter *tc, 34void timecounter_init(struct timecounter *tc,
36 const struct cyclecounter *cc, 35 const struct cyclecounter *cc,
@@ -511,13 +510,13 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
511 } 510 }
512 511
513 /* 512 /*
514 * Check to make sure we don't switch to a non-HRT usable 513 * Check to make sure we don't switch to a non-highres capable
515 * clocksource if HRT is enabled and running 514 * clocksource if the tick code is in oneshot mode (highres or nohz)
516 */ 515 */
517 if (hrtimer_hres_active() && 516 if (tick_oneshot_mode_active() &&
518 !(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) { 517 !(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) {
519 printk(KERN_WARNING "%s clocksource is not HRT compatible. " 518 printk(KERN_WARNING "%s clocksource is not HRT compatible. "
520 "Cannot switch while in HRT mode\n", ovr->name); 519 "Cannot switch while in HRT/NOHZ mode\n", ovr->name);
521 ovr = NULL; 520 ovr = NULL;
522 override_name[0] = 0; 521 override_name[0] = 0;
523 } 522 }
@@ -550,9 +549,12 @@ sysfs_show_available_clocksources(struct sys_device *dev,
550 549
551 spin_lock_irq(&clocksource_lock); 550 spin_lock_irq(&clocksource_lock);
552 list_for_each_entry(src, &clocksource_list, list) { 551 list_for_each_entry(src, &clocksource_list, list) {
553 /* Don't show non-HRES clocksource if HRES is enabled */ 552 /*
554 if (!hrtimer_hres_active() || 553 * Don't show non-HRES clocksource if the tick code is
555 (src->flags & CLOCK_SOURCE_VALID_FOR_HRES)) 554 * in one shot mode (highres=on or nohz=on)
555 */
556 if (!tick_oneshot_mode_active() ||
557 (src->flags & CLOCK_SOURCE_VALID_FOR_HRES))
556 count += snprintf(buf + count, 558 count += snprintf(buf + count,
557 max((ssize_t)PAGE_SIZE - count, (ssize_t)0), 559 max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
558 "%s ", src->name); 560 "%s ", src->name);
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
index 2e8de678e767..a96c0e2b89cf 100644
--- a/kernel/time/tick-oneshot.c
+++ b/kernel/time/tick-oneshot.c
@@ -128,6 +128,23 @@ int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
128 return 0; 128 return 0;
129} 129}
130 130
131/**
132 * tick_check_oneshot_mode - check whether the system is in oneshot mode
133 *
134 * returns 1 when either nohz or highres are enabled. otherwise 0.
135 */
136int tick_oneshot_mode_active(void)
137{
138 unsigned long flags;
139 int ret;
140
141 local_irq_save(flags);
142 ret = __get_cpu_var(tick_cpu_device).mode == TICKDEV_MODE_ONESHOT;
143 local_irq_restore(flags);
144
145 return ret;
146}
147
131#ifdef CONFIG_HIGH_RES_TIMERS 148#ifdef CONFIG_HIGH_RES_TIMERS
132/** 149/**
133 * tick_init_highres - switch to high resolution mode 150 * tick_init_highres - switch to high resolution mode