Skip to contentSkip to conversation

ACPI: sleep: mechanism to query wakeup reasons

RFC PATCH In review Lv Zheng 2 participants 5 messages Dec 14, 2017 – Dec 15, 2017

Subsystems (2)
lore
Share & tools
lore

Lv Zheng

author
#0 lore raw

cover ACPI: sleep: mechanism to query wakeup reasons

This patchset adds a mechanism to query wakeup reasons (fixed events and GPEs).

Chen Yu (1):
ACPICA: Add new API to query wakeup reasons

Lv Zheng (2):
ACPI: Add GPE number in wakeup device list
ACPI: Add wakeup reason support

 drivers/acpi/acpica/acevents.h  |   2 +
 drivers/acpi/acpica/acglobal.h  |   1 +
 drivers/acpi/acpica/achware.h   |   4 ++
 drivers/acpi/acpica/aclocal.h   |   1 +
 drivers/acpi/acpica/evevent.c   |  25 ++++++++++
 drivers/acpi/acpica/hwgpe.c     | 102 ++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/acpica/hwsleep.c   |  38 +++++++++++++++
 drivers/acpi/acpica/hwxfsleep.c |  23 +++++++++
 drivers/acpi/proc.c             |   7 +--
 drivers/acpi/sleep.c            |   3 ++
 include/acpi/acpixf.h           |   1 +
 11 files changed, 204 insertions(+), 3 deletions(-)
Signature · 1 line
2.7.4
author
#1 lore raw

RFC PATCH 1/3 ACPICA: Add new API to query wakeup reasons

From: Chen Yu <[email protected]>

This patch adds a new API to be invoked right after resuming to query wakeup reasons.

---
 drivers/acpi/acpica/acevents.h  |   2 +
 drivers/acpi/acpica/acglobal.h  |   1 +
 drivers/acpi/acpica/achware.h   |   4 ++
 drivers/acpi/acpica/aclocal.h   |   1 +
 drivers/acpi/acpica/evevent.c   |  25 ++++++++++
 drivers/acpi/acpica/hwgpe.c     | 102 ++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/acpica/hwsleep.c   |  38 +++++++++++++++
 drivers/acpi/acpica/hwxfsleep.c |  23 +++++++++
 drivers/acpi/sleep.c            |   1 +
 include/acpi/acpixf.h           |   1 +
 10 files changed, 198 insertions(+)
drivers/acpi/acpica/acevents.h +2 -0
index a2adfd4..007f877 100644
@@ -53,6 +53,8 @@ acpi_status acpi_ev_install_xrupt_handlers(void);
 
 u32 acpi_ev_fixed_event_detect(void);
 
+void acpi_ev_save_wokenup_fixed_events(u8 save_flags);
+
 /*
  * evmisc
  */
drivers/acpi/acpica/acglobal.h +1 -0
index 95eed44..cefa574 100644
@@ -272,6 +272,7 @@ ACPI_GLOBAL(acpi_gbl_event_handler, acpi_gbl_global_event_handler);
 ACPI_GLOBAL(void *, acpi_gbl_global_event_handler_context);
 ACPI_GLOBAL(struct acpi_fixed_event_handler,
 	    acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]);
+ACPI_GLOBAL(u32, acpi_gbl_wokenup_fixed_events);
 
 extern struct acpi_fixed_event_info
     acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS];
drivers/acpi/acpica/achware.h +4 -0
index cd722d8..b209c23 100644
@@ -89,6 +89,8 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state);
 
 acpi_status acpi_hw_legacy_wake(u8 sleep_state);
 
+void acpi_hw_detect_wakeup_events(u8 is_wakeup);
+
 /*
  * hwesleep - sleep/wake support (Extended FADT-V5 sleep registers)
  */
@@ -140,6 +142,8 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 				 struct acpi_gpe_block_info *gpe_block,
 				 void *context);
 
+acpi_status acpi_hw_save_wokenup_gpes(u8 save_flags);
+
 /*
  * hwpci - PCI configuration support
  */
drivers/acpi/acpica/aclocal.h +1 -0
index a56675f..ff1ed01 100644
@@ -498,6 +498,7 @@ struct acpi_gpe_register_info {
 	u8 enable_for_run;	/* GPEs to keep enabled when running */
 	u8 mask_for_run;	/* GPEs to keep masked when running */
 	u8 enable_mask;		/* Current mask of enabled GPEs */
+	u8 wokenup;		/* GPEs flagged for the last resume */
 };
 
 /*
drivers/acpi/acpica/evevent.c +25 -0
index d3b6b31..70e0459 100644
@@ -294,4 +294,29 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
 		 handler) (acpi_gbl_fixed_event_handlers[event].context));
 }
 
+void acpi_ev_save_wokenup_fixed_events(u8 save_flags)
+{
+	u32 fixed_status;
+	u32 fixed_enable;
+
+	ACPI_FUNCTION_NAME(ev_save_wokenup_fixed_events);
+
+	/*
+	 * Read the fixed feature status and enable registers, as all the cases
+	 * depend on their values. Ignore errors here.
+	 */
+	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
+	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+			  "Wakeup Fixed Event Block: Enable %08X Status %08X\n",
+			  fixed_enable, fixed_status));
+
+	if (save_flags) {
+		acpi_gbl_wokenup_fixed_events = (fixed_status & fixed_enable);
+	} else {
+		acpi_gbl_wokenup_fixed_events = 0;
+	}
+}
+
 #endif				/* !ACPI_REDUCED_HARDWARE */
drivers/acpi/acpica/hwgpe.c +102 -0

