summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Grover <agrover@groveronline.com>2003-03-27 22:10:34 -0800
committerAndy Grover <agrover@groveronline.com>2003-03-27 22:10:34 -0800
commitd162a3eaeea8d139379771cb5245fc66c99ba916 (patch)
tree21fe91bf361e0255bc64997c9bc1fbcdd73b0293
parent50a94a30e2262b8ee9dddc98d69487682172af7a (diff)
ACPI: Interpreter update to 20030328
- Add APIs to add and remove GPE Block devices - Clean up problems with semaphore acquisition from the ISR
-rw-r--r--drivers/acpi/acpi_ksyms.c2
-rw-r--r--drivers/acpi/ec.c4
-rw-r--r--drivers/acpi/events/evgpe.c12
-rw-r--r--drivers/acpi/events/evgpeblk.c182
-rw-r--r--drivers/acpi/events/evmisc.c22
-rw-r--r--drivers/acpi/events/evsci.c8
-rw-r--r--drivers/acpi/events/evxfevnt.c213
-rw-r--r--drivers/acpi/utilities/utdelete.c9
-rw-r--r--drivers/acpi/utilities/utinit.c26
-rw-r--r--include/acpi/acconfig.h2
-rw-r--r--include/acpi/acevents.h13
-rw-r--r--include/acpi/aclocal.h1
-rw-r--r--include/acpi/acpiosxf.h16
-rw-r--r--include/acpi/acpixf.h16
-rw-r--r--include/acpi/actypes.h23
15 files changed, 455 insertions, 94 deletions
diff --git a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c
index 4904f0925dbf..985c34762505 100644
--- a/drivers/acpi/acpi_ksyms.c
+++ b/drivers/acpi/acpi_ksyms.c
@@ -74,6 +74,8 @@ EXPORT_SYMBOL(acpi_install_fixed_event_handler);
EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
EXPORT_SYMBOL(acpi_acquire_global_lock);
EXPORT_SYMBOL(acpi_release_global_lock);
+EXPORT_SYMBOL(acpi_install_gpe_block);
+EXPORT_SYMBOL(acpi_remove_gpe_block);
EXPORT_SYMBOL(acpi_get_current_resources);
EXPORT_SYMBOL(acpi_get_possible_resources);
EXPORT_SYMBOL(acpi_walk_resources);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 63775d68f3d8..cd9dd6d1c89a 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -378,7 +378,7 @@ acpi_ec_gpe_query (
acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
end:
- acpi_enable_gpe(NULL, ec->gpe_bit, 0);
+ acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
}
static void
@@ -391,7 +391,7 @@ acpi_ec_gpe_handler (
if (!ec)
return;
- acpi_disable_gpe(NULL, ec->gpe_bit, 0);
+ acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
acpi_ec_gpe_query, ec);
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index 8f309c75dfc3..d716979df4ab 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -53,8 +53,8 @@
*
* FUNCTION: acpi_ev_get_gpe_event_info
*
- * PARAMETERS: gpe_number - Raw GPE number
- * owning_gpe_block - Block ptr. NULL for GPE0/GPE1
+ * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
+ * gpe_number - Raw GPE number
*
* RETURN: A GPE event_info struct. NULL if not a valid GPE
*
@@ -76,6 +76,9 @@ acpi_ev_get_gpe_event_info (
acpi_native_uint i;
+ ACPI_FUNCTION_NAME ("ev_get_gpe_event_info");
+
+
/* A NULL gpe_block means use the FADT-defined GPE block(s) */
if (!gpe_device) {
@@ -120,7 +123,8 @@ acpi_ev_get_gpe_event_info (
*
* FUNCTION: acpi_ev_gpe_detect
*
- * PARAMETERS: None
+ * PARAMETERS: gpe_xrupt_list - Interrupt block for this interrupt.
+ * Can have multiple GPE blocks attached.
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
@@ -231,7 +235,7 @@ unlock_and_exit:
*
* FUNCTION: acpi_ev_asynch_execute_gpe_method
*
- * PARAMETERS: gpe_event_info - Info for this GPE
+ * PARAMETERS: Context (gpe_event_info) - Info for this GPE
*
* RETURN: None
*
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index a3b54addbbf2..06733397fc69 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -71,6 +71,9 @@ acpi_ev_valid_gpe_event (
struct acpi_gpe_block_info *gpe_block;
+ ACPI_FUNCTION_NAME ("ev_valid_gpe_event");
+
+
/* No need for spin lock since we are not changing any list elements */
gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head;
@@ -322,7 +325,6 @@ acpi_ev_get_gpe_xrupt_block (
}
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
-
/* Install new interrupt handler if not SCI_INT */
if (interrupt_level != acpi_gbl_FADT->sci_int) {
@@ -336,6 +338,63 @@ acpi_ev_get_gpe_xrupt_block (
/*******************************************************************************
*
+ * FUNCTION: acpi_ev_delete_gpe_xrupt
+ *
+ * PARAMETERS: gpe_xrupt - A GPE interrupt info block
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated
+ * interrupt handler if not the SCI interrupt.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_delete_gpe_xrupt (
+ struct acpi_gpe_xrupt_info *gpe_xrupt)
+{
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("ev_delete_gpe_xrupt");
+
+
+ /* We never want to remove the SCI interrupt handler */
+
+ if (gpe_xrupt->interrupt_level == acpi_gbl_FADT->sci_int) {
+ gpe_xrupt->gpe_block_list_head = NULL;
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Disable this interrupt */
+
+ status = acpi_os_remove_interrupt_handler (gpe_xrupt->interrupt_level,
+ acpi_ev_gpe_xrupt_handler);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Unlink the interrupt block with lock */
+
+ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ if (gpe_xrupt->previous) {
+ gpe_xrupt->previous->next = gpe_xrupt->next;
+ }
+
+ if (gpe_xrupt->next) {
+ gpe_xrupt->next->previous = gpe_xrupt->previous;
+ }
+ acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+
+ /* Free the block */
+
+ ACPI_MEM_FREE (gpe_xrupt);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ev_install_gpe_block
*
* PARAMETERS: gpe_block - New GPE block
@@ -357,9 +416,12 @@ acpi_ev_install_gpe_block (
acpi_status status;
+ ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
+
+
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
- return (status);
+ return_ACPI_STATUS (status);
}
gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level);
@@ -383,11 +445,81 @@ acpi_ev_install_gpe_block (
else {
gpe_xrupt_block->gpe_block_list_head = gpe_block;
}
+
+ gpe_block->xrupt_block = gpe_xrupt_block;
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
unlock_and_exit:
status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
- return (status);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ev_delete_gpe_block
+ *
+ * PARAMETERS: gpe_block - Existing GPE block
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Install new GPE block with mutex support
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_delete_gpe_block (
+ struct acpi_gpe_block_info *gpe_block)
+{
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
+
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Disable all GPEs in this block */
+
+ status = acpi_hw_disable_gpe_block (gpe_block->xrupt_block, gpe_block);
+
+ if (!gpe_block->previous && !gpe_block->next) {
+ /* This is the last gpe_block on this interrupt */
+
+ status = acpi_ev_delete_gpe_xrupt (gpe_block->xrupt_block);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+ }
+ else {
+ /* Remove the block on this interrupt with lock */
+
+ acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ if (gpe_block->previous) {
+ gpe_block->previous->next = gpe_block->next;
+ }
+ else {
+ gpe_block->xrupt_block->gpe_block_list_head = gpe_block->next;
+ }
+
+ if (gpe_block->next) {
+ gpe_block->next->previous = gpe_block->previous;
+ }
+ acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+ }
+
+ /* Free the gpe_block */
+
+ ACPI_MEM_FREE (gpe_block->register_info);
+ ACPI_MEM_FREE (gpe_block->event_info);
+ ACPI_MEM_FREE (gpe_block);
+
+unlock_and_exit:
+ status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ return_ACPI_STATUS (status);
}
@@ -526,7 +658,12 @@ error_exit:
*
* FUNCTION: acpi_ev_create_gpe_block
*
- * PARAMETERS: TBD
+ * PARAMETERS: gpe_device - Handle to the parent GPE block
+ * gpe_block_address - Address and space_iD
+ * register_count - Number of GPE register pairs in the block
+ * gpe_block_base_number - Starting GPE number for the block
+ * interrupt_level - H/W interrupt for the block
+ * return_gpe_block - Where the new block descriptor is returned
*
* RETURN: Status
*
@@ -536,7 +673,7 @@ error_exit:
acpi_status
acpi_ev_create_gpe_block (
- char *pathname,
+ struct acpi_namespace_node *gpe_device,
struct acpi_generic_address *gpe_block_address,
u32 register_count,
u8 gpe_block_base_number,
@@ -545,7 +682,6 @@ acpi_ev_create_gpe_block (
{
struct acpi_gpe_block_info *gpe_block;
acpi_status status;
- acpi_handle obj_handle;
ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
@@ -555,13 +691,6 @@ acpi_ev_create_gpe_block (
return_ACPI_STATUS (AE_OK);
}
- /* Get a handle to the parent object for this GPE block */
-
- status = acpi_get_handle (NULL, pathname, &obj_handle);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
-
/* Allocate a new GPE block */
gpe_block = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_block_info));
@@ -594,10 +723,12 @@ acpi_ev_create_gpe_block (
/* Dump info about this GPE block */
- ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block: %X registers at %8.8X%8.8X\n",
+ ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block: [%4.4s] %X registers at %8.8X%8.8X on interrupt %d\n",
+ gpe_device->name.ascii,
gpe_block->register_count,
ACPI_HIDWORD (gpe_block->block_address.address),
- ACPI_LODWORD (gpe_block->block_address.address)));
+ ACPI_LODWORD (gpe_block->block_address.address),
+ interrupt_level));
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block defined as GPE 0x%.2X to GPE 0x%.2X\n",
gpe_block->block_base_number,
@@ -606,13 +737,16 @@ acpi_ev_create_gpe_block (
/* Find all GPE methods (_Lxx, _Exx) for this block */
- status = acpi_walk_namespace (ACPI_TYPE_METHOD, obj_handle,
- ACPI_UINT32_MAX, acpi_ev_save_method_info,
+ status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
gpe_block, NULL);
/* Return the new block */
- (*return_gpe_block) = gpe_block;
+ if (return_gpe_block) {
+ (*return_gpe_block) = gpe_block;
+ }
+
return_ACPI_STATUS (AE_OK);
}
@@ -635,12 +769,20 @@ acpi_ev_gpe_initialize (void)
u32 register_count0 = 0;
u32 register_count1 = 0;
u32 gpe_number_max = 0;
+ acpi_handle gpe_device;
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_gpe_initialize");
+ /* Get a handle to the predefined _GPE object */
+
+ status = acpi_get_handle (NULL, "\\_GPE", &gpe_device);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
/*
* Initialize the GPE Blocks defined in the FADT
*
@@ -676,7 +818,7 @@ acpi_ev_gpe_initialize (void)
/* Install GPE Block 0 */
- status = acpi_ev_create_gpe_block ("\\_GPE", &acpi_gbl_FADT->xgpe0_blk,
+ status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe0_blk,
register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
@@ -708,7 +850,7 @@ acpi_ev_gpe_initialize (void)
else {
/* Install GPE Block 1 */
- status = acpi_ev_create_gpe_block ("\\_GPE", &acpi_gbl_FADT->xgpe1_blk,
+ status = acpi_ev_create_gpe_block (gpe_device, &acpi_gbl_FADT->xgpe1_blk,
register_count1, acpi_gbl_FADT->gpe1_base,
acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
if (ACPI_FAILURE (status)) {
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index b286400db543..c76f24fb372e 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -523,10 +523,6 @@ acpi_ev_terminate (void)
{
acpi_native_uint i;
acpi_status status;
- struct acpi_gpe_block_info *gpe_block;
- struct acpi_gpe_block_info *next_gpe_block;
- struct acpi_gpe_xrupt_info *gpe_xrupt_info;
- struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
ACPI_FUNCTION_TRACE ("ev_terminate");
@@ -567,24 +563,6 @@ acpi_ev_terminate (void)
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_disable failed\n"));
}
}
-
- /* Free global GPE blocks and related info structures */
-
- gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
- while (gpe_xrupt_info) {
- gpe_block = gpe_xrupt_info->gpe_block_list_head;
- while (gpe_block) {
- next_gpe_block = gpe_block->next;
- ACPI_MEM_FREE (gpe_block->event_info);
- ACPI_MEM_FREE (gpe_block->register_info);
- ACPI_MEM_FREE (gpe_block);
-
- gpe_block = next_gpe_block;
- }
- next_gpe_xrupt_info = gpe_xrupt_info->next;
- ACPI_MEM_FREE (gpe_xrupt_info);
- gpe_xrupt_info = next_gpe_xrupt_info;
- }
return_VOID;
}
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index eb5ab972eba2..afa76a8f6a26 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -80,15 +80,13 @@ acpi_ev_sci_xrupt_handler (
*/
/*
- * Fixed acpi_events:
- * Check for and dispatch any Fixed acpi_events that have occurred
+ * Fixed Events:
+ * Check for and dispatch any Fixed Events that have occurred
*/
interrupt_handled |= acpi_ev_fixed_event_detect ();
-/* TBD: What if there are no GPEs defined? */
-
/*
- * GPEs:
+ * General Purpose Events:
* Check for and dispatch any GPEs that have occurred
*/
interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index bf3876bdabf2..89122dfc72a1 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -44,6 +44,7 @@
#include <acpi/acpi.h>
#include <acpi/acevents.h>
+#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME ("evxfevnt")
@@ -116,6 +117,7 @@ acpi_disable (void)
ACPI_FUNCTION_TRACE ("acpi_disable");
+
if (!acpi_gbl_FADT) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
return_ACPI_STATUS (AE_NO_ACPI_TABLES);
@@ -207,6 +209,7 @@ acpi_enable_event (
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable?
+ * Called from ISR or not
*
* RETURN: Status
*
@@ -227,9 +230,13 @@ acpi_enable_gpe (
ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ /* Use semaphore lock if not executing at interrupt level */
+
+ if (flags & ACPI_NOT_ISR) {
+ status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
/* Ensure that we have a valid GPE number */
@@ -252,7 +259,9 @@ acpi_enable_gpe (
}
unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ if (flags & ACPI_NOT_ISR) {
+ (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ }
return_ACPI_STATUS (status);
}
@@ -321,6 +330,7 @@ acpi_disable_event (
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable?
+ * Called from ISR or not
*
* RETURN: Status
*
@@ -341,9 +351,13 @@ acpi_disable_gpe (
ACPI_FUNCTION_TRACE ("acpi_disable_gpe");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ /* Use semaphore lock if not executing at interrupt level */
+
+ if (flags & ACPI_NOT_ISR) {
+ status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
/* Ensure that we have a valid GPE number */
@@ -366,7 +380,9 @@ acpi_disable_gpe (
}
unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ if (flags & ACPI_NOT_ISR) {
+ (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ }
return_ACPI_STATUS (status);
}
@@ -416,6 +432,7 @@ acpi_clear_event (
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
+ * Flags - Called from an ISR or not
*
* RETURN: Status
*
@@ -426,7 +443,8 @@ acpi_clear_event (
acpi_status
acpi_clear_gpe (
acpi_handle gpe_device,
- u32 gpe_number)
+ u32 gpe_number,
+ u32 flags)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
@@ -435,9 +453,13 @@ acpi_clear_gpe (
ACPI_FUNCTION_TRACE ("acpi_clear_gpe");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ /* Use semaphore lock if not executing at interrupt level */
+
+ if (flags & ACPI_NOT_ISR) {
+ status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
/* Ensure that we have a valid GPE number */
@@ -451,7 +473,9 @@ acpi_clear_gpe (
status = acpi_hw_clear_gpe (gpe_event_info);
unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ if (flags & ACPI_NOT_ISR) {
+ (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ }
return_ACPI_STATUS (status);
}
@@ -506,6 +530,7 @@ acpi_get_event_status (
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
+ * Flags - Called from an ISR or not
* Event Status - Where the current status of the event will
* be returned
*
@@ -519,6 +544,7 @@ acpi_status
acpi_get_gpe_status (
acpi_handle gpe_device,
u32 gpe_number,
+ u32 flags,
acpi_event_status *event_status)
{
acpi_status status = AE_OK;
@@ -528,9 +554,13 @@ acpi_get_gpe_status (
ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
- status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ /* Use semaphore lock if not executing at interrupt level */
+
+ if (flags & ACPI_NOT_ISR) {
+ status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
}
/* Ensure that we have a valid GPE number */
@@ -546,8 +576,157 @@ acpi_get_gpe_status (
status = acpi_hw_get_gpe_status (gpe_event_info, event_status);
unlock_and_exit:
- (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ if (flags & ACPI_NOT_ISR) {
+ (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+ }
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_install_gpe_block
+ *
+ * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
+ * gpe_block_address - Address and space_iD
+ * register_count - Number of GPE register pairs in the block
+ * interrupt_level - H/W interrupt for the block
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create and Install a block of GPE registers
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_install_gpe_block (
+ acpi_handle gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count,
+ u32 interrupt_level)
+{
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ struct acpi_gpe_block_info *gpe_block;
+
+
+ ACPI_FUNCTION_TRACE ("acpi_install_gpe_block");
+
+
+ if ((!gpe_device) ||
+ (!gpe_block_address) ||
+ (!register_count)) {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ node = acpi_ns_map_handle_to_node (gpe_device);
+ if (!node) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+ /*
+ * For user-installed GPE Block Devices, the gpe_block_base_number
+ * is always zero
+ */
+ status = acpi_ev_create_gpe_block (node, gpe_block_address, register_count,
+ 0, interrupt_level, &gpe_block);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+
+ /* Get the device_object attached to the node */
+
+ obj_desc = acpi_ns_get_attached_object (node);
+ if (!obj_desc) {
+ /* No object, create a new one */
+
+ obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_DEVICE);
+ if (!obj_desc) {
+ status = AE_NO_MEMORY;
+ goto unlock_and_exit;
+ }
+
+ status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE);
+ acpi_ut_remove_reference (obj_desc);
+ if (ACPI_FAILURE (status)) {
+ goto unlock_and_exit;
+ }
+ }
+
+ /* Install the GPE block in the device_object */
+
+ obj_desc->device.gpe_block = gpe_block;
+
+
+unlock_and_exit:
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (status);
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_remove_gpe_block
+ *
+ * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Remove a previously installed block of GPE registers
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_remove_gpe_block (
+ acpi_handle gpe_device)
+{
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+
+
+ ACPI_FUNCTION_TRACE ("acpi_remove_gpe_block");
+
+
+ if (!gpe_device) {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ node = acpi_ns_map_handle_to_node (gpe_device);
+ if (!node) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit;
+ }
+
+ /* Get the device_object attached to the node */
+
+ obj_desc = acpi_ns_get_attached_object (node);
+ if (!obj_desc ||
+ !obj_desc->device.gpe_block) {
+ return_ACPI_STATUS (AE_NULL_OBJECT);
+ }
+
+ /* Delete the GPE block (but not the device_object) */
+
+ status = acpi_ev_delete_gpe_block (obj_desc->device.gpe_block);
+ if (ACPI_SUCCESS (status)) {
+ obj_desc->device.gpe_block = NULL;
+ }
+
+unlock_and_exit:
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ return_ACPI_STATUS (status);
+}
+
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 106ce0847863..2e2b8f44d47e 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -45,6 +45,7 @@
#include <acpi/acpi.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
+#include <acpi/acevents.h>
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utdelete")
@@ -130,6 +131,14 @@ acpi_ut_delete_internal_obj (
break;
+ case ACPI_TYPE_DEVICE:
+
+ if (object->device.gpe_block) {
+ (void) acpi_ev_delete_gpe_block (object->device.gpe_block);
+ }
+ break;
+
+
case ACPI_TYPE_MUTEX:
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Mutex %p, Semaphore %p\n",
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
index 8a84bd523077..536326359d55 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/utilities/utinit.c
@@ -166,20 +166,42 @@ acpi_ut_validate_fadt (
*
* RETURN: none
*
- * DESCRIPTION: free memory allocated for table storage.
+ * DESCRIPTION: free global memory
*
******************************************************************************/
void
acpi_ut_terminate (void)
{
+ struct acpi_gpe_block_info *gpe_block;
+ struct acpi_gpe_block_info *next_gpe_block;
+ struct acpi_gpe_xrupt_info *gpe_xrupt_info;
+ struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
+
ACPI_FUNCTION_TRACE ("ut_terminate");
/* Free global tables, etc. */
- /* Nothing to do at this time */
+
+ /* Free global GPE blocks and related info structures */
+
+ gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
+ while (gpe_xrupt_info) {
+ gpe_block = gpe_xrupt_info->gpe_block_list_head;
+ while (gpe_block) {
+ next_gpe_block = gpe_block->next;
+ ACPI_MEM_FREE (gpe_block->event_info);
+ ACPI_MEM_FREE (gpe_block->register_info);
+ ACPI_MEM_FREE (gpe_block);
+
+ gpe_block = next_gpe_block;
+ }
+ next_gpe_xrupt_info = gpe_xrupt_info->next;
+ ACPI_MEM_FREE (gpe_xrupt_info);
+ gpe_xrupt_info = next_gpe_xrupt_info;
+ }
return_VOID;
}
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index c68b7280ba47..2a8c7f85d2f7 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -72,7 +72,7 @@
/* Version string */
-#define ACPI_CA_VERSION 0x20030321
+#define ACPI_CA_VERSION 0x20030328
/* Version of ACPI supported */
diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h
index 9071567435a6..f23360115e83 100644
--- a/include/acpi/acevents.h
+++ b/include/acpi/acevents.h
@@ -126,6 +126,19 @@ acpi_status
acpi_ev_gpe_initialize (
void);
+acpi_status
+acpi_ev_create_gpe_block (
+ struct acpi_namespace_node *gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count,
+ u8 gpe_block_base_number,
+ u32 interrupt_level,
+ struct acpi_gpe_block_info **return_gpe_block);
+
+acpi_status
+acpi_ev_delete_gpe_block (
+ struct acpi_gpe_block_info *gpe_block);
+
u32
acpi_ev_gpe_dispatch (
struct acpi_gpe_event_info *gpe_event_info,
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index f9f80c0e61e1..911283ffed90 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -340,6 +340,7 @@ struct acpi_gpe_block_info
{
struct acpi_gpe_block_info *previous;
struct acpi_gpe_block_info *next;
+ struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */
struct acpi_gpe_register_info *register_info; /* One per GPE register pair */
struct acpi_gpe_event_info *event_info; /* One for each GPE */
struct acpi_generic_address block_address; /* Base address of the block */
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 356e34ac98c4..58c6d1500417 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -77,19 +77,6 @@ struct acpi_signal_fatal_info
/*
- * Types specific to the OS service interfaces
- */
-
-typedef u32
-(ACPI_SYSTEM_XFACE *OSD_HANDLER) (
- void *context);
-
-typedef void
-(ACPI_SYSTEM_XFACE *OSD_EXECUTION_CALLBACK) (
- void *context);
-
-
-/*
* OSL Initialization and shutdown primitives
*/
@@ -165,9 +152,6 @@ acpi_os_release_lock (
acpi_handle handle,
u32 flags);
-#define ACPI_NOT_ISR 1
-#define ACPI_ISR 0
-
/*
* Memory allocation and mapping
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 8809b85beb9b..aa97e22aeb0d 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -348,14 +348,28 @@ acpi_disable_gpe (
acpi_status
acpi_clear_gpe (
acpi_handle gpe_device,
- u32 gpe_number);
+ u32 gpe_number,
+ u32 flags);
acpi_status
acpi_get_gpe_status (
acpi_handle gpe_device,
u32 gpe_number,
+ u32 flags,
acpi_event_status *event_status);
+acpi_status
+acpi_install_gpe_block (
+ acpi_handle gpe_device,
+ struct acpi_generic_address *gpe_block_address,
+ u32 register_count,
+ u32 interrupt_level);
+
+acpi_status
+acpi_remove_gpe_block (
+ acpi_handle gpe_device);
+
+
/*
* Resource interfaces
*/
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 02fc0054a286..d19ff567b92f 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -516,7 +516,7 @@ typedef u32 acpi_object_type;
/*
- * acpi_event Types: Fixed & General Purpose
+ * Acpi Event Types: Fixed & General Purpose
*/
typedef u32 acpi_event_type;
@@ -539,10 +539,13 @@ typedef u32 acpi_event_type;
#define ACPI_EVENT_EDGE_TRIGGERED 2
/*
- * GPEs
+ * Flags for GPE and Lock interfaces
*/
-#define ACPI_EVENT_WAKE_ENABLE 0x1
-#define ACPI_EVENT_WAKE_DISABLE 0x1
+#define ACPI_EVENT_WAKE_ENABLE 0x2
+#define ACPI_EVENT_WAKE_DISABLE 0x2
+
+#define ACPI_NOT_ISR 0x1
+#define ACPI_ISR 0x0
/*
@@ -749,6 +752,18 @@ struct acpi_system_info
/*
+ * Types specific to the OS service interfaces
+ */
+
+typedef u32
+(ACPI_SYSTEM_XFACE *OSD_HANDLER) (
+ void *context);
+
+typedef void
+(ACPI_SYSTEM_XFACE *OSD_EXECUTION_CALLBACK) (
+ void *context);
+
+/*
* Various handlers and callback procedures
*/
typedef