diff options
author | Laurentiu TUDOR <Laurentiu.Tudor@freescale.com> | 2013-07-03 17:13:15 +0300 |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2013-08-07 18:38:06 -0500 |
commit | 4e21b94c9c644c43223878f4c848e852743e789c (patch) | |
tree | 70671b6571cb5c92752264d26a174cbc0d9034b8 /arch | |
parent | f31dd9443afd35696a833c2a32d584a9257abd40 (diff) | |
download | linux-4e21b94c9c644c43223878f4c848e852743e789c.tar.bz2 |
powerpc/85xx: Move ePAPR paravirt initialization earlier
At console init, when the kernel tries to flush the log buffer
the ePAPR byte-channel based console write fails silently,
losing the buffered messages.
This happens because The ePAPR para-virtualization init isn't
done early enough so that the hcall instruction to be set,
causing the byte-channel write hcall to be a nop.
To fix, change the ePAPR para-virt init to use early device
tree functions and move it in early init.
Signed-off-by: Laurentiu Tudor <Laurentiu.Tudor@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/epapr_hcalls.h | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/epapr_paravirt.c | 28 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_32.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 3 |
4 files changed, 28 insertions, 13 deletions
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h index d3d634274d2c..86b0ac79990c 100644 --- a/arch/powerpc/include/asm/epapr_hcalls.h +++ b/arch/powerpc/include/asm/epapr_hcalls.h @@ -105,6 +105,12 @@ extern bool epapr_paravirt_enabled; extern u32 epapr_hypercall_start[]; +#ifdef CONFIG_EPAPR_PARAVIRT +int __init epapr_paravirt_early_init(void); +#else +static inline int epapr_paravirt_early_init(void) { return 0; } +#endif + /* * We use "uintptr_t" to define a register because it's guaranteed to be a * 32-bit integer on a 32-bit platform, and a 64-bit integer on a 64-bit diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c index d44a571e45a7..6300c13bbde4 100644 --- a/arch/powerpc/kernel/epapr_paravirt.c +++ b/arch/powerpc/kernel/epapr_paravirt.c @@ -30,22 +30,20 @@ extern u32 epapr_ev_idle_start[]; bool epapr_paravirt_enabled; -static int __init epapr_paravirt_init(void) +static int __init early_init_dt_scan_epapr(unsigned long node, + const char *uname, + int depth, void *data) { - struct device_node *hyper_node; const u32 *insts; - int len, i; + unsigned long len; + int i; - hyper_node = of_find_node_by_path("/hypervisor"); - if (!hyper_node) - return -ENODEV; - - insts = of_get_property(hyper_node, "hcall-instructions", &len); + insts = of_get_flat_dt_prop(node, "hcall-instructions", &len); if (!insts) - return -ENODEV; + return 0; if (len % 4 || len > (4 * 4)) - return -ENODEV; + return -1; for (i = 0; i < (len / 4); i++) { patch_instruction(epapr_hypercall_start + i, insts[i]); @@ -55,13 +53,19 @@ static int __init epapr_paravirt_init(void) } #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64) - if (of_get_property(hyper_node, "has-idle", NULL)) + if (of_get_flat_dt_prop(node, "has-idle", NULL)) ppc_md.power_save = epapr_ev_idle; #endif epapr_paravirt_enabled = true; + return 1; +} + +int __init epapr_paravirt_early_init(void) +{ + of_scan_flat_dt(early_init_dt_scan_epapr, NULL); + return 0; } -early_initcall(epapr_paravirt_init); diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index a8f54ecb091f..a4bbcae72578 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -38,6 +38,7 @@ #include <asm/serial.h> #include <asm/udbg.h> #include <asm/mmu_context.h> +#include <asm/epapr_hcalls.h> #include "setup.h" @@ -128,6 +129,8 @@ notrace void __init machine_init(u64 dt_ptr) /* Do some early initialization based on the flat device tree */ early_init_devtree(__va(dt_ptr)); + epapr_paravirt_early_init(); + early_init_mmu(); probe_machine(); @@ -326,5 +329,4 @@ void __init setup_arch(char **cmdline_p) /* Initialize the MMU context management stuff */ mmu_context_init(); - } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 389fb8077cc9..f03770e0fc8d 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -66,6 +66,7 @@ #include <asm/code-patching.h> #include <asm/kvm_ppc.h> #include <asm/hugetlb.h> +#include <asm/epapr_hcalls.h> #include "setup.h" @@ -215,6 +216,8 @@ void __init early_setup(unsigned long dt_ptr) */ early_init_devtree(__va(dt_ptr)); + epapr_paravirt_early_init(); + /* Now we know the logical id of our boot cpu, setup the paca. */ setup_paca(&paca[boot_cpuid]); fixup_boot_paca(); |