Re: [PATCH 2/2] LoongArch: Fix ACPI standard register based S3 support

From: Huacai Chen
Date: Thu Jun 13 2024 - 22:11:50 EST


Hi, Jiaxun,

On Fri, Jun 14, 2024 at 12:41 AM Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx> wrote:
>
> Most LoongArch 64 machines are using custom "SADR" ACPI extension
> to perform ACPI S3 sleep. However the standard ACPI way to perform
> sleep is to write a value to ACPI PM1/SLEEP_CTL register, and this
> is never supported properly in kernel.
Maybe our hardware is insane so we need "SADR", if so, this patch may
break real hardware. What's your opinion, Jianmin?

Huacai

>
> Fix standard S3 sleep by providing a fallback DoSuspend function
> which calls ACPI's acpi_enter_sleep_state routine when SADR is
> not provided by the firmware.
>
> Also fix suspend assembly code so that ra is set properly before
> go into sleep routine. (Previously linked address of jirl was set
> to a0, some firmware do require return address in a0 but it's
> already set with la.pcrel before).
>
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Jiaxun Yang <jiaxun.yang@xxxxxxxxxxx>
> ---
> arch/loongarch/power/platform.c | 24 ++++++++++++++++++------
> arch/loongarch/power/suspend_asm.S | 2 +-
> 2 files changed, 19 insertions(+), 7 deletions(-)
>
> diff --git a/arch/loongarch/power/platform.c b/arch/loongarch/power/platform.c
> index 3ea8e07aa225..2aea41f8e3ff 100644
> --- a/arch/loongarch/power/platform.c
> +++ b/arch/loongarch/power/platform.c
> @@ -34,22 +34,34 @@ void enable_pci_wakeup(void)
> acpi_write_bit_register(ACPI_BITREG_PCIEXP_WAKE_DISABLE, 0);
> }
>
> +static void acpi_suspend_register_fallback(void)
> +{
> + acpi_enter_sleep_state(ACPI_STATE_S3);
> +}
> +
> static int __init loongson3_acpi_suspend_init(void)
> {
> #ifdef CONFIG_ACPI
> acpi_status status;
> uint64_t suspend_addr = 0;
>
> - if (acpi_disabled || acpi_gbl_reduced_hardware)
> + if (acpi_disabled)
> return 0;
>
> - acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
> + if (!acpi_sleep_state_supported(ACPI_STATE_S3))
> + return 0;
> +
> + if (!acpi_gbl_reduced_hardware)
> + acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
> +
> status = acpi_evaluate_integer(NULL, "\\SADR", NULL, &suspend_addr);
> - if (ACPI_FAILURE(status) || !suspend_addr) {
> - pr_err("ACPI S3 is not support!\n");
> - return -1;
> + if (!ACPI_FAILURE(status) && suspend_addr) {
> + loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr));
> + return 0;
> }
> - loongson_sysconf.suspend_addr = (u64)phys_to_virt(PHYSADDR(suspend_addr));
> +
> + pr_info("ACPI S3 supported with hw register fallback\n");
> + loongson_sysconf.suspend_addr = (u64)acpi_suspend_register_fallback;
> #endif
> return 0;
> }
> diff --git a/arch/loongarch/power/suspend_asm.S b/arch/loongarch/power/suspend_asm.S
> index 6fdd74eb219b..fe08dbb73c87 100644
> --- a/arch/loongarch/power/suspend_asm.S
> +++ b/arch/loongarch/power/suspend_asm.S
> @@ -66,7 +66,7 @@ SYM_FUNC_START(loongarch_suspend_enter)
> la.pcrel a0, loongarch_wakeup_start
> la.pcrel t0, loongarch_suspend_addr
> ld.d t0, t0, 0
> - jirl a0, t0, 0 /* Call BIOS's STR sleep routine */
> + jirl ra, t0, 0 /* Call BIOS's STR sleep routine */
>
> /*
> * This is where we return upon wakeup.
>
> --
> 2.43.0
>
>