Re: [PATCH] PM / sleep: Mechanism to find source aborting kernel suspend transition

From: Christophe JAILLET
Date: Sat Dec 09 2023 - 10:27:08 EST


Le 09/12/2023 à 09:10, Vimal Kumar a écrit :
Sometimes kernel suspend transitions can be aborted unconditionally by
manipulating pm_abort_suspend value using "hard" wakeup triggers or
through "pm_system_wakeup()".

There is no way to trace the source path of module or subsystem which
aborted the suspend transitions. This change will create a list of
wakeup sources aborting suspend in progress through "hard" events as
well as subsytems aborting suspend using "pm_system_wakeup()".

Example: Existing suspend failure logs:
[ 349.708359] PM: Some devices failed to suspend, or early wake event detected
[ 350.327842] PM: suspend exit

Suspend failure logs with this change:
[ 518.761835] PM: Some devices failed to suspend, or early wake event detected
[ 519.486939] Abort: ws or subsystem uart_suspend_port aborted suspend
[ 519.500594] PM: suspend exit

Here we can clearly identify the module triggerring abort suspend.

Co-developed-by: Chinmoy Ghosh <chinmoyghosh2001@xxxxxxxxx>
Signed-off-by: Chinmoy Ghosh <chinmoyghosh2001@xxxxxxxxx>
Co-developed-by: Mintu Patel <mintupatel89@xxxxxxxxx>
Signed-off-by: Mintu Patel <mintupatel89@xxxxxxxxx>
Co-developed-by: Vishal Badole <badolevishal1116@xxxxxxxxx>
Signed-off-by: Vishal Badole <badolevishal1116@xxxxxxxxx>
Signed-off-by: Vimal Kumar <vimal.kumar32@xxxxxxxxx>
---

...

+void pm_add_abort_suspend_source(const char *source_name)
+{
+ struct pm_abort_suspend_source *info = NULL;

No need to init.

+
+ info = kmalloc(sizeof(struct pm_abort_suspend_source), GFP_KERNEL);

Could be sizeof(*info).

+ if (unlikely(!info)) {
+ pr_err("Failed to alloc memory for pm_abort_suspend_source info\n");

No need to log a message if kmalloc() fails, a trace is already logged.

+ return;
+ }
+
+ /* Initialize the list within the struct if it's not already initialized */
+ if (list_empty(&info->list))
+ INIT_LIST_HEAD(&info->list);
+
+ info->source_triggering_abort_suspend = kstrdup(source_name, GFP_KERNEL);
+ if (unlikely(!info->source_triggering_abort_suspend)) {
+ pr_err("Failed to get abort_suspend source_name\n");

Same here.

+ kfree(info);
+ return;
+ }
+
+ list_add_tail(&info->list, &pm_abort_suspend_list);

...

CJ