linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mario Limonciello <mario.limonciello@amd.com>
To: Sven van Ashbrook <svenva@chromium.org>,
	Rafael J Wysocki <rafael@kernel.org>, <linux-pm@vger.kernel.org>,
	<platform-driver-x86@vger.kernel.org>,
	Pavel Machek <pavel@ucw.cz>, Len Brown <len.brown@intel.com>,
	John Stultz <jstultz@google.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Stephen Boyd <sboyd@kernel.org>
Cc: Rajneesh Bhardwaj <irenic.rajneesh@gmail.com>,
	S-k Shyam-sundar <Shyam-sundar.S-k@amd.com>,
	<rrangel@chromium.org>, Rajat Jain <rajatja@google.com>,
	David E Box <david.e.box@intel.com>,
	Hans de Goede <hdegoede@redhat.com>,
	<linux-kernel@vger.kernel.org>,
	Mario Limonciello <mario.limonciello@amd.com>
Subject: [RFC v2 1/3] PM: Add a sysfs files to represent sleep duration
Date: Thu, 10 Nov 2022 00:47:21 -0600	[thread overview]
Message-ID: <20221110064723.8882-2-mario.limonciello@amd.com> (raw)
In-Reply-To: <20221110064723.8882-1-mario.limonciello@amd.com>

Both AMD and Intel SoCs have a concept of reporting whether the hardware
reached a hardware sleep state over s2idle as well as how much
time was spent in such a state.

This information is valuable to both chip designers and system designers
as it helps to identify when there are problems with power consumption
over an s2idle cycle.

To make the information discoverable, create a new sysfs file and a symbol
that drivers from supported manufacturers can use to advertise this
information. This file will only be exported when the system supports low
power idle in the ACPI table.

In order to effectively use this information you will ideally want to
compare against the total duration of sleep, so export a second sysfs file
that will show total time. This file will be exported on all systems and
used both for s2idle and s3.

Suggested-by: David E Box <david.e.box@intel.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
 Documentation/ABI/testing/sysfs-power | 17 +++++++++++
 include/linux/suspend.h               |  4 +++
 kernel/power/main.c                   | 42 +++++++++++++++++++++++++++
 kernel/power/suspend.c                |  2 ++
 kernel/time/timekeeping.c             |  2 ++
 5 files changed, 67 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index f99d433ff311..5b47cbb4dc9e 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -413,6 +413,23 @@ Description:
 		The /sys/power/suspend_stats/last_failed_step file contains
 		the last failed step in the suspend/resume path.
 
+What:		/sys/power/suspend_stats/last_hw_state_residency
+Date:		December 2022
+Contact:	Mario Limonciello <mario.limonciello@amd.com>
+Description:
+		The /sys/power/suspend_stats/last_hw_state_residency file contains
+		the amount of time spent in a hardware sleep state.
+		This attribute is only available if the system supports
+		low power idle.  This is measured in microseconds.
+
+What:		/sys/power/suspend_stats/last_suspend_total
+Date:		December 2022
+Contact:	Mario Limonciello <mario.limonciello@amd.com>
+Description:
+		The /sys/power/suspend_stats/last_suspend_total file contains
+		the total duration of the sleep cycle.
+		This is measured in microseconds.
+
 What:		/sys/power/sync_on_suspend
 Date:		October 2019
 Contact:	Jonas Meurer <jonas@freesources.org>
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index cfe19a028918..af343c3f8198 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -68,6 +68,8 @@ struct suspend_stats {
 	int	last_failed_errno;
 	int	errno[REC_FAILED_NUM];
 	int	last_failed_step;
+	u64	last_hw_state_residency;
+	u64	last_suspend_total;
 	enum suspend_stat_step	failed_steps[REC_FAILED_NUM];
 };
 
@@ -489,6 +491,8 @@ void restore_processor_state(void);
 extern int register_pm_notifier(struct notifier_block *nb);
 extern int unregister_pm_notifier(struct notifier_block *nb);
 extern void ksys_sync_helper(void);
+extern void pm_set_hw_state_residency(u64 duration);
+extern void pm_account_suspend_type(const struct timespec64 *t);
 
 #define pm_notifier(fn, pri) {				\
 	static struct notifier_block fn##_nb =			\
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 31ec4a9b9d70..11bd658583b0 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -6,6 +6,7 @@
  * Copyright (c) 2003 Open Source Development Lab
  */
 
+#include <linux/acpi.h>
 #include <linux/export.h>
 #include <linux/kobject.h>
 #include <linux/string.h>
@@ -54,6 +55,19 @@ void unlock_system_sleep(unsigned int flags)
 }
 EXPORT_SYMBOL_GPL(unlock_system_sleep);
 
