diff mbox series

[V4] acpi: trigger wakeup key event from power button

Message ID 20230913002145.743571-1-Ken.Xue@amd.com (mailing list archive)
State Superseded, archived
Headers show
Series [V4] acpi: trigger wakeup key event from power button | expand

Commit Message

Ken Xue Sept. 13, 2023, 12:21 a.m. UTC
Andorid can wakeup from various wakeup sources, but only several wakeup
sources can wake up screen with right events(POWER, WAKEUP) from input
device.

Regarding pressing acpi power button, it can resume system and
ACPI_BITMASK_WAKE_STATUS and ACPI_BITMASK_POWER_BUTTON_STATUS are set in
pm1a_sts, but kernel does not report any key event to user space during
resuming by default.

So, send wakeup key event to user space during resuming from power button.

Signed-off-by: Ken Xue <Ken.Xue@amd.com>

---
V1->V2: fix some compile warning/error caused by lack of
        "struct acpi_device" declaration by including acpi.h.
V2->V3: use "forward declaration" to fix compile warning/error.
V3->V4: refine coding style and commit message

 drivers/acpi/button.c | 17 +++++++++++++++++
 drivers/acpi/sleep.c  |  5 +++++
 include/acpi/button.h |  4 ++++
 3 files changed, 26 insertions(+)


base-commit: b483d3b8a54a544ab8854ca6dbb8d99c423b3ba4

Comments

Andy Shevchenko Sept. 13, 2023, 11:25 a.m. UTC | #1
On Wed, Sep 13, 2023 at 08:21:46AM +0800, Ken Xue wrote:
> Andorid can wakeup from various wakeup sources, but only several wakeup
> sources can wake up screen with right events(POWER, WAKEUP) from input
> device.
> 
> Regarding pressing acpi power button, it can resume system and
> ACPI_BITMASK_WAKE_STATUS and ACPI_BITMASK_POWER_BUTTON_STATUS are set in
> pm1a_sts, but kernel does not report any key event to user space during
> resuming by default.
> 
> So, send wakeup key event to user space during resuming from power button.

LGTM from code perspective, FWIW,
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
assuming that maintainers will check the code from functional perspective.
kernel test robot Sept. 14, 2023, 9:58 p.m. UTC | #2
Hi Ken,

kernel test robot noticed the following build errors:

[auto build test ERROR on b483d3b8a54a544ab8854ca6dbb8d99c423b3ba4]

