Commit 71712b45 authored by Tony Breeds's avatar Tony Breeds Committed by Paul Mackerras

[POWERPC] Move iSeries_tb_recal into its own late_initcall.

Currently iSeries will recalibrate the cputime_factors in the first
settimeofday() call.

It seems the reason for doing this is to ensure a resaonable time delta after
time_init().  On current kernels (with udev), this call is made 40-60 seconds
into the boot process, by moving it to a late initcall it is called
approximately 5 seconds after time_init() is called.  This is sufficient to
recalibrate the timebase.
Signed-off-by: default avatarTony Breeds <tony@bakeyournoodle.com>
CC: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent a5c631b1
...@@ -77,9 +77,8 @@ ...@@ -77,9 +77,8 @@
/* keep track of when we need to update the rtc */ /* keep track of when we need to update the rtc */
time_t last_rtc_update; time_t last_rtc_update;
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
unsigned long iSeries_recal_titan = 0; static unsigned long __initdata iSeries_recal_titan;
unsigned long iSeries_recal_tb = 0; static signed long __initdata iSeries_recal_tb;
static unsigned long first_settimeofday = 1;
#endif #endif
/* The decrementer counts down by 128 every 128ns on a 601. */ /* The decrementer counts down by 128 every 128ns on a 601. */
...@@ -556,10 +555,15 @@ EXPORT_SYMBOL(profile_pc); ...@@ -556,10 +555,15 @@ EXPORT_SYMBOL(profile_pc);
* returned by the service processor for the timebase frequency. * returned by the service processor for the timebase frequency.
*/ */
static void iSeries_tb_recal(void) static int __init iSeries_tb_recal(void)
{ {
struct div_result divres; struct div_result divres;
unsigned long titan, tb; unsigned long titan, tb;
/* Make sure we only run on iSeries */
if (!firmware_has_feature(FW_FEATURE_ISERIES))
return -ENODEV;
tb = get_tb(); tb = get_tb();
titan = HvCallXm_loadTod(); titan = HvCallXm_loadTod();
if ( iSeries_recal_titan ) { if ( iSeries_recal_titan ) {
...@@ -600,8 +604,18 @@ static void iSeries_tb_recal(void) ...@@ -600,8 +604,18 @@ static void iSeries_tb_recal(void)
} }
iSeries_recal_titan = titan; iSeries_recal_titan = titan;
iSeries_recal_tb = tb; iSeries_recal_tb = tb;
return 0;
} }
#endif late_initcall(iSeries_tb_recal);
/* Called from platform early init */
void __init iSeries_time_init_early(void)
{
iSeries_recal_tb = get_tb();
iSeries_recal_titan = HvCallXm_loadTod();
}
#endif /* CONFIG_PPC_ISERIES */
/* /*
* For iSeries shared processors, we have to let the hypervisor * For iSeries shared processors, we have to let the hypervisor
...@@ -765,12 +779,6 @@ int do_settimeofday(struct timespec *tv) ...@@ -765,12 +779,6 @@ int do_settimeofday(struct timespec *tv)
* to the RTC again, or write to the RTC but then they don't call * to the RTC again, or write to the RTC but then they don't call
* settimeofday to perform this operation. * settimeofday to perform this operation.
*/ */
#ifdef CONFIG_PPC_ISERIES
if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
iSeries_tb_recal();
first_settimeofday = 0;
}
#endif
/* Make userspace gettimeofday spin until we're done. */ /* Make userspace gettimeofday spin until we're done. */
++vdso_data->tb_update_count; ++vdso_data->tb_update_count;
......
...@@ -79,8 +79,6 @@ extern void iSeries_pci_final_fixup(void); ...@@ -79,8 +79,6 @@ extern void iSeries_pci_final_fixup(void);
static void iSeries_pci_final_fixup(void) { } static void iSeries_pci_final_fixup(void) { }
#endif #endif
extern unsigned long iSeries_recal_tb;
extern unsigned long iSeries_recal_titan;
struct MemoryBlock { struct MemoryBlock {
unsigned long absStart; unsigned long absStart;
...@@ -292,8 +290,8 @@ static void __init iSeries_init_early(void) ...@@ -292,8 +290,8 @@ static void __init iSeries_init_early(void)
{ {
DBG(" -> iSeries_init_early()\n"); DBG(" -> iSeries_init_early()\n");
iSeries_recal_tb = get_tb(); /* Snapshot the timebase, for use in later recalibration */
iSeries_recal_titan = HvCallXm_loadTod(); iSeries_time_init_early();
/* /*
* Initialize the DMA/TCE management * Initialize the DMA/TCE management
......
...@@ -240,5 +240,7 @@ extern void snapshot_timebases(void); ...@@ -240,5 +240,7 @@ extern void snapshot_timebases(void);
#define snapshot_timebases() do { } while (0) #define snapshot_timebases() do { } while (0)
#endif #endif
extern void iSeries_time_init_early(void);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __POWERPC_TIME_H */ #endif /* __POWERPC_TIME_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment