aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2017-09-14 21:13:45 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-09-28 00:30:02 -0500
commitab101cb041a985f99c9e05977d4d43ad4baaeef8 (patch)
tree5319cfb04f4ca70e364958edf85a75904685d97f
parent210cb11e02cb77c060dbecb50e1aa185913e1e1d (diff)
downloadskiboot-ab101cb041a985f99c9e05977d4d43ad4baaeef8.zip
skiboot-ab101cb041a985f99c9e05977d4d43ad4baaeef8.tar.gz
skiboot-ab101cb041a985f99c9e05977d4d43ad4baaeef8.tar.bz2
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 <npiggin@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--core/cpu.c91
-rw-r--r--core/fast-reboot.c3
-rw-r--r--core/init.c10
-rw-r--r--include/cpu.h8
4 files changed, 74 insertions, 38 deletions
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
diff --git a/include/cpu.h b/include/cpu.h
index 77419ca..168fa99 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -263,8 +263,12 @@ extern void cpu_process_jobs(void);
extern void cpu_process_local_jobs(void);
/* Check if there's any job pending */
bool cpu_check_jobs(struct cpu_thread *cpu);
-/* Enable/disable PM */
-void cpu_set_pm_enable(bool pm_enabled);
+
+/* OPAL sreset vector in place at 0x100 */
+void cpu_set_sreset_enable(bool sreset_enabled);
+
+/* IPI for PM modes is enabled */
+void cpu_set_ipi_enable(bool sreset_enabled);
static inline void cpu_give_self_os(void)
{