From: Vimal Kumar <vimal.kumar32@gmail.com>
To: "Rafael J. Wysocki" <rafael@kernel.org>,
Len Brown <len.brown@intel.com>, Pavel Machek <pavel@ucw.cz>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: chinmoyghosh2001@gmail.com, badolevishal1116@gmail.com,
mintupatel89@gmail.com, Vimal Kumar <vimal.kumar32@gmail.com>
Subject: [PATCH v2] PM / sleep: Mechanism to find source aborting kernel suspend transition
Date: Sun, 10 Dec 2023 15:33:01 +0530 [thread overview]
Message-ID: <20231210100303.491-1-vimal.kumar32@gmail.com> (raw)
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] PM: wakeup source 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@gmail.com>
Signed-off-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
Co-developed-by: Mintu Patel <mintupatel89@gmail.com>
Signed-off-by: Mintu Patel <mintupatel89@gmail.com>
Co-developed-by: Vishal Badole <badolevishal1116@gmail.com>
Signed-off-by: Vishal Badole <badolevishal1116@gmail.com>
Signed-off-by: Vimal Kumar <vimal.kumar32@gmail.com>
---
Changes in v2:
- Make pm_abort_suspend_list static.
- Added locks.
- Removed list_empty check as not needed.
- Fix Doc format.
- Fix function name as per global functions.
- Removed use of unlikely/likely.
- Removed extra logging for kmalloc failure.
- Use *info instead of struct name.
---
drivers/base/power/wakeup.c | 82 ++++++++++++++++++++++++++++++++++++-
include/linux/suspend.h | 2 +
kernel/power/suspend.c | 1 +
3 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index a917219feea6..fa1e3369b0f6 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -73,6 +73,15 @@ static struct wakeup_source deleted_ws = {
static DEFINE_IDA(wakeup_ida);
+#define MAX_SUSPEND_ABORT_LEN 256
+static DEFINE_RAW_SPINLOCK(abort_suspend_lock);
+
+struct pm_abort_suspend_source {
+ struct list_head list;
+ char *source_triggering_abort_suspend;
+};
+static LIST_HEAD(pm_abort_suspend_list);
+
/**
* wakeup_source_create - Create a struct wakeup_source object.
* @name: Name of the new wakeup source.
@@ -575,6 +584,56 @@ static void wakeup_source_activate(struct wakeup_source *ws)
trace_wakeup_source_activate(ws->name, cec);
}
+/**
+ * abort_suspend_list_clear - Clear pm_abort_suspend_list.
+ *
+ * The pm_abort_suspend_list will be cleared when system PM exits.
+ */
+void abort_suspend_list_clear(void)
+{
+ struct pm_abort_suspend_source *info, *tmp;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&abort_suspend_lock, flags);
+ list_for_each_entry_safe(info, tmp, &pm_abort_suspend_list, list) {
+ list_del(&info->list);
+ kfree(info);
+ }
+ raw_spin_unlock_irqrestore(&abort_suspend_lock, flags);
+}
+EXPORT_SYMBOL_GPL(abort_suspend_list_clear);
+
+/**
+ * pm_abort_suspend_source_add - Update pm_abort_suspend_list
+ * @source_name: Wakeup_source or function aborting suspend transitions.
+ *
+ * Add the source name responsible for updating the abort_suspend flag in the
+ * pm_abort_suspend_list.
+ */
+static void pm_abort_suspend_source_add(const char *source_name)
+{
+ struct pm_abort_suspend_source *info;
+ unsigned long flags;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ 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 (!info->source_triggering_abort_suspend) {
+ kfree(info);
+ return;
+ }
+
+ raw_spin_lock_irqsave(&abort_suspend_lock, flags);
+ list_add_tail(&info->list, &pm_abort_suspend_list);
+ raw_spin_unlock_irqrestore(&abort_suspend_lock, flags);
+}
+
/**
* wakeup_source_report_event - Report wakeup event using the given source.
* @ws: Wakeup source to report the event for.
@@ -590,8 +649,11 @@ static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
if (!ws->active)
wakeup_source_activate(ws);
- if (hard)
+ if (hard) {
+ if (pm_suspend_target_state != PM_SUSPEND_ON)
+ pm_abort_suspend_source_add(ws->name);
pm_system_wakeup();
+ }
}
/**
@@ -877,6 +939,7 @@ bool pm_wakeup_pending(void)
{
unsigned long flags;
bool ret = false;
+ struct pm_abort_suspend_source *info;
raw_spin_lock_irqsave(&events_lock, flags);
if (events_check_enabled) {
@@ -893,12 +956,29 @@ bool pm_wakeup_pending(void)
pm_print_active_wakeup_sources();
}
+ if (atomic_read(&pm_abort_suspend) > 0) {
+ raw_spin_lock_irqsave(&abort_suspend_lock, flags);
+ list_for_each_entry(info, &pm_abort_suspend_list, list) {
+ pm_pr_dbg("wakeup source or subsystem %s aborted suspend\n",
+ info->source_triggering_abort_suspend);
+ }
+ raw_spin_unlock_irqrestore(&abort_suspend_lock, flags);
+ }
+
return ret || atomic_read(&pm_abort_suspend) > 0;
}
EXPORT_SYMBOL_GPL(pm_wakeup_pending);
void pm_system_wakeup(void)
{
+ char buf[MAX_SUSPEND_ABORT_LEN];
+
+ if (pm_suspend_target_state != PM_SUSPEND_ON) {
+ sprintf(buf, "%ps", __builtin_return_address(0));
+ if (strcmp(buf, "pm_wakeup_ws_event"))
+ pm_abort_suspend_source_add(buf);
+ }
+
atomic_inc(&pm_abort_suspend);
s2idle_wake();
}
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index ef503088942d..2eef5817b825 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -528,6 +528,7 @@ extern void pm_print_active_wakeup_sources(void);
extern unsigned int lock_system_sleep(void);
extern void unlock_system_sleep(unsigned int);
+extern void abort_suspend_list_clear(void);
#else /* !CONFIG_PM_SLEEP */
@@ -556,6 +557,7 @@ static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
static inline unsigned int lock_system_sleep(void) { return 0; }
static inline void unlock_system_sleep(unsigned int flags) {}
+static inline void abort_suspend_list_clear(void) {}
#endif /* !CONFIG_PM_SLEEP */
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index fa3bf161d13f..49c830246930 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -623,6 +623,7 @@ int pm_suspend(suspend_state_t state)
} else {
suspend_stats.success++;
}
+ abort_suspend_list_clear();
pr_info("suspend exit\n");
return error;
}
--
2.25.1
next reply other threads:[~2023-12-10 10:03 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-10 10:03 Vimal Kumar [this message]
2023-12-10 10:28 ` [PATCH v2] PM / sleep: Mechanism to find source aborting kernel suspend transition Greg Kroah-Hartman
2023-12-10 10:28 ` Greg Kroah-Hartman
2023-12-10 10:35 ` Greg Kroah-Hartman
2024-01-09 4:48 ` Vimal Kumar
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=20231210100303.491-1-vimal.kumar32@gmail.com \
--to=vimal.kumar32@gmail.com \
--cc=badolevishal1116@gmail.com \
--cc=chinmoyghosh2001@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=len.brown@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=mintupatel89@gmail.com \
--cc=pavel@ucw.cz \
--cc=rafael@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.