From ab101cb041a985f99c9e05977d4d43ad4baaeef8 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 14 Sep 2017 21:13:45 +1000 Subject: cpu: idle split pm enable into sreset and ipi components pm idle requires the system reset vector and IPI facilities before it can be enabled. Split these out and manage them individually. Signed-off-by: Nicholas Piggin Signed-off-by: Stewart Smith --- core/cpu.c | 91 +++++++++++++++++++++++++++++++++++------------------- core/fast-reboot.c | 3 +- core/init.c | 10 ++++-- 3 files changed, 68 insertions(+), 36 deletions(-) (limited to 'core') diff --git a/core/cpu.c b/core/cpu.c index cf86039..367856c 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -52,6 +52,8 @@ static bool hile_supported; static bool radix_supported; static unsigned long hid0_hile; static unsigned long hid0_attn; +static bool sreset_enabled; +static bool ipi_enabled; static bool pm_enabled; static bool current_hile_mode; static bool current_radix_mode; @@ -321,9 +323,7 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on) mtspr(SPR_LPCR, lpcr); } else { - /* Mark outselves sleeping so cpu_set_pm_enable knows to - * send an IPI - */ + /* Mark outselves sleeping so wakeup knows to send an IPI */ cpu->in_sleep = true; sync(); @@ -346,35 +346,6 @@ skip_sleep: reset_cpu_icp(); } -void cpu_set_pm_enable(bool enabled) -{ - struct cpu_thread *cpu; - - prlog(PR_INFO, "CPU: %sing power management\n", - enabled ? "enabl" : "disabl"); - - if (proc_gen != proc_gen_p8) - return; - - /* Public P8 Mambo has broken NAP */ - if (chip_quirk(QUIRK_MAMBO_CALLOUTS)) - return; - - pm_enabled = enabled; - - if (enabled) - return; - - /* If disabling, take everybody out of PM */ - sync(); - for_each_available_cpu(cpu) { - while (cpu->in_sleep || cpu->in_idle) { - icp_kick_cpu(cpu); - cpu_relax(); - } - } -} - static void cpu_idle_pm(enum cpu_wake_cause wake_on) { switch(proc_gen) { @@ -444,6 +415,62 @@ no_pm: } } +static void cpu_pm_disable(void) +{ + struct cpu_thread *cpu; + + pm_enabled = false; + sync(); + + if (proc_gen == proc_gen_p8) { + for_each_available_cpu(cpu) { + while (cpu->in_sleep || cpu->in_idle) { + icp_kick_cpu(cpu); + cpu_relax(); + } + } + } +} + +void cpu_set_sreset_enable(bool enabled) +{ + if (sreset_enabled == enabled) + return; + + if (proc_gen == proc_gen_p8) { + /* Public P8 Mambo has broken NAP */ + if (chip_quirk(QUIRK_MAMBO_CALLOUTS)) + return; + + sreset_enabled = enabled; + sync(); + + if (!enabled) { + cpu_pm_disable(); + } else { + if (ipi_enabled) + pm_enabled = true; + } + } +} + +void cpu_set_ipi_enable(bool enabled) +{ + if (ipi_enabled == enabled) + return; + + if (proc_gen == proc_gen_p8) { + ipi_enabled = enabled; + sync(); + if (!enabled) { + cpu_pm_disable(); + } else { + if (sreset_enabled) + pm_enabled = true; + } + } +} + void cpu_process_local_jobs(void) { struct cpu_thread *cpu = first_available_cpu(); diff --git a/core/fast-reboot.c b/core/fast-reboot.c index 7bfc06d..8af5c59 100644 --- a/core/fast-reboot.c +++ b/core/fast-reboot.c @@ -564,7 +564,8 @@ void __noreturn fast_reboot_entry(void) cpu_fast_reboot_complete(); /* We can now do NAP mode */ - cpu_set_pm_enable(true); + cpu_set_sreset_enable(true); + cpu_set_ipi_enable(true); /* Start preloading kernel and ramdisk */ start_preload_kernel(); diff --git a/core/init.c b/core/init.c index ab260d4..be49c3f 100644 --- a/core/init.c +++ b/core/init.c @@ -382,7 +382,7 @@ static bool load_kernel(void) * by our vectors. */ if (kernel_entry < 0x2000) { - cpu_set_pm_enable(false); + cpu_set_sreset_enable(false); memcpy(NULL, old_vectors, 0x2000); sync_icache(); } @@ -545,7 +545,8 @@ void __noreturn load_and_boot_kernel(bool is_reboot) mem_dump_free(); /* Take processours out of nap */ - cpu_set_pm_enable(false); + cpu_set_sreset_enable(false); + cpu_set_ipi_enable(false); /* Dump the selected console */ stdoutp = dt_prop_get_def(dt_chosen, "linux,stdout-path", NULL); @@ -725,6 +726,7 @@ void setup_reset_vector(void) while(src < &reset_patch_end) *(dst++) = *(src++); sync_icache(); + cpu_set_sreset_enable(true); } void copy_exception_vectors(void) @@ -932,6 +934,8 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) /* On P7/P8, get the ICPs and make sure they are in a sane state */ init_interrupts(); + if (proc_gen == proc_gen_p7 || proc_gen == proc_gen_p8) + cpu_set_ipi_enable(true); /* On P9, initialize XIVE */ init_xive(); @@ -957,7 +961,7 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt) setup_reset_vector(); /* We can now do NAP mode */ - cpu_set_pm_enable(true); + cpu_set_sreset_enable(true); /* * Synchronize time bases. Thi resets all the TB values to a small -- cgit v1.1