In modern Chromebooks, the embedded controller has a mechanism where
it will watch a hardware-controlled line that toggles in suspend, and
wake the system up if an expected sleep transition didn't occur. This
can be very useful for detecting power management issues where the
system appears to suspend, but doesn't actually reach its lowest
expected power states.
Sometimes it's useful in debug and test scenarios to be able to control
the duration of that timeout, or even disable the EC timeout mechanism
altogether. Add a debugfs control to set the timeout to values other
than the EC-defined default, for more convenient debug and
development iteration.
Signed-off-by: Evan Green <[email protected]>
---
Documentation/ABI/testing/debugfs-cros-ec | 22 +++++++++++++++++++++
drivers/platform/chrome/cros_ec.c | 3 ++-
drivers/platform/chrome/cros_ec_debugfs.c | 3 +++
include/linux/platform_data/cros_ec_proto.h | 1 +
4 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/debugfs-cros-ec b/Documentation/ABI/testing/debugfs-cros-ec
index 1fe0add99a2a99..8e7e76e6481550 100644
--- a/Documentation/ABI/testing/debugfs-cros-ec
+++ b/Documentation/ABI/testing/debugfs-cros-ec
@@ -54,3 +54,25 @@ Description:
this feature.
Output will be in the format: "0x%08x\n".
+
+What: /sys/kernel/debug/<cros-ec-device>/suspend_timeout
+Date: August 2022
+KernelVersion: 6.0
+Description:
+ Some ECs have a feature where they will track transitions to the
+ a hardware-controlled sleep line, such as Intel's SLP_S0 line,
+ in order to detect cases where a system failed to go into deep
+ sleep states. The suspend_timeout file controls the amount of
+ time in milliseconds the EC will wait before declaring a sleep
+ timeout event and attempting to wake the system.
+
+ Supply 0 to use the default value coded into EC firmware. Supply
+ 65535 to disable the EC sleep failure detection mechanism.
+ Values in between 0 and 65535 indicate the number of
+ milliseconds the EC should wait after a sleep transition before
+ declaring a timeout. This includes both the duration after a
+ sleep command was received but before the hardware line changed,
+ as well as the duration between when the hardware line changed
+ and the kernel sent an EC resume command.
+
+ Output will be in the format: "%u\n".
diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c
index 8aace50d446d65..e8d3e2a29a58f5 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -115,7 +115,7 @@ static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
if (ec_dev->host_sleep_v1) {
buf.u.req1.sleep_event = sleep_event;
buf.u.req1.suspend_params.sleep_timeout_ms =
- EC_HOST_SLEEP_TIMEOUT_DEFAULT;
+ ec_dev->suspend_timeout;
buf.msg.outsize = sizeof(buf.u.req1);
if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) ||
@@ -188,6 +188,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
ec_dev->max_passthru = 0;
ec_dev->ec = NULL;
ec_dev->pd = NULL;
+ ec_dev->suspend_timeout = EC_HOST_SLEEP_TIMEOUT_DEFAULT;
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
if (!ec_dev->din)
diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
index 0dbceee87a4b1a..530378bd4359dd 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -470,6 +470,9 @@ static int cros_ec_debugfs_probe(struct platform_device *pd)
debugfs_create_x32("last_resume_result", 0444, debug_info->dir,
&ec->ec_dev->last_resume_result);
+ debugfs_create_u16("suspend_timeout", 0664, debug_info->dir,
+ &ec->ec_dev->suspend_timeout);
+
ec->debug_info = debug_info;
dev_set_drvdata(&pd->dev, ec);
diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h
index 408b29ca4004be..60132444f7daa6 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -169,6 +169,7 @@ struct cros_ec_device {
int event_size;
u32 host_event_wake_mask;
u32 last_resume_result;
+ u16 suspend_timeout;
ktime_t last_event_time;
struct notifier_block notifier_ready;
--
2.31.0
On Fri, Aug 05, 2022 at 03:17:17PM -0700, Evan Green wrote:
> diff --git a/Documentation/ABI/testing/debugfs-cros-ec b/Documentation/ABI/testing/debugfs-cros-ec
> index 1fe0add99a2a99..8e7e76e6481550 100644
> --- a/Documentation/ABI/testing/debugfs-cros-ec
> +++ b/Documentation/ABI/testing/debugfs-cros-ec
> @@ -54,3 +54,25 @@ Description:
> this feature.
>
> Output will be in the format: "0x%08x\n".
> +
> +What: /sys/kernel/debug/<cros-ec-device>/suspend_timeout
> +Date: August 2022
> +KernelVersion: 6.0
The merge window is opened. It's too late for the patch if the following
outcome version is 6.0.
> +Description:
> + Some ECs have a feature where they will track transitions to the
> + a hardware-controlled sleep line, such as Intel's SLP_S0 line,
> + in order to detect cases where a system failed to go into deep
> + sleep states. The suspend_timeout file controls the amount of
> + time in milliseconds the EC will wait before declaring a sleep
> + timeout event and attempting to wake the system.
> +
> + Supply 0 to use the default value coded into EC firmware. Supply
> + 65535 to disable the EC sleep failure detection mechanism.
Better to mention EC_HOST_SLEEP_TIMEOUT_INFINITE or [1] in the description.
Or, it's not obvious from the patch that 65535 disables the mechanism.
[1]: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/main/power/host_sleep.c
Hi Evan,
On Fri, Aug 5, 2022 at 3:17 PM Evan Green <[email protected]> wrote:
>
> diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
> index 0dbceee87a4b1a..530378bd4359dd 100644
> --- a/drivers/platform/chrome/cros_ec_debugfs.c
> +++ b/drivers/platform/chrome/cros_ec_debugfs.c
> @@ -470,6 +470,9 @@ static int cros_ec_debugfs_probe(struct platform_device *pd)
> debugfs_create_x32("last_resume_result", 0444, debug_info->dir,
> &ec->ec_dev->last_resume_result);
>
> + debugfs_create_u16("suspend_timeout", 0664, debug_info->dir,
> + &ec->ec_dev->suspend_timeout);
Can we call this "suspend_timeout_ms" instead? That makes it clear what the
units being used are.
BR,
- Prashant