Skip to contentSkip to conversation

ACPICA: Implicit notify support

PATCH In review Lin Ming 2 participants 2 messages Dec 13, 2010 – Jan 3, 2011

Subsystems (2)
lore
Share & tools
lore

Lin Ming

author
#0 lore raw

PATCH v2 6/8 ACPICA: Implicit notify support

This feature provides an automatic device notification for wake devices when a wakeup GPE occurs and there is no corresponding GPE method or handler. Rather than ignoring such a GPE, an implicit AML Notify operation is performed on the parent device object.
This feature is not part of the ACPI specification and is provided for Windows compatibility only.

---
 drivers/acpi/acpica/acevents.h  |    2 +
 drivers/acpi/acpica/aclocal.h   |    1 +
 drivers/acpi/acpica/evgpe.c     |  172 +++++++++++++++++++++++----------------
 drivers/acpi/acpica/evgpeblk.c  |   11 ++-
 drivers/acpi/acpica/evgpeinit.c |    1 +
 drivers/acpi/acpica/evxfgpe.c   |   58 +++++++++++---
 drivers/acpi/scan.c             |    3 +-
 include/acpi/acpixf.h           |    6 +-
 include/acpi/actypes.h          |   37 +++++----
 9 files changed, 186 insertions(+), 105 deletions(-)
drivers/acpi/acpica/acevents.h +2 -0
index 04a83fe..70e0b28 100644
@@ -91,6 +91,8 @@ struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
 						     struct acpi_gpe_block_info
 						     *gpe_block);
 
+acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info);
+
 /*
  * evgpeblk - Upper-level GPE block support
  */
drivers/acpi/acpica/aclocal.h +1 -0
index 6a71f8e..74000f5 100644
@@ -419,6 +419,7 @@ struct acpi_gpe_handler_info {
 union acpi_gpe_dispatch_info {
 	struct acpi_namespace_node *method_node;	/* Method node for this GPE level */
 	struct acpi_gpe_handler_info *handler;  /* Installed GPE handler */
+	struct acpi_namespace_node *device_node;        /* Parent _PRW device for implicit notify */
 };
 
 /*
drivers/acpi/acpica/evgpe.c +100 -72

251 lines not on this page · raw message

drivers/acpi/acpica/evgpeblk.c +8 -3
index 2a445df..e2e8164 100644
@@ -472,9 +472,14 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
 			gpe_event_info = &gpe_block->event_info[gpe_index];
 
-			/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
-
-			if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
+			/*
+			 * Ignore GPEs that have no corresponding _Lxx/_Exx method
+			 * and GPEs that are used to wake the system
+			 */
+			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+			     ACPI_GPE_DISPATCH_NONE)
+			    || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
+				== ACPI_GPE_DISPATCH_HANDLER)
 			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
 				continue;
 			}
drivers/acpi/acpica/evgpeinit.c +1 -0
index 2c7def9..223dba2 100644
@@ -412,6 +412,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
 	 * Add the GPE information from above to the gpe_event_info block for
 	 * use during dispatch of this GPE.
 	 */
+	gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);
 	gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
 	gpe_event_info->dispatch.method_node = method_node;
 
drivers/acpi/acpica/evxfgpe.c +47 -11

86 lines not on this page · raw message

drivers/acpi/scan.c +2 -1
index afdbd6e..8d77cf5 100644
@@ -750,7 +750,8 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
 		device->wakeup.resources.handles[i] = element->reference.handle;
 	}
 
-	acpi_setup_gpe_for_wake(device->wakeup.gpe_device, device->wakeup.gpe_number);
+	acpi_setup_gpe_for_wake(device->wakeup.gpe_device, NULL,
+		device->wakeup.gpe_number);
 
 	return AE_OK;
 }
include/acpi/acpixf.h +4 -2
index b806e56..9de6a17 100644
@@ -292,10 +292,12 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number);
 
 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number);
 
-acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number);
-
 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number);
 
+acpi_status
+acpi_setup_gpe_for_wake(acpi_handle parent_device,
+			acpi_handle gpe_device, u32 gpe_number);
+
 acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action);
 
 acpi_status
include/acpi/actypes.h +21 -16
index b9575ad..d7274ee 100644
@@ -664,25 +664,26 @@ typedef u32 acpi_event_status;
 
 /*
  * GPE info flags - Per GPE
- * +-------+---+-+-+
- * |  7:4  |3:2|1|0|
- * +-------+---+-+-+
- *     |     |  | |
- *     |     |  | +--- Interrupt type: edge or level triggered
- *     |     |  +----- GPE can wake the system
- *     |     +-------- Type of dispatch:to method, handler, or none
- *     +-------------- <Reserved>
+ * +-------+-+-+---+
+ * |  7:4  |3|2|1:0|
+ * +-------+-+-+---+
+ *     |    | |  |
+ *     |    | |  +-- Type of dispatch:to method, handler, notify, or none
+ *     |    | +----- Interrupt type: edge or level triggered
+ *     |    +------- Is a Wake GPE
+ *     +------------ <Reserved>
  */