112 lines not on this page · raw message

drivers/acpi/acpica/hwsleep.c +38 -0
index 1fe7387..4186b83 100644
@@ -44,6 +44,7 @@
 
 #include <acpi/acpi.h>
 #include "accommon.h"
+#include "acevents.h"
 
 #define _COMPONENT          ACPI_HARDWARE
 ACPI_MODULE_NAME("hwsleep")
@@ -51,6 +52,31 @@ ACPI_MODULE_NAME("hwsleep")
 #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_hw_detect_wakeup_events
+ *
+ * PARAMETERS:  is_wakeup           - Whether system is being woken up
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Check the status of the platform wakeup events (GPEs or
+ *              fixed events). This can be invoked right before suspending or
+ *              right after resuming.
+ *
+ ******************************************************************************/
+void acpi_hw_detect_wakeup_events(u8 is_wakeup)
+{
+
+	ACPI_FUNCTION_NAME(hw_detect_wakeup_events);
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+			  "Detecting wakup GPEs/Events %s",
+			  is_wakeup ? "after resuming" : "before suspending"));
+	(void)acpi_hw_save_wokenup_gpes(is_wakeup);
+	(void)acpi_ev_save_wokenup_fixed_events(is_wakeup);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_hw_legacy_sleep
  *
  * PARAMETERS:  sleep_state         - Which sleep state to enter
@@ -61,6 +87,7 @@ ACPI_MODULE_NAME("hwsleep")
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
+
 acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
 {
 	struct acpi_bit_register_info *sleep_type_reg_info;
@@ -159,6 +186,10 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
 		return_ACPI_STATUS(status);
 	}
 
+	/* Debugging purpose: record wakeup events before sleeping */
+
+	acpi_hw_detect_wakeup_events(FALSE);
+
 	/* Write #2: Write both SLP_TYP + SLP_EN */
 
 	status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
@@ -199,6 +230,13 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
 
 	} while (!in_value);
 
+	/*
+	 * This may not be reached, as OSPM should have chosen to jump back
+	 * from FACS waking vector to a different point. Normally, where
+	 * acpi_enter_sleep_state() is invoked.
+	 */
+	acpi_hw_detect_wakeup_events(TRUE);
+
 	return_ACPI_STATUS(AE_OK);
 }
 
drivers/acpi/acpica/hwxfsleep.c +23 -0
index e5c095c..baa7028 100644
@@ -452,3 +452,26 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
 }
 
 ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_detect_waekup_reasons
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Save platform wakeup reasons (flagged GPEs/fixed_events) right
+ *              after resuming.
+ *
+ ******************************************************************************/
+void acpi_detect_wakeup_reasons(void)
+{
+
+	ACPI_FUNCTION_TRACE(acpi_detect_wakeup_reasons);
+
+	acpi_hw_detect_wakeup_events(TRUE);
+	return_VOID;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_detect_wakeup_reasons)
drivers/acpi/sleep.c +1 -0
index 15cd862..7c70c3c 100644
@@ -582,6 +582,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
 		if (error)
 			return error;
 		pr_info(PREFIX "Low-level resume complete\n");
+		acpi_detect_wakeup_reasons();
 		pm_set_resume_via_firmware();
 		break;
 	}
include/acpi/acpixf.h +1 -0
index e02610a..c514edd 100644
@@ -891,6 +891,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
 				acpi_set_firmware_waking_vector
 				(acpi_physical_address physical_address,
 				 acpi_physical_address physical_address64))
+ACPI_EXTERNAL_RETURN_VOID(void acpi_detect_wakeup_reasons(void))
 /*
  * ACPI Timer interfaces
  */
Signature · 1 line
2.7.4
author
#2 lore raw

RFC PATCH 2/3 ACPI: Add GPE number in wakeup device list

In reply to Lv Zheng

This patch adds GPE wakeup number in /proc/acpi/wakeup.

---
 drivers/acpi/proc.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/acpi/proc.c +4 -3
index 652f19e..32fdec4 100644
@@ -24,7 +24,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 {
 	struct list_head *node, *next;
 
-	seq_printf(seq, "Device\tS-state\t  Status   Sysfs node\n");
+	seq_printf(seq, "Device\tS-state\tGPE\t  Status   Sysfs node\n");
 
 	mutex_lock(&acpi_device_lock);
 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
@@ -35,9 +35,10 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 		if (!dev->wakeup.flags.valid)
 			continue;
 
-		seq_printf(seq, "%s\t  S%d\t",
+		seq_printf(seq, "%s\t  S%d\t%02x\t",
 			   dev->pnp.bus_id,
-			   (u32) dev->wakeup.sleep_state);
+			   (u32) dev->wakeup.sleep_state,
+			   (u8) dev->wakeup.gpe_number);
 
 		mutex_lock(&dev->physical_node_lock);
 
Signature · 1 line
2.7.4
author
#3 lore raw

RFC PATCH 3/3 ACPI: Add wakeup reason support

In reply to Lv Zheng

This patch adds kernel side invocation of wakeup reason detection mechanism.

---
 drivers/acpi/sleep.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/acpi/sleep.c +2 -0
index 7c70c3c..9b245a6 100644
@@ -963,6 +963,8 @@ static int acpi_s2idle_prepare(void)
 	}
 	if (acpi_sci_irq_valid())
 		enable_irq_wake(acpi_sci_irq);
+	pr_info(PREFIX "Low-level suspend completed\n");
+	acpi_detect_wakeup_reasons();
 
 	return 0;
 }
Signature · 1 line
2.7.4