Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion drivers/firmware/psci/psci.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
#include <asm/system_misc.h>
#include <asm/smp_plat.h>
#include <asm/suspend.h>

#ifdef CONFIG_ARCH_PHYTIUM
#include <asm/phytium_cputype.h>
#endif
/*
* While a 64-bit OS can make calls with SMC32 calling conventions, for some
* calls it is necessary to use SMC64 to pass or return 64-bit values.
Expand Down Expand Up @@ -495,6 +497,31 @@ int psci_cpu_suspend_enter(u32 state)
}
#endif

#ifdef CONFIG_ARCH_PHYTIUM
static int phytium_psci_system_suspend(unsigned long state)
{
phys_addr_t pa_cpu_resume = __pa_symbol(cpu_resume);

if (state == PM_SUSPEND_STANDBY)
return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Suspend failures report wrong errno

When PSCI SYSTEM_SUSPEND returns an error for standby or memory suspend, phytium_psci_system_suspend returns the raw firmware status through cpu_suspend() to the PM core instead of translating it with psci_to_linux_errno(); for example, PSCI_RET_DENIED reaches callers as -3 (-ESRCH) rather than -EPERM, so they see the wrong suspend failure reason.

Translate each invoke_psci_fn() result with psci_to_linux_errno() before returning it.

Also at drivers/firmware/psci/psci.c:507-510.

Prompt for AI agents
In `drivers/firmware/psci/psci.c` at line 506:

**Suspend failures report wrong errno**

When PSCI SYSTEM_SUSPEND returns an error for standby or memory suspend, `phytium_psci_system_suspend` returns the raw firmware status through `cpu_suspend()` to the PM core instead of translating it with `psci_to_linux_errno()`; for example, `PSCI_RET_DENIED` reaches callers as `-3` (`-ESRCH`) rather than `-EPERM`, so they see the wrong suspend failure reason.

Translate each `invoke_psci_fn()` result with `psci_to_linux_errno()` before returning it.

Also at `drivers/firmware/psci/psci.c:507-510`.

pa_cpu_resume, 0x544600c2, 0);
else
return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
pa_cpu_resume, 0, 0);
}

static int phytium_psci_system_suspend_enter(suspend_state_t state)
{
return cpu_suspend(state, phytium_psci_system_suspend);
}


static const struct platform_suspend_ops phytium_psci_suspend_ops = {
.valid = phytium_suspend_valid_mem,
.enter = phytium_psci_system_suspend_enter,
};
#endif

static int psci_system_suspend(unsigned long unused)
{
int err;
Expand Down Expand Up @@ -535,7 +562,16 @@ static void __init psci_init_system_suspend(void)
ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));

if (ret != PSCI_RET_NOT_SUPPORTED)
{
#ifdef CONFIG_ARCH_PHYTIUM
if (is_pd2408())
suspend_set_ops(&phytium_psci_suspend_ops);
else
suspend_set_ops(&psci_suspend_ops);
#else
suspend_set_ops(&psci_suspend_ops);
#endif
}
}

static void __init psci_init_cpu_suspend(void)
Expand Down
3 changes: 3 additions & 0 deletions include/linux/suspend.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ extern suspend_state_t mem_sleep_default;
*/
extern void suspend_set_ops(const struct platform_suspend_ops *ops);
extern int suspend_valid_only_mem(suspend_state_t state);
#ifdef CONFIG_ARCH_PHYTIUM
extern int phytium_suspend_valid_mem(suspend_state_t state);
#endif

extern unsigned int pm_suspend_global_flags;

Expand Down
16 changes: 16 additions & 0 deletions kernel/power/suspend.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,22 @@ int suspend_valid_only_mem(suspend_state_t state)
}
EXPORT_SYMBOL_GPL(suspend_valid_only_mem);

#ifdef CONFIG_ARCH_PHYTIUM
int phytium_suspend_valid_mem(suspend_state_t state)
{
switch (state) {
case PM_SUSPEND_MEM:
return state == PM_SUSPEND_MEM;
case PM_SUSPEND_STANDBY:
return state == PM_SUSPEND_STANDBY;
default:
pr_err("no valid state support\n");
return 0;
}
}
EXPORT_SYMBOL_GPL(phytium_suspend_valid_mem);
#endif

static bool sleep_state_supported(suspend_state_t state)
{
return state == PM_SUSPEND_TO_IDLE ||
Expand Down
Loading