Subject: perf, arch: Use perf_initcall() for all arch pmu implementations From: Peter Zijlstra Date: Tue Nov 16 22:08:28 CET 2010 Currently architectures use various random locations to init the PMU driver, for some this happens before the perf core code is initialized. In order to avoid calling perf_pmu_register() before the core code is up and running and able to deal with it, move all arch pmu init calls to perf_initcall(). Cc: Michael Cree Cc: David Miller Cc: Paul Mundt Cc: Will Deacon Cc: paulus Cc: Deng-Cheng Zhu Signed-off-by: Peter Zijlstra LKML-Reference: <20101117222056.040309789@chello.nl> --- arch/alpha/include/asm/perf_event.h | 6 ------ arch/alpha/kernel/irq_alpha.c | 2 -- arch/alpha/kernel/perf_event.c | 9 ++++++--- arch/arm/kernel/perf_event.c | 2 +- arch/mips/kernel/perf_event_mipsxx.c | 2 +- arch/powerpc/kernel/e500-pmu.c | 2 +- arch/powerpc/kernel/mpc7450-pmu.c | 2 +- arch/powerpc/kernel/power4-pmu.c | 2 +- arch/powerpc/kernel/power5+-pmu.c | 2 +- arch/powerpc/kernel/power5-pmu.c | 2 +- arch/powerpc/kernel/power6-pmu.c | 2 +- arch/powerpc/kernel/power7-pmu.c | 2 +- arch/powerpc/kernel/ppc970-pmu.c | 2 +- arch/sh/kernel/cpu/sh4/perf_event.c | 2 +- arch/sh/kernel/cpu/sh4a/perf_event.c | 2 +- arch/sparc/include/asm/perf_event.h | 4 ---- arch/sparc/kernel/nmi.c | 2 -- arch/sparc/kernel/perf_event.c | 7 +++++-- arch/x86/include/asm/perf_event.h | 2 -- arch/x86/kernel/cpu/common.c | 1 - arch/x86/kernel/cpu/perf_event.c | 11 +++++++---- 21 files changed, 30 insertions(+), 38 deletions(-) Index: linux-2.6/arch/alpha/include/asm/perf_event.h =================================================================== --- linux-2.6.orig/arch/alpha/include/asm/perf_event.h +++ linux-2.6/arch/alpha/include/asm/perf_event.h @@ -1,10 +1,4 @@ #ifndef __ASM_ALPHA_PERF_EVENT_H #define __ASM_ALPHA_PERF_EVENT_H -#ifdef CONFIG_PERF_EVENTS -extern void init_hw_perf_events(void); -#else -static inline void init_hw_perf_events(void) { } -#endif - #endif /* __ASM_ALPHA_PERF_EVENT_H */ Index: linux-2.6/arch/alpha/kernel/irq_alpha.c =================================================================== --- linux-2.6.orig/arch/alpha/kernel/irq_alpha.c +++ linux-2.6/arch/alpha/kernel/irq_alpha.c @@ -112,8 +112,6 @@ init_IRQ(void) wrent(entInt, 0); alpha_mv.init_irq(); - - init_hw_perf_events(); } /* Index: linux-2.6/arch/alpha/kernel/perf_event.c =================================================================== --- linux-2.6.orig/arch/alpha/kernel/perf_event.c +++ linux-2.6/arch/alpha/kernel/perf_event.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -863,13 +864,13 @@ static void alpha_perf_event_irq_handler /* * Init call to initialise performance events at kernel startup. */ -void __init init_hw_perf_events(void) +int __init init_hw_perf_events(void) { pr_info("Performance events: "); if (!supported_cpu()) { pr_cont("No support for your CPU.\n"); - return; + return 0; } pr_cont("Supported CPU type!\n"); @@ -882,5 +883,7 @@ void __init init_hw_perf_events(void) alpha_pmu = &ev67_pmu; perf_pmu_register(&pmu); -} + return 0; +} +perf_initcall(init_hw_perf_events); Index: linux-2.6/arch/sparc/include/asm/perf_event.h =================================================================== --- linux-2.6.orig/arch/sparc/include/asm/perf_event.h +++ linux-2.6/arch/sparc/include/asm/perf_event.h @@ -4,8 +4,6 @@ #ifdef CONFIG_PERF_EVENTS #include -extern void init_hw_perf_events(void); - #define perf_arch_fetch_caller_regs(regs, ip) \ do { \ unsigned long _pstate, _asi, _pil, _i7, _fp; \ @@ -26,8 +24,6 @@ do { \ (regs)->u_regs[UREG_I6] = _fp; \ (regs)->u_regs[UREG_I7] = _i7; \ } while (0) -#else -static inline void init_hw_perf_events(void) { } #endif #endif Index: linux-2.6/arch/sparc/kernel/nmi.c =================================================================== --- linux-2.6.orig/arch/sparc/kernel/nmi.c +++ linux-2.6/arch/sparc/kernel/nmi.c @@ -270,8 +270,6 @@ int __init nmi_init(void) atomic_set(&nmi_active, -1); } } - if (!err) - init_hw_perf_events(); return err; } Index: linux-2.6/arch/sparc/kernel/perf_event.c =================================================================== --- linux-2.6.orig/arch/sparc/kernel/perf_event.c +++ linux-2.6/arch/sparc/kernel/perf_event.c @@ -1307,20 +1307,23 @@ static bool __init supported_pmu(void) return false; } -void __init init_hw_perf_events(void) +int __init init_hw_perf_events(void) { pr_info("Performance events: "); if (!supported_pmu()) { pr_cont("No support for PMU type '%s'\n", sparc_pmu_type); - return; + return 0; } pr_cont("Supported PMU type is '%s'\n", sparc_pmu_type); perf_pmu_register(&pmu); register_die_notifier(&perf_event_nmi_notifier); + + return 0; } +perf_initcall(init_hw_perf_event); void perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) Index: linux-2.6/arch/x86/include/asm/perf_event.h =================================================================== --- linux-2.6.orig/arch/x86/include/asm/perf_event.h +++ linux-2.6/arch/x86/include/asm/perf_event.h @@ -125,7 +125,6 @@ union cpuid10_edx { #define IBS_OP_MAX_CNT_EXT 0x007FFFFFULL /* not a register bit mask */ #ifdef CONFIG_PERF_EVENTS -extern void init_hw_perf_events(void); extern void perf_events_lapic_init(void); #define PERF_EVENT_INDEX_OFFSET 0 @@ -156,7 +155,6 @@ extern unsigned long perf_misc_flags(str } #else -static inline void init_hw_perf_events(void) { } static inline void perf_events_lapic_init(void) { } #endif Index: linux-2.6/arch/x86/kernel/cpu/common.c =================================================================== --- linux-2.6.orig/arch/x86/kernel/cpu/common.c +++ linux-2.6/arch/x86/kernel/cpu/common.c @@ -894,7 +894,6 @@ void __init identify_boot_cpu(void) #else vgetcpu_set_mode(); #endif - init_hw_perf_events(); } void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) Index: linux-2.6/arch/x86/kernel/cpu/perf_event.c =================================================================== --- linux-2.6.orig/arch/x86/kernel/cpu/perf_event.c +++ linux-2.6/arch/x86/kernel/cpu/perf_event.c @@ -1423,7 +1423,7 @@ static void __init pmu_check_apic(void) pr_info("no hardware sampling interrupt available.\n"); } -void __init init_hw_perf_events(void) +int __init init_hw_perf_events(void) { struct event_constraint *c; int err; @@ -1438,11 +1438,11 @@ void __init init_hw_perf_events(void) err = amd_pmu_init(); break; default: - return; + return 0; } if (err != 0) { pr_cont("no PMU driver, software events only.\n"); - return; + return 0; } pmu_check_apic(); @@ -1450,7 +1450,7 @@ void __init init_hw_perf_events(void) /* sanity check that the hardware exists or is emulated */ if (!check_hw_exists()) { pr_cont("Broken PMU hardware detected, software events only.\n"); - return; + return 0; } pr_cont("%s PMU driver.\n", x86_pmu.name); @@ -1501,7 +1501,10 @@ void __init init_hw_perf_events(void) perf_pmu_register(&pmu); perf_cpu_notifier(x86_pmu_notifier); + + return 0; } +perf_initcall(init_hw_perf_events); static inline void x86_pmu_read(struct perf_event *event) { Index: linux-2.6/arch/arm/kernel/perf_event.c =================================================================== --- linux-2.6.orig/arch/arm/kernel/perf_event.c +++ linux-2.6/arch/arm/kernel/perf_event.c @@ -3038,7 +3038,7 @@ init_hw_perf_events(void) return 0; } -arch_initcall(init_hw_perf_events); +perf_initcall(init_hw_perf_events); /* * Callchain handling code. Index: linux-2.6/arch/mips/kernel/perf_event_mipsxx.c =================================================================== --- linux-2.6.orig/arch/mips/kernel/perf_event_mipsxx.c +++ linux-2.6/arch/mips/kernel/perf_event_mipsxx.c @@ -1047,6 +1047,6 @@ init_hw_perf_events(void) return 0; } -arch_initcall(init_hw_perf_events); +perf_initcall(init_hw_perf_events); #endif /* defined(CONFIG_CPU_MIPS32)... */ Index: linux-2.6/arch/powerpc/kernel/e500-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/e500-pmu.c +++ linux-2.6/arch/powerpc/kernel/e500-pmu.c @@ -126,4 +126,4 @@ static int init_e500_pmu(void) return register_fsl_emb_pmu(&e500_pmu); } -arch_initcall(init_e500_pmu); +perf_initcall(init_e500_pmu); Index: linux-2.6/arch/powerpc/kernel/mpc7450-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/mpc7450-pmu.c +++ linux-2.6/arch/powerpc/kernel/mpc7450-pmu.c @@ -414,4 +414,4 @@ static int init_mpc7450_pmu(void) return register_power_pmu(&mpc7450_pmu); } -arch_initcall(init_mpc7450_pmu); +perf_initcall(init_mpc7450_pmu); Index: linux-2.6/arch/powerpc/kernel/power4-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/power4-pmu.c +++ linux-2.6/arch/powerpc/kernel/power4-pmu.c @@ -613,4 +613,4 @@ static int init_power4_pmu(void) return register_power_pmu(&power4_pmu); } -arch_initcall(init_power4_pmu); +perf_initcall(init_power4_pmu); Index: linux-2.6/arch/powerpc/kernel/power5+-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/power5+-pmu.c +++ linux-2.6/arch/powerpc/kernel/power5+-pmu.c @@ -682,4 +682,4 @@ static int init_power5p_pmu(void) return register_power_pmu(&power5p_pmu); } -arch_initcall(init_power5p_pmu); +perf_initcall(init_power5p_pmu); Index: linux-2.6/arch/powerpc/kernel/power5-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/power5-pmu.c +++ linux-2.6/arch/powerpc/kernel/power5-pmu.c @@ -621,4 +621,4 @@ static int init_power5_pmu(void) return register_power_pmu(&power5_pmu); } -arch_initcall(init_power5_pmu); +perf_initcall(init_power5_pmu); Index: linux-2.6/arch/powerpc/kernel/power6-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/power6-pmu.c +++ linux-2.6/arch/powerpc/kernel/power6-pmu.c @@ -544,4 +544,4 @@ static int init_power6_pmu(void) return register_power_pmu(&power6_pmu); } -arch_initcall(init_power6_pmu); +perf_initcall(init_power6_pmu); Index: linux-2.6/arch/powerpc/kernel/power7-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/power7-pmu.c +++ linux-2.6/arch/powerpc/kernel/power7-pmu.c @@ -369,4 +369,4 @@ static int init_power7_pmu(void) return register_power_pmu(&power7_pmu); } -arch_initcall(init_power7_pmu); +perf_initcall(init_power7_pmu); Index: linux-2.6/arch/powerpc/kernel/ppc970-pmu.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/ppc970-pmu.c +++ linux-2.6/arch/powerpc/kernel/ppc970-pmu.c @@ -494,4 +494,4 @@ static int init_ppc970_pmu(void) return register_power_pmu(&ppc970_pmu); } -arch_initcall(init_ppc970_pmu); +perf_initcall(init_ppc970_pmu); Index: linux-2.6/arch/sh/kernel/cpu/sh4/perf_event.c =================================================================== --- linux-2.6.orig/arch/sh/kernel/cpu/sh4/perf_event.c +++ linux-2.6/arch/sh/kernel/cpu/sh4/perf_event.c @@ -250,4 +250,4 @@ static int __init sh7750_pmu_init(void) return register_sh_pmu(&sh7750_pmu); } -arch_initcall(sh7750_pmu_init); +perf_initcall(sh7750_pmu_init); Index: linux-2.6/arch/sh/kernel/cpu/sh4a/perf_event.c =================================================================== --- linux-2.6.orig/arch/sh/kernel/cpu/sh4a/perf_event.c +++ linux-2.6/arch/sh/kernel/cpu/sh4a/perf_event.c @@ -284,4 +284,4 @@ static int __init sh4a_pmu_init(void) return register_sh_pmu(&sh4a_pmu); } -arch_initcall(sh4a_pmu_init); +perf_initcall(sh4a_pmu_init);