Commit d162a3ea authored by Andy Grover's avatar Andy Grover

ACPI: Interpreter update to 20030328

- Add APIs to add and remove GPE Block devices
- Clean up problems with semaphore acquisition from the ISR
parent 50a94a30
...@@ -74,6 +74,8 @@ EXPORT_SYMBOL(acpi_install_fixed_event_handler); ...@@ -74,6 +74,8 @@ EXPORT_SYMBOL(acpi_install_fixed_event_handler);
EXPORT_SYMBOL(acpi_remove_fixed_event_handler); EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
EXPORT_SYMBOL(acpi_acquire_global_lock); EXPORT_SYMBOL(acpi_acquire_global_lock);
EXPORT_SYMBOL(acpi_release_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_current_resources);
EXPORT_SYMBOL(acpi_get_possible_resources); EXPORT_SYMBOL(acpi_get_possible_resources);
EXPORT_SYMBOL(acpi_walk_resources); EXPORT_SYMBOL(acpi_walk_resources);
......
...@@ -378,7 +378,7 @@ acpi_ec_gpe_query ( ...@@ -378,7 +378,7 @@ acpi_ec_gpe_query (
acpi_evaluate_object(ec->handle, object_name, NULL, NULL); acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
end: end:
acpi_enable_gpe(NULL, ec->gpe_bit, 0); acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
} }
static void static void
...@@ -391,7 +391,7 @@ acpi_ec_gpe_handler ( ...@@ -391,7 +391,7 @@ acpi_ec_gpe_handler (
if (!ec) if (!ec)
return; 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, status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
acpi_ec_gpe_query, ec); acpi_ec_gpe_query, ec);
......
...@@ -53,8 +53,8 @@ ...@@ -53,8 +53,8 @@
* *
* FUNCTION: acpi_ev_get_gpe_event_info * FUNCTION: acpi_ev_get_gpe_event_info
* *
* PARAMETERS: gpe_number - Raw GPE number * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
* owning_gpe_block - Block ptr. NULL for GPE0/GPE1 * gpe_number - Raw GPE number
* *
* RETURN: A GPE event_info struct. NULL if not a valid GPE * RETURN: A GPE event_info struct. NULL if not a valid GPE
* *
...@@ -76,6 +76,9 @@ acpi_ev_get_gpe_event_info ( ...@@ -76,6 +76,9 @@ acpi_ev_get_gpe_event_info (
acpi_native_uint i; acpi_native_uint i;
ACPI_FUNCTION_NAME ("ev_get_gpe_event_info");
/* A NULL gpe_block means use the FADT-defined GPE block(s) */ /* A NULL gpe_block means use the FADT-defined GPE block(s) */
if (!gpe_device) { if (!gpe_device) {
...@@ -120,7 +123,8 @@ acpi_ev_get_gpe_event_info ( ...@@ -120,7 +123,8 @@ acpi_ev_get_gpe_event_info (
* *
* FUNCTION: acpi_ev_gpe_detect * 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 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
* *
...@@ -231,7 +235,7 @@ acpi_ev_gpe_detect ( ...@@ -231,7 +235,7 @@ acpi_ev_gpe_detect (
* *
* FUNCTION: acpi_ev_asynch_execute_gpe_method * 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 * RETURN: None
* *
......
...@@ -71,6 +71,9 @@ acpi_ev_valid_gpe_event ( ...@@ -71,6 +71,9 @@ acpi_ev_valid_gpe_event (
struct acpi_gpe_block_info *gpe_block; 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 */ /* No need for spin lock since we are not changing any list elements */
gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head; gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head;
...@@ -322,7 +325,6 @@ acpi_ev_get_gpe_xrupt_block ( ...@@ -322,7 +325,6 @@ acpi_ev_get_gpe_xrupt_block (
} }
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR); acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
/* Install new interrupt handler if not SCI_INT */ /* Install new interrupt handler if not SCI_INT */
if (interrupt_level != acpi_gbl_FADT->sci_int) { if (interrupt_level != acpi_gbl_FADT->sci_int) {
...@@ -334,6 +336,63 @@ acpi_ev_get_gpe_xrupt_block ( ...@@ -334,6 +336,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 * FUNCTION: acpi_ev_install_gpe_block
...@@ -357,9 +416,12 @@ acpi_ev_install_gpe_block ( ...@@ -357,9 +416,12 @@ acpi_ev_install_gpe_block (
acpi_status status; acpi_status status;
ACPI_FUNCTION_TRACE ("ev_install_gpe_block");
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return (status); return_ACPI_STATUS (status);
} }
gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level); gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level);
...@@ -383,11 +445,81 @@ acpi_ev_install_gpe_block ( ...@@ -383,11 +445,81 @@ acpi_ev_install_gpe_block (
else { else {
gpe_xrupt_block->gpe_block_list_head = gpe_block; 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); acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
unlock_and_exit: unlock_and_exit:
status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); 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 @@ acpi_ev_create_gpe_info_blocks ( ...@@ -526,7 +658,12 @@ acpi_ev_create_gpe_info_blocks (
* *
* FUNCTION: acpi_ev_create_gpe_block * 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 * RETURN: Status
* *
...@@ -536,7 +673,7 @@ acpi_ev_create_gpe_info_blocks ( ...@@ -536,7 +673,7 @@ acpi_ev_create_gpe_info_blocks (
acpi_status acpi_status
acpi_ev_create_gpe_block ( acpi_ev_create_gpe_block (
char *pathname, struct acpi_namespace_node *gpe_device,
struct acpi_generic_address *gpe_block_address, struct acpi_generic_address *gpe_block_address,
u32 register_count, u32 register_count,
u8 gpe_block_base_number, u8 gpe_block_base_number,
...@@ -545,7 +682,6 @@ acpi_ev_create_gpe_block ( ...@@ -545,7 +682,6 @@ acpi_ev_create_gpe_block (
{ {
struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_block_info *gpe_block;
acpi_status status; acpi_status status;
acpi_handle obj_handle;
ACPI_FUNCTION_TRACE ("ev_create_gpe_block"); ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
...@@ -555,13 +691,6 @@ acpi_ev_create_gpe_block ( ...@@ -555,13 +691,6 @@ acpi_ev_create_gpe_block (
return_ACPI_STATUS (AE_OK); 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 */ /* Allocate a new GPE block */
gpe_block = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_block_info)); gpe_block = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_block_info));
...@@ -594,10 +723,12 @@ acpi_ev_create_gpe_block ( ...@@ -594,10 +723,12 @@ acpi_ev_create_gpe_block (
/* Dump info about this 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, gpe_block->register_count,
ACPI_HIDWORD (gpe_block->block_address.address), 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", ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block defined as GPE 0x%.2X to GPE 0x%.2X\n",
gpe_block->block_base_number, gpe_block->block_base_number,
...@@ -606,13 +737,16 @@ acpi_ev_create_gpe_block ( ...@@ -606,13 +737,16 @@ acpi_ev_create_gpe_block (
/* Find all GPE methods (_Lxx, _Exx) for this block */ /* Find all GPE methods (_Lxx, _Exx) for this block */
status = acpi_walk_namespace (ACPI_TYPE_METHOD, obj_handle, status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
ACPI_UINT32_MAX, acpi_ev_save_method_info, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
gpe_block, NULL); gpe_block, NULL);
/* Return the new block */ /* Return the new block */
(*return_gpe_block) = gpe_block; if (return_gpe_block) {
(*return_gpe_block) = gpe_block;
}
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
} }
...@@ -635,12 +769,20 @@ acpi_ev_gpe_initialize (void) ...@@ -635,12 +769,20 @@ acpi_ev_gpe_initialize (void)
u32 register_count0 = 0; u32 register_count0 = 0;
u32 register_count1 = 0; u32 register_count1 = 0;
u32 gpe_number_max = 0; u32 gpe_number_max = 0;
acpi_handle gpe_device;
acpi_status status; acpi_status status;
ACPI_FUNCTION_TRACE ("ev_gpe_initialize"); 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 * Initialize the GPE Blocks defined in the FADT
* *
...@@ -676,7 +818,7 @@ acpi_ev_gpe_initialize (void) ...@@ -676,7 +818,7 @@ acpi_ev_gpe_initialize (void)
/* Install GPE Block 0 */ /* 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]); register_count0, 0, acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[0]);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (( ACPI_REPORT_ERROR ((
...@@ -708,7 +850,7 @@ acpi_ev_gpe_initialize (void) ...@@ -708,7 +850,7 @@ acpi_ev_gpe_initialize (void)
else { else {
/* Install GPE Block 1 */ /* 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, register_count1, acpi_gbl_FADT->gpe1_base,
acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]); acpi_gbl_FADT->sci_int, &acpi_gbl_gpe_fadt_blocks[1]);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
......
...@@ -523,10 +523,6 @@ acpi_ev_terminate (void) ...@@ -523,10 +523,6 @@ acpi_ev_terminate (void)
{ {
acpi_native_uint i; acpi_native_uint i;
acpi_status status; 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"); ACPI_FUNCTION_TRACE ("ev_terminate");
...@@ -567,24 +563,6 @@ acpi_ev_terminate (void) ...@@ -567,24 +563,6 @@ acpi_ev_terminate (void)
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "acpi_disable failed\n")); 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; return_VOID;
} }
...@@ -80,15 +80,13 @@ acpi_ev_sci_xrupt_handler ( ...@@ -80,15 +80,13 @@ acpi_ev_sci_xrupt_handler (
*/ */
/* /*
* Fixed acpi_events: * Fixed Events:
* Check for and dispatch any Fixed acpi_events that have occurred * Check for and dispatch any Fixed Events that have occurred
*/ */
interrupt_handled |= acpi_ev_fixed_event_detect (); 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 * Check for and dispatch any GPEs that have occurred
*/ */
interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list); interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acevents.h> #include <acpi/acevents.h>
#include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS #define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME ("evxfevnt") ACPI_MODULE_NAME ("evxfevnt")
...@@ -116,6 +117,7 @@ acpi_disable (void) ...@@ -116,6 +117,7 @@ acpi_disable (void)
ACPI_FUNCTION_TRACE ("acpi_disable"); ACPI_FUNCTION_TRACE ("acpi_disable");
if (!acpi_gbl_FADT) { if (!acpi_gbl_FADT) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n")); ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
return_ACPI_STATUS (AE_NO_ACPI_TABLES); return_ACPI_STATUS (AE_NO_ACPI_TABLES);
...@@ -207,6 +209,7 @@ acpi_enable_event ( ...@@ -207,6 +209,7 @@ acpi_enable_event (
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable? * Flags - Just enable, or also wake enable?
* Called from ISR or not
* *
* RETURN: Status * RETURN: Status
* *
...@@ -227,9 +230,13 @@ acpi_enable_gpe ( ...@@ -227,9 +230,13 @@ acpi_enable_gpe (
ACPI_FUNCTION_TRACE ("acpi_enable_gpe"); ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Use semaphore lock if not executing at interrupt level */
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); 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 */ /* Ensure that we have a valid GPE number */
...@@ -252,7 +259,9 @@ acpi_enable_gpe ( ...@@ -252,7 +259,9 @@ acpi_enable_gpe (
} }
unlock_and_exit: 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); return_ACPI_STATUS (status);
} }
...@@ -321,6 +330,7 @@ acpi_disable_event ( ...@@ -321,6 +330,7 @@ acpi_disable_event (
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable? * Flags - Just enable, or also wake enable?
* Called from ISR or not
* *
* RETURN: Status * RETURN: Status
* *
...@@ -341,9 +351,13 @@ acpi_disable_gpe ( ...@@ -341,9 +351,13 @@ acpi_disable_gpe (
ACPI_FUNCTION_TRACE ("acpi_disable_gpe"); ACPI_FUNCTION_TRACE ("acpi_disable_gpe");
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Use semaphore lock if not executing at interrupt level */
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); 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 */ /* Ensure that we have a valid GPE number */
...@@ -366,7 +380,9 @@ acpi_disable_gpe ( ...@@ -366,7 +380,9 @@ acpi_disable_gpe (
} }
unlock_and_exit: 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); return_ACPI_STATUS (status);
} }
...@@ -416,6 +432,7 @@ acpi_clear_event ( ...@@ -416,6 +432,7 @@ acpi_clear_event (
* *
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block * gpe_number - GPE level within the GPE block
* Flags - Called from an ISR or not
* *
* RETURN: Status * RETURN: Status
* *
...@@ -426,7 +443,8 @@ acpi_clear_event ( ...@@ -426,7 +443,8 @@ acpi_clear_event (
acpi_status acpi_status
acpi_clear_gpe ( acpi_clear_gpe (
acpi_handle gpe_device, acpi_handle gpe_device,
u32 gpe_number) u32 gpe_number,
u32 flags)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info; struct acpi_gpe_event_info *gpe_event_info;
...@@ -435,9 +453,13 @@ acpi_clear_gpe ( ...@@ -435,9 +453,13 @@ acpi_clear_gpe (
ACPI_FUNCTION_TRACE ("acpi_clear_gpe"); ACPI_FUNCTION_TRACE ("acpi_clear_gpe");
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Use semaphore lock if not executing at interrupt level */
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); 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 */ /* Ensure that we have a valid GPE number */
...@@ -451,7 +473,9 @@ acpi_clear_gpe ( ...@@ -451,7 +473,9 @@ acpi_clear_gpe (
status = acpi_hw_clear_gpe (gpe_event_info); status = acpi_hw_clear_gpe (gpe_event_info);
unlock_and_exit: 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); return_ACPI_STATUS (status);
} }
...@@ -506,6 +530,7 @@ acpi_get_event_status ( ...@@ -506,6 +530,7 @@ acpi_get_event_status (
* *
* PARAMETERS: gpe_device - Parent GPE Device * PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block * 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 * Event Status - Where the current status of the event will
* be returned * be returned
* *
...@@ -519,6 +544,7 @@ acpi_status ...@@ -519,6 +544,7 @@ acpi_status
acpi_get_gpe_status ( acpi_get_gpe_status (
acpi_handle gpe_device, acpi_handle gpe_device,
u32 gpe_number, u32 gpe_number,
u32 flags,
acpi_event_status *event_status) acpi_event_status *event_status)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
...@@ -528,9 +554,13 @@ acpi_get_gpe_status ( ...@@ -528,9 +554,13 @@ acpi_get_gpe_status (
ACPI_FUNCTION_TRACE ("acpi_get_gpe_status"); ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS); /* Use semaphore lock if not executing at interrupt level */
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); 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 */ /* Ensure that we have a valid GPE number */
...@@ -546,8 +576,157 @@ acpi_get_gpe_status ( ...@@ -546,8 +576,157 @@ acpi_get_gpe_status (
status = acpi_hw_get_gpe_status (gpe_event_info, event_status); status = acpi_hw_get_gpe_status (gpe_event_info, event_status);
unlock_and_exit: 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); 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);
}
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acinterp.h> #include <acpi/acinterp.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_UTILITIES #define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utdelete") ACPI_MODULE_NAME ("utdelete")
...@@ -130,6 +131,14 @@ acpi_ut_delete_internal_obj ( ...@@ -130,6 +131,14 @@ acpi_ut_delete_internal_obj (
break; 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: case ACPI_TYPE_MUTEX:
ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Mutex %p, Semaphore %p\n", ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "***** Mutex %p, Semaphore %p\n",
......
...@@ -166,20 +166,42 @@ acpi_ut_validate_fadt ( ...@@ -166,20 +166,42 @@ acpi_ut_validate_fadt (
* *
* RETURN: none * RETURN: none
* *
* DESCRIPTION: free memory allocated for table storage. * DESCRIPTION: free global memory
* *
******************************************************************************/ ******************************************************************************/
void void
acpi_ut_terminate (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"); ACPI_FUNCTION_TRACE ("ut_terminate");
/* Free global tables, etc. */ /* 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; return_VOID;
} }
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
/* Version string */ /* Version string */
#define ACPI_CA_VERSION 0x20030321 #define ACPI_CA_VERSION 0x20030328
/* Version of ACPI supported */ /* Version of ACPI supported */
......
...@@ -126,6 +126,19 @@ acpi_status ...@@ -126,6 +126,19 @@ acpi_status
acpi_ev_gpe_initialize ( acpi_ev_gpe_initialize (
void); 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 u32
acpi_ev_gpe_dispatch ( acpi_ev_gpe_dispatch (
struct acpi_gpe_event_info *gpe_event_info, struct acpi_gpe_event_info *gpe_event_info,
......
...@@ -340,6 +340,7 @@ struct acpi_gpe_block_info ...@@ -340,6 +340,7 @@ struct acpi_gpe_block_info
{ {
struct acpi_gpe_block_info *previous; struct acpi_gpe_block_info *previous;
struct acpi_gpe_block_info *next; 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_register_info *register_info; /* One per GPE register pair */
struct acpi_gpe_event_info *event_info; /* One for each GPE */ struct acpi_gpe_event_info *event_info; /* One for each GPE */
struct acpi_generic_address block_address; /* Base address of the block */ struct acpi_generic_address block_address; /* Base address of the block */
......
...@@ -76,19 +76,6 @@ struct acpi_signal_fatal_info ...@@ -76,19 +76,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 * OSL Initialization and shutdown primitives
*/ */
...@@ -165,9 +152,6 @@ acpi_os_release_lock ( ...@@ -165,9 +152,6 @@ acpi_os_release_lock (
acpi_handle handle, acpi_handle handle,
u32 flags); u32 flags);
#define ACPI_NOT_ISR 1
#define ACPI_ISR 0
/* /*
* Memory allocation and mapping * Memory allocation and mapping
......
...@@ -348,14 +348,28 @@ acpi_disable_gpe ( ...@@ -348,14 +348,28 @@ acpi_disable_gpe (
acpi_status acpi_status
acpi_clear_gpe ( acpi_clear_gpe (
acpi_handle gpe_device, acpi_handle gpe_device,
u32 gpe_number); u32 gpe_number,
u32 flags);
acpi_status acpi_status
acpi_get_gpe_status ( acpi_get_gpe_status (
acpi_handle gpe_device, acpi_handle gpe_device,
u32 gpe_number, u32 gpe_number,
u32 flags,
acpi_event_status *event_status); 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 * Resource interfaces
*/ */
......
...@@ -516,7 +516,7 @@ typedef u32 acpi_object_type; ...@@ -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; typedef u32 acpi_event_type;
...@@ -539,10 +539,13 @@ typedef u32 acpi_event_type; ...@@ -539,10 +539,13 @@ typedef u32 acpi_event_type;
#define ACPI_EVENT_EDGE_TRIGGERED 2 #define ACPI_EVENT_EDGE_TRIGGERED 2
/* /*
* GPEs * Flags for GPE and Lock interfaces
*/ */
#define ACPI_EVENT_WAKE_ENABLE 0x1 #define ACPI_EVENT_WAKE_ENABLE 0x2
#define ACPI_EVENT_WAKE_DISABLE 0x1 #define ACPI_EVENT_WAKE_DISABLE 0x2
#define ACPI_NOT_ISR 0x1
#define ACPI_ISR 0x0
/* /*
...@@ -748,6 +751,18 @@ struct acpi_system_info ...@@ -748,6 +751,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 * Various handlers and callback procedures
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment