diff mbox series

[2/3] s3: Add support for checking last sleep cycle residency

Message ID 20231207101927.9378-3-mario.limonciello@amd.com
State Accepted
Headers show
Series [1/3] s3: Add support for reading total s2idle residency from generic API | expand

Commit Message

Mario Limonciello Dec. 7, 2023, 10:19 a.m. UTC
A good system will spend at least 70% of an s2idle sleep cycle in
a hardware sleep state.  Check for this.

Link: https://bugs.launchpad.net/fwts/+bug/2019728
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
 src/acpi/s3/s3.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Comments

ivanhu Dec. 14, 2023, 8:29 a.m. UTC | #1
Thanks!

Let's see the feedback for the empirical measurements 70%.

Acked-by: Ivan Hu <ivan.hu@canonical.com>

On 2023/12/7 18:19, Mario Limonciello wrote:
> A good system will spend at least 70% of an s2idle sleep cycle in
> a hardware sleep state.  Check for this.
> 
> Link: https://bugs.launchpad.net/fwts/+bug/2019728
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
>   src/acpi/s3/s3.c | 29 +++++++++++++++++++++++++++++
>   1 file changed, 29 insertions(+)
> 
> diff --git a/src/acpi/s3/s3.c b/src/acpi/s3/s3.c
> index ba705441..222d9f57 100644
> --- a/src/acpi/s3/s3.c
> +++ b/src/acpi/s3/s3.c
> @@ -33,6 +33,7 @@
>   #define PM_SUSPEND_PMUTILS		"pm-suspend"
>   #define PM_SUSPEND_HYBRID_PMUTILS	"pm-suspend-hybrid"
>   #define PM_SUSPEND_PATH			"/sys/power/mem_sleep"
> +#define PM_SUSPEND_LAST_HW_SLEEP	"/sys/power/suspend_stats/last_hw_sleep"
>   #define PM_SUSPEND_TOTAL_HW_SLEEP	"/sys/power/suspend_stats/total_hw_sleep"
>   #define WAKEUP_SOURCE_PATH		"/sys/kernel/debug/wakeup_sources"
>   #define INTEL_PM_S2IDLE_SLP_S0		"/sys/kernel/debug/pmc_core/slp_s0_residency_usec"
> @@ -377,6 +378,22 @@ static uint64_t get_uint64_sysfs(const char *path)
>   	return val;
>   }
>   
> +/*
> + *  get_last_s2idle_residency()
> + *
> + *  Returns:
> + *  - Hardware sleep residency from the last sleep cycle
> + *  - 0 if it is not available
> + *
> + */
> +static uint64_t get_last_s2idle_residency(void)
> +{
> +	if (access(PM_SUSPEND_LAST_HW_SLEEP, F_OK) != 0)
> +		return 0;
> +
> +	return get_uint64_sysfs(PM_SUSPEND_LAST_HW_SLEEP);
> +}
> +
>   /*
>    *  get_total_s2idle_residency()
>    *  @fname: Optional parameter to set the filename used to check residency
> @@ -562,6 +579,18 @@ static int s3_do_suspend_resume(fwts_framework *fw,
>   				    fname, *total_s2idle_residency, residency);
>   		}
>   		*total_s2idle_residency = residency;
> +
> +		residency = get_last_s2idle_residency();
> +		if (duration > 10 && residency) {
> +			float pct = (float)residency / ((float)duration * 1000000) * 100.0;
> +			if (pct < 70) {
> +				(*s2idle_errors)++;
> +				fwts_failed(fw, LOG_LEVEL_HIGH, "S2idleNotDeepest",
> +					    "Expected %s to be at least 70%% of the last sleep cycle, got %.2f%%.",
> +					    PM_SUSPEND_LAST_HW_SLEEP, pct);
> +				} else
> +					fwts_log_info(fw, "Spent %.2f%% of %ds in hardware sleep state", pct, duration);
> +		}
>   	}
>   
>   	if (duration < delay) {
diff mbox series

Patch

diff --git a/src/acpi/s3/s3.c b/src/acpi/s3/s3.c
index ba705441..222d9f57 100644
--- a/src/acpi/s3/s3.c
+++ b/src/acpi/s3/s3.c
@@ -33,6 +33,7 @@ 
 #define PM_SUSPEND_PMUTILS		"pm-suspend"
 #define PM_SUSPEND_HYBRID_PMUTILS	"pm-suspend-hybrid"
 #define PM_SUSPEND_PATH			"/sys/power/mem_sleep"
+#define PM_SUSPEND_LAST_HW_SLEEP	"/sys/power/suspend_stats/last_hw_sleep"
 #define PM_SUSPEND_TOTAL_HW_SLEEP	"/sys/power/suspend_stats/total_hw_sleep"
 #define WAKEUP_SOURCE_PATH		"/sys/kernel/debug/wakeup_sources"
 #define INTEL_PM_S2IDLE_SLP_S0		"/sys/kernel/debug/pmc_core/slp_s0_residency_usec"
@@ -377,6 +378,22 @@  static uint64_t get_uint64_sysfs(const char *path)
 	return val;
 }
 
+/*
+ *  get_last_s2idle_residency()
+ *
+ *  Returns:
+ *  - Hardware sleep residency from the last sleep cycle
+ *  - 0 if it is not available
+ *
+ */
+static uint64_t get_last_s2idle_residency(void)
+{
+	if (access(PM_SUSPEND_LAST_HW_SLEEP, F_OK) != 0)
+		return 0;
+
+	return get_uint64_sysfs(PM_SUSPEND_LAST_HW_SLEEP);
+}
+
 /*
  *  get_total_s2idle_residency()
  *  @fname: Optional parameter to set the filename used to check residency
@@ -562,6 +579,18 @@  static int s3_do_suspend_resume(fwts_framework *fw,
 				    fname, *total_s2idle_residency, residency);
 		}
 		*total_s2idle_residency = residency;
+
+		residency = get_last_s2idle_residency();
+		if (duration > 10 && residency) {
+			float pct = (float)residency / ((float)duration * 1000000) * 100.0;
+			if (pct < 70) {
+				(*s2idle_errors)++;
+				fwts_failed(fw, LOG_LEVEL_HIGH, "S2idleNotDeepest",
+					    "Expected %s to be at least 70%% of the last sleep cycle, got %.2f%%.",
+					    PM_SUSPEND_LAST_HW_SLEEP, pct);
+				} else
+					fwts_log_info(fw, "Spent %.2f%% of %ds in hardware sleep state", pct, duration);
+		}
 	}
 
 	if (duration < delay) {