-#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
-#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x01
-#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
+#define ACPI_GPE_DISPATCH_NONE          (u8) 0x00
+#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x01
+#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x02
+#define ACPI_GPE_DISPATCH_NOTIFY        (u8) 0x03
+#define ACPI_GPE_DISPATCH_MASK          (u8) 0x03
 
-#define ACPI_GPE_CAN_WAKE		(u8) 0x02
+#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x04
+#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
+#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x04
 
-#define ACPI_GPE_DISPATCH_MASK          (u8) 0x0C
-#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x04
-#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x08
-#define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00
+#define ACPI_GPE_CAN_WAKE               (u8) 0x08
 
 /*
  * Flags for GPE and Lock interfaces
@@ -954,6 +955,10 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
 #define ACPI_INTERRUPT_NOT_HANDLED      0x00
 #define ACPI_INTERRUPT_HANDLED          0x01
 
+/* GPE handler return values */
+
+#define ACPI_REENABLE_GPE               0x80
+
 /* Length of 32-bit EISAID values when converted back to a string */
 
 #define ACPI_EISAID_STRING_SIZE         8	/* Includes null terminator */
Signature · 1 line
1.5.3
#1 lore raw
Quoted 8 lines · Lin Ming

This feature provides an automatic device notification for wake devices when a wakeup GPE occurs and there is no corresponding GPE method or handler. Rather than ignoring such a GPE, an implicit AML Notify operation is performed on the parent device object.
This feature is not part of the ACPI specification and is provided for Windows compatibility only.

Unfortunately, this patch contains a bug:

drivers/acpi/scan.c acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, · line 754

Quoted 11 lines
drivers/acpi/scan.c +2 -1
index afdbd6e..8d77cf5 100644
@@ -750,7 +750,8 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
 		device->wakeup.resources.handles[i] = element->reference.handle;
 	}
 
-	acpi_setup_gpe_for_wake(device->wakeup.gpe_device, device->wakeup.gpe_number);
+	acpi_setup_gpe_for_wake(device->wakeup.gpe_device, NULL,
+		device->wakeup.gpe_number);

because this change makes acpi_setup_gpe_for_wake() return with error code (the first argument here should be device->handle and the second one should be device->wakeup.gpe_device instead of NULL).

Appended is a rebased and fixed replacement of this patch (it also contains a missing change in ec.c).

Thanks,
Rafael

---
From: Lin Ming <[email protected]>
Subject: ACPICA: Implicit notify support (v2)

This feature provides an automatic device notification for wake devices when a wakeup GPE occurs and there is no corresponding GPE method or handler. Rather than ignoring such a GPE, an implicit AML Notify operation is performed on the parent device object.
This feature is not part of the ACPI specification and is provided for Windows compatibility only.

---
 drivers/acpi/acpica/acevents.h  |    2 
 drivers/acpi/acpica/aclocal.h   |    1 
 drivers/acpi/acpica/evgpe.c     |  172 +++++++++++++++++++++++-----------------
 drivers/acpi/acpica/evgpeblk.c  |   11 +-
 drivers/acpi/acpica/evgpeinit.c |    1 
 drivers/acpi/acpica/evxfgpe.c   |   58 ++++++++++---
 drivers/acpi/ec.c               |    2 
 drivers/acpi/scan.c             |    2 
 include/acpi/acpixf.h           |    6 -
 include/acpi/actypes.h          |   39 +++++----
 10 files changed, 187 insertions(+), 107 deletions(-)
drivers/acpi/acpica/acevents.h +2 -0
Index: linux-2.6/drivers/acpi/acpica/acevents.h
===================================================================
@@ -91,6 +91,8 @@ struct acpi_gpe_event_info *acpi_ev_low_
 						     struct acpi_gpe_block_info
 						     *gpe_block);
 
+acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info);
+
 /*
  * evgpeblk - Upper-level GPE block support
  */