+void pm_set_hw_state_residency(u64 duration)
+{
+	suspend_stats.last_hw_state_residency = duration;
+}
+EXPORT_SYMBOL_GPL(pm_set_hw_state_residency);
+
+void pm_account_suspend_type(const struct timespec64 *t)
+{
+	suspend_stats.last_suspend_total += (s64)t->tv_sec * USEC_PER_SEC +
+						 t->tv_nsec / NSEC_PER_USEC;
+}
+EXPORT_SYMBOL_GPL(pm_account_suspend_type);
+
 void ksys_sync_helper(void)
 {
 	ktime_t start;
@@ -377,6 +391,20 @@ static ssize_t last_failed_step_show(struct kobject *kobj,
 }
 static struct kobj_attribute last_failed_step = __ATTR_RO(last_failed_step);
 
+static ssize_t last_hw_state_residency_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%llu\n", suspend_stats.last_hw_state_residency);
+}
+static struct kobj_attribute last_hw_state_residency = __ATTR_RO(last_hw_state_residency);
+
+static ssize_t last_suspend_total_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%llu\n", suspend_stats.last_suspend_total);
+}
+static struct kobj_attribute last_suspend_total = __ATTR_RO(last_suspend_total);
+
 static struct attribute *suspend_attrs[] = {
 	&success.attr,
 	&fail.attr,
@@ -391,12 +419,26 @@ static struct attribute *suspend_attrs[] = {
 	&last_failed_dev.attr,
 	&last_failed_errno.attr,
 	&last_failed_step.attr,
+	&last_hw_state_residency.attr,
+	&last_suspend_total.attr,
 	NULL,
 };
 
+static umode_t suspend_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
+{
+	if (attr != &last_hw_state_residency.attr)
+		return 0444;
+#ifdef CONFIG_ACPI
+	if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)
+		return 0444;
+#endif
+	return 0;
+}
+
 static const struct attribute_group suspend_attr_group = {
 	.name = "suspend_stats",
 	.attrs = suspend_attrs,
+	.is_visible = suspend_attr_is_visible,
 };
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index fa3bf161d13f..b6c4a3733212 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -423,6 +423,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 	if (suspend_test(TEST_PLATFORM))
 		goto Platform_wake;
 
+	suspend_stats.last_suspend_total = 0;
+
 	if (state == PM_SUSPEND_TO_IDLE) {
 		s2idle_loop();
 		goto Platform_wake;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index f72b9f1de178..e1b356787e53 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 #include <linux/audit.h>
 #include <linux/random.h>
+#include <linux/suspend.h>
 
 #include "tick-internal.h"
 #include "ntp_internal.h"
@@ -1698,6 +1699,7 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
 	tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, *delta));
 	tk_update_sleep_time(tk, timespec64_to_ktime(*delta));
 	tk_debug_account_sleep_time(delta);
+	pm_account_suspend_type(delta);
 }
 
 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_RTC_HCTOSYS_DEVICE)
-- 
2.34.1


  reply	other threads:[~2022-11-10  6:49 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-10  6:47 [RFC v2 0/3] Introduce infrastructure to report time in hardware sleep state Mario Limonciello
2022-11-10  6:47 ` Mario Limonciello [this message]
2022-11-13 23:53   ` [RFC v2 1/3] PM: Add a sysfs files to represent sleep duration Thomas Gleixner
2022-11-14 19:12     ` Limonciello, Mario
2022-11-15 10:32       ` Hans de Goede
2022-11-15 14:13         ` Limonciello, Mario
2022-11-17  2:40           ` Box, David E
2022-11-14  7:12   ` Greg KH
2022-11-15 14:45   ` Rafael J. Wysocki
2022-11-15 15:17     ` Limonciello, Mario
2022-11-15 16:35       ` Rafael J. Wysocki
     [not found]         ` <CAHQZ30BCXtyJ9qqHHX5eztXbgA_A8yH48+AQVMCB64CXjqE+hQ@mail.gmail.com>
2022-11-15 17:26           ` Limonciello, Mario
2022-11-15 17:52             ` Rafael J. Wysocki
2022-11-15 17:58               ` Limonciello, Mario
2022-11-15 19:08                 ` Rafael J. Wysocki
2022-11-10  6:47 ` [RFC v2 2/3] platform/x86/amd: pmc: Report duration of time in deepest hw state Mario Limonciello
2022-11-10  6:47 ` [RFC v2 3/3] platform/x86/intel/pmc: core: Report duration of time in HW sleep state Mario Limonciello
2022-11-13 23:57   ` Thomas Gleixner
2022-11-14 19:06     ` Limonciello, Mario

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221110064723.8882-2-mario.limonciello@amd.com \
    --to=mario.limonciello@amd.com \
    --cc=Shyam-sundar.S-k@amd.com \
    --cc=david.e.box@intel.com \
    --cc=hdegoede@redhat.com \
    --cc=irenic.rajneesh@gmail.com \
    --cc=jstultz@google.com \
    --cc=len.brown@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=pavel@ucw.cz \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=rafael@kernel.org \
    --cc=rajatja@google.com \
    --cc=rrangel@chromium.org \
    --cc=sboyd@kernel.org \
    --cc=svenva@chromium.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).