url:    https://github.com/intel-lab-lkp/linux/commits/Ken-Xue/acpi-trigger-wakeup-key-event-from-power-button/20230913-084852
base:   b483d3b8a54a544ab8854ca6dbb8d99c423b3ba4
patch link:    https://lore.kernel.org/r/20230913002145.743571-1-Ken.Xue%40amd.com
patch subject: [PATCH V4] acpi: trigger wakeup key event from power button
config: loongarch-randconfig-001-20230914 (https://download.01.org/0day-ci/archive/20230915/202309150547.0dolJMlI-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230915/202309150547.0dolJMlI-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/oe-kbuild-all/202309150547.0dolJMlI-lkp@intel.com/

All errors (new ones prefixed by >>):

   loongarch64-linux-ld: drivers/acpi/sleep.o: in function `acpi_pm_finish':
>> drivers/acpi/sleep.c:514:(.text+0x29c): undefined reference to `acpi_power_button_wakeup'


vim +514 drivers/acpi/sleep.c

   472	
   473	/**
   474	 *	acpi_pm_finish - Instruct the platform to leave a sleep state.
   475	 *
   476	 *	This is called after we wake back up (or if entering the sleep state
   477	 *	failed).
   478	 */
   479	static void acpi_pm_finish(void)
   480	{
   481		struct acpi_device *pwr_btn_adev;
   482		u32 acpi_state = acpi_target_sleep_state;
   483	
   484		acpi_ec_unblock_transactions();
   485		suspend_nvs_free();
   486	
   487		if (acpi_state == ACPI_STATE_S0)
   488			return;
   489	
   490		pr_info("Waking up from system sleep state S%d\n", acpi_state);
   491		acpi_disable_wakeup_devices(acpi_state);
   492		acpi_leave_sleep_state(acpi_state);
   493	
   494		/* reset firmware waking vector */
   495		acpi_set_waking_vector(0);
   496	
   497		acpi_target_sleep_state = ACPI_STATE_S0;
   498	
   499		acpi_resume_power_resources();
   500	
   501		/* If we were woken with the fixed power button, provide a small
   502		 * hint to userspace in the form of a wakeup event on the fixed power
   503		 * button device (if it can be found).
   504		 *
   505		 * We delay the event generation til now, as the PM layer requires
   506		 * timekeeping to be running before we generate events. */
   507		if (!pwr_btn_event_pending)
   508			return;
   509	
   510		pwr_btn_event_pending = false;
   511		pwr_btn_adev = acpi_dev_get_first_match_dev(ACPI_BUTTON_HID_POWERF,
   512							    NULL, -1);
   513		if (pwr_btn_adev) {
 > 514			acpi_power_button_wakeup(pwr_btn_adev);
   515			pm_wakeup_event(&pwr_btn_adev->dev, 0);
   516			acpi_dev_put(pwr_btn_adev);
   517		}
   518	}
   519
kernel test robot Sept. 15, 2023, 2:12 a.m. UTC | #3
Hi Ken,

kernel test robot noticed the following build errors:

[auto build test ERROR on b483d3b8a54a544ab8854ca6dbb8d99c423b3ba4]

url:    https://github.com/intel-lab-lkp/linux/commits/Ken-Xue/acpi-trigger-wakeup-key-event-from-power-button/20230913-084852
base:   b483d3b8a54a544ab8854ca6dbb8d99c423b3ba4
patch link:    https://lore.kernel.org/r/20230913002145.743571-1-Ken.Xue%40amd.com
patch subject: [PATCH V4] acpi: trigger wakeup key event from power button
config: i386-debian-10.3 (https://download.01.org/0day-ci/archive/20230915/202309150947.YLjvs2Vv-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230915/202309150947.YLjvs2Vv-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/oe-kbuild-all/202309150947.YLjvs2Vv-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/acpi/sleep.o: in function `acpi_pm_finish':
>> drivers/acpi/sleep.c:514: undefined reference to `acpi_power_button_wakeup'


vim +514 drivers/acpi/sleep.c

   472	
   473	/**
   474	 *	acpi_pm_finish - Instruct the platform to leave a sleep state.
   475	 *
   476	 *	This is called after we wake back up (or if entering the sleep state
   477	 *	failed).
   478	 */
   479	static void acpi_pm_finish(void)
   480	{
   481		struct acpi_device *pwr_btn_adev;
   482		u32 acpi_state = acpi_target_sleep_state;
   483	
   484		acpi_ec_unblock_transactions();
   485		suspend_nvs_free();
   486	
   487		if (acpi_state == ACPI_STATE_S0)
   488			return;
   489	
   490		pr_info("Waking up from system sleep state S%d\n", acpi_state);
   491		acpi_disable_wakeup_devices(acpi_state);
   492		acpi_leave_sleep_state(acpi_state);
   493	
   494		/* reset firmware waking vector */
   495		acpi_set_waking_vector(0);
   496	
   497		acpi_target_sleep_state = ACPI_STATE_S0;
   498	
   499		acpi_resume_power_resources();
   500	
   501		/* If we were woken with the fixed power button, provide a small
   502		 * hint to userspace in the form of a wakeup event on the fixed power
   503		 * button device (if it can be found).
   504		 *
   505		 * We delay the event generation til now, as the PM layer requires
   506		 * timekeeping to be running before we generate events. */
   507		if (!pwr_btn_event_pending)
   508			return;
   509	
   510		pwr_btn_event_pending = false;
   511		pwr_btn_adev = acpi_dev_get_first_match_dev(ACPI_BUTTON_HID_POWERF,
   512							    NULL, -1);
   513		if (pwr_btn_adev) {
 > 514			acpi_power_button_wakeup(pwr_btn_adev);
   515			pm_wakeup_event(&pwr_btn_adev->dev, 0);
   516			acpi_dev_put(pwr_btn_adev);
   517		}
   518	}
   519
diff mbox series

Patch

diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 1e76a64cce0a..3baddecd66c6 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -363,6 +363,22 @@  static int acpi_button_remove_fs(struct acpi_device *device)
 	return 0;
 }
 
+void acpi_power_button_wakeup(struct acpi_device *dev)
+{
+	struct acpi_button *button = acpi_driver_data(dev);
+	struct input_dev *input;
+
+	if (button->type != ACPI_BUTTON_TYPE_POWER)
+		return;
+
+	input = button->input;
+	input_report_key(input, KEY_WAKEUP, 1);
+	input_sync(input);
+	input_report_key(input, KEY_WAKEUP, 0);
+	input_sync(input);
+}
+EXPORT_SYMBOL(acpi_power_button_wakeup);
+
 /* Driver Interface */
 int acpi_lid_open(void)
 {
@@ -579,6 +595,7 @@  static int acpi_button_add(struct acpi_device *device)
 	switch (button->type) {
 	case ACPI_BUTTON_TYPE_POWER:
 		input_set_capability(input, EV_KEY, KEY_POWER);
+		input_set_capability(input, EV_KEY, KEY_WAKEUP);
 		break;
 
 	case ACPI_BUTTON_TYPE_SLEEP:
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 808484d11209..f816606abd71 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -20,9 +20,13 @@ 
 #include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/syscore_ops.h>
+
 #include <asm/io.h>
+
 #include <trace/events/power.h>
 
+#include <acpi/button.h>
+
 #include "internal.h"
 #include "sleep.h"
 
@@ -507,6 +511,7 @@  static void acpi_pm_finish(void)
 	pwr_btn_adev = acpi_dev_get_first_match_dev(ACPI_BUTTON_HID_POWERF,
 						    NULL, -1);
 	if (pwr_btn_adev) {
+		acpi_power_button_wakeup(pwr_btn_adev);
 		pm_wakeup_event(&pwr_btn_adev->dev, 0);
 		acpi_dev_put(pwr_btn_adev);
 	}
diff --git a/include/acpi/button.h b/include/acpi/button.h
index af2fce5d2ee3..6126d665aa42 100644
--- a/include/acpi/button.h
+++ b/include/acpi/button.h
@@ -2,17 +2,21 @@ 
 #ifndef ACPI_BUTTON_H
 #define ACPI_BUTTON_H
 
+struct acpi_device;
+
 #define ACPI_BUTTON_HID_POWER	"PNP0C0C"
 #define ACPI_BUTTON_HID_LID	"PNP0C0D"
 #define ACPI_BUTTON_HID_SLEEP	"PNP0C0E"
 
 #if IS_ENABLED(CONFIG_ACPI_BUTTON)
 extern int acpi_lid_open(void);
+extern void acpi_power_button_wakeup(struct acpi_device *dev);
 #else
 static inline int acpi_lid_open(void)
 {
 	return 1;
 }
+static inline void acpi_power_button_wakeup(struct acpi_device *dev) {}
 #endif /* IS_ENABLED(CONFIG_ACPI_BUTTON) */
 
 #endif /* ACPI_BUTTON_H */