drivers/acpi/acpica/aclocal.h +1 -0
Index: linux-2.6/drivers/acpi/acpica/aclocal.h
===================================================================
@@ -419,6 +419,7 @@ struct acpi_gpe_handler_info {
 union acpi_gpe_dispatch_info {
 	struct acpi_namespace_node *method_node;	/* Method node for this GPE level */
 	struct acpi_gpe_handler_info *handler;  /* Installed GPE handler */
+	struct acpi_namespace_node *device_node;        /* Parent _PRW device for implicit notify */
 };
 
 /*
drivers/acpi/acpica/evgpe.c +100 -72

251 lines not on this page · raw message

drivers/acpi/acpica/evgpeblk.c +8 -3
Index: linux-2.6/drivers/acpi/acpica/evgpeblk.c
===================================================================
@@ -472,9 +472,14 @@ acpi_ev_initialize_gpe_block(struct acpi
 			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
 			gpe_event_info = &gpe_block->event_info[gpe_index];
 
-			/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
-
-			if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
+			/*
+			 * Ignore GPEs that have no corresponding _Lxx/_Exx method
+			 * and GPEs that are used to wake the system
+			 */
+			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
+			     ACPI_GPE_DISPATCH_NONE)
+			    || ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
+				== ACPI_GPE_DISPATCH_HANDLER)
 			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
 				continue;
 			}
drivers/acpi/acpica/evgpeinit.c +1 -0
Index: linux-2.6/drivers/acpi/acpica/evgpeinit.c
===================================================================
@@ -415,6 +415,7 @@ acpi_ev_match_gpe_method(acpi_handle obj
 	 * Add the GPE information from above to the gpe_event_info block for
 	 * use during dispatch of this GPE.
 	 */
+	gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);
 	gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
 	gpe_event_info->dispatch.method_node = method_node;
 
drivers/acpi/acpica/evxfgpe.c +47 -11

86 lines not on this page · raw message

drivers/acpi/scan.c +1 -1
Index: linux-2.6/drivers/acpi/scan.c
===================================================================
@@ -778,7 +778,7 @@ acpi_bus_extract_wakeup_device_power_pac
 		wakeup->resources.handles[i] = element->reference.handle;
 	}
 
-	acpi_setup_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number);
+	acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number);
 
  out:
 	kfree(buffer.pointer);
include/acpi/acpixf.h +4 -2
Index: linux-2.6/include/acpi/acpixf.h
===================================================================
@@ -292,10 +292,12 @@ acpi_status acpi_enable_gpe(acpi_handle
 
 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number);
 
-acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number);
-
 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number);
 
+acpi_status
+acpi_setup_gpe_for_wake(acpi_handle parent_device,
+			acpi_handle gpe_device, u32 gpe_number);
+
 acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action);
 
 acpi_status
include/acpi/actypes.h +22 -17
Index: linux-2.6/include/acpi/actypes.h
===================================================================
@@ -664,25 +664,26 @@ typedef u32 acpi_event_status;
 
 /*
  * GPE info flags - Per GPE
- * +-------+---+-+-+
- * |  7:4  |3:2|1|0|
- * +-------+---+-+-+
- *     |     |  | |
- *     |     |  | +--- Interrupt type: edge or level triggered
- *     |     |  +----- GPE can wake the system
- *     |     +-------- Type of dispatch:to method, handler, or none
- *     +-------------- <Reserved>
- */
-#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
-#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x01
-#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
+ * +-------+-+-+---+
+ * |  7:4  |3|2|1:0|
+ * +-------+-+-+---+
+ *     |    | |  |
+ *     |    | |  +-- Type of dispatch:to method, handler, notify, or none
+ *     |    | +----- Interrupt type: edge or level triggered
+ *     |    +------- Is a Wake GPE
+ *     +------------ <Reserved>
+ */
+#define ACPI_GPE_DISPATCH_NONE          (u8) 0x00
+#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x01
+#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x02
+#define ACPI_GPE_DISPATCH_NOTIFY        (u8) 0x03
+#define ACPI_GPE_DISPATCH_MASK          (u8) 0x03
 
-#define ACPI_GPE_CAN_WAKE		(u8) 0x02
+#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x04
+#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
+#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x04
 
-#define ACPI_GPE_DISPATCH_MASK          (u8) 0x0C
-#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x04
-#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x08
-#define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00
+#define ACPI_GPE_CAN_WAKE               (u8) 0x08
 
 /*
  * Flags for GPE and Lock interfaces
@@ -954,6 +955,10 @@ u32 (*acpi_interface_handler) (acpi_stri
 #define ACPI_INTERRUPT_NOT_HANDLED      0x00
 #define ACPI_INTERRUPT_HANDLED          0x01
 
+/* GPE handler return values */
+
+#define ACPI_REENABLE_GPE               0x80
+
 /* Length of 32-bit EISAID values when converted back to a string */
 
 #define ACPI_EISAID_STRING_SIZE         8	/* Includes null terminator */
drivers/acpi/ec.c +1 -1
Index: linux-2.6/drivers/acpi/ec.c
===================================================================
@@ -619,7 +619,7 @@ static u32 acpi_ec_gpe_handler(acpi_hand
 		wake_up(&ec->wait);
 		ec_check_sci(ec, acpi_ec_read_status(ec));
 	}
-	return ACPI_INTERRUPT_HANDLED;
+	return (ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE);
 }
 
 /* --------------------------------------------------------------------------