* [PATCH 1/5] Implement {read,update}_persistent_clock.
@ 2007-09-19 6:49 Tony Breeds
2007-09-19 6:49 ` [PATCH 3/5] Implement clockevents driver for powerpc Tony Breeds
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: Tony Breeds @ 2007-09-19 6:49 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
With these functions implemented we cooperate better with the generic
timekeeping code. This obsoletes the need for the timer sysdev as a bonus.
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
* Compile tested for arch/powerpc/configs/*_defconfig
* Booted on pSeries, iSeries, Cell and PS3
arch/powerpc/Kconfig | 3 +
arch/powerpc/kernel/time.c | 85 ++++++++++-------------------------
arch/powerpc/sysdev/Makefile | 5 --
arch/powerpc/sysdev/timer.c | 81 ---------------------------------
4 files changed, 29 insertions(+), 145 deletions(-)
Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -21,6 +21,9 @@ config MMU
bool
default y
+config GENERIC_CMOS_UPDATE
+ def_bool y
+
config GENERIC_HARDIRQS
bool
default y
Index: working/arch/powerpc/kernel/time.c
===================================================================
--- working.orig/arch/powerpc/kernel/time.c
+++ working/arch/powerpc/kernel/time.c
@@ -74,16 +74,11 @@
#endif
#include <asm/smp.h>
-/* keep track of when we need to update the rtc */
-time_t last_rtc_update;
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
static signed long __initdata iSeries_recal_tb;
#endif
-/* The decrementer counts down by 128 every 128ns on a 601. */
-#define DECREMENTER_COUNT_601 (1000000000 / HZ)
-
#define XSEC_PER_SEC (1024*1024)
#ifdef CONFIG_PPC64
@@ -349,39 +344,6 @@ void udelay(unsigned long usecs)
}
EXPORT_SYMBOL(udelay);
-static __inline__ void timer_check_rtc(void)
-{
- /*
- * update the rtc when needed, this should be performed on the
- * right fraction of a second. Half or full second ?
- * Full second works on mk48t59 clocks, others need testing.
- * Note that this update is basically only used through
- * the adjtimex system calls. Setting the HW clock in
- * any other way is a /dev/rtc and userland business.
- * This is still wrong by -0.5/+1.5 jiffies because of the
- * timer interrupt resolution and possible delay, but here we
- * hit a quantization limit which can only be solved by higher
- * resolution timers and decoupling time management from timer
- * interrupts. This is also wrong on the clocks
- * which require being written at the half second boundary.
- * We should have an rtc call that only sets the minutes and
- * seconds like on Intel to avoid problems with non UTC clocks.
- */
- if (ppc_md.set_rtc_time && ntp_synced() &&
- xtime.tv_sec - last_rtc_update >= 659 &&
- abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ) {
- struct rtc_time tm;
- to_tm(xtime.tv_sec + 1 + timezone_offset, &tm);
- tm.tm_year -= 1900;
- tm.tm_mon -= 1;
- if (ppc_md.set_rtc_time(&tm) == 0)
- last_rtc_update = xtime.tv_sec + 1;
- else
- /* Try again one minute later */
- last_rtc_update += 60;
- }
-}
-
/*
* This version of gettimeofday has microsecond resolution.
*/
@@ -690,7 +652,6 @@ void timer_interrupt(struct pt_regs * re
tb_last_jiffy = tb_next_jiffy;
do_timer(1);
timer_recalc_offset(tb_last_jiffy);
- timer_check_rtc();
}
write_sequnlock(&xtime_lock);
}
@@ -802,11 +763,6 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, new_sec, new_nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
- /* In case of a large backwards jump in time with NTP, we want the
- * clock to be updated as soon as the PLL is again in lock.
- */
- last_rtc_update = new_sec - 658;
-
ntp_clear();
new_xsec = xtime.tv_nsec;
@@ -882,12 +838,35 @@ void __init generic_calibrate_decr(void)
#endif
}
-unsigned long get_boot_time(void)
+int update_persistent_clock(struct timespec now)
{
struct rtc_time tm;
- if (ppc_md.get_boot_time)
- return ppc_md.get_boot_time();
+ if (!ppc_md.set_rtc_time)
+ return 0;
+
+ to_tm(now.tv_sec + 1 + timezone_offset, &tm);
+ tm.tm_year -= 1900;
+ tm.tm_mon -= 1;
+
+ return ppc_md.set_rtc_time(&tm);
+}
+
+unsigned long read_persistent_clock(void)
+{
+ struct rtc_time tm;
+ static int first = 1;
+
+ /* XXX this is a litle fragile but will work okay in the short term */
+ if (first) {
+ first = 0;
+ if (ppc_md.time_init)
+ timezone_offset = ppc_md.time_init();
+
+ /* get_boot_time() isn't guaranteed to be safe to call late */
+ if (ppc_md.get_boot_time)
+ return ppc_md.get_boot_time() -timezone_offset;
+ }
if (!ppc_md.get_rtc_time)
return 0;
ppc_md.get_rtc_time(&tm);
@@ -899,14 +878,10 @@ unsigned long get_boot_time(void)
void __init time_init(void)
{
unsigned long flags;
- unsigned long tm = 0;
struct div_result res;
u64 scale, x;
unsigned shift;
- if (ppc_md.time_init != NULL)
- timezone_offset = ppc_md.time_init();
-
if (__USE_RTC()) {
/* 601 processor: dec counts down by 128 every 128ns */
ppc_tb_freq = 1000000000;
@@ -981,19 +956,14 @@ void __init time_init(void)
/* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
boot_tb = get_tb_or_rtc();
- tm = get_boot_time();
-
write_seqlock_irqsave(&xtime_lock, flags);
/* If platform provided a timezone (pmac), we correct the time */
if (timezone_offset) {
sys_tz.tz_minuteswest = -timezone_offset / 60;
sys_tz.tz_dsttime = 0;
- tm -= timezone_offset;
}
- xtime.tv_sec = tm;
- xtime.tv_nsec = 0;
do_gtod.varp = &do_gtod.vars[0];
do_gtod.var_idx = 0;
do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
@@ -1011,9 +981,6 @@ void __init time_init(void)
time_freq = 0;
- last_rtc_update = xtime.tv_sec;
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irqrestore(&xtime_lock, flags);
/* Not exact, but the timer interrupt takes care of this */
Index: working/arch/powerpc/sysdev/Makefile
===================================================================
--- working.orig/arch/powerpc/sysdev/Makefile
+++ working/arch/powerpc/sysdev/Makefile
@@ -20,11 +20,6 @@ obj-$(CONFIG_MV64X60) += $(mv64x60-y) m
obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o
obj-$(CONFIG_AXON_RAM) += axonram.o
-# contains only the suspend handler for time
-ifeq ($(CONFIG_RTC_CLASS),)
-obj-$(CONFIG_PM) += timer.o
-endif
-
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
obj-$(CONFIG_PPC_I8259) += i8259.o
Index: working/arch/powerpc/sysdev/timer.c
===================================================================
--- working.orig/arch/powerpc/sysdev/timer.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Common code to keep time when machine suspends.
- *
- * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
- *
- * GPLv2
- */
-
-#include <linux/time.h>
-#include <linux/sysdev.h>
-#include <asm/rtc.h>
-
-static unsigned long suspend_rtc_time;
-
-/*
- * Reset the time after a sleep.
- */
-static int timer_resume(struct sys_device *dev)
-{
- struct timeval tv;
- struct timespec ts;
- struct rtc_time cur_rtc_tm;
- unsigned long cur_rtc_time, diff;
-
- /* get current RTC time and convert to seconds */
- get_rtc_time(&cur_rtc_tm);
- cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900,
- cur_rtc_tm.tm_mon + 1,
- cur_rtc_tm.tm_mday,
- cur_rtc_tm.tm_hour,
- cur_rtc_tm.tm_min,
- cur_rtc_tm.tm_sec);
-
- diff = cur_rtc_time - suspend_rtc_time;
-
- /* adjust time of day by seconds that elapsed while
- * we were suspended */
- do_gettimeofday(&tv);
- ts.tv_sec = tv.tv_sec + diff;
- ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC;
- do_settimeofday(&ts);
-
- return 0;
-}
-
-static int timer_suspend(struct sys_device *dev, pm_message_t state)
-{
- struct rtc_time suspend_rtc_tm;
- WARN_ON(!ppc_md.get_rtc_time);
-
- get_rtc_time(&suspend_rtc_tm);
- suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900,
- suspend_rtc_tm.tm_mon + 1,
- suspend_rtc_tm.tm_mday,
- suspend_rtc_tm.tm_hour,
- suspend_rtc_tm.tm_min,
- suspend_rtc_tm.tm_sec);
-
- return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
- .resume = timer_resume,
- .suspend = timer_suspend,
- set_kset_name("timer"),
-};
-
-static struct sys_device device_timer = {
- .id = 0,
- .cls = &timer_sysclass,
-};
-
-static int time_init_device(void)
-{
- int error = sysdev_class_register(&timer_sysclass);
- if (!error)
- error = sysdev_register(&device_timer);
- return error;
-}
-
-device_initcall(time_init_device);
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 4/5] Include hrtimer.h in tick.h.
2007-09-19 6:49 [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
2007-09-19 6:49 ` [PATCH 3/5] Implement clockevents driver for powerpc Tony Breeds
@ 2007-09-19 6:49 ` Tony Breeds
2007-09-19 6:49 ` [PATCH 2/5] Implement generic time of day clocksource for powerpc machines Tony Breeds
` (2 subsequent siblings)
4 siblings, 0 replies; 15+ messages in thread
From: Tony Breeds @ 2007-09-19 6:49 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
struct tick_shed uses struct hrtimer, explictly include the right header file.
preemtivly fixes the following warning
CC arch/powerpc/platforms/iseries/setup.o
In file included from arch/powerpc/platforms/iseries/setup.c:30:
include/linux/tick.h:45: error: field 'sched_timer' has incomplete type
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
include/linux/tick.h | 1 +
1 file changed, 1 insertion(+)
Index: working/include/linux/tick.h
===================================================================
--- working.orig/include/linux/tick.h
+++ working/include/linux/tick.h
@@ -7,6 +7,7 @@
#define _LINUX_TICK_H
#include <linux/clockchips.h>
+#include <linux/hrtimer.h>
#ifdef CONFIG_GENERIC_CLOCKEVENTS
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-19 6:49 [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
2007-09-19 6:49 ` [PATCH 3/5] Implement clockevents driver for powerpc Tony Breeds
2007-09-19 6:49 ` [PATCH 4/5] Include hrtimer.h in tick.h Tony Breeds
@ 2007-09-19 6:49 ` Tony Breeds
2007-09-19 15:43 ` Daniel Walker
2007-09-19 6:49 ` [PATCH 5/5] Enable tickless idle and high res timers for powerpc Tony Breeds
2007-09-19 6:53 ` [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
4 siblings, 1 reply; 15+ messages in thread
From: Tony Breeds @ 2007-09-19 6:49 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/Kconfig | 6
arch/powerpc/kernel/time.c | 255 ++++++++++++-------------------------
2 files changed, 91 insertions(+), 170 deletions(-)
Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -24,6 +24,12 @@ config MMU
config GENERIC_CMOS_UPDATE
def_bool y
+config GENERIC_TIME
+ def_bool y
+
+config GENERIC_TIME_VSYSCALL
+ def_bool y
+
config GENERIC_HARDIRQS
bool
default y
Index: working/arch/powerpc/kernel/time.c
===================================================================
--- working.orig/arch/powerpc/kernel/time.c
+++ working/arch/powerpc/kernel/time.c
@@ -74,9 +74,28 @@
#endif
#include <asm/smp.h>
+/* powerpc clocksource/clockevent code */
+
+#include <linux/clocksource.h>
+
+static cycle_t timebase_read(void);
+
+static struct clocksource clocksource_timebase = {
+ .name = "timebase",
+ .rating = 400,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .mask = CLOCKSOURCE_MASK(64),
+ .shift = 22,
+ .mult = 0, /* To be filled in */
+ .read = timebase_read,
+};
+
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
static signed long __initdata iSeries_recal_tb;
+
+/* Forward declaration is only needed for iSereis compiles */
+void __init clocksource_init(void);
#endif
#define XSEC_PER_SEC (1024*1024)
@@ -344,65 +363,6 @@ void udelay(unsigned long usecs)
}
EXPORT_SYMBOL(udelay);
-/*
- * This version of gettimeofday has microsecond resolution.
- */
-static inline void __do_gettimeofday(struct timeval *tv)
-{
- unsigned long sec, usec;
- u64 tb_ticks, xsec;
- struct gettimeofday_vars *temp_varp;
- u64 temp_tb_to_xs, temp_stamp_xsec;
-
- /*
- * These calculations are faster (gets rid of divides)
- * if done in units of 1/2^20 rather than microseconds.
- * The conversion to microseconds at the end is done
- * without a divide (and in fact, without a multiply)
- */
- temp_varp = do_gtod.varp;
-
- /* Sampling the time base must be done after loading
- * do_gtod.varp in order to avoid racing with update_gtod.
- */
- data_barrier(temp_varp);
- tb_ticks = get_tb() - temp_varp->tb_orig_stamp;
- temp_tb_to_xs = temp_varp->tb_to_xs;
- temp_stamp_xsec = temp_varp->stamp_xsec;
- xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
- sec = xsec / XSEC_PER_SEC;
- usec = (unsigned long)xsec & (XSEC_PER_SEC - 1);
- usec = SCALE_XSEC(usec, 1000000);
-
- tv->tv_sec = sec;
- tv->tv_usec = usec;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
- if (__USE_RTC()) {
- /* do this the old way */
- unsigned long flags, seq;
- unsigned int sec, nsec, usec;
-
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- sec = xtime.tv_sec;
- nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
- usec = nsec / 1000;
- while (usec >= 1000000) {
- usec -= 1000000;
- ++sec;
- }
- tv->tv_sec = sec;
- tv->tv_usec = usec;
- return;
- }
- __do_gettimeofday(tv);
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
/*
* There are two copies of tb_to_xs and stamp_xsec so that no
@@ -448,56 +408,6 @@ static inline void update_gtod(u64 new_t
++(vdso_data->tb_update_count);
}
-/*
- * When the timebase - tb_orig_stamp gets too big, we do a manipulation
- * between tb_orig_stamp and stamp_xsec. The goal here is to keep the
- * difference tb - tb_orig_stamp small enough to always fit inside a
- * 32 bits number. This is a requirement of our fast 32 bits userland
- * implementation in the vdso. If we "miss" a call to this function
- * (interrupt latency, CPU locked in a spinlock, ...) and we end up
- * with a too big difference, then the vdso will fallback to calling
- * the syscall
- */
-static __inline__ void timer_recalc_offset(u64 cur_tb)
-{
- unsigned long offset;
- u64 new_stamp_xsec;
- u64 tlen, t2x;
- u64 tb, xsec_old, xsec_new;
- struct gettimeofday_vars *varp;
-
- if (__USE_RTC())
- return;
- tlen = current_tick_length();
- offset = cur_tb - do_gtod.varp->tb_orig_stamp;
- if (tlen == last_tick_len && offset < 0x80000000u)
- return;
- if (tlen != last_tick_len) {
- t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs);
- last_tick_len = tlen;
- } else
- t2x = do_gtod.varp->tb_to_xs;
- new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
- do_div(new_stamp_xsec, 1000000000);
- new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
-
- ++vdso_data->tb_update_count;
- smp_mb();
-
- /*
- * Make sure time doesn't go backwards for userspace gettimeofday.
- */
- tb = get_tb();
- varp = do_gtod.varp;
- xsec_old = mulhdu(tb - varp->tb_orig_stamp, varp->tb_to_xs)
- + varp->stamp_xsec;
- xsec_new = mulhdu(tb - cur_tb, t2x) + new_stamp_xsec;
- if (xsec_new < xsec_old)
- new_stamp_xsec += xsec_old - xsec_new;
-
- update_gtod(cur_tb, new_stamp_xsec, t2x);
-}
-
#ifdef CONFIG_SMP
unsigned long profile_pc(struct pt_regs *regs)
{
@@ -569,6 +479,8 @@ static int __init iSeries_tb_recal(void)
iSeries_recal_titan = titan;
iSeries_recal_tb = tb;
+ /* Called here as now we know accurate values for the timebase */
+ clocksource_init();
return 0;
}
late_initcall(iSeries_tb_recal);
@@ -651,7 +563,6 @@ void timer_interrupt(struct pt_regs * re
if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
tb_last_jiffy = tb_next_jiffy;
do_timer(1);
- timer_recalc_offset(tb_last_jiffy);
}
write_sequnlock(&xtime_lock);
}
@@ -723,66 +634,6 @@ unsigned long long sched_clock(void)
return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
}
-int do_settimeofday(struct timespec *tv)
-{
- time_t wtm_sec, new_sec = tv->tv_sec;
- long wtm_nsec, new_nsec = tv->tv_nsec;
- unsigned long flags;
- u64 new_xsec;
- unsigned long tb_delta;
-
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
- return -EINVAL;
-
- write_seqlock_irqsave(&xtime_lock, flags);
-
- /*
- * Updating the RTC is not the job of this code. If the time is
- * stepped under NTP, the RTC will be updated after STA_UNSYNC
- * is cleared. Tools like clock/hwclock either copy the RTC
- * to the system time, in which case there is no point in writing
- * to the RTC again, or write to the RTC but then they don't call
- * settimeofday to perform this operation.
- */
-
- /* Make userspace gettimeofday spin until we're done. */
- ++vdso_data->tb_update_count;
- smp_mb();
-
- /*
- * Subtract off the number of nanoseconds since the
- * beginning of the last tick.
- */
- tb_delta = tb_ticks_since(tb_last_jiffy);
- tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
- new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
-
- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
-
- set_normalized_timespec(&xtime, new_sec, new_nsec);
- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
- ntp_clear();
-
- new_xsec = xtime.tv_nsec;
- if (new_xsec != 0) {
- new_xsec *= XSEC_PER_SEC;
- do_div(new_xsec, NSEC_PER_SEC);
- }
- new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
- update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
-
- vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
- vdso_data->tz_dsttime = sys_tz.tz_dsttime;
-
- write_sequnlock_irqrestore(&xtime_lock, flags);
- clock_was_set();
- return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
static int __init get_freq(char *name, int cells, unsigned long *val)
{
struct device_node *cpu;
@@ -874,6 +725,64 @@ unsigned long read_persistent_clock(void
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
+/* clocksource code */
+/* FIXME: provide an RTC clocksource /or/ use a better name */
+static cycle_t timebase_read(void)
+{
+ if (__USE_RTC())
+ return (cycle_t)get_rtc();
+ return (cycle_t)get_tb();
+}
+
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+{
+ u64 t2x, stamp_xsec;
+
+ if (__USE_RTC() || clock != &clocksource_timebase)
+ return;
+
+ /* Make userspace gettimeofday spin until we're done. */
+ ++vdso_data->tb_update_count;
+ smp_mb();
+
+ /* XXX this assumes clock->shift == 22 */
+ /* 4611686018 ~= 2^(20+64-22) / 1e9 */
+ t2x = (u64) clock->mult * 4611686018ULL;
+ stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
+ do_div(stamp_xsec, 1000000000);
+ stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
+ update_gtod(clock->cycle_last, stamp_xsec, t2x);
+}
+
+void update_vsyscall_tz(void)
+{
+ /* Make userspace gettimeofday spin until we're done. */
+ ++vdso_data->tb_update_count;
+ smp_mb();
+ vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
+ vdso_data->tz_dsttime = sys_tz.tz_dsttime;
+ smp_mb();
+ ++vdso_data->tb_update_count;
+}
+
+void __init clocksource_init(void)
+{
+ int mult = clocksource_hz2mult(tb_ticks_per_sec,
+ clocksource_timebase.shift);
+
+ clocksource_timebase.mult = mult;
+
+ if (clocksource_register(&clocksource_timebase)) {
+ printk(KERN_ERR "clocksource: %s is already registered\n",
+ clocksource_timebase.name);
+ return;
+ }
+
+ printk(KERN_INFO "clocksource: %s mult[%x] shift[%d] registered\n",
+ clocksource_timebase.name,
+ clocksource_timebase.mult, clocksource_timebase.shift);
+}
+
/* This function is only called on the boot processor */
void __init time_init(void)
{
@@ -983,6 +892,12 @@ void __init time_init(void)
write_sequnlock_irqrestore(&xtime_lock, flags);
+ /* Register the clocksource, if we're not running on iSeries */
+#ifdef CONFIG_ISERIES
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+#endif
+ clocksource_init();
+
/* Not exact, but the timer interrupt takes care of this */
set_dec(tb_ticks_per_jiffy);
}
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/5] Implement clockevents driver for powerpc
2007-09-19 6:49 [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
@ 2007-09-19 6:49 ` Tony Breeds
2007-09-19 6:49 ` [PATCH 4/5] Include hrtimer.h in tick.h Tony Breeds
` (3 subsequent siblings)
4 siblings, 0 replies; 15+ messages in thread
From: Tony Breeds @ 2007-09-19 6:49 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/Kconfig | 3
arch/powerpc/kernel/smp.c | 3
arch/powerpc/kernel/time.c | 134 +++++++++++++++++++++++++------------
include/asm-powerpc/time.h | 1
4 files changed, 98 insertions(+), 43 deletions(-)
Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -30,6 +30,9 @@ config GENERIC_TIME
config GENERIC_TIME_VSYSCALL
def_bool y
+config GENERIC_CLOCKEVENTS
+ def_bool y
+
config GENERIC_HARDIRQS
bool
default y
Index: working/arch/powerpc/kernel/smp.c
===================================================================
--- working.orig/arch/powerpc/kernel/smp.c
+++ working/arch/powerpc/kernel/smp.c
@@ -560,6 +560,9 @@ int __devinit start_secondary(void *unus
if (system_state > SYSTEM_BOOTING)
snapshot_timebase();
+ /* FIXME: should be in if() above */
+ secondary_cpu_time_init();
+
spin_lock(&call_lock);
cpu_set(cpu, cpu_online_map);
spin_unlock(&call_lock);
Index: working/arch/powerpc/kernel/time.c
===================================================================
--- working.orig/arch/powerpc/kernel/time.c
+++ working/arch/powerpc/kernel/time.c
@@ -76,6 +76,7 @@
/* powerpc clocksource/clockevent code */
+#include <linux/clockchips.h>
#include <linux/clocksource.h>
static cycle_t timebase_read(void);
@@ -90,6 +91,27 @@ static struct clocksource clocksource_ti
.read = timebase_read,
};
+#define DECREMENTER_MAX 0x7fffffff
+
+static int decrementer_set_next_event(unsigned long evt,
+ struct clock_event_device *dev);
+static void decrementer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *dev);
+
+static struct clock_event_device decrementer_clockevent = {
+ .name = "decrementer",
+ .rating = 200,
+ .shift = 32,
+ .mult = 0, /* To be filled in */
+ .irq = -1,
+ .set_next_event = decrementer_set_next_event,
+ .set_mode = decrementer_set_mode,
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+};
+
+static DEFINE_PER_CPU(struct clock_event_device, decrementers);
+void init_decrementer_clockevent(void);
+
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
static signed long __initdata iSeries_recal_tb;
@@ -510,10 +532,12 @@ void __init iSeries_time_init_early(void
void timer_interrupt(struct pt_regs * regs)
{
struct pt_regs *old_regs;
- int next_dec;
int cpu = smp_processor_id();
- unsigned long ticks;
- u64 tb_next_jiffy;
+ struct clock_event_device *evt = &per_cpu(decrementers, cpu);
+
+ /* Ensure a positive value is written to the decrementer, or else
+ * some CPUs will continuue to take decrementer exceptions */
+ set_dec(DECREMENTER_MAX);
#ifdef CONFIG_PPC32
if (atomic_read(&ppc_n_lost_interrupts) != 0)
@@ -523,7 +547,6 @@ void timer_interrupt(struct pt_regs * re
old_regs = set_irq_regs(regs);
irq_enter();
- profile_tick(CPU_PROFILING);
calculate_steal_time();
#ifdef CONFIG_PPC_ISERIES
@@ -531,44 +554,20 @@ void timer_interrupt(struct pt_regs * re
get_lppaca()->int_dword.fields.decr_int = 0;
#endif
- while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
- >= tb_ticks_per_jiffy) {
- /* Update last_jiffy */
- per_cpu(last_jiffy, cpu) += tb_ticks_per_jiffy;
- /* Handle RTCL overflow on 601 */
- if (__USE_RTC() && per_cpu(last_jiffy, cpu) >= 1000000000)
- per_cpu(last_jiffy, cpu) -= 1000000000;
-
- /*
- * We cannot disable the decrementer, so in the period
- * between this cpu's being marked offline in cpu_online_map
- * and calling stop-self, it is taking timer interrupts.
- * Avoid calling into the scheduler rebalancing code if this
- * is the case.
- */
- if (!cpu_is_offline(cpu))
- account_process_time(regs);
-
- /*
- * No need to check whether cpu is offline here; boot_cpuid
- * should have been fixed up by now.
- */
- if (cpu != boot_cpuid)
- continue;
+ /*
+ * We cannot disable the decrementer, so in the period
+ * between this cpu's being marked offline in cpu_online_map
+ * and calling stop-self, it is taking timer interrupts.
+ * Avoid calling into the scheduler rebalancing code if this
+ * is the case.
+ */
+ if (!cpu_is_offline(cpu))
+ account_process_time(regs);
- write_seqlock(&xtime_lock);
- tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
- if (__USE_RTC() && tb_next_jiffy >= 1000000000)
- tb_next_jiffy -= 1000000000;
- if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
- tb_last_jiffy = tb_next_jiffy;
- do_timer(1);
- }
- write_sequnlock(&xtime_lock);
- }
-
- next_dec = tb_ticks_per_jiffy - ticks;
- set_dec(next_dec);
+ if (evt->event_handler)
+ evt->event_handler(evt);
+ else
+ evt->set_next_event(DECREMENTER_MAX, evt);
#ifdef CONFIG_PPC_ISERIES
if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending())
@@ -781,8 +780,58 @@ void __init clocksource_init(void)
printk(KERN_INFO "clocksource: %s mult[%x] shift[%d] registered\n",
clocksource_timebase.name,
clocksource_timebase.mult, clocksource_timebase.shift);
+
+ return;
+}
+
+static int decrementer_set_next_event(unsigned long evt,
+ struct clock_event_device *dev)
+{
+ set_dec(evt);
+ return 0;
+}
+
+static void decrementer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *dev)
+{
+ if (mode != CLOCK_EVT_MODE_ONESHOT)
+ decrementer_set_next_event(DECREMENTER_MAX, dev);
+}
+
+static void register_decrementer_clockevent(int cpu)
+{
+ struct clock_event_device *dec = &per_cpu(decrementers, cpu);
+
+ *dec = decrementer_clockevent;
+ dec->cpumask = cpumask_of_cpu(cpu);
+
+ printk(KERN_ERR "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n",
+ dec->name, dec->mult, dec->shift, cpu);
+
+ clockevents_register_device(dec);
+}
+
+void init_decrementer_clockevent(void)
+{
+ int cpu = smp_processor_id();
+
+ decrementer_clockevent.mult = div_sc(ppc_tb_freq, NSEC_PER_SEC,
+ decrementer_clockevent.shift);
+ decrementer_clockevent.max_delta_ns =
+ clockevent_delta2ns(DECREMENTER_MAX, &decrementer_clockevent);
+ decrementer_clockevent.min_delta_ns = 1000;
+
+ register_decrementer_clockevent(cpu);
}
+void secondary_cpu_time_init(void)
+{
+ /* FIME: Should make unrelatred change to move snapshot_timebase
+ * call here ! */
+ register_decrementer_clockevent(smp_processor_id());
+}
+
+
/* This function is only called on the boot processor */
void __init time_init(void)
{
@@ -898,8 +947,7 @@ void __init time_init(void)
#endif
clocksource_init();
- /* Not exact, but the timer interrupt takes care of this */
- set_dec(tb_ticks_per_jiffy);
+ init_decrementer_clockevent();
}
Index: working/include/asm-powerpc/time.h
===================================================================
--- working.orig/include/asm-powerpc/time.h
+++ working/include/asm-powerpc/time.h
@@ -245,6 +245,7 @@ extern void snapshot_timebases(void);
#define snapshot_timebases() do { } while (0)
#endif
+extern void secondary_cpu_time_init(void);
extern void iSeries_time_init_early(void);
#endif /* __KERNEL__ */
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/5] Enable tickless idle and high res timers for powerpc
2007-09-19 6:49 [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
` (2 preceding siblings ...)
2007-09-19 6:49 ` [PATCH 2/5] Implement generic time of day clocksource for powerpc machines Tony Breeds
@ 2007-09-19 6:49 ` Tony Breeds
2007-09-19 6:53 ` [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
4 siblings, 0 replies; 15+ messages in thread
From: Tony Breeds @ 2007-09-19 6:49 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/idle.c | 3 +++
arch/powerpc/platforms/iseries/setup.c | 5 +++++
3 files changed, 9 insertions(+)
Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -168,6 +168,7 @@ config HIGHMEM
bool "High memory support"
depends on PPC32
+source kernel/time/Kconfig
source kernel/Kconfig.hz
source kernel/Kconfig.preempt
source "fs/Kconfig.binfmt"
Index: working/arch/powerpc/kernel/idle.c
===================================================================
--- working.orig/arch/powerpc/kernel/idle.c
+++ working/arch/powerpc/kernel/idle.c
@@ -24,6 +24,7 @@
#include <linux/smp.h>
#include <linux/cpu.h>
#include <linux/sysctl.h>
+#include <linux/tick.h>
#include <asm/system.h>
#include <asm/processor.h>
@@ -59,6 +60,7 @@ void cpu_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
+ tick_nohz_stop_sched_tick();
while (!need_resched() && !cpu_should_die()) {
ppc64_runlatch_off();
@@ -90,6 +92,7 @@ void cpu_idle(void)
HMT_medium();
ppc64_runlatch_on();
+ tick_nohz_restart_sched_tick();
if (cpu_should_die())
cpu_die();
preempt_enable_no_resched();
Index: working/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- working.orig/arch/powerpc/platforms/iseries/setup.c
+++ working/arch/powerpc/platforms/iseries/setup.c
@@ -26,6 +26,7 @@
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/kernel.h>
+#include <linux/tick.h>
#include <asm/processor.h>
#include <asm/machdep.h>
@@ -562,6 +563,7 @@ static void yield_shared_processor(void)
static void iseries_shared_idle(void)
{
while (1) {
+ tick_nohz_stop_sched_tick();
while (!need_resched() && !hvlpevent_is_pending()) {
local_irq_disable();
ppc64_runlatch_off();
@@ -575,6 +577,7 @@ static void iseries_shared_idle(void)
}
ppc64_runlatch_on();
+ tick_nohz_restart_sched_tick();
if (hvlpevent_is_pending())
process_iSeries_events();
@@ -590,6 +593,7 @@ static void iseries_dedicated_idle(void)
set_thread_flag(TIF_POLLING_NRFLAG);
while (1) {
+ tick_nohz_stop_sched_tick();
if (!need_resched()) {
while (!need_resched()) {
ppc64_runlatch_off();
@@ -606,6 +610,7 @@ static void iseries_dedicated_idle(void)
}
ppc64_runlatch_on();
+ tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] Implement {read,update}_persistent_clock.
2007-09-19 6:49 [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
` (3 preceding siblings ...)
2007-09-19 6:49 ` [PATCH 5/5] Enable tickless idle and high res timers for powerpc Tony Breeds
@ 2007-09-19 6:53 ` Tony Breeds
4 siblings, 0 replies; 15+ messages in thread
From: Tony Breeds @ 2007-09-19 6:53 UTC (permalink / raw)
To: linuxppc-dev, Paul Mackerras; +Cc: Thomas Gleixner, Realtime Kernel
On Wed, Sep 19, 2007 at 04:49:46PM +1000, Tony Breeds wrote:
> With these functions implemented we cooperate better with the generic
> timekeeping code. This obsoletes the need for the timer sysdev as a bonus.
I should have added that this patch series applies on top of Benh's 601
fixes.
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-19 6:49 ` [PATCH 2/5] Implement generic time of day clocksource for powerpc machines Tony Breeds
@ 2007-09-19 15:43 ` Daniel Walker
2007-09-20 0:52 ` Paul Mackerras
0 siblings, 1 reply; 15+ messages in thread
From: Daniel Walker @ 2007-09-19 15:43 UTC (permalink / raw)
To: Tony Breeds
Cc: linuxppc-dev, Thomas Gleixner, Paul Mackerras, Realtime Kernel,
johnstul
On Wed, 2007-09-19 at 16:49 +1000, Tony Breeds wrote:
> +/* clocksource code */
> +/* FIXME: provide an RTC clocksource /or/ use a better name */
> +static cycle_t timebase_read(void)
> +{
> + if (__USE_RTC())
> + return (cycle_t)get_rtc();
> + return (cycle_t)get_tb();
> +}
If you switch to the rtc do the shift and mult need to change?
> +void update_vsyscall(struct timespec *wall_time, struct clocksource
> *clock)
> +{
> + u64 t2x, stamp_xsec;
> +
> + if (__USE_RTC() || clock != &clocksource_timebase)
> + return;
> +
> + /* Make userspace gettimeofday spin until we're done. */
> + ++vdso_data->tb_update_count;
> + smp_mb();
> +
> + /* XXX this assumes clock->shift == 22 */
> + /* 4611686018 ~= 2^(20+64-22) / 1e9 */
> + t2x = (u64) clock->mult * 4611686018ULL;
It might make the code more readable if you put that constant into a
macro that gives it a name.
Daniel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-19 15:43 ` Daniel Walker
@ 2007-09-20 0:52 ` Paul Mackerras
2007-09-20 1:35 ` Daniel Walker
2007-09-20 16:35 ` john stultz
0 siblings, 2 replies; 15+ messages in thread
From: Paul Mackerras @ 2007-09-20 0:52 UTC (permalink / raw)
To: Daniel Walker; +Cc: linuxppc-dev, Thomas Gleixner, johnstul, Realtime Kernel
Daniel Walker writes:
> If you switch to the rtc do the shift and mult need to change?
You can't switch; any given CPU chip will have either the RTC or the
timebase but not both.
> > + /* XXX this assumes clock->shift == 22 */
> > + /* 4611686018 ~= 2^(20+64-22) / 1e9 */
> > + t2x = (u64) clock->mult * 4611686018ULL;
>
> It might make the code more readable if you put that constant into a
> macro that gives it a name.
The comment already gives more information than some arbitrary name
would.
Paul.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-20 0:52 ` Paul Mackerras
@ 2007-09-20 1:35 ` Daniel Walker
2007-09-20 1:46 ` Paul Mackerras
2007-09-20 16:35 ` john stultz
1 sibling, 1 reply; 15+ messages in thread
From: Daniel Walker @ 2007-09-20 1:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Thomas Gleixner, johnstul, Realtime Kernel
On Thu, 2007-09-20 at 10:52 +1000, Paul Mackerras wrote:
> Daniel Walker writes:
>
> > If you switch to the rtc do the shift and mult need to change?
>
> You can't switch; any given CPU chip will have either the RTC or the
> timebase but not both.
The code is switching between to clock read functions .. If they are
running at different frequencies then the time isn't going to be
converted to nanosecond properly.
So is the rtc running at the same frequency as the timebase? I'd guess
no..
> > > + /* XXX this assumes clock->shift == 22 */
> > > + /* 4611686018 ~= 2^(20+64-22) / 1e9 */
> > > + t2x = (u64) clock->mult * 4611686018ULL;
> >
> > It might make the code more readable if you put that constant into a
> > macro that gives it a name.
>
> The comment already gives more information than some arbitrary name
> would.
I'm not a powerpc expect, but I have no idea what that constant is..
Daniel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-20 1:35 ` Daniel Walker
@ 2007-09-20 1:46 ` Paul Mackerras
2007-09-20 1:54 ` Daniel Walker
0 siblings, 1 reply; 15+ messages in thread
From: Paul Mackerras @ 2007-09-20 1:46 UTC (permalink / raw)
To: Daniel Walker; +Cc: linuxppc-dev, Thomas Gleixner, johnstul, Realtime Kernel
Daniel Walker writes:
> On Thu, 2007-09-20 at 10:52 +1000, Paul Mackerras wrote:
> > Daniel Walker writes:
> >
> > > If you switch to the rtc do the shift and mult need to change?
> >
> > You can't switch; any given CPU chip will have either the RTC or the
> > timebase but not both.
>
> The code is switching between to clock read functions .. If they are
What part of "you can't switch" wasn't clear? __USE_RTC() is a
constant on any given machine.
Paul.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-20 1:46 ` Paul Mackerras
@ 2007-09-20 1:54 ` Daniel Walker
2007-09-20 3:29 ` David Gibson
0 siblings, 1 reply; 15+ messages in thread
From: Daniel Walker @ 2007-09-20 1:54 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Thomas Gleixner, johnstul, Realtime Kernel
On Thu, 2007-09-20 at 11:46 +1000, Paul Mackerras wrote:
> Daniel Walker writes:
>
> > On Thu, 2007-09-20 at 10:52 +1000, Paul Mackerras wrote:
> > > Daniel Walker writes:
> > >
> > > > If you switch to the rtc do the shift and mult need to change?
> > >
> > > You can't switch; any given CPU chip will have either the RTC or the
> > > timebase but not both.
> >
> > The code is switching between to clock read functions .. If they are
>
> What part of "you can't switch" wasn't clear? __USE_RTC() is a
> constant on any given machine.
Maybe say "It a constant" up front .. The value that is output from the
clocksource read is converted to nanoseconds .. This clocksource is only
designed to work with the timebase, so it doesn't make sense to output
an rtc value.
Daniel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-20 1:54 ` Daniel Walker
@ 2007-09-20 3:29 ` David Gibson
2007-09-20 3:38 ` Daniel Walker
0 siblings, 1 reply; 15+ messages in thread
From: David Gibson @ 2007-09-20 3:29 UTC (permalink / raw)
To: Daniel Walker
Cc: linuxppc-dev, Thomas Gleixner, Paul Mackerras, Realtime Kernel,
johnstul
On Wed, Sep 19, 2007 at 06:54:41PM -0700, Daniel Walker wrote:
> On Thu, 2007-09-20 at 11:46 +1000, Paul Mackerras wrote:
> > Daniel Walker writes:
> >
> > > On Thu, 2007-09-20 at 10:52 +1000, Paul Mackerras wrote:
> > > > Daniel Walker writes:
> > > >
> > > > > If you switch to the rtc do the shift and mult need to change?
> > > >
> > > > You can't switch; any given CPU chip will have either the RTC or the
> > > > timebase but not both.
> > >
> > > The code is switching between to clock read functions .. If they are
> >
> > What part of "you can't switch" wasn't clear? __USE_RTC() is a
> > constant on any given machine.
>
> Maybe say "It a constant" up front .. The value that is output from the
> clocksource read is converted to nanoseconds .. This clocksource is only
> designed to work with the timebase, so it doesn't make sense to output
> an rtc value.
I believe "rtc" in a 601 context means something different to "rtc" in
a general context...
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-20 3:29 ` David Gibson
@ 2007-09-20 3:38 ` Daniel Walker
0 siblings, 0 replies; 15+ messages in thread
From: Daniel Walker @ 2007-09-20 3:38 UTC (permalink / raw)
To: David Gibson
Cc: linuxppc-dev, Thomas Gleixner, Paul Mackerras, Realtime Kernel,
johnstul
On Thu, 2007-09-20 at 13:29 +1000, David Gibson wrote:
> > Maybe say "It a constant" up front .. The value that is output from the
> > clocksource read is converted to nanoseconds .. This clocksource is only
> > designed to work with the timebase, so it doesn't make sense to output
> > an rtc value.
>
> I believe "rtc" in a 601 context means something different to "rtc" in
> a general context...
What's a 601 context?
Daniel
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-20 0:52 ` Paul Mackerras
2007-09-20 1:35 ` Daniel Walker
@ 2007-09-20 16:35 ` john stultz
2007-09-20 23:46 ` Tony Breeds
1 sibling, 1 reply; 15+ messages in thread
From: john stultz @ 2007-09-20 16:35 UTC (permalink / raw)
To: Paul Mackerras
Cc: Realtime Kernel, Daniel Walker, Thomas Gleixner, linuxppc-dev
On Thu, 2007-09-20 at 10:52 +1000, Paul Mackerras wrote:
> Daniel Walker writes:
>
> > If you switch to the rtc do the shift and mult need to change?
>
> You can't switch; any given CPU chip will have either the RTC or the
> timebase but not both.
I think what Daniel is pointing out is that the clocksource read
function isn't the place for the __USE_RTC() conditional.
It would likely be better instead of the timebase clocksource managing
multiple type of hardware (timebase and RTC), to have a separate simple
RTC clocksource, and then conditionally register one or the other at
init time.
thanks
-john
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] Implement generic time of day clocksource for powerpc machines.
2007-09-20 16:35 ` john stultz
@ 2007-09-20 23:46 ` Tony Breeds
0 siblings, 0 replies; 15+ messages in thread
From: Tony Breeds @ 2007-09-20 23:46 UTC (permalink / raw)
To: john stultz
Cc: Daniel Walker, Thomas Gleixner, Paul Mackerras, Realtime Kernel,
linuxppc-dev
On Thu, Sep 20, 2007 at 09:35:10AM -0700, john stultz wrote:
> I think what Daniel is pointing out is that the clocksource read
> function isn't the place for the __USE_RTC() conditional.
>
> It would likely be better instead of the timebase clocksource managing
> multiple type of hardware (timebase and RTC), to have a separate simple
> RTC clocksource, and then conditionally register one or the other at
> init time.
I'll create a seperate clocksource for the RTC case and use that as
appropriate. I'll resend the patch series after I've booted it :)
Yours Tony
linux.conf.au http://linux.conf.au/ || http://lca2008.linux.org.au/
Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2007-09-20 23:46 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-19 6:49 [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
2007-09-19 6:49 ` [PATCH 3/5] Implement clockevents driver for powerpc Tony Breeds
2007-09-19 6:49 ` [PATCH 4/5] Include hrtimer.h in tick.h Tony Breeds
2007-09-19 6:49 ` [PATCH 2/5] Implement generic time of day clocksource for powerpc machines Tony Breeds
2007-09-19 15:43 ` Daniel Walker
2007-09-20 0:52 ` Paul Mackerras
2007-09-20 1:35 ` Daniel Walker
2007-09-20 1:46 ` Paul Mackerras
2007-09-20 1:54 ` Daniel Walker
2007-09-20 3:29 ` David Gibson
2007-09-20 3:38 ` Daniel Walker
2007-09-20 16:35 ` john stultz
2007-09-20 23:46 ` Tony Breeds
2007-09-19 6:49 ` [PATCH 5/5] Enable tickless idle and high res timers for powerpc Tony Breeds
2007-09-19 6:53 ` [PATCH 1/5] Implement {read,update}_persistent_clock Tony Breeds
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).