All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4] ACPI: button: Report wakeup key only for power button wakeups
  2026-09-17 14:31 [PATCH v3] " Baorui.Liu
@ 2026-09-22  2:42 ` Baorui.Liu
  0 siblings, 0 replies; 2+ messages in thread
From: Baorui.Liu @ 2026-09-22  2:42 UTC (permalink / raw)
  To: rafael
  Cc: lenb, robert.moore, linux-acpi, linux-kernel, acpica-devel,
	Baorui.Liu

The ACPI button driver reports KEY_WAKEUP from the Power Button input
device to let userspace know that the system was resumed by a power
button wakeup.

However, reporting KEY_WAKEUP from generic system resume paths can make
userspace observe a Power Button wakeup even when the system was resumed
by a different wake source.

This is reproducible on an AMD Android 15 Xen guest. With a kernel
without this fix, a non-power-button S3 resume:

  echo mem > /sys/power/state
  xl trigger android s3resume

makes the Power Button input device report KEY_WAKEUP. The same test on
a kernel with this fix no longer reports KEY_WAKEUP from the Power Button
input device.

Track whether a power button event/notify is observed while the ACPI
button device is suspended, and report KEY_WAKEUP on resume only in that
case.

When the fixed power-button status bit is set during early S3 resume,
clear it to avoid a deferred KEY_POWER delivery to userspace, and mark
wakeup_pending so button resume can still report KEY_WAKEUP. Also clear
wakeup_pending before setting suspended to avoid a race with a power
button SCI during suspend entry.

Signed-off-by: Baorui.Liu <baorliu@amd.com>
---
 drivers/acpi/button.c | 46 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/acpi/sleep.c  | 27 +++++++++++--------------
 include/acpi/button.h |  5 +++++
 3 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index cdbb1023a8ee..c07de417df5d 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -191,6 +191,7 @@ struct acpi_button {
 	bool last_state;
 	ktime_t last_time;
 	bool suspended;
+	bool wakeup_pending;
 	bool lid_state_initialized;
 	bool gpe_enabled;
 };
@@ -397,6 +398,34 @@ static void acpi_lid_forget(struct acpi_device *adev)
 }
 
 /* Driver Interface */
+/**
+ * acpi_button_power_wakeup_pending - Mark fixed power button wakeup pending.
+ *
+ * Used when the fixed power-button status bit is observed and cleared during
+ * early S3 resume, so KEY_WAKEUP can still be reported from button resume
+ * without delivering a deferred KEY_POWER to userspace.
+ */
+void acpi_button_power_wakeup_pending(void)
+{
+	struct acpi_device *adev;
+	struct device *phys_dev;
+	struct acpi_button *button;
+
+	adev = acpi_dev_get_first_match_dev(ACPI_BUTTON_HID_POWERF, NULL, -1);
+	if (!adev)
+		return;
+
+	phys_dev = acpi_get_first_physical_node(adev);
+	if (phys_dev) {
+		button = dev_get_drvdata(phys_dev);
+		if (button && button->type == ACPI_BUTTON_TYPE_POWER)
+			button->wakeup_pending = true;
+	}
+
+	acpi_dev_put(adev);
+}
+EXPORT_SYMBOL_GPL(acpi_button_power_wakeup_pending);
+
 int acpi_lid_open(void)
 {
 	guard(mutex)(&acpi_lid_lock);
@@ -476,6 +505,9 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
 
 	acpi_pm_wakeup_event(button->dev);
 
+	if (button->type == ACPI_BUTTON_TYPE_POWER && button->suspended)
+		button->wakeup_pending = true;
+
 	if (button->suspended || event == ACPI_BUTTON_NOTIFY_WAKE)
 		return;
 
@@ -498,6 +530,11 @@ static void acpi_button_notify_run(void *data)
 
 static u32 acpi_button_event(void *data)
 {
+	struct acpi_button *button = data;
+
+	if (button->type == ACPI_BUTTON_TYPE_POWER && button->suspended)
+		button->wakeup_pending = true;
+
 	acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_button_notify_run, data);
 	return ACPI_INTERRUPT_HANDLED;
 }
@@ -507,6 +544,12 @@ static int acpi_button_suspend(struct device *dev)
 {
 	struct acpi_button *button = dev_get_drvdata(dev);
 
+	/*
+	 * Clear wakeup_pending before marking suspended. Otherwise a power
+	 * button SCI between the two stores could set wakeup_pending and then
+	 * be overwritten here, losing a real wakeup.
+	 */
+	button->wakeup_pending = false;
 	button->suspended = true;
 	return 0;
 }
@@ -523,12 +566,13 @@ static int acpi_button_resume(struct device *dev)
 		acpi_lid_initialize_state(button);
 	}
 
-	if (button->type == ACPI_BUTTON_TYPE_POWER) {
+	if (button->type == ACPI_BUTTON_TYPE_POWER && button->wakeup_pending) {
 		input = button->input;
 		input_report_key(input, KEY_WAKEUP, 1);
 		input_sync(input);
 		input_report_key(input, KEY_WAKEUP, 0);
 		input_sync(input);
+		button->wakeup_pending = false;
 	}
 	return 0;
 }
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 132a9df98471..30e268987e37 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -22,6 +22,7 @@
 #include <linux/syscore_ops.h>
 #include <asm/io.h>
 #include <trace/events/power.h>
+#include <acpi/button.h>
 
 #include "internal.h"
 #include "sleep.h"
@@ -504,12 +505,11 @@ static void acpi_pm_finish(void)
 
 	acpi_resume_power_resources();
 
-	/* If we were woken with the fixed power button, provide a small
-	 * hint to userspace in the form of a wakeup event on the fixed power
-	 * button device (if it can be found).
-	 *
-	 * We delay the event generation til now, as the PM layer requires
-	 * timekeeping to be running before we generate events. */
+	/*
+	 * If woken by the fixed power button, provide a wakeup event on that
+	 * device. KEY_WAKEUP input reporting is handled by the button driver
+	 * via wakeup_pending; do not synthesize KEY_POWER here.
+	 */
 	if (!pwr_btn_event_pending)
 		return;
 
@@ -626,14 +626,11 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 	/* Reprogram control registers */
 	acpi_leave_sleep_state_prep(acpi_state);
 
-	/* ACPI 3.0 specs (P62) says that it's the responsibility
-	 * of the OSPM to clear the status bit [ implying that the
-	 * POWER_BUTTON event should not reach userspace ]
-	 *
-	 * However, we do generate a small hint for userspace in the form of
-	 * a wakeup event. We flag this condition for now and generate the
-	 * event later, as we're currently too early in resume to be able to
-	 * generate wakeup events.
+	/*
+	 * ACPI 3.0 (P62): OSPM should clear the fixed power-button status bit
+	 * so the event does not reach userspace as KEY_POWER. Remember that a
+	 * power-button wake occurred so button resume can report KEY_WAKEUP
+	 * and acpi_pm_finish() can emit a PM wakeup event.
 	 */
 	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
 		acpi_event_status pwr_btn_status = ACPI_EVENT_FLAG_DISABLED;
@@ -642,8 +639,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 
 		if (pwr_btn_status & ACPI_EVENT_FLAG_STATUS_SET) {
 			acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
-			/* Flag for later */
 			pwr_btn_event_pending = true;
+			acpi_button_power_wakeup_pending();
 		}
 	}
 
diff --git a/include/acpi/button.h b/include/acpi/button.h
index af2fce5d2ee3..213c6cfd0264 100644
--- a/include/acpi/button.h
+++ b/include/acpi/button.h
@@ -8,11 +8,16 @@
 
 #if IS_ENABLED(CONFIG_ACPI_BUTTON)
 extern int acpi_lid_open(void);
+extern void acpi_button_power_wakeup_pending(void);
 #else
 static inline int acpi_lid_open(void)
 {
 	return 1;
 }
+
+static inline void acpi_button_power_wakeup_pending(void)
+{
+}
 #endif /* IS_ENABLED(CONFIG_ACPI_BUTTON) */
 
 #endif /* ACPI_BUTTON_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v4] ACPI: button: Report wakeup key only for power button wakeups
@ 2026-09-29  2:52 kernel test robot
  0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-09-29  2:52 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp

:::::: 
:::::: Manual check reason: "linux-review patch is more than 7 days old, verify it wasn't already superseded"
:::::: 

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20260922024232.816-1-baorliu@amd.com>
References: <20260922024232.816-1-baorliu@amd.com>
TO: "Baorui.Liu" <baorliu@amd.com>
TO: rafael@kernel.org
CC: lenb@kernel.org
CC: linux-acpi@vger.kernel.org
CC: linux-kernel@vger.kernel.org
CC: acpica-devel@lists.linuxfoundation.org
CC: "Baorui.Liu" <baorliu@amd.com>

Hi Baorui.Liu,

kernel test robot noticed the following build errors:

[auto build test ERROR on rafael-pm/linux-next]
[also build test ERROR on linus/master v7.3-rc5 next-20260928]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Baorui-Liu/ACPI-button-Report-wakeup-key-only-for-power-button-wakeups/20260922-104232
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link:    https://lore.kernel.org/r/20260922024232.816-1-baorliu%40amd.com
patch subject: [PATCH v4] ACPI: button: Report wakeup key only for power button wakeups
:::::: branch date: 7 days ago
:::::: commit date: 7 days ago
config: x86_64-randconfig-2100-20260928 (https://download.01.org/0day-ci/archive/20260929/202609290454.LJrhMCb3-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260929/202609290454.LJrhMCb3-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/r/202609290454.LJrhMCb3-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: vmlinux.o: in function `acpi_suspend_enter':
>> drivers/acpi/sleep.c:643:(.text+0x147f324): undefined reference to `acpi_button_power_wakeup_pending'


vim +643 drivers/acpi/sleep.c

e9b3aba887f47f drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-17  589  
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  590  /**
2c6e33c366bff2 drivers/acpi/sleep/main.c Len Brown             2008-04-23  591   *	acpi_suspend_enter - Actually enter a sleep state.
e9b3aba887f47f drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-17  592   *	@pm_state: ignored
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  593   *
50ad147aa09c82 drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-24  594   *	Flush caches and go to sleep. For STR we have to call arch-specific
50ad147aa09c82 drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-24  595   *	assembly, which in turn call acpi_enter_sleep_state().
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  596   *	It's unfortunate, but it works. Please fix if you're feeling frisky.
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  597   */
2c6e33c366bff2 drivers/acpi/sleep/main.c Len Brown             2008-04-23  598  static int acpi_suspend_enter(suspend_state_t pm_state)
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  599  {
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  600  	acpi_status status = AE_OK;
e9b3aba887f47f drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-17  601  	u32 acpi_state = acpi_target_sleep_state;
979f11b060c0b3 drivers/acpi/sleep.c      Rafael J. Wysocki     2011-02-08  602  	int error;
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  603  
bb3632c6101b2f drivers/acpi/sleep.c      Todd E Brandt         2014-06-06  604  	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, true);
e9b3aba887f47f drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-17  605  	switch (acpi_state) {
e9b3aba887f47f drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-17  606  	case ACPI_STATE_S1:
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  607  		barrier();
3f6f49c7854c92 drivers/acpi/sleep.c      Len Brown             2012-07-26  608  		status = acpi_enter_sleep_state(acpi_state);
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  609  		break;
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  610  
e9b3aba887f47f drivers/acpi/sleep/main.c Rafael J. Wysocki     2007-07-17  611  	case ACPI_STATE_S3:
d6a77ead21b69c drivers/acpi/sleep.c      Konrad Rzeszutek Wilk 2013-05-14  612  		if (!acpi_suspend_lowlevel)
d6a77ead21b69c drivers/acpi/sleep.c      Konrad Rzeszutek Wilk 2013-05-14  613  			return -ENOSYS;
f1a2003e22f6b5 drivers/acpi/sleep.c      Rafael J. Wysocki     2011-02-08  614  		error = acpi_suspend_lowlevel();
979f11b060c0b3 drivers/acpi/sleep.c      Rafael J. Wysocki     2011-02-08  615  		if (error)
979f11b060c0b3 drivers/acpi/sleep.c      Rafael J. Wysocki     2011-02-08  616  			return error;
f5ee87df7a4dab drivers/acpi/sleep.c      Hanjun Guo            2021-06-02  617  		pr_info("Low-level resume complete\n");
ef25ba04760159 drivers/acpi/sleep.c      Rafael J. Wysocki     2015-10-07  618  		pm_set_resume_via_firmware();
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  619  		break;
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  620  	}
bb3632c6101b2f drivers/acpi/sleep.c      Todd E Brandt         2014-06-06  621  	trace_suspend_resume(TPS("acpi_suspend"), acpi_state, false);
872d83d00f6702 drivers/acpi/sleep/main.c Arnaud Patard         2006-04-27  622  
b6dacf63e9fb2e drivers/acpi/sleep.c      Matthew Garrett       2010-05-11  623  	/* This violates the spec but is required for bug compatibility. */
50ffba1bd3120b drivers/acpi/sleep.c      Bob Moore             2009-02-23  624  	acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
65df78473ffbf3 drivers/acpi/sleep/main.c Rafael J. Wysocki     2008-11-26  625  
3f6f49c7854c92 drivers/acpi/sleep.c      Len Brown             2012-07-26  626  	/* Reprogram control registers */
3f6f49c7854c92 drivers/acpi/sleep.c      Len Brown             2012-07-26  627  	acpi_leave_sleep_state_prep(acpi_state);
c95d47a868f35c drivers/acpi/sleep/main.c Rafael J. Wysocki     2008-01-08  628  
81320b20cf47de drivers/acpi/sleep.c      Baorui.Liu            2026-09-22  629  	/*
81320b20cf47de drivers/acpi/sleep.c      Baorui.Liu            2026-09-22  630  	 * ACPI 3.0 (P62): OSPM should clear the fixed power-button status bit
81320b20cf47de drivers/acpi/sleep.c      Baorui.Liu            2026-09-22  631  	 * so the event does not reach userspace as KEY_POWER. Remember that a
81320b20cf47de drivers/acpi/sleep.c      Baorui.Liu            2026-09-22  632  	 * power-button wake occurred so button resume can report KEY_WAKEUP
81320b20cf47de drivers/acpi/sleep.c      Baorui.Liu            2026-09-22  633  	 * and acpi_pm_finish() can emit a PM wakeup event.
872d83d00f6702 drivers/acpi/sleep/main.c Arnaud Patard         2006-04-27  634  	 */
c10d7a13846bff drivers/acpi/sleep.c      Daniel Drake          2012-05-10  635  	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) {
51468a9d3a8024 drivers/acpi/sleep.c      Al Stone              2013-11-20  636  		acpi_event_status pwr_btn_status = ACPI_EVENT_FLAG_DISABLED;
c10d7a13846bff drivers/acpi/sleep.c      Daniel Drake          2012-05-10  637  
c10d7a13846bff drivers/acpi/sleep.c      Daniel Drake          2012-05-10  638  		acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status);
c10d7a13846bff drivers/acpi/sleep.c      Daniel Drake          2012-05-10  639  
18864cc4892d20 drivers/acpi/sleep.c      Lv Zheng              2016-08-04  640  		if (pwr_btn_status & ACPI_EVENT_FLAG_STATUS_SET) {
872d83d00f6702 drivers/acpi/sleep/main.c Arnaud Patard         2006-04-27  641  			acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
c10d7a13846bff drivers/acpi/sleep.c      Daniel Drake          2012-05-10  642  			pwr_btn_event_pending = true;
81320b20cf47de drivers/acpi/sleep.c      Baorui.Liu            2026-09-22 @643  			acpi_button_power_wakeup_pending();
c10d7a13846bff drivers/acpi/sleep.c      Daniel Drake          2012-05-10  644  		}
c10d7a13846bff drivers/acpi/sleep.c      Daniel Drake          2012-05-10  645  	}
872d83d00f6702 drivers/acpi/sleep/main.c Arnaud Patard         2006-04-27  646  
a3627f67b1d5dd drivers/acpi/sleep/main.c Shaohua Li            2007-06-20  647  	/*
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  648  	 * Disable all GPE and clear their status bits before interrupts are
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  649  	 * enabled. Some GPEs (like wakeup GPEs) have no handlers and this can
a508939e15356d drivers/acpi/sleep.c      Chu Guangqing         2025-11-25  650  	 * prevent them from producing spurious interrupts.
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  651  	 *
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  652  	 * acpi_leave_sleep_state() will reenable specific GPEs later.
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  653  	 *
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  654  	 * Because this code runs on one CPU with disabled interrupts (all of
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  655  	 * the other CPUs are offline at this time), it need not acquire any
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  656  	 * sleeping locks which may trigger an implicit preemption point even
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  657  	 * if there is no contention, so avoid doing that by using a low-level
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  658  	 * library routine here.
a3627f67b1d5dd drivers/acpi/sleep/main.c Shaohua Li            2007-06-20  659  	 */
22db06337f590d drivers/acpi/sleep.c      Rafael J. Wysocki     2023-06-14  660  	acpi_hw_disable_all_gpes();
d5a64513c6a171 drivers/acpi/sleep.c      Rafael J. Wysocki     2010-04-09  661  	/* Allow EC transactions to happen. */
c2b46d679b30c5 drivers/acpi/sleep.c      Lv Zheng              2016-08-03  662  	acpi_ec_unblock_transactions();
a3627f67b1d5dd drivers/acpi/sleep/main.c Shaohua Li            2007-06-20  663  
2a6b69765ad794 drivers/acpi/sleep.c      Matthew Garrett       2010-05-28  664  	suspend_nvs_restore();
2a6b69765ad794 drivers/acpi/sleep.c      Matthew Garrett       2010-05-28  665  
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  666  	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  667  }
^1da177e4c3f41 drivers/acpi/sleep/main.c Linus Torvalds        2005-04-16  668  

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-29  2:52 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-29  2:52 [PATCH v4] ACPI: button: Report wakeup key only for power button wakeups kernel test robot
  -- strict thread matches above, loose matches on Subject: below --
2026-09-17 14:31 [PATCH v3] " Baorui.Liu
2026-09-22  2:42 ` [PATCH v4] " Baorui.Liu

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.