diff mbox series

[v2] PM: sleep: Optimize the pm_debug_messages_should_print() condition

Message ID 20240909080726.16811-1-xiongxin@kylinos.cn (mailing list archive)
State Changes Requested, archived
Headers show
Series [v2] PM: sleep: Optimize the pm_debug_messages_should_print() condition | expand

Commit Message

XiongXin Sept. 9, 2024, 8:07 a.m. UTC
From: xiongxin <xiongxin@kylinos.cn>

pm_pr_dbg() is useful when debugging suspend and hibernate processes. In
commit cdb8c100d8a4 ("include/linux/suspend.h: Only show pm_pr_dbg
messages at suspend/resume") using pm_suspend_target_state to limits the
output range of pm_pr_dbg(), causes the original pm_pr_dbg() output
range to change.

In the suspend process, pm_pr_dbg() is called before setting
pm_suspend_target_state. As a result, this part of the log cannot be
output.

pm_pr_dbg() also outputs debug logs for hibernate, but
pm_suspend_target_state is not set, resulting in hibernate debug logs
can only be output through dynamic debug, which is very inconvenient.

Expand the scope of the state variable in state_store() and add judgment
on it in pm_debug_messages_should_print() to extend the debugging output
of pm_pr_dbg() to suspend and hibernate processes.

Fixes: cdb8c100d8a4 ("include/linux/suspend.h: Only show pm_pr_dbg messages at suspend/resume").
Signed-off-by: xiongxin <xiongxin@kylinos.cn>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
---
 kernel/power/main.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

Comments

Rafael J. Wysocki Sept. 10, 2024, 6:08 p.m. UTC | #1
On Mon, Sep 9, 2024 at 10:07 AM Xiong Xin <xiongxin@kylinos.cn> wrote:
>
> From: xiongxin <xiongxin@kylinos.cn>
>
> pm_pr_dbg() is useful when debugging suspend and hibernate processes. In
> commit cdb8c100d8a4 ("include/linux/suspend.h: Only show pm_pr_dbg
> messages at suspend/resume") using pm_suspend_target_state to limits the
> output range of pm_pr_dbg(), causes the original pm_pr_dbg() output
> range to change.
>
> In the suspend process, pm_pr_dbg() is called before setting
> pm_suspend_target_state. As a result, this part of the log cannot be
> output.
>
> pm_pr_dbg() also outputs debug logs for hibernate, but
> pm_suspend_target_state is not set, resulting in hibernate debug logs
> can only be output through dynamic debug, which is very inconvenient.
>
> Expand the scope of the state variable in state_store() and add judgment
> on it in pm_debug_messages_should_print() to extend the debugging output
> of pm_pr_dbg() to suspend and hibernate processes.
>
> Fixes: cdb8c100d8a4 ("include/linux/suspend.h: Only show pm_pr_dbg messages at suspend/resume").
> Signed-off-by: xiongxin <xiongxin@kylinos.cn>
> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
>  kernel/power/main.c | 21 +++++++++++++--------
>  1 file changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/kernel/power/main.c b/kernel/power/main.c
> index a9e0693aaf69..a376107efbb4 100644
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -559,6 +559,8 @@ late_initcall(pm_debugfs_init);
>
>  #endif /* CONFIG_PM_SLEEP */
>
> +static suspend_state_t pm_state = PM_SUSPEND_ON;
> +
>  #ifdef CONFIG_PM_SLEEP_DEBUG
>  /*
>   * pm_print_times: print time taken by devices to suspend and resume.
> @@ -613,7 +615,9 @@ bool pm_debug_messages_on __read_mostly;
>
>  bool pm_debug_messages_should_print(void)
>  {
> -       return pm_debug_messages_on && pm_suspend_target_state != PM_SUSPEND_ON;
> +       return pm_debug_messages_on &&
> +              (pm_suspend_target_state != PM_SUSPEND_ON ||
> +               pm_state != PM_SUSPEND_ON);
>  }
>  EXPORT_SYMBOL_GPL(pm_debug_messages_should_print);
>
> @@ -715,7 +719,6 @@ static suspend_state_t decode_state(const char *buf, size_t n)
>  static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>                            const char *buf, size_t n)
>  {
> -       suspend_state_t state;
>         int error;
>
>         error = pm_autosleep_lock();
> @@ -727,18 +730,20 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>                 goto out;
>         }
>
> -       state = decode_state(buf, n);
> -       if (state < PM_SUSPEND_MAX) {
> -               if (state == PM_SUSPEND_MEM)
> -                       state = mem_sleep_current;
> +       pm_state = decode_state(buf, n);
> +       if (pm_state < PM_SUSPEND_MAX) {
> +               if (pm_state == PM_SUSPEND_MEM)
> +                       pm_state = mem_sleep_current;
>
> -               error = pm_suspend(state);
> -       } else if (state == PM_SUSPEND_MAX) {
> +               error = pm_suspend(pm_state);
> +       } else if (pm_state == PM_SUSPEND_MAX) {
>                 error = hibernate();
>         } else {
>                 error = -EINVAL;
>         }
>
> +       pm_state = PM_SUSPEND_ON;
> +
>   out:
>         pm_autosleep_unlock();
>         return error ? error : n;
> --

This would only work for transitions started via /sys/power/state
AFAICS, but there are other ways to start them (eg. autosleep).
XiongXin Sept. 11, 2024, 2:54 a.m. UTC | #2
在 2024/9/11 02:08, Rafael J. Wysocki 写道:
> On Mon, Sep 9, 2024 at 10:07 AM Xiong Xin <xiongxin@kylinos.cn> wrote:
>>
>> From: xiongxin <xiongxin@kylinos.cn>
>>
>> pm_pr_dbg() is useful when debugging suspend and hibernate processes. In
>> commit cdb8c100d8a4 ("include/linux/suspend.h: Only show pm_pr_dbg
>> messages at suspend/resume") using pm_suspend_target_state to limits the
>> output range of pm_pr_dbg(), causes the original pm_pr_dbg() output
>> range to change.
>>
>> In the suspend process, pm_pr_dbg() is called before setting
>> pm_suspend_target_state. As a result, this part of the log cannot be
>> output.
>>
>> pm_pr_dbg() also outputs debug logs for hibernate, but
>> pm_suspend_target_state is not set, resulting in hibernate debug logs
>> can only be output through dynamic debug, which is very inconvenient.
>>
>> Expand the scope of the state variable in state_store() and add judgment
>> on it in pm_debug_messages_should_print() to extend the debugging output
>> of pm_pr_dbg() to suspend and hibernate processes.
>>
>> Fixes: cdb8c100d8a4 ("include/linux/suspend.h: Only show pm_pr_dbg messages at suspend/resume").
>> Signed-off-by: xiongxin <xiongxin@kylinos.cn>
>> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
>> ---
>>   kernel/power/main.c | 21 +++++++++++++--------
>>   1 file changed, 13 insertions(+), 8 deletions(-)
>>
>> diff --git a/kernel/power/main.c b/kernel/power/main.c
>> index a9e0693aaf69..a376107efbb4 100644
>> --- a/kernel/power/main.c
>> +++ b/kernel/power/main.c
>> @@ -559,6 +559,8 @@ late_initcall(pm_debugfs_init);
>>
>>   #endif /* CONFIG_PM_SLEEP */
>>
>> +static suspend_state_t pm_state = PM_SUSPEND_ON;
>> +
>>   #ifdef CONFIG_PM_SLEEP_DEBUG
>>   /*
>>    * pm_print_times: print time taken by devices to suspend and resume.
>> @@ -613,7 +615,9 @@ bool pm_debug_messages_on __read_mostly;
>>
>>   bool pm_debug_messages_should_print(void)
>>   {
>> -       return pm_debug_messages_on && pm_suspend_target_state != PM_SUSPEND_ON;
>> +       return pm_debug_messages_on &&
>> +              (pm_suspend_target_state != PM_SUSPEND_ON ||
>> +               pm_state != PM_SUSPEND_ON);
>>   }
>>   EXPORT_SYMBOL_GPL(pm_debug_messages_should_print);
>>
>> @@ -715,7 +719,6 @@ static suspend_state_t decode_state(const char *buf, size_t n)
>>   static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>>                             const char *buf, size_t n)
>>   {
>> -       suspend_state_t state;
>>          int error;
>>
>>          error = pm_autosleep_lock();
>> @@ -727,18 +730,20 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
>>                  goto out;
>>          }
>>
>> -       state = decode_state(buf, n);
>> -       if (state < PM_SUSPEND_MAX) {
>> -               if (state == PM_SUSPEND_MEM)
>> -                       state = mem_sleep_current;
>> +       pm_state = decode_state(buf, n);
>> +       if (pm_state < PM_SUSPEND_MAX) {
>> +               if (pm_state == PM_SUSPEND_MEM)
>> +                       pm_state = mem_sleep_current;
>>
>> -               error = pm_suspend(state);
>> -       } else if (state == PM_SUSPEND_MAX) {
>> +               error = pm_suspend(pm_state);
>> +       } else if (pm_state == PM_SUSPEND_MAX) {
>>                  error = hibernate();
>>          } else {
>>                  error = -EINVAL;
>>          }
>>
>> +       pm_state = PM_SUSPEND_ON;
>> +
>>    out:
>>          pm_autosleep_unlock();
>>          return error ? error : n;
>> --
> 
> This would only work for transitions started via /sys/power/state
> AFAICS, but there are other ways to start them (eg. autosleep).

Yes, the current patch does not yet control the resume process in 
kernel/power/hibernate.c

As suggested earlier, to define a global variable, such as bool 
is_pm_process, to determin whether in the suspend, hibernate, resume 
process?
diff mbox series

Patch

diff --git a/kernel/power/main.c b/kernel/power/main.c
index a9e0693aaf69..a376107efbb4 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -559,6 +559,8 @@  late_initcall(pm_debugfs_init);
 
 #endif /* CONFIG_PM_SLEEP */
 
+static suspend_state_t pm_state = PM_SUSPEND_ON;
+
 #ifdef CONFIG_PM_SLEEP_DEBUG
 /*
  * pm_print_times: print time taken by devices to suspend and resume.
@@ -613,7 +615,9 @@  bool pm_debug_messages_on __read_mostly;
 
 bool pm_debug_messages_should_print(void)
 {
-	return pm_debug_messages_on && pm_suspend_target_state != PM_SUSPEND_ON;
+	return pm_debug_messages_on &&
+	       (pm_suspend_target_state != PM_SUSPEND_ON ||
+		pm_state != PM_SUSPEND_ON);
 }
 EXPORT_SYMBOL_GPL(pm_debug_messages_should_print);
 
@@ -715,7 +719,6 @@  static suspend_state_t decode_state(const char *buf, size_t n)
 static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
 			   const char *buf, size_t n)
 {
-	suspend_state_t state;
 	int error;
 
 	error = pm_autosleep_lock();
@@ -727,18 +730,20 @@  static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
 		goto out;
 	}
 
-	state = decode_state(buf, n);
-	if (state < PM_SUSPEND_MAX) {
-		if (state == PM_SUSPEND_MEM)
-			state = mem_sleep_current;
+	pm_state = decode_state(buf, n);
+	if (pm_state < PM_SUSPEND_MAX) {
+		if (pm_state == PM_SUSPEND_MEM)
+			pm_state = mem_sleep_current;
 
-		error = pm_suspend(state);
-	} else if (state == PM_SUSPEND_MAX) {
+		error = pm_suspend(pm_state);
+	} else if (pm_state == PM_SUSPEND_MAX) {
 		error = hibernate();
 	} else {
 		error = -EINVAL;
 	}
 
+	pm_state = PM_SUSPEND_ON;
+
  out:
 	pm_autosleep_unlock();
 	return error ? error : n;