diff options
Diffstat (limited to 'arch/powerpc/kernel/time.c')
| -rw-r--r-- | arch/powerpc/kernel/time.c | 105 | 
1 files changed, 30 insertions, 75 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 522bb1dfc35..567dd7c3ac2 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -86,8 +86,6 @@ static struct clocksource clocksource_rtc = {  	.rating       = 400,  	.flags        = CLOCK_SOURCE_IS_CONTINUOUS,  	.mask         = CLOCKSOURCE_MASK(64), -	.shift        = 22, -	.mult         = 0,	/* To be filled in */  	.read         = rtc_read,  }; @@ -97,8 +95,6 @@ static struct clocksource clocksource_timebase = {  	.rating       = 400,  	.flags        = CLOCK_SOURCE_IS_CONTINUOUS,  	.mask         = CLOCKSOURCE_MASK(64), -	.shift        = 22, -	.mult         = 0,	/* To be filled in */  	.read         = timebase_read,  }; @@ -110,22 +106,16 @@ 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          = 0,	/* To be filled in */ -       .mult           = 0,	/* To be filled in */ -       .irq            = 0, -       .set_next_event = decrementer_set_next_event, -       .set_mode       = decrementer_set_mode, -       .features       = CLOCK_EVT_FEAT_ONESHOT, +	.name           = "decrementer", +	.rating         = 200, +	.irq            = 0, +	.set_next_event = decrementer_set_next_event, +	.set_mode       = decrementer_set_mode, +	.features       = CLOCK_EVT_FEAT_ONESHOT,  }; -struct decrementer_clock { -	struct clock_event_device event; -	u64 next_tb; -}; - -static DEFINE_PER_CPU(struct decrementer_clock, decrementers); +DEFINE_PER_CPU(u64, decrementers_next_tb); +static DEFINE_PER_CPU(struct clock_event_device, decrementers);  #ifdef CONFIG_PPC_ISERIES  static unsigned long __initdata iSeries_recal_titan; @@ -168,13 +158,13 @@ EXPORT_SYMBOL_GPL(ppc_tb_freq);  #ifdef CONFIG_VIRT_CPU_ACCOUNTING  /*   * Factors for converting from cputime_t (timebase ticks) to - * jiffies, milliseconds, seconds, and clock_t (1/USER_HZ seconds). + * jiffies, microseconds, seconds, and clock_t (1/USER_HZ seconds).   * These are all stored as 0.64 fixed-point binary fractions.   */  u64 __cputime_jiffies_factor;  EXPORT_SYMBOL(__cputime_jiffies_factor); -u64 __cputime_msec_factor; -EXPORT_SYMBOL(__cputime_msec_factor); +u64 __cputime_usec_factor; +EXPORT_SYMBOL(__cputime_usec_factor);  u64 __cputime_sec_factor;  EXPORT_SYMBOL(__cputime_sec_factor);  u64 __cputime_clockt_factor; @@ -192,8 +182,8 @@ static void calc_cputime_factors(void)  	div128_by_32(HZ, 0, tb_ticks_per_sec, &res);  	__cputime_jiffies_factor = res.result_low; -	div128_by_32(1000, 0, tb_ticks_per_sec, &res); -	__cputime_msec_factor = res.result_low; +	div128_by_32(1000000, 0, tb_ticks_per_sec, &res); +	__cputime_usec_factor = res.result_low;  	div128_by_32(1, 0, tb_ticks_per_sec, &res);  	__cputime_sec_factor = res.result_low;  	div128_by_32(USER_HZ, 0, tb_ticks_per_sec, &res); @@ -441,7 +431,7 @@ EXPORT_SYMBOL(profile_pc);  /*    * This function recalibrates the timebase based on the 49-bit time-of-day   * value in the Titan chip.  The Titan is much more accurate than the value - * returned by the service processor for the timebase frequency.   + * returned by the service processor for the timebase frequency.   */  static int __init iSeries_tb_recal(void) @@ -576,9 +566,8 @@ void arch_irq_work_raise(void)  void timer_interrupt(struct pt_regs * regs)  {  	struct pt_regs *old_regs; -	struct decrementer_clock *decrementer =  &__get_cpu_var(decrementers); -	struct clock_event_device *evt = &decrementer->event; -	u64 now; +	u64 *next_tb = &__get_cpu_var(decrementers_next_tb); +	struct clock_event_device *evt = &__get_cpu_var(decrementers);  	/* Ensure a positive value is written to the decrementer, or else  	 * some CPUs will continue to take decrementer exceptions. @@ -613,16 +602,9 @@ void timer_interrupt(struct pt_regs * regs)  		get_lppaca()->int_dword.fields.decr_int = 0;  #endif -	now = get_tb_or_rtc(); -	if (now >= decrementer->next_tb) { -		decrementer->next_tb = ~(u64)0; -		if (evt->event_handler) -			evt->event_handler(evt); -	} else { -		now = decrementer->next_tb - now; -		if (now <= DECREMENTER_MAX) -			set_dec((int)now); -	} +	*next_tb = ~(u64)0; +	if (evt->event_handler) +		evt->event_handler(evt);  #ifdef CONFIG_PPC_ISERIES  	if (firmware_has_feature(FW_FEATURE_ISERIES) && hvlpevent_is_pending()) @@ -650,9 +632,9 @@ static void generic_suspend_disable_irqs(void)  	 * with suspending.  	 */ -	set_dec(0x7fffffff); +	set_dec(DECREMENTER_MAX);  	local_irq_disable(); -	set_dec(0x7fffffff); +	set_dec(DECREMENTER_MAX);  }  static void generic_suspend_enable_irqs(void) @@ -824,9 +806,8 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,  	++vdso_data->tb_update_count;  	smp_mb(); -	/* XXX this assumes clock->shift == 22 */ -	/* 4611686018 ~= 2^(20+64-22) / 1e9 */ -	new_tb_to_xs = (u64) mult * 4611686018ULL; +	/* 19342813113834067 ~= 2^(20+64) / 1e9 */ +	new_tb_to_xs = (u64) mult * (19342813113834067ULL >> clock->shift);  	new_stamp_xsec = (u64) wall_time->tv_nsec * XSEC_PER_SEC;  	do_div(new_stamp_xsec, 1000000000);  	new_stamp_xsec += (u64) wall_time->tv_sec * XSEC_PER_SEC; @@ -877,9 +858,7 @@ static void __init clocksource_init(void)  	else  		clock = &clocksource_timebase; -	clock->mult = clocksource_hz2mult(tb_ticks_per_sec, clock->shift); - -	if (clocksource_register(clock)) { +	if (clocksource_register_hz(clock, tb_ticks_per_sec)) {  		printk(KERN_ERR "clocksource: %s is already registered\n",  		       clock->name);  		return; @@ -892,7 +871,7 @@ static void __init clocksource_init(void)  static int decrementer_set_next_event(unsigned long evt,  				      struct clock_event_device *dev)  { -	__get_cpu_var(decrementers).next_tb = get_tb_or_rtc() + evt; +	__get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;  	set_dec(evt);  	return 0;  } @@ -904,34 +883,9 @@ static void decrementer_set_mode(enum clock_event_mode mode,  		decrementer_set_next_event(DECREMENTER_MAX, dev);  } -static inline uint64_t div_sc64(unsigned long ticks, unsigned long nsec, -				int shift) -{ -	uint64_t tmp = ((uint64_t)ticks) << shift; - -	do_div(tmp, nsec); -	return tmp; -} - -static void __init setup_clockevent_multiplier(unsigned long hz) -{ -	u64 mult, shift = 32; - -	while (1) { -		mult = div_sc64(hz, NSEC_PER_SEC, shift); -		if (mult && (mult >> 32UL) == 0UL) -			break; - -		shift--; -	} - -	decrementer_clockevent.shift = shift; -	decrementer_clockevent.mult = mult; -} -  static void register_decrementer_clockevent(int cpu)  { -	struct clock_event_device *dec = &per_cpu(decrementers, cpu).event; +	struct clock_event_device *dec = &per_cpu(decrementers, cpu);  	*dec = decrementer_clockevent;  	dec->cpumask = cpumask_of(cpu); @@ -946,7 +900,8 @@ static void __init init_decrementer_clockevent(void)  {  	int cpu = smp_processor_id(); -	setup_clockevent_multiplier(ppc_tb_freq); +	clockevents_calc_mult_shift(&decrementer_clockevent, ppc_tb_freq, 4); +  	decrementer_clockevent.max_delta_ns =  		clockevent_delta2ns(DECREMENTER_MAX, &decrementer_clockevent);  	decrementer_clockevent.min_delta_ns = @@ -1014,10 +969,10 @@ void __init time_init(void)  	boot_tb = get_tb_or_rtc();  	/* If platform provided a timezone (pmac), we correct the time */ -        if (timezone_offset) { +	if (timezone_offset) {  		sys_tz.tz_minuteswest = -timezone_offset / 60;  		sys_tz.tz_dsttime = 0; -        } +	}  	vdso_data->tb_update_count = 0;  	vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;  |