[PATCH] printk: Debug new vs. old suspend/resume behavior

From: John Ogness

Date: Thu Jan 08 2026 - 04:31:51 EST


This is just for debugging. It should restore the old console_lock
behavior for suspend/resume and also adds some debugging information.
Please compile with CONFIG_PRINTK_CALLER=y so that we can see which
tasks are locking/unlocking the console during suspend/resume.
---
kernel/printk/printk.c | 61 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 1d765ad242b8..fd69cab4368e 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -356,6 +356,22 @@ static void __up_console_sem(unsigned long ip)
*/
static int console_locked;

+static int console_suspended;
+
+int vprintk_store(int facility, int level,
+ const struct dev_printk_info *dev_info,
+ const char *fmt, va_list args);
+
+/* Helper function to store-only. */
+static void printk_store(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
+ va_end(args);
+}
+
/*
* Array of consoles built from command line options (console=)
*/
@@ -2841,6 +2857,15 @@ void console_lock(void)
msleep(1000);

down_console_sem();
+ if (console_suspended) {
+ printk_store(KERN_INFO "printk: %s\n", __func__);
+ /*
+ * Keep console locked, but do not touch
+ * @console_locked or @console_may_schedule.
+ * (Although they will both be 1 here anyway.)
+ */
+ return;
+ }
console_locked = 1;
console_may_schedule = 1;
}
@@ -2861,6 +2886,15 @@ int console_trylock(void)
return 0;
if (down_trylock_console_sem())
return 0;
+ if (console_suspended) {
+ printk_store(KERN_INFO "printk: %s\n", __func__);
+ /*
+ * The lock was acquired, but unlock directly and report
+ * failure. Here console_locked=1 and console_may_schedule=1.
+ */
+ up_console_sem();
+ return 0;
+ }
console_locked = 1;
console_may_schedule = 0;
return 1;
@@ -3354,6 +3388,16 @@ void console_unlock(void)
{
struct console_flush_type ft;

+ if (console_suspended) {
+ printk_store(KERN_INFO "printk: %s\n", __func__);
+ /*
+ * Simply unlock directly.
+ * Here console_locked=1 and console_may_schedule=1.
+ */
+ up_console_sem();
+ return;
+ }
+
printk_get_console_flush_type(&ft);
if (ft.legacy_direct)
__console_flush_and_unlock();
@@ -3559,6 +3603,7 @@ struct tty_driver *console_device(int *index)
void console_suspend(struct console *console)
{
__pr_flush(console, 1000, true);
+
console_list_lock();
console_srcu_write_flags(console, console->flags & ~CON_ENABLED);
console_list_unlock();
@@ -3570,6 +3615,12 @@ void console_suspend(struct console *console)
* using the port.
*/
synchronize_srcu(&console_srcu);
+
+ console_lock();
+ console_suspended = 1;
+ printk_store(KERN_INFO "printk: %s\n", __func__);
+ /* Unlock directly (i.e. without clearing @console_locked). */
+ up_console_sem();
}
EXPORT_SYMBOL(console_suspend);

@@ -3597,6 +3648,16 @@ void console_resume(struct console *console)
defer_console_output();

__pr_flush(console, 1000, true);
+
+ down_console_sem();
+ printk_store(KERN_INFO "printk: %s\n", __func__);
+ console_suspended = 0;
+ /*
+ * Perform a regular unlock.
+ * Here console_locked=1 and console_may_schedule=1.
+ * @console_unlocked will be cleared.
+ */
+ console_unlock();
}
EXPORT_SYMBOL(console_resume);

--
2.30.2


--=-=-=--