diff options
| author | Andy Grover <agrover@groveronline.com> | 2003-03-27 22:10:34 -0800 |
|---|---|---|
| committer | Andy Grover <agrover@groveronline.com> | 2003-03-27 22:10:34 -0800 |
| commit | d162a3eaeea8d139379771cb5245fc66c99ba916 (patch) | |
| tree | 21fe91bf361e0255bc64997c9bc1fbcdd73b0293 | |
| parent | 50a94a30e2262b8ee9dddc98d69487682172af7a (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.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/ec.c | 4 | ||||
| -rw-r--r-- | drivers/acpi/events/evgpe.c | 12 | ||||
| -rw-r--r-- | drivers/acpi/events/evgpeblk.c | 182 | ||||
| -rw-r--r-- | drivers/acpi/events/evmisc.c | 22 | ||||
| -rw-r--r-- | drivers/acpi/events/evsci.c | 8 | ||||
| -rw-r--r-- | drivers/acpi/events/evxfevnt.c | 213 | ||||
| -rw-r--r-- | drivers/acpi/utilities/utdelete.c | 9 | ||||
| -rw-r--r-- | drivers/acpi/utilities/utinit.c | 26 | ||||
| -rw-r--r-- | include/acpi/acconfig.h | 2 | ||||
| -rw-r--r-- | include/acpi/acevents.h | 13 | ||||
| -rw-r--r-- | include/acpi/aclocal.h | 1 | ||||
| -rw-r--r-- | include/acpi/acpiosxf.h | 16 | ||||
| -rw-r--r-- | include/acpi/acpixf.h | 16 | ||||
| -rw-r--r-- | include/acpi/actypes.h | 23 |
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 |
