From 2eb736d6b425cb932b038fd555243b9b0e59c036 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 18 Jan 2015 13:13:32 +0000 Subject: [PATCH] ARM: Revert ARM side of PSCI backports We use the old interfaces on ARM for TC2 and have no pressing need to update. Signed-off-by: Mark Brown --- arch/arm/include/asm/psci.h | 7 +- arch/arm/kernel/Makefile | 1 - arch/arm/kernel/psci.c | 219 +++++++++++------------------------- arch/arm/kernel/psci_smp.c | 39 +------ arch/arm/kernel/setup.c | 10 +- 5 files changed, 76 insertions(+), 200 deletions(-) diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h index b1946b7bbe94..f0a8627c9f1c 100644 --- a/arch/arm/include/asm/psci.h +++ b/arch/arm/include/asm/psci.h @@ -33,19 +33,16 @@ struct psci_operations { int (*cpu_off)(struct psci_power_state state); int (*cpu_on)(unsigned long cpuid, unsigned long entry_point); int (*migrate)(unsigned long cpuid); - int (*affinity_info)(unsigned long target_affinity, - unsigned long lowest_affinity_level); - int (*migrate_info_type)(void); }; extern struct psci_operations psci_ops; extern struct smp_operations psci_smp_ops; #ifdef CONFIG_ARM_PSCI -int psci_init(void); +void psci_init(void); bool psci_smp_available(void); #else -static inline int psci_init(void) { } +static inline void psci_init(void) { } static inline bool psci_smp_available(void) { return false; } #endif diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 39754851a3b1..65160d5fe850 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -32,7 +32,6 @@ obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o isa.o obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o -obj-$(CONFIG_ARM_CPU_IDLE) += cpuidle.o obj-$(CONFIG_SMP) += smp.o smp_tlb.o obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c index f705c1b27bb3..0daf4f252284 100644 --- a/arch/arm/kernel/psci.c +++ b/arch/arm/kernel/psci.c @@ -18,16 +18,12 @@ #include #include #include -#include -#include -#include #include #include #include #include #include -#include struct psci_operations psci_ops; @@ -35,47 +31,58 @@ struct psci_operations psci_ops; #define PSCI_SUP_DISABLED 0 #define PSCI_SUP_ENABLED 1 +static unsigned int psci; static int (*invoke_psci_fn)(u32, u32, u32, u32); -typedef int (*psci_initcall_t)(const struct device_node *); enum psci_function { PSCI_FN_CPU_SUSPEND, PSCI_FN_CPU_ON, PSCI_FN_CPU_OFF, PSCI_FN_MIGRATE, - PSCI_FN_AFFINITY_INFO, - PSCI_FN_MIGRATE_INFO_TYPE, PSCI_FN_MAX, }; static u32 psci_function_id[PSCI_FN_MAX]; +#define PSCI_RET_SUCCESS 0 +#define PSCI_RET_EOPNOTSUPP -1 +#define PSCI_RET_EINVAL -2 +#define PSCI_RET_EPERM -3 +#define PSCI_RET_EALREADYON -4 + static int psci_to_linux_errno(int errno) { switch (errno) { case PSCI_RET_SUCCESS: return 0; - case PSCI_RET_NOT_SUPPORTED: + case PSCI_RET_EOPNOTSUPP: return -EOPNOTSUPP; - case PSCI_RET_INVALID_PARAMS: + case PSCI_RET_EINVAL: return -EINVAL; - case PSCI_RET_DENIED: + case PSCI_RET_EPERM: return -EPERM; - case PSCI_RET_ALREADY_ON: + case PSCI_RET_EALREADYON: return -EAGAIN; }; return -EINVAL; } +#define PSCI_POWER_STATE_ID_MASK 0xffff +#define PSCI_POWER_STATE_ID_SHIFT 0 +#define PSCI_POWER_STATE_TYPE_MASK 0x1 +#define PSCI_POWER_STATE_TYPE_SHIFT 16 +#define PSCI_POWER_STATE_AFFL_MASK 0x3 +#define PSCI_POWER_STATE_AFFL_SHIFT 24 + static u32 psci_power_state_pack(struct psci_power_state state) { - return ((state.id << PSCI_0_2_POWER_STATE_ID_SHIFT) - & PSCI_0_2_POWER_STATE_ID_MASK) | - ((state.type << PSCI_0_2_POWER_STATE_TYPE_SHIFT) - & PSCI_0_2_POWER_STATE_TYPE_MASK) | - ((state.affinity_level << PSCI_0_2_POWER_STATE_AFFL_SHIFT) - & PSCI_0_2_POWER_STATE_AFFL_MASK); + return ((state.id & PSCI_POWER_STATE_ID_MASK) + << PSCI_POWER_STATE_ID_SHIFT) | + ((state.type & PSCI_POWER_STATE_TYPE_MASK) + << PSCI_POWER_STATE_TYPE_SHIFT) | + ((state.affinity_level & PSCI_POWER_STATE_AFFL_MASK) + << PSCI_POWER_STATE_AFFL_SHIFT); } /* @@ -112,14 +119,6 @@ static noinline int __invoke_psci_fn_smc(u32 function_id, u32 arg0, u32 arg1, return function_id; } -static int psci_get_version(void) -{ - int err; - - err = invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0); - return err; -} - static int psci_cpu_suspend(struct psci_power_state state, unsigned long entry_point) { @@ -163,36 +162,29 @@ static int psci_migrate(unsigned long cpuid) return psci_to_linux_errno(err); } -static int psci_affinity_info(unsigned long target_affinity, - unsigned long lowest_affinity_level) -{ - int err; - u32 fn; - - fn = psci_function_id[PSCI_FN_AFFINITY_INFO]; - err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0); - return err; -} +static const struct of_device_id psci_of_match[] __initconst = { + { .compatible = "arm,psci", }, + {}, +}; -static int psci_migrate_info_type(void) +void __init psci_init(void) { - int err; - u32 fn; + struct device_node *np; + const char *method; + u32 id; - fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE]; - err = invoke_psci_fn(fn, 0, 0, 0); - return err; -} + if (psci == PSCI_SUP_DISABLED) + return; -static int get_set_conduit_method(struct device_node *np) -{ - const char *method; + np = of_find_matching_node(NULL, psci_of_match); + if (!np) + return; - pr_info("probing for conduit method from DT.\n"); + pr_info("probing function IDs from device-tree\n"); if (of_property_read_string(np, "method", &method)) { - pr_warn("missing \"method\" property\n"); - return -ENXIO; + pr_warning("missing \"method\" property\n"); + goto out_put_node; } if (!strcmp("hvc", method)) { @@ -200,99 +192,10 @@ static int get_set_conduit_method(struct device_node *np) } else if (!strcmp("smc", method)) { invoke_psci_fn = __invoke_psci_fn_smc; } else { - pr_warn("invalid \"method\" property: %s\n", method); - return -EINVAL; - } - return 0; -} - -static void psci_sys_reset(enum reboot_mode reboot_mode, const char *cmd) -{ - invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); -} - -static void psci_sys_poweroff(void) -{ - invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0); -} - -/* - * PSCI Function IDs for v0.2+ are well defined so use - * standard values. - */ -static int psci_0_2_init(struct device_node *np) -{ - int err, ver; - - err = get_set_conduit_method(np); - - if (err) + pr_warning("invalid \"method\" property: %s\n", method); goto out_put_node; - - ver = psci_get_version(); - - if (ver == PSCI_RET_NOT_SUPPORTED) { - /* PSCI v0.2 mandates implementation of PSCI_ID_VERSION. */ - pr_err("PSCI firmware does not comply with the v0.2 spec.\n"); - err = -EOPNOTSUPP; - goto out_put_node; - } else { - pr_info("PSCIv%d.%d detected in firmware.\n", - PSCI_VERSION_MAJOR(ver), - PSCI_VERSION_MINOR(ver)); - - if (PSCI_VERSION_MAJOR(ver) == 0 && - PSCI_VERSION_MINOR(ver) < 2) { - err = -EINVAL; - pr_err("Conflicting PSCI version detected.\n"); - goto out_put_node; - } } - pr_info("Using standard PSCI v0.2 function IDs\n"); - psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN_CPU_SUSPEND; - psci_ops.cpu_suspend = psci_cpu_suspend; - - psci_function_id[PSCI_FN_CPU_OFF] = PSCI_0_2_FN_CPU_OFF; - psci_ops.cpu_off = psci_cpu_off; - - psci_function_id[PSCI_FN_CPU_ON] = PSCI_0_2_FN_CPU_ON; - psci_ops.cpu_on = psci_cpu_on; - - psci_function_id[PSCI_FN_MIGRATE] = PSCI_0_2_FN_MIGRATE; - psci_ops.migrate = psci_migrate; - - psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_0_2_FN_AFFINITY_INFO; - psci_ops.affinity_info = psci_affinity_info; - - psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] = - PSCI_0_2_FN_MIGRATE_INFO_TYPE; - psci_ops.migrate_info_type = psci_migrate_info_type; - - arm_pm_restart = psci_sys_reset; - - pm_power_off = psci_sys_poweroff; - -out_put_node: - of_node_put(np); - return err; -} - -/* - * PSCI < v0.2 get PSCI Function IDs via DT. - */ -static int psci_0_1_init(struct device_node *np) -{ - u32 id; - int err; - - err = get_set_conduit_method(np); - - if (err) - goto out_put_node; - - pr_info("Using PSCI v0.1 Function IDs from DT\n"); - if (!of_property_read_u32(np, "cpu_suspend", &id)) { psci_function_id[PSCI_FN_CPU_SUSPEND] = id; psci_ops.cpu_suspend = psci_cpu_suspend; @@ -315,25 +218,35 @@ static int psci_0_1_init(struct device_node *np) out_put_node: of_node_put(np); - return err; + return; } -static const struct of_device_id psci_of_match[] __initconst = { - { .compatible = "arm,psci", .data = psci_0_1_init}, - { .compatible = "arm,psci-0.2", .data = psci_0_2_init}, - {}, -}; - -int __init psci_init(void) +int __init psci_probe(void) { struct device_node *np; - const struct of_device_id *matched_np; - psci_initcall_t init_fn; + int ret = -ENODEV; - np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np); - if (!np) - return -ENODEV; + if (psci == PSCI_SUP_ENABLED) { + np = of_find_matching_node(NULL, psci_of_match); + if (np) + ret = 0; + } + + of_node_put(np); + return ret; +} + +static int __init early_psci(char *val) +{ + int ret = 0; + + if (strcmp(val, "enable") == 0) + psci = PSCI_SUP_ENABLED; + else if (strcmp(val, "disable") == 0) + psci = PSCI_SUP_DISABLED; + else + ret = -EINVAL; - init_fn = (psci_initcall_t)matched_np->data; - return init_fn(np); + return ret; } +early_param("psci", early_psci); diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index 3af4190e4d9d..23a11424c568 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c @@ -17,10 +17,6 @@ #include #include #include -#include -#include -#include -#include #include #include @@ -72,36 +68,8 @@ void __ref psci_cpu_die(unsigned int cpu) /* We should never return */ panic("psci: cpu %d failed to shutdown\n", cpu); } - -int __ref psci_cpu_kill(unsigned int cpu) -{ - int err, i; - - if (!psci_ops.affinity_info) - return 1; - /* - * cpu_kill could race with cpu_die and we can - * potentially end up declaring this cpu undead - * while it is dying. So, try again a few times. - */ - - for (i = 0; i < 10; i++) { - err = psci_ops.affinity_info(cpu_logical_map(cpu), 0); - if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) { - pr_info("CPU%d killed.\n", cpu); - return 1; - } - - msleep(10); - pr_info("Retrying again to check for CPU kill\n"); - } - - pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n", - cpu, err); - /* Make platform_cpu_kill() fail. */ - return 0; -} - +#else +#define psci_cpu_die NULL #endif bool __init psci_smp_available(void) @@ -112,8 +80,5 @@ bool __init psci_smp_available(void) struct smp_operations __initdata psci_smp_ops = { .smp_boot_secondary = psci_boot_secondary, -#ifdef CONFIG_HOTPLUG_CPU .cpu_die = psci_cpu_die, - .cpu_kill = psci_cpu_kill, -#endif }; diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d4d020178d77..29beb8c76560 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -835,10 +835,12 @@ void __init setup_arch(char **cmdline_p) psci_init(); #ifdef CONFIG_SMP if (is_smp()) { - if (psci_smp_available()) - smp_set_ops(&psci_smp_ops); - else if (mdesc->smp) - smp_set_ops(mdesc->smp); + if (!mdesc->smp_init || !mdesc->smp_init()) { + if (psci_smp_available()) + smp_set_ops(&psci_smp_ops); + else if (mdesc->smp) + smp_set_ops(mdesc->smp); + } smp_init_cpus(); } #endif -- 2.34.1