* [PATCH v4 0/3] PSCI v0.2 support and DT bindings
@ 2014-03-31 15:02 Ashwin Chaugule
2014-03-31 15:02 ` [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions Ashwin Chaugule
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Ashwin Chaugule @ 2014-03-31 15:02 UTC (permalink / raw)
To: linux-arm-kernel
Changes in v4:
- Correct copyright banner format.
- Check if PSCI Version ID is supported.
- Add all PSCI RET codes in uapi header.
- Explicitely ret 1 from psci_cpu_kill()
Changes in v3:
- Roll up common functionality for getting conduit method.
- Remove #defines for ARM32 and ARM64 in uapi/linux/psci.h
- Remove functions not supported by PSCI v0.1
- Misc cleanups.
- Add PSCI_AFFINITY_INFO return types in uapi header.
- Changed function names for PSCI v0.1 and PSCI v0.2
- Added copyright info to uapi header.
- Fixed args to affinity_info call.
- Fix typo in psci_init definition when PSCI is not defined.
Changes in v2:
- Add AFFINITY_INFO and MIGRATE_INFO_TYPE functions.
- Add binding Documentation.
- Add function to get PSCI version.
- Add common #defines in uapi/linux/psci.h
- Implement cpu_kill and check if CPU is dead via AFFINITY_INFO.
- Misc cleanups.
Changes in v1:
- Add new binding "arm, psci-0.2"
- Separate conduit and PSCI function assignment methods.
Ashwin Chaugule (3):
PSCI: Add initial support for PSCIv0.2 functions
Documentation: devicetree: Add new binding for PSCIv0.2
ARM: Check if a CPU has gone offline
Documentation/devicetree/bindings/arm/psci.txt | 35 +++++-
arch/arm/include/asm/psci.h | 7 +-
arch/arm/kernel/psci.c | 155 +++++++++++++++++++-----
arch/arm/kernel/psci_smp.c | 21 ++++
arch/arm64/kernel/psci.c | 160 ++++++++++++++++++++-----
include/uapi/linux/psci.h | 66 ++++++++++
6 files changed, 383 insertions(+), 61 deletions(-)
create mode 100644 include/uapi/linux/psci.h
--
1.8.3.2
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions 2014-03-31 15:02 [PATCH v4 0/3] PSCI v0.2 support and DT bindings Ashwin Chaugule @ 2014-03-31 15:02 ` Ashwin Chaugule 2014-03-31 16:52 ` [Linaro-acpi] " Sudeep Holla 2014-03-31 15:02 ` [PATCH v4 2/3] Documentation: devicetree: Add new binding for PSCIv0.2 Ashwin Chaugule 2014-03-31 15:02 ` [PATCH v4 3/3] ARM: Check if a CPU has gone offline Ashwin Chaugule 2 siblings, 1 reply; 8+ messages in thread From: Ashwin Chaugule @ 2014-03-31 15:02 UTC (permalink / raw) To: linux-arm-kernel The PSCIv0.2 spec defines standard values of function IDs and introduces a few new functions. Detect version of PSCI and appropriately select the right PSCI functions. Signed-off-by: Ashwin Chaugule <ashwin.chaugule@linaro.org> --- arch/arm/include/asm/psci.h | 7 +- arch/arm/kernel/psci.c | 155 ++++++++++++++++++++++++++++++++++-------- arch/arm64/kernel/psci.c | 160 +++++++++++++++++++++++++++++++++++--------- include/uapi/linux/psci.h | 61 +++++++++++++++++ 4 files changed, 323 insertions(+), 60 deletions(-) create mode 100644 include/uapi/linux/psci.h diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h index c4ae171..b93e34a 100644 --- a/arch/arm/include/asm/psci.h +++ b/arch/arm/include/asm/psci.h @@ -29,16 +29,19 @@ 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 -void psci_init(void); +int psci_init(void); bool psci_smp_available(void); #else -static inline void psci_init(void) { } +static inline int psci_init(void) { } static inline bool psci_smp_available(void) { return false; } #endif diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c index 4693188..46b23b6 100644 --- a/arch/arm/kernel/psci.c +++ b/arch/arm/kernel/psci.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/of.h> +#include <uapi/linux/psci.h> #include <asm/compiler.h> #include <asm/errno.h> @@ -27,22 +28,20 @@ struct psci_operations psci_ops; 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 - static int psci_to_linux_errno(int errno) { switch (errno) { @@ -59,13 +58,6 @@ static int psci_to_linux_errno(int errno) 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_POWER_STATE_ID_MASK) @@ -110,6 +102,14 @@ 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_ID_VERSION, 0, 0, 0); + return err; +} + static int psci_cpu_suspend(struct psci_power_state state, unsigned long entry_point) { @@ -153,26 +153,36 @@ static int psci_migrate(unsigned long cpuid) return psci_to_linux_errno(err); } -static const struct of_device_id psci_of_match[] __initconst = { - { .compatible = "arm,psci", }, - {}, -}; +static int psci_affinity_info(unsigned long target_affinity, + unsigned long lowest_affinity_level) +{ + int err; + u32 fn; -void __init psci_init(void) + fn = psci_function_id[PSCI_FN_AFFINITY_INFO]; + err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0); + return err; +} + +static int psci_migrate_info_type(void) { - struct device_node *np; - const char *method; - u32 id; + int err; + u32 fn; - np = of_find_matching_node(NULL, psci_of_match); - if (!np) - return; + fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE]; + err = invoke_psci_fn(fn, 0, 0, 0); + return err; +} - pr_info("probing function IDs from device-tree\n"); +static int get_set_conduit_method(struct device_node *np) +{ + const char *method; + + pr_info("probing for conduit method from DT.\n"); if (of_property_read_string(np, "method", &method)) { - pr_warning("missing \"method\" property\n"); - goto out_put_node; + pr_warn("missing \"method\" property\n"); + return -ENXIO; } if (!strcmp("hvc", method)) { @@ -180,10 +190,79 @@ void __init psci_init(void) } else if (!strcmp("smc", method)) { invoke_psci_fn = __invoke_psci_fn_smc; } else { - pr_warning("invalid \"method\" property: %s\n", method); + pr_warn("invalid \"method\" property: %s\n", method); + return -EINVAL; + } + return 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) goto out_put_node; + + ver = psci_get_version(); + + if (ver == PSCI_RET_EOPNOTSUPP) { + pr_info("PSCI_ID_VERSION Function not supported in firmware.\n"); + } else { + pr_info("PSCIv%d.%d detected in firmware.\n", + PSCI_VER_MAJOR(ver), PSCI_VER_MINOR(ver)); + + if (PSCI_VER_MAJOR(ver) == 0 && PSCI_VER_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_ID_CPU_SUSPEND_32; + psci_ops.cpu_suspend = psci_cpu_suspend; + + psci_function_id[PSCI_FN_CPU_OFF] = PSCI_ID_CPU_OFF; + psci_ops.cpu_off = psci_cpu_off; + + psci_function_id[PSCI_FN_CPU_ON] = PSCI_ID_CPU_ON_32; + psci_ops.cpu_on = psci_cpu_on; + + psci_function_id[PSCI_FN_MIGRATE] = PSCI_ID_CPU_MIGRATE_32; + psci_ops.migrate = psci_migrate; + + psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_ID_AFFINITY_INFO_32; + psci_ops.affinity_info = psci_affinity_info; + + psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] = PSCI_ID_MIGRATE_INFO_TYPE; + psci_ops.migrate_info_type = psci_migrate_info_type; + +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; @@ -206,5 +285,25 @@ void __init psci_init(void) out_put_node: of_node_put(np); - return; + return err; +} + +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) +{ + struct device_node *np; + const struct of_device_id *matched_np; + psci_initcall_t init_fn; + + np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np); + if (!np) + return -ENODEV; + + init_fn = (psci_initcall_t)matched_np->data; + return init_fn(np); } diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 4f97db3..46b72b6 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/of.h> #include <linux/smp.h> +#include <uapi/linux/psci.h> #include <asm/compiler.h> #include <asm/cpu_ops.h> @@ -40,27 +41,28 @@ 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); }; static struct psci_operations psci_ops; static int (*invoke_psci_fn)(u64, u64, u64, u64); +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 - static int psci_to_linux_errno(int errno) { switch (errno) { @@ -77,13 +79,6 @@ static int psci_to_linux_errno(int errno) 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_POWER_STATE_ID_MASK) @@ -128,6 +123,14 @@ static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, return function_id; } +static int psci_get_version(void) +{ + int err; + + err = invoke_psci_fn(PSCI_ID_VERSION, 0, 0, 0); + return err; +} + static int psci_cpu_suspend(struct psci_power_state state, unsigned long entry_point) { @@ -171,28 +174,36 @@ static int psci_migrate(unsigned long cpuid) return psci_to_linux_errno(err); } -static const struct of_device_id psci_of_match[] __initconst = { - { .compatible = "arm,psci", }, - {}, -}; +static int psci_affinity_info(unsigned long target_affinity, + unsigned long lowest_affinity_level) +{ + int err; + u32 fn; -int __init psci_init(void) + fn = psci_function_id[PSCI_FN_AFFINITY_INFO]; + err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0); + return err; +} + +static int psci_migrate_info_type(void) { - struct device_node *np; - const char *method; - u32 id; - int err = 0; + int err; + u32 fn; - np = of_find_matching_node(NULL, psci_of_match); - if (!np) - return -ENODEV; + fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE]; + err = invoke_psci_fn(fn, 0, 0, 0); + return err; +} - pr_info("probing function IDs from device-tree\n"); +static int get_set_conduit_method(struct device_node *np) +{ + const char *method; + + pr_info("probing for conduit method from DT.\n"); if (of_property_read_string(np, "method", &method)) { - pr_warning("missing \"method\" property\n"); - err = -ENXIO; - goto out_put_node; + pr_warn("missing \"method\" property\n"); + return -ENXIO; } if (!strcmp("hvc", method)) { @@ -200,11 +211,79 @@ int __init psci_init(void) } else if (!strcmp("smc", method)) { invoke_psci_fn = __invoke_psci_fn_smc; } else { - pr_warning("invalid \"method\" property: %s\n", method); - err = -EINVAL; + pr_warn("invalid \"method\" property: %s\n", method); + return -EINVAL; + } + return 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) goto out_put_node; + + ver = psci_get_version(); + + if (ver == PSCI_RET_EOPNOTSUPP) { + pr_info("PSCI_ID_VERSION Function not supported in firmware.\n"); + } else { + pr_info("PSCIv%d.%d detected in firmware.\n", + PSCI_VER_MAJOR(ver), PSCI_VER_MINOR(ver)); + + if (PSCI_VER_MAJOR(ver) == 0 && PSCI_VER_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_ID_CPU_SUSPEND_64; + psci_ops.cpu_suspend = psci_cpu_suspend; + + psci_function_id[PSCI_FN_CPU_OFF] = PSCI_ID_CPU_OFF; + psci_ops.cpu_off = psci_cpu_off; + + psci_function_id[PSCI_FN_CPU_ON] = PSCI_ID_CPU_ON_64; + psci_ops.cpu_on = psci_cpu_on; + + psci_function_id[PSCI_FN_MIGRATE] = PSCI_ID_CPU_MIGRATE_64; + psci_ops.migrate = psci_migrate; + + psci_function_id[PSCI_FN_AFFINITY_INFO] = PSCI_ID_AFFINITY_INFO_64; + psci_ops.affinity_info = psci_affinity_info; + + psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE] = PSCI_ID_MIGRATE_INFO_TYPE; + psci_ops.migrate_info_type = psci_migrate_info_type; + +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; @@ -230,6 +309,27 @@ out_put_node: return err; } +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) +{ + struct device_node *np; + const struct of_device_id *matched_np; + psci_initcall_t init_fn; + + np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np); + + if (!np) + return -ENODEV; + + init_fn = (psci_initcall_t)matched_np->data; + return init_fn(np); +} + #ifdef CONFIG_SMP static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu) diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h new file mode 100644 index 0000000..0354bb1 --- /dev/null +++ b/include/uapi/linux/psci.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * Author: Ashwin Chaugule <ashwin.chaugule@linaro.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _UAPI_LINUX_PSCI_H +#define _UAPI_LINUX_PSCI_H + +/* PSCI Function IDs as per PSCI spec v0.2 */ +#define PSCI_ID_VERSION 0x84000000 +#define PSCI_ID_CPU_SUSPEND_32 0x84000001 +#define PSCI_ID_CPU_SUSPEND_64 0xc4000001 +#define PSCI_ID_CPU_OFF 0x84000002 +#define PSCI_ID_CPU_ON_32 0x84000003 +#define PSCI_ID_CPU_ON_64 0xC4000003 +#define PSCI_ID_AFFINITY_INFO_32 0x84000004 +#define PSCI_ID_AFFINITY_INFO_64 0xC4000004 +#define PSCI_ID_CPU_MIGRATE_32 0x84000005 +#define PSCI_ID_CPU_MIGRATE_64 0xc4000005 +#define PSCI_ID_MIGRATE_INFO_TYPE 0x84000006 +#define PSCI_ID_MIGRATE_INFO_UP_CPU_32 0x84000007 +#define PSCI_ID_MIGRATE_INFO_UP_CPU_64 0xc4000007 +#define PSCI_ID_SYSTEM_OFF 0x84000008 +#define PSCI_ID_SYSTEM_RESET 0x84000009 + +#define PSCI_RET_SUCCESS 0 +#define PSCI_RET_EOPNOTSUPP -1 +#define PSCI_RET_EINVAL -2 +#define PSCI_RET_EPERM -3 +#define PSCI_RET_ALREADY_ON -4 +#define PSCI_RET_ON_PENDING -5 +#define PSCI_RET_INTERNAL_FAILURE -6 +#define PSCI_RET_NOT_PRESENT -7 +#define PSCI_RET_DISABLED -8 + +#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 + +#define PSCI_VER_MAJOR_MASK 0xffff0000 +#define PSCI_VER_MINOR_MASK 0x0000ffff +#define PSCI_VER_MAJOR_SHIFT 16 +#define PSCI_VER_MAJOR(ver) \ + ((ver & PSCI_VER_MAJOR_MASK) >> PSCI_VER_MAJOR_SHIFT) +#define PSCI_VER_MINOR(ver) (ver & PSCI_VER_MINOR_MASK) + +#endif /* _UAPI_LINUX_PSCI_H */ -- 1.8.3.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Linaro-acpi] [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions 2014-03-31 15:02 ` [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions Ashwin Chaugule @ 2014-03-31 16:52 ` Sudeep Holla 2014-03-31 17:09 ` Ashwin Chaugule 0 siblings, 1 reply; 8+ messages in thread From: Sudeep Holla @ 2014-03-31 16:52 UTC (permalink / raw) To: linux-arm-kernel Hi Ashwin, On 31/03/14 16:02, Ashwin Chaugule wrote: > The PSCIv0.2 spec defines standard values of function IDs > and introduces a few new functions. Detect version of PSCI > and appropriately select the right PSCI functions. > > Signed-off-by: Ashwin Chaugule <ashwin.chaugule@linaro.org> > --- > arch/arm/include/asm/psci.h | 7 +- > arch/arm/kernel/psci.c | 155 ++++++++++++++++++++++++++++++++++-------- > arch/arm64/kernel/psci.c | 160 +++++++++++++++++++++++++++++++++++--------- > include/uapi/linux/psci.h | 61 +++++++++++++++++ > 4 files changed, 323 insertions(+), 60 deletions(-) > create mode 100644 include/uapi/linux/psci.h > > diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h > index c4ae171..b93e34a 100644 > --- a/arch/arm/include/asm/psci.h > +++ b/arch/arm/include/asm/psci.h > @@ -29,16 +29,19 @@ 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 > -void psci_init(void); > +int psci_init(void); > bool psci_smp_available(void); > #else > -static inline void psci_init(void) { } > +static inline int psci_init(void) { } > static inline bool psci_smp_available(void) { return false; } > #endif > > diff --git a/arch/arm/kernel/psci.c b/arch/arm/kernel/psci.c > index 4693188..46b23b6 100644 > --- a/arch/arm/kernel/psci.c > +++ b/arch/arm/kernel/psci.c > @@ -17,6 +17,7 @@ > > #include <linux/init.h> > #include <linux/of.h> > +#include <uapi/linux/psci.h> > > #include <asm/compiler.h> > #include <asm/errno.h> > @@ -27,22 +28,20 @@ > struct psci_operations psci_ops; > > 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 > - > static int psci_to_linux_errno(int errno) > { > switch (errno) { > @@ -59,13 +58,6 @@ static int psci_to_linux_errno(int errno) > 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_POWER_STATE_ID_MASK) > @@ -110,6 +102,14 @@ 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_ID_VERSION, 0, 0, 0); > + return err; > +} > + > static int psci_cpu_suspend(struct psci_power_state state, > unsigned long entry_point) > { > @@ -153,26 +153,36 @@ static int psci_migrate(unsigned long cpuid) > return psci_to_linux_errno(err); > } > > -static const struct of_device_id psci_of_match[] __initconst = { > - { .compatible = "arm,psci", }, > - {}, > -}; > +static int psci_affinity_info(unsigned long target_affinity, > + unsigned long lowest_affinity_level) > +{ > + int err; > + u32 fn; > > -void __init psci_init(void) > + fn = psci_function_id[PSCI_FN_AFFINITY_INFO]; > + err = invoke_psci_fn(fn, target_affinity, lowest_affinity_level, 0); > + return err; > +} > + > +static int psci_migrate_info_type(void) > { > - struct device_node *np; > - const char *method; > - u32 id; > + int err; > + u32 fn; > > - np = of_find_matching_node(NULL, psci_of_match); > - if (!np) > - return; > + fn = psci_function_id[PSCI_FN_MIGRATE_INFO_TYPE]; > + err = invoke_psci_fn(fn, 0, 0, 0); > + return err; > +} > > - pr_info("probing function IDs from device-tree\n"); > +static int get_set_conduit_method(struct device_node *np) > +{ > + const char *method; > + > + pr_info("probing for conduit method from DT.\n"); > > if (of_property_read_string(np, "method", &method)) { > - pr_warning("missing \"method\" property\n"); > - goto out_put_node; > + pr_warn("missing \"method\" property\n"); > + return -ENXIO; > } > > if (!strcmp("hvc", method)) { > @@ -180,10 +190,79 @@ void __init psci_init(void) > } else if (!strcmp("smc", method)) { > invoke_psci_fn = __invoke_psci_fn_smc; > } else { > - pr_warning("invalid \"method\" property: %s\n", method); > + pr_warn("invalid \"method\" property: %s\n", method); > + return -EINVAL; > + } > + return 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) > goto out_put_node; > + > + ver = psci_get_version(); > + > + if (ver == PSCI_RET_EOPNOTSUPP) { > + pr_info("PSCI_ID_VERSION Function not supported in firmware.\n"); IMO you should stop here as the implementation conforming to the specification must return a minor version number of 2 and major version number of 0. You can't proceed, assume ids and use them. Regards, Sudeep ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Linaro-acpi] [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions 2014-03-31 16:52 ` [Linaro-acpi] " Sudeep Holla @ 2014-03-31 17:09 ` Ashwin Chaugule 2014-03-31 17:25 ` Ashwin Chaugule 0 siblings, 1 reply; 8+ messages in thread From: Ashwin Chaugule @ 2014-03-31 17:09 UTC (permalink / raw) To: linux-arm-kernel Hi Sudeep, On 31 March 2014 12:52, Sudeep Holla <sudeep.holla@arm.com> wrote: >> + if (ver == PSCI_RET_EOPNOTSUPP) { >> + pr_info("PSCI_ID_VERSION Function not supported in firmware.\n"); > > IMO you should stop here as the implementation conforming to the specification > must return a minor version number of 2 and major version number of 0. You > can't proceed, assume ids and use them. > hm, you're right, I missed that. Cheers, Ashwin ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Linaro-acpi] [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions 2014-03-31 17:09 ` Ashwin Chaugule @ 2014-03-31 17:25 ` Ashwin Chaugule 2014-03-31 18:25 ` Sudeep Holla 0 siblings, 1 reply; 8+ messages in thread From: Ashwin Chaugule @ 2014-03-31 17:25 UTC (permalink / raw) To: linux-arm-kernel On 31 March 2014 13:09, Ashwin Chaugule <ashwin.chaugule@linaro.org> wrote: > Hi Sudeep, > > On 31 March 2014 12:52, Sudeep Holla <sudeep.holla@arm.com> wrote: > >>> + if (ver == PSCI_RET_EOPNOTSUPP) { >>> + pr_info("PSCI_ID_VERSION Function not supported in firmware.\n"); >> >> IMO you should stop here as the implementation conforming to the specification >> must return a minor version number of 2 and major version number of 0. You >> can't proceed, assume ids and use them. >> > > hm, you're right, I missed that. Something like this? if (ver == PSCI_RET_EOPNOTSUPP) { /* 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; > > Cheers, > Ashwin ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Linaro-acpi] [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions 2014-03-31 17:25 ` Ashwin Chaugule @ 2014-03-31 18:25 ` Sudeep Holla 0 siblings, 0 replies; 8+ messages in thread From: Sudeep Holla @ 2014-03-31 18:25 UTC (permalink / raw) To: linux-arm-kernel Hi Ashwin, On 31/03/14 18:25, Ashwin Chaugule wrote: > On 31 March 2014 13:09, Ashwin Chaugule <ashwin.chaugule@linaro.org> wrote: >> Hi Sudeep, >> >> On 31 March 2014 12:52, Sudeep Holla <sudeep.holla@arm.com> wrote: >> >>>> + if (ver == PSCI_RET_EOPNOTSUPP) { >>>> + pr_info("PSCI_ID_VERSION Function not supported in firmware.\n"); >>> >>> IMO you should stop here as the implementation conforming to the specification >>> must return a minor version number of 2 and major version number of 0. You >>> can't proceed, assume ids and use them. >>> >> >> hm, you're right, I missed that. > > Something like this? > > if (ver == PSCI_RET_EOPNOTSUPP) { > /* 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; > Yes that looks fine to me. Regards, Sudeep ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4 2/3] Documentation: devicetree: Add new binding for PSCIv0.2 2014-03-31 15:02 [PATCH v4 0/3] PSCI v0.2 support and DT bindings Ashwin Chaugule 2014-03-31 15:02 ` [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions Ashwin Chaugule @ 2014-03-31 15:02 ` Ashwin Chaugule 2014-03-31 15:02 ` [PATCH v4 3/3] ARM: Check if a CPU has gone offline Ashwin Chaugule 2 siblings, 0 replies; 8+ messages in thread From: Ashwin Chaugule @ 2014-03-31 15:02 UTC (permalink / raw) To: linux-arm-kernel The PSCI v0.2+ spec defines standard values for PSCI function IDs. Add a new binding entry so that pre v0.2 implementations can use DT entries for function IDs and v0.2+ implementations use standard entries as defined by the PSCIv0.2 specification. Signed-off-by: Ashwin Chaugule <ashwin.chaugule@linaro.org> Acked-by: Rob Herring <robh@kernel.org> --- Documentation/devicetree/bindings/arm/psci.txt | 35 +++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/psci.txt b/Documentation/devicetree/bindings/arm/psci.txt index 433afe9..d01a90b 100644 --- a/Documentation/devicetree/bindings/arm/psci.txt +++ b/Documentation/devicetree/bindings/arm/psci.txt @@ -21,7 +21,15 @@ to #0. Main node required properties: - - compatible : Must be "arm,psci" + - compatible : should contain at least one of: + + * "arm,psci" : for implementations complying to PSCI versions prior to + 0.2. For these cases function IDs must be provided. + + * "arm,psci-0.2" : for implementations complying to PSCI 0.2. Function + IDs are not required and should be ignored by an OS with PSCI 0.2 + support, but are permitted to be present for compatibility with + existing software when "arm,psci" is later in the compatible list. - method : The method of calling the PSCI firmware. Permitted values are: @@ -45,6 +53,8 @@ Main node optional properties: Example: +Case 1: PSCI v0.1 only. + psci { compatible = "arm,psci"; method = "smc"; @@ -53,3 +63,26 @@ Example: cpu_on = <0x95c10002>; migrate = <0x95c10003>; }; + + +Case 2: PSCI v0.2 only + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + +Case 3: PSCI v0.2 and PSCI v0.1. + + As described above, for compatibility with existing kernels, the + hypervisor will likely want to provide IDs, e.g. + + psci { + compatible = "arm,psci-0.2", "arm,psci"; + method = "hvc"; + + cpu_on = < arbitrary value >; + cpu_off = < arbitrary value >; + + ... + }; -- 1.8.3.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 3/3] ARM: Check if a CPU has gone offline 2014-03-31 15:02 [PATCH v4 0/3] PSCI v0.2 support and DT bindings Ashwin Chaugule 2014-03-31 15:02 ` [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions Ashwin Chaugule 2014-03-31 15:02 ` [PATCH v4 2/3] Documentation: devicetree: Add new binding for PSCIv0.2 Ashwin Chaugule @ 2014-03-31 15:02 ` Ashwin Chaugule 2 siblings, 0 replies; 8+ messages in thread From: Ashwin Chaugule @ 2014-03-31 15:02 UTC (permalink / raw) To: linux-arm-kernel PSCIv0.2 adds a new function called AFFINITY_INFO, which can be used to query if a specified CPU has actually gone offline. Calling this function via cpu_kill ensures that a CPU has quiesced after a call to cpu_die. Signed-off-by: Ashwin Chaugule <ashwin.chaugule@linaro.org> Reviewed-by: Rob Herring <robh@kernel.org> --- arch/arm/kernel/psci_smp.c | 21 +++++++++++++++++++++ include/uapi/linux/psci.h | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c index 570a48c..c6f1420 100644 --- a/arch/arm/kernel/psci_smp.c +++ b/arch/arm/kernel/psci_smp.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/smp.h> #include <linux/of.h> +#include <uapi/linux/psci.h> #include <asm/psci.h> #include <asm/smp_plat.h> @@ -66,6 +67,25 @@ 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; + + if (!psci_ops.affinity_info) + return 1; + + err = psci_ops.affinity_info(cpu_logical_map(cpu), 0); + + if (err != PSCI_AFFINITY_INFO_RET_OFF) { + pr_err("psci: Cannot kill CPU:%d, psci ret val: %d\n", + cpu, err); + /* Make platform_cpu_kill() fail. */ + return 0; + } + return 1; +} + #endif bool __init psci_smp_available(void) @@ -78,5 +98,6 @@ 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/include/uapi/linux/psci.h b/include/uapi/linux/psci.h index 0354bb1..65b4878 100644 --- a/include/uapi/linux/psci.h +++ b/include/uapi/linux/psci.h @@ -58,4 +58,9 @@ ((ver & PSCI_VER_MAJOR_MASK) >> PSCI_VER_MAJOR_SHIFT) #define PSCI_VER_MINOR(ver) (ver & PSCI_VER_MINOR_MASK) +/* Return values from the PSCI_ID_AFFINITY_INFO Function. */ +#define PSCI_AFFINITY_INFO_RET_ON 0 +#define PSCI_AFFINITY_INFO_RET_OFF 1 +#define PSCI_AFFINITY_INFO_RET_ON_PENDING 2 + #endif /* _UAPI_LINUX_PSCI_H */ -- 1.8.3.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-03-31 18:25 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-03-31 15:02 [PATCH v4 0/3] PSCI v0.2 support and DT bindings Ashwin Chaugule 2014-03-31 15:02 ` [PATCH v4 1/3] PSCI: Add initial support for PSCIv0.2 functions Ashwin Chaugule 2014-03-31 16:52 ` [Linaro-acpi] " Sudeep Holla 2014-03-31 17:09 ` Ashwin Chaugule 2014-03-31 17:25 ` Ashwin Chaugule 2014-03-31 18:25 ` Sudeep Holla 2014-03-31 15:02 ` [PATCH v4 2/3] Documentation: devicetree: Add new binding for PSCIv0.2 Ashwin Chaugule 2014-03-31 15:02 ` [PATCH v4 3/3] ARM: Check if a CPU has gone offline Ashwin Chaugule
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).