From 12df29b64c782133afea8cacc6acdad68a6b7d17 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 2 Jan 2007 23:54:16 +0100 Subject: [PARISC] GENERIC_TIME patchset for parisc Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/time.c | 134 +++++++++------------------------------------- 1 file changed, 24 insertions(+), 110 deletions(-) (limited to 'arch/parisc/kernel/time.c') diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index bad7d1eb62b..e47e27cea42 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -172,121 +173,23 @@ unsigned long profile_pc(struct pt_regs *regs) EXPORT_SYMBOL(profile_pc); -/* - * Return the number of micro-seconds that elapsed since the last - * update to wall time (aka xtime). The xtime_lock - * must be at least read-locked when calling this routine. - */ -static inline unsigned long gettimeoffset (void) -{ -#ifndef CONFIG_SMP - /* - * FIXME: This won't work on smp because jiffies are updated by cpu 0. - * Once parisc-linux learns the cr16 difference between processors, - * this could be made to work. - */ - unsigned long now; - unsigned long prev_tick; - unsigned long next_tick; - unsigned long elapsed_cycles; - unsigned long usec; - unsigned long cpuid = smp_processor_id(); - unsigned long cpt = clocktick; +/* clock source code */ - next_tick = cpu_data[cpuid].it_value; - now = mfctl(16); /* Read the hardware interval timer. */ - - prev_tick = next_tick - cpt; - - /* Assume Scenario 1: "now" is later than prev_tick. */ - elapsed_cycles = now - prev_tick; - -/* aproximate HZ with shifts. Intended math is "(elapsed/clocktick) > HZ" */ -#if HZ == 1000 - if (elapsed_cycles > (cpt << 10) ) -#elif HZ == 250 - if (elapsed_cycles > (cpt << 8) ) -#elif HZ == 100 - if (elapsed_cycles > (cpt << 7) ) -#else -#warn WTF is HZ set to anyway? - if (elapsed_cycles > (HZ * cpt) ) -#endif - { - /* Scenario 3: clock ticks are missing. */ - printk (KERN_CRIT "gettimeoffset(CPU %ld): missing %ld ticks!" - " cycles %lX prev/now/next %lX/%lX/%lX clock %lX\n", - cpuid, elapsed_cycles / cpt, - elapsed_cycles, prev_tick, now, next_tick, cpt); - } - - /* FIXME: Can we improve the precision? Not with PAGE0. */ - usec = (elapsed_cycles * 10000) / PAGE0->mem_10msec; - return usec; -#else - return 0; -#endif -} - -void -do_gettimeofday (struct timeval *tv) +static cycle_t read_cr16(void) { - unsigned long flags, seq, usec, sec; - - /* Hold xtime_lock and adjust timeval. */ - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - usec = gettimeoffset(); - sec = xtime.tv_sec; - usec += (xtime.tv_nsec / 1000); - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - /* Move adjusted usec's into sec's. */ - while (usec >= USEC_PER_SEC) { - usec -= USEC_PER_SEC; - ++sec; - } - - /* Return adjusted result. */ - tv->tv_sec = sec; - tv->tv_usec = usec; + return get_cycles(); } -EXPORT_SYMBOL(do_gettimeofday); - -int -do_settimeofday (struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - { - /* - * This is revolting. We need to set "xtime" - * correctly. However, the value in this location is - * the value at the most recent update of wall time. - * Discover what correction gettimeofday would have - * done, and then undo it! - */ - nsec -= gettimeoffset() * 1000; +static struct clocksource clocksource_cr16 = { + .name = "cr16", + .rating = 300, + .read = read_cr16, + .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), + .mult = 0, /* to be set */ + .shift = 22, + .is_continuous = 1, +}; - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - } - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} -EXPORT_SYMBOL(do_settimeofday); /* * XXX: We can do better than this. @@ -312,11 +215,22 @@ void __init start_cpu_itimer(void) void __init time_init(void) { static struct pdc_tod tod_data; + unsigned long current_cr16_khz; clocktick = (100 * PAGE0->mem_10msec) / HZ; start_cpu_itimer(); /* get CPU 0 started */ + /* register at clocksource framework */ + current_cr16_khz = PAGE0->mem_10msec/10; /* kHz */ + clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz, + clocksource_cr16.shift); + /* lower the rating if we already know its unstable: */ + if (num_online_cpus()>1) + clocksource_cr16.rating = 200; + + clocksource_register(&clocksource_cr16); + if (pdc_tod_read(&tod_data) == 0) { unsigned long flags; -- cgit v1.2.3 From 324c7e6545539d2f7736be930d4833deb32b1b95 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 3 Jan 2007 19:25:37 +0100 Subject: [PARISC] disable cr16 clocksource when multiple CPUs are online Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/time.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'arch/parisc/kernel/time.c') diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index e47e27cea42..c33b6e0f7c4 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -99,7 +99,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) * cycles after the IT fires. But it's arbitrary how much time passes * before we call it "late". I've picked one second. */ - if (ticks_elapsed > HZ) { + if (unlikely(ticks_elapsed > HZ)) { /* Scenario 3: very long delay? bad in any case */ printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!" " cycles %lX rem %lX " @@ -180,6 +180,8 @@ static cycle_t read_cr16(void) return get_cycles(); } +static int cr16_update_callback(void); + static struct clocksource clocksource_cr16 = { .name = "cr16", .rating = 300, @@ -187,9 +189,25 @@ static struct clocksource clocksource_cr16 = { .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), .mult = 0, /* to be set */ .shift = 22, + .update_callback = cr16_update_callback, .is_continuous = 1, }; +static int cr16_update_callback(void) +{ + int change = 0; + + /* since the cr16 cycle counters are not syncronized across CPUs, + we'll check if we should switch to a safe clocksource: */ + if (clocksource_cr16.rating != 0 && num_online_cpus() > 1) { + clocksource_cr16.rating = 0; + clocksource_reselect(); + change = 1; + } + + return change; +} + /* * XXX: We can do better than this. @@ -225,10 +243,6 @@ void __init time_init(void) current_cr16_khz = PAGE0->mem_10msec/10; /* kHz */ clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz, clocksource_cr16.shift); - /* lower the rating if we already know its unstable: */ - if (num_online_cpus()>1) - clocksource_cr16.rating = 200; - clocksource_register(&clocksource_cr16); if (pdc_tod_read(&tod_data) == 0) { -- cgit v1.2.3 From 6e16d9409e1f08594587855d2a280c391ba985ff Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 7 Jan 2007 16:07:48 +0100 Subject: [PARISC] Convert soft power switch driver to kthread And remove it's reference in time.c. Allow lcd_print() to take a const char *. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/kernel/time.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/parisc/kernel/time.c') diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index c33b6e0f7c4..ccdce6ef67c 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -148,10 +148,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) write_sequnlock(&xtime_lock); } - /* check soft power switch status */ - if (cpu == 0 && !atomic_read(&power_tasklet.count)) - tasklet_schedule(&power_tasklet); - return IRQ_HANDLED; } -- cgit v1.2.3