Skip to content

Commit

Permalink
arm64: psci: support unsigned return values
Browse files Browse the repository at this point in the history
PSCI_VERSION and MIGRATE_INFO_TYPE_UP_CPU return unsigned values, with
the latter returning a 64-bit value. However, the PSCI invocation
functions have prototypes returning int.

This patch upgrades the invocation functions to return unsigned long,
with a new typedef to keep things legible. As PSCI_VERSION cannot return
a negative value, the erroneous check against PSCI_RET_NOT_SUPPORTED is
also removed. The unrelated psci_initcall_t typedef is moved closer to
its first user, to avoid confusion with the invocation functions.

In preparation for sharing the code with ARM, unsigned long is used in
preference of u64. In the SMC32 calling convention, the relevant fields
will be 32 bits wide.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
  • Loading branch information
Mark Rutland committed May 27, 2015
1 parent 2a7cd0e commit a06eed3
Showing 1 changed file with 18 additions and 29 deletions.
47 changes: 18 additions & 29 deletions arch/arm64/kernel/psci.c
Original file line number Diff line number Diff line change
@@ -56,11 +56,11 @@ struct psci_operations {

static struct psci_operations psci_ops;

static int (*invoke_psci_fn)(u64, u64, u64, u64);
typedef int (*psci_initcall_t)(const struct device_node *);

asmlinkage int __invoke_psci_fn_hvc(u64, u64, u64, u64);
asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64);
typedef unsigned long (psci_fn)(unsigned long, unsigned long,
unsigned long, unsigned long);
asmlinkage psci_fn __invoke_psci_fn_hvc;
asmlinkage psci_fn __invoke_psci_fn_smc;
static psci_fn *invoke_psci_fn;

enum psci_function {
PSCI_FN_CPU_SUSPEND,
@@ -112,12 +112,9 @@ static void psci_power_state_unpack(u32 power_state,
PSCI_0_2_POWER_STATE_AFFL_SHIFT;
}

static int psci_get_version(void)
static u32 psci_get_version(void)
{
int err;

err = invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
return err;
return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
}

static int psci_cpu_suspend(struct psci_power_state state,
@@ -296,32 +293,24 @@ static void __init psci_0_2_set_functions(void)
*/
static int __init psci_probe(void)
{
int ver = psci_get_version();

if (ver == PSCI_RET_NOT_SUPPORTED) {
/*
* PSCI versions >=0.2 mandates implementation of
* PSCI_VERSION.
*/
pr_err("PSCI firmware does not comply with the v0.2 spec.\n");
return -EOPNOTSUPP;
} 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) {
pr_err("Conflicting PSCI version detected.\n");
return -EINVAL;
}
u32 ver = psci_get_version();

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) {
pr_err("Conflicting PSCI version detected.\n");
return -EINVAL;
}

psci_0_2_set_functions();

return 0;
}

typedef int (*psci_initcall_t)(const struct device_node *);

/*
* PSCI init function for PSCI versions >=0.2
*

0 comments on commit a06eed3

Please sign in to comment.