Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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: Tony Breeds <tony@bakeyournoodle.com>
CC: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by

Tony Breeds and committed by
Paul Mackerras
71712b45 a5c631b1

+23 -15
+19 -11
arch/powerpc/kernel/time.c
··· 77 77 /* keep track of when we need to update the rtc */ 78 78 time_t last_rtc_update; 79 79 #ifdef CONFIG_PPC_ISERIES 80 - unsigned long iSeries_recal_titan = 0; 81 - unsigned long iSeries_recal_tb = 0; 82 - static unsigned long first_settimeofday = 1; 80 + static unsigned long __initdata iSeries_recal_titan; 81 + static signed long __initdata iSeries_recal_tb; 83 82 #endif 84 83 85 84 /* The decrementer counts down by 128 every 128ns on a 601. */ ··· 555 556 * returned by the service processor for the timebase frequency. 556 557 */ 557 558 558 - static void iSeries_tb_recal(void) 559 + static int __init iSeries_tb_recal(void) 559 560 { 560 561 struct div_result divres; 561 562 unsigned long titan, tb; 563 + 564 + /* Make sure we only run on iSeries */ 565 + if (!firmware_has_feature(FW_FEATURE_ISERIES)) 566 + return -ENODEV; 567 + 562 568 tb = get_tb(); 563 569 titan = HvCallXm_loadTod(); 564 570 if ( iSeries_recal_titan ) { ··· 604 600 } 605 601 iSeries_recal_titan = titan; 606 602 iSeries_recal_tb = tb; 603 + 604 + return 0; 607 605 } 608 - #endif 606 + late_initcall(iSeries_tb_recal); 607 + 608 + /* Called from platform early init */ 609 + void __init iSeries_time_init_early(void) 610 + { 611 + iSeries_recal_tb = get_tb(); 612 + iSeries_recal_titan = HvCallXm_loadTod(); 613 + } 614 + #endif /* CONFIG_PPC_ISERIES */ 609 615 610 616 /* 611 617 * For iSeries shared processors, we have to let the hypervisor ··· 779 765 * to the RTC again, or write to the RTC but then they don't call 780 766 * settimeofday to perform this operation. 781 767 */ 782 - #ifdef CONFIG_PPC_ISERIES 783 - if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) { 784 - iSeries_tb_recal(); 785 - first_settimeofday = 0; 786 - } 787 - #endif 788 768 789 769 /* Make userspace gettimeofday spin until we're done. */ 790 770 ++vdso_data->tb_update_count;
+2 -4
arch/powerpc/platforms/iseries/setup.c
··· 79 79 static void iSeries_pci_final_fixup(void) { } 80 80 #endif 81 81 82 - extern unsigned long iSeries_recal_tb; 83 - extern unsigned long iSeries_recal_titan; 84 82 85 83 struct MemoryBlock { 86 84 unsigned long absStart; ··· 290 292 { 291 293 DBG(" -> iSeries_init_early()\n"); 292 294 293 - iSeries_recal_tb = get_tb(); 294 - iSeries_recal_titan = HvCallXm_loadTod(); 295 + /* Snapshot the timebase, for use in later recalibration */ 296 + iSeries_time_init_early(); 295 297 296 298 /* 297 299 * Initialize the DMA/TCE management
+2
include/asm-powerpc/time.h
··· 240 240 #define snapshot_timebases() do { } while (0) 241 241 #endif 242 242 243 + extern void iSeries_time_init_early(void); 244 + 243 245 #endif /* __KERNEL__ */ 244 246 #endif /* __POWERPC_TIME_H */