aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2016-09-14 06:00:27 -0400
committerRalf Baechle <ralf@linux-mips.org>2016-10-04 19:31:20 -0400
commitba7505022c8b7c7366b905262631b293ac60c863 (patch)
tree75747633b37dc86e7df2e4f746b4f02d26aa0196 /arch/mips/kernel
parentcd14c92bbd095fdc2d0b78f7dac920769ff06a9f (diff)
MIPS: pm-cps: Generate idle state entry code when CPUs are onlined
The MIPS Coherent Processing System (CPS) power management code has previously generated code used to enter low power idle states once during boot for all CPUs. This has the drawback that if a CPU is present in the system but not being used (for example due to the maxcpus kernel parameter) then we encounter problems due to not having probed that CPU for information about its type & properties. The result of this is that we generate entry code which is both unused, potentially entirely invalid & likely to be unsuitable for the CPU in question anyway. Avoid this by generating idle state entry code only when a CPU is brought online. This way we only ever generate code for CPUs that we know we've probed the properties of, and that will actually be used. [ralf@linux-mips.org: Resolve merge conflict.] Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: Adam Buchbinder <adam.buchbinder@gmail.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com> Cc: Markos Chandras <markos.chandras@imgtec.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14259/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/pm-cps.c45
1 files changed, 19 insertions, 26 deletions
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index 05bcdedcf9bd..7cf653e21423 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -8,6 +8,7 @@
8 * option) any later version. 8 * option) any later version.
9 */ 9 */
10 10
11#include <linux/cpuhotplug.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/percpu.h> 13#include <linux/percpu.h>
13#include <linux/slab.h> 14#include <linux/slab.h>
@@ -70,8 +71,8 @@ static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier);
70DEFINE_PER_CPU_ALIGNED(struct mips_static_suspend_state, cps_cpu_state); 71DEFINE_PER_CPU_ALIGNED(struct mips_static_suspend_state, cps_cpu_state);
71 72
72/* A somewhat arbitrary number of labels & relocs for uasm */ 73/* A somewhat arbitrary number of labels & relocs for uasm */
73static struct uasm_label labels[32] __initdata; 74static struct uasm_label labels[32];
74static struct uasm_reloc relocs[32] __initdata; 75static struct uasm_reloc relocs[32];
75 76
76enum mips_reg { 77enum mips_reg {
77 zero, at, v0, v1, a0, a1, a2, a3, 78 zero, at, v0, v1, a0, a1, a2, a3,
@@ -193,10 +194,10 @@ int cps_pm_enter_state(enum cps_pm_state state)
193 return 0; 194 return 0;
194} 195}
195 196
196static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl, 197static void cps_gen_cache_routine(u32 **pp, struct uasm_label **pl,
197 struct uasm_reloc **pr, 198 struct uasm_reloc **pr,
198 const struct cache_desc *cache, 199 const struct cache_desc *cache,
199 unsigned op, int lbl) 200 unsigned op, int lbl)
200{ 201{
201 unsigned cache_size = cache->ways << cache->waybit; 202 unsigned cache_size = cache->ways << cache->waybit;
202 unsigned i; 203 unsigned i;
@@ -237,10 +238,10 @@ static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl,
237 uasm_i_nop(pp); 238 uasm_i_nop(pp);
238} 239}
239 240
240static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl, 241static int cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
241 struct uasm_reloc **pr, 242 struct uasm_reloc **pr,
242 const struct cpuinfo_mips *cpu_info, 243 const struct cpuinfo_mips *cpu_info,
243 int lbl) 244 int lbl)
244{ 245{
245 unsigned i, fsb_size = 8; 246 unsigned i, fsb_size = 8;
246 unsigned num_loads = (fsb_size * 3) / 2; 247 unsigned num_loads = (fsb_size * 3) / 2;
@@ -330,9 +331,9 @@ static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl,
330 return 0; 331 return 0;
331} 332}
332 333
333static void __init cps_gen_set_top_bit(u32 **pp, struct uasm_label **pl, 334static void cps_gen_set_top_bit(u32 **pp, struct uasm_label **pl,
334 struct uasm_reloc **pr, 335 struct uasm_reloc **pr,
335 unsigned r_addr, int lbl) 336 unsigned r_addr, int lbl)
336{ 337{
337 uasm_i_lui(pp, t0, uasm_rel_hi(0x80000000)); 338 uasm_i_lui(pp, t0, uasm_rel_hi(0x80000000));
338 uasm_build_label(pl, *pp, lbl); 339 uasm_build_label(pl, *pp, lbl);
@@ -343,7 +344,7 @@ static void __init cps_gen_set_top_bit(u32 **pp, struct uasm_label **pl,
343 uasm_i_nop(pp); 344 uasm_i_nop(pp);
344} 345}
345 346
346static void * __init cps_gen_entry_code(unsigned cpu, enum cps_pm_state state) 347static void *cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
347{ 348{
348 struct uasm_label *l = labels; 349 struct uasm_label *l = labels;
349 struct uasm_reloc *r = relocs; 350 struct uasm_reloc *r = relocs;
@@ -637,7 +638,7 @@ out_err:
637 return NULL; 638 return NULL;
638} 639}
639 640
640static int __init cps_gen_core_entries(unsigned cpu) 641static int cps_pm_online_cpu(unsigned int cpu)
641{ 642{
642 enum cps_pm_state state; 643 enum cps_pm_state state;
643 unsigned core = cpu_data[cpu].core; 644 unsigned core = cpu_data[cpu].core;
@@ -679,13 +680,10 @@ static int __init cps_gen_core_entries(unsigned cpu)
679 680
680static int __init cps_pm_init(void) 681static int __init cps_pm_init(void)
681{ 682{
682 unsigned cpu;
683 int err;
684
685 /* A CM is required for all non-coherent states */ 683 /* A CM is required for all non-coherent states */
686 if (!mips_cm_present()) { 684 if (!mips_cm_present()) {
687 pr_warn("pm-cps: no CM, non-coherent states unavailable\n"); 685 pr_warn("pm-cps: no CM, non-coherent states unavailable\n");
688 goto out; 686 return 0;
689 } 687 }
690 688
691 /* 689 /*
@@ -715,12 +713,7 @@ static int __init cps_pm_init(void)
715 pr_warn("pm-cps: no CPC, clock & power gating unavailable\n"); 713 pr_warn("pm-cps: no CPC, clock & power gating unavailable\n");
716 } 714 }
717 715
718 for_each_present_cpu(cpu) { 716 return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "AP_PM_CPS_CPU_ONLINE",
719 err = cps_gen_core_entries(cpu); 717 cps_pm_online_cpu, NULL);
720 if (err)
721 return err;
722 }
723out:
724 return 0;
725} 718}
726arch_initcall(cps_pm_init); 719arch_initcall(cps_pm_init);