Commit db888b2a authored by Andy Grover's avatar Andy Grover

Merge groveronline.com:/root/bk/linux-2.5

into groveronline.com:/root/bk/linux-acpi
parents b4f6270e 680b47b9
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/io.h>
#include <asm/mpspec.h> #include <asm/mpspec.h>
#if defined (CONFIG_X86_LOCAL_APIC) #if defined (CONFIG_X86_LOCAL_APIC)
......
...@@ -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_event(ec->gpe_bit, ACPI_EVENT_GPE, 0); acpi_enable_gpe(NULL, ec->gpe_bit, 0);
} }
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_event(ec->gpe_bit, ACPI_EVENT_GPE, 0); acpi_disable_gpe(NULL, ec->gpe_bit, 0);
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);
...@@ -589,12 +589,13 @@ acpi_ec_add ( ...@@ -589,12 +589,13 @@ acpi_ec_add (
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
acpi_remove_gpe_handler(ec_ecdt->gpe_bit, &acpi_ec_gpe_handler); acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, &acpi_ec_gpe_handler);
kfree(ec_ecdt); kfree(ec_ecdt);
} }
/* Get GPE bit assignment (EC events). */ /* Get GPE bit assignment (EC events). */
/* TODO: Add support for _GPE returning a package */
status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit); status = acpi_evaluate_integer(ec->handle, "_GPE", NULL, &ec->gpe_bit);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
...@@ -714,7 +715,7 @@ acpi_ec_start ( ...@@ -714,7 +715,7 @@ acpi_ec_start (
/* /*
* Install GPE handler * Install GPE handler
*/ */
status = acpi_install_gpe_handler(ec->gpe_bit, status = acpi_install_gpe_handler(NULL, ec->gpe_bit,
ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
...@@ -724,7 +725,7 @@ acpi_ec_start ( ...@@ -724,7 +725,7 @@ acpi_ec_start (
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
&acpi_ec_space_setup, ec); &acpi_ec_space_setup, ec);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
acpi_remove_gpe_handler(ec->gpe_bit, &acpi_ec_gpe_handler); acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
} }
...@@ -752,7 +753,7 @@ acpi_ec_stop ( ...@@ -752,7 +753,7 @@ acpi_ec_stop (
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
status = acpi_remove_gpe_handler(ec->gpe_bit, &acpi_ec_gpe_handler); status = acpi_remove_gpe_handler(NULL, ec->gpe_bit, &acpi_ec_gpe_handler);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
...@@ -798,7 +799,7 @@ acpi_ec_ecdt_probe (void) ...@@ -798,7 +799,7 @@ acpi_ec_ecdt_probe (void)
/* /*
* Install GPE handler * Install GPE handler
*/ */
status = acpi_install_gpe_handler(ec_ecdt->gpe_bit, status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit,
ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
ec_ecdt); ec_ecdt);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
...@@ -809,7 +810,7 @@ acpi_ec_ecdt_probe (void) ...@@ -809,7 +810,7 @@ acpi_ec_ecdt_probe (void)
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
&acpi_ec_space_setup, ec_ecdt); &acpi_ec_space_setup, ec_ecdt);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
acpi_remove_gpe_handler(ec_ecdt->gpe_bit, acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit,
&acpi_ec_gpe_handler); &acpi_ec_gpe_handler);
goto error; goto error;
} }
......
...@@ -78,9 +78,9 @@ acpi_ev_initialize ( ...@@ -78,9 +78,9 @@ acpi_ev_initialize (
} }
/* /*
* Initialize the Fixed and General Purpose acpi_events prior. This is * Initialize the Fixed and General Purpose Events. This is
* done prior to enabling SCIs to prevent interrupts from occurring * done prior to enabling SCIs to prevent interrupts from
* before handers are installed. * occurring before handers are installed.
*/ */
status = acpi_ev_fixed_event_initialize (); status = acpi_ev_fixed_event_initialize ();
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
...@@ -225,7 +225,7 @@ acpi_ev_fixed_event_detect ( ...@@ -225,7 +225,7 @@ acpi_ev_fixed_event_detect (
(void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &fixed_enable); (void) acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
"Fixed acpi_event Block: Enable %08X Status %08X\n", "Fixed Event Block: Enable %08X Status %08X\n",
fixed_enable, fixed_status)); fixed_enable, fixed_status));
/* /*
...@@ -282,7 +282,7 @@ acpi_ev_fixed_event_dispatch ( ...@@ -282,7 +282,7 @@ acpi_ev_fixed_event_dispatch (
0, ACPI_MTX_DO_NOT_LOCK); 0, ACPI_MTX_DO_NOT_LOCK);
ACPI_REPORT_ERROR ( ACPI_REPORT_ERROR (
("ev_gpe_dispatch: No installed handler for fixed event [%08X]\n", ("No installed handler for fixed event [%08X]\n",
event)); event));
return (ACPI_INTERRUPT_NOT_HANDLED); return (ACPI_INTERRUPT_NOT_HANDLED);
......
...@@ -53,44 +53,60 @@ ...@@ -53,44 +53,60 @@
* *
* FUNCTION: acpi_ev_get_gpe_event_info * FUNCTION: acpi_ev_get_gpe_event_info
* *
* PARAMETERS: gpe_number - Raw GPE number * PARAMETERS: gpe_number - Raw GPE number
* owning_gpe_block - Block ptr. NULL for GPE0/GPE1
* *
* RETURN: None. * RETURN: A GPE event_info struct. NULL if not a valid GPE
* *
* DESCRIPTION: Returns the event_info struct * DESCRIPTION: Returns the event_info struct associated with this GPE.
* associated with this GPE. * Validates the gpe_block and the gpe_number
* *
* TBD: this function will go away when full support of GPE block devices * Should be called only when the GPE lists are semaphore locked
* is implemented! * and not subject to change.
* *
******************************************************************************/ ******************************************************************************/
struct acpi_gpe_event_info * struct acpi_gpe_event_info *
acpi_ev_get_gpe_event_info ( acpi_ev_get_gpe_event_info (
acpi_handle gpe_device,
u32 gpe_number) u32 gpe_number)
{ {
union acpi_operand_object *obj_desc;
struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_block_info *gpe_block;
acpi_native_uint i;
/* Examine GPE Block 0 */ /* A NULL gpe_block means use the FADT-defined GPE block(s) */
gpe_block = acpi_gbl_gpe_block_list_head; if (!gpe_device) {
if (!gpe_block) { /* Examine GPE Block 0 and 1 (These blocks are permanent) */
return (NULL);
}
if ((gpe_number >= gpe_block->block_base_number) && for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { gpe_block = acpi_gbl_gpe_fadt_blocks[i];
return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]); if (gpe_block) {
} if ((gpe_number >= gpe_block->block_base_number) &&
(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
}
}
}
/* Examine GPE Block 1 */ /* The gpe_number was not in the range of either FADT GPE block */
return (NULL);
}
gpe_block = gpe_block->next; /*
if (!gpe_block) { * A Non-null gpe_device means this is a GPE Block Device.
*/
obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) gpe_device);
if (!obj_desc ||
!obj_desc->device.gpe_block) {
return (NULL); return (NULL);
} }
gpe_block = obj_desc->device.gpe_block;
if ((gpe_number >= gpe_block->block_base_number) && if ((gpe_number >= gpe_block->block_base_number) &&
(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]); return (&gpe_block->event_info[gpe_number - gpe_block->block_base_number]);
...@@ -99,6 +115,7 @@ acpi_ev_get_gpe_event_info ( ...@@ -99,6 +115,7 @@ acpi_ev_get_gpe_event_info (
return (NULL); return (NULL);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ev_gpe_detect * FUNCTION: acpi_ev_gpe_detect
...@@ -113,17 +130,19 @@ acpi_ev_get_gpe_event_info ( ...@@ -113,17 +130,19 @@ acpi_ev_get_gpe_event_info (
******************************************************************************/ ******************************************************************************/
u32 u32
acpi_ev_gpe_detect (void) acpi_ev_gpe_detect (
struct acpi_gpe_xrupt_info *gpe_xrupt_list)
{ {
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
u32 i;
u32 j;
u8 enabled_status_byte; u8 enabled_status_byte;
u8 bit_mask; u8 bit_mask;
struct acpi_gpe_register_info *gpe_register_info; struct acpi_gpe_register_info *gpe_register_info;
u32 in_value; u32 in_value;
acpi_status status; acpi_status status;
struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_block_info *gpe_block;
u32 gpe_number;
u32 i;
u32 j;
ACPI_FUNCTION_NAME ("ev_gpe_detect"); ACPI_FUNCTION_NAME ("ev_gpe_detect");
...@@ -131,7 +150,8 @@ acpi_ev_gpe_detect (void) ...@@ -131,7 +150,8 @@ acpi_ev_gpe_detect (void)
/* Examine all GPE blocks attached to this interrupt level */ /* Examine all GPE blocks attached to this interrupt level */
gpe_block = acpi_gbl_gpe_block_list_head; acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
gpe_block = gpe_xrupt_list->gpe_block_list_head;
while (gpe_block) { while (gpe_block) {
/* /*
* Read all of the 8-bit GPE status and enable registers * Read all of the 8-bit GPE status and enable registers
...@@ -143,18 +163,22 @@ acpi_ev_gpe_detect (void) ...@@ -143,18 +163,22 @@ acpi_ev_gpe_detect (void)
gpe_register_info = &gpe_block->register_info[i]; gpe_register_info = &gpe_block->register_info[i];
/* Read the Status Register */
status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
&gpe_register_info->status_address, 0); &gpe_register_info->status_address, 0);
gpe_register_info->status = (u8) in_value; gpe_register_info->status = (u8) in_value;
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return (ACPI_INTERRUPT_NOT_HANDLED); goto unlock_and_exit;
} }
/* Read the Enable Register */
status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
&gpe_register_info->enable_address, 0); &gpe_register_info->enable_address, 0);
gpe_register_info->enable = (u8) in_value; gpe_register_info->enable = (u8) in_value;
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return (ACPI_INTERRUPT_NOT_HANDLED); goto unlock_and_exit;
} }
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
...@@ -184,8 +208,11 @@ acpi_ev_gpe_detect (void) ...@@ -184,8 +208,11 @@ acpi_ev_gpe_detect (void)
* Found an active GPE. Dispatch the event to a handler * Found an active GPE. Dispatch the event to a handler
* or method. * or method.
*/ */
gpe_number = (i * ACPI_GPE_REGISTER_WIDTH) + j;
int_status |= acpi_ev_gpe_dispatch ( int_status |= acpi_ev_gpe_dispatch (
&gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) +j]); &gpe_block->event_info[gpe_number],
gpe_number + gpe_block->register_info[gpe_number].base_gpe_number);
} }
} }
} }
...@@ -193,6 +220,9 @@ acpi_ev_gpe_detect (void) ...@@ -193,6 +220,9 @@ acpi_ev_gpe_detect (void)
gpe_block = gpe_block->next; gpe_block = gpe_block->next;
} }
unlock_and_exit:
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
return (int_status); return (int_status);
} }
...@@ -209,7 +239,7 @@ acpi_ev_gpe_detect (void) ...@@ -209,7 +239,7 @@ acpi_ev_gpe_detect (void)
* function is called from an invocation of acpi_os_queue_for_execution * function is called from an invocation of acpi_os_queue_for_execution
* (and therefore does NOT execute at interrupt level) so that * (and therefore does NOT execute at interrupt level) so that
* the control method itself is not executed in the context of * the control method itself is not executed in the context of
* the SCI interrupt handler. * an interrupt handler.
* *
******************************************************************************/ ******************************************************************************/
...@@ -220,44 +250,54 @@ acpi_ev_asynch_execute_gpe_method ( ...@@ -220,44 +250,54 @@ acpi_ev_asynch_execute_gpe_method (
struct acpi_gpe_event_info *gpe_event_info = (void *) context; struct acpi_gpe_event_info *gpe_event_info = (void *) context;
u32 gpe_number = 0; u32 gpe_number = 0;
acpi_status status; acpi_status status;
struct acpi_gpe_event_info local_gpe_event_info;
ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method"); ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
/*
* Take a snapshot of the GPE info for this level - we copy the
* info to prevent a race condition with remove_handler.
*/
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_VOID; return_VOID;
} }
/* Must revalidate the gpe_number/gpe_block */
if (!acpi_ev_valid_gpe_event (gpe_event_info)) {
status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_VOID;
}
/*
* Take a snapshot of the GPE info for this level - we copy the
* info to prevent a race condition with remove_handler/remove_block.
*/
ACPI_MEMCPY (&local_gpe_event_info, gpe_event_info, sizeof (struct acpi_gpe_event_info));
status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_VOID; return_VOID;
} }
if (gpe_event_info->method_node) { if (local_gpe_event_info.method_node) {
/* /*
* Invoke the GPE Method (_Lxx, _Exx): * Invoke the GPE Method (_Lxx, _Exx):
* (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.) * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
*/ */
status = acpi_ns_evaluate_by_handle (gpe_event_info->method_node, NULL, NULL); status = acpi_ns_evaluate_by_handle (local_gpe_event_info.method_node, NULL, NULL);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2.2X]\n", ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
acpi_format_exception (status), acpi_format_exception (status),
gpe_event_info->method_node->name.ascii, gpe_number)); local_gpe_event_info.method_node->name.ascii, gpe_number));
} }
} }
if (gpe_event_info->type & ACPI_EVENT_LEVEL_TRIGGERED) { if (local_gpe_event_info.flags & ACPI_EVENT_LEVEL_TRIGGERED) {
/* /*
* GPE is level-triggered, we clear the GPE status bit after handling * GPE is level-triggered, we clear the GPE status bit after handling
* the event. * the event.
*/ */
status = acpi_hw_clear_gpe (gpe_event_info); status = acpi_hw_clear_gpe (&local_gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_VOID; return_VOID;
} }
...@@ -265,7 +305,7 @@ acpi_ev_asynch_execute_gpe_method ( ...@@ -265,7 +305,7 @@ acpi_ev_asynch_execute_gpe_method (
/* Enable this GPE */ /* Enable this GPE */
(void) acpi_hw_enable_gpe (gpe_event_info); (void) acpi_hw_enable_gpe (&local_gpe_event_info);
return_VOID; return_VOID;
} }
...@@ -274,21 +314,23 @@ acpi_ev_asynch_execute_gpe_method ( ...@@ -274,21 +314,23 @@ acpi_ev_asynch_execute_gpe_method (
* *
* FUNCTION: acpi_ev_gpe_dispatch * FUNCTION: acpi_ev_gpe_dispatch
* *
* PARAMETERS: gpe_event_info - info for this GPE * PARAMETERS: gpe_event_info - info for this GPE
* gpe_number - Number relative to the parent GPE block
* *
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
* *
* DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
* or method (e.g. _Lxx/_Exx) handler. This function executes * or method (e.g. _Lxx/_Exx) handler.
* at interrupt level. *
* This function executes at interrupt level.
* *
******************************************************************************/ ******************************************************************************/
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,
u32 gpe_number)
{ {
u32 gpe_number = 0; /* TBD: remove */
acpi_status status; acpi_status status;
...@@ -299,10 +341,10 @@ acpi_ev_gpe_dispatch ( ...@@ -299,10 +341,10 @@ acpi_ev_gpe_dispatch (
* If edge-triggered, clear the GPE status bit now. Note that * If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced. * level-triggered events are cleared after the GPE is serviced.
*/ */
if (gpe_event_info->type & ACPI_EVENT_EDGE_TRIGGERED) { if (gpe_event_info->flags & ACPI_EVENT_EDGE_TRIGGERED) {
status = acpi_hw_clear_gpe (gpe_event_info); status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2.2X]\n", ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
gpe_number)); gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
} }
...@@ -327,19 +369,18 @@ acpi_ev_gpe_dispatch ( ...@@ -327,19 +369,18 @@ acpi_ev_gpe_dispatch (
*/ */
status = acpi_hw_disable_gpe (gpe_event_info); status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2.2X]\n", ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
gpe_number)); gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
} }
/* /* Execute the method associated with the GPE. */
* Execute the method associated with the GPE.
*/
if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE, if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
acpi_ev_asynch_execute_gpe_method, acpi_ev_asynch_execute_gpe_method,
gpe_event_info))) { gpe_event_info))) {
ACPI_REPORT_ERROR (( ACPI_REPORT_ERROR ((
"acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2.2X], event is disabled\n", "acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
gpe_number)); gpe_number));
} }
} }
...@@ -347,7 +388,7 @@ acpi_ev_gpe_dispatch ( ...@@ -347,7 +388,7 @@ acpi_ev_gpe_dispatch (
/* No handler or method to run! */ /* No handler or method to run! */
ACPI_REPORT_ERROR (( ACPI_REPORT_ERROR ((
"acpi_ev_gpe_dispatch: No handler or method for GPE[%2.2X], disabling event\n", "acpi_ev_gpe_dispatch: No handler or method for GPE[%2X], disabling event\n",
gpe_number)); gpe_number));
/* /*
...@@ -356,19 +397,18 @@ acpi_ev_gpe_dispatch ( ...@@ -356,19 +397,18 @@ acpi_ev_gpe_dispatch (
*/ */
status = acpi_hw_disable_gpe (gpe_event_info); status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2.2X]\n", ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
gpe_number)); gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
} }
} }
/* /* It is now safe to clear level-triggered events. */
* It is now safe to clear level-triggered evnets.
*/ if (gpe_event_info->flags & ACPI_EVENT_LEVEL_TRIGGERED) {
if (gpe_event_info->type & ACPI_EVENT_LEVEL_TRIGGERED) {
status = acpi_hw_clear_gpe (gpe_event_info); status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2.2X]\n", ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
gpe_number)); gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
} }
......
...@@ -46,7 +46,104 @@ ...@@ -46,7 +46,104 @@
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#define _COMPONENT ACPI_EVENTS #define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME ("evgpe") ACPI_MODULE_NAME ("evgpeblk")
/*******************************************************************************
*
* FUNCTION: acpi_ev_valid_gpe_event
*
* PARAMETERS: gpe_event_info - Info for this GPE
*
* RETURN: TRUE if the gpe_event is valid
*
* DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
*
******************************************************************************/
u8
acpi_ev_valid_gpe_event (
struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_xrupt_info *gpe_xrupt_block;
struct acpi_gpe_block_info *gpe_block;
/* No need for spin lock since we are not changing any list elements */
gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head;
while (gpe_xrupt_block) {
gpe_block = gpe_xrupt_block->gpe_block_list_head;
while (gpe_block) {
if ((&gpe_block->event_info[0] <= gpe_event_info) &&
(&gpe_block->event_info[gpe_block->register_count * 8] > gpe_event_info)) {
return (TRUE);
}
gpe_block = gpe_block->next;
}
gpe_xrupt_block = gpe_xrupt_block->next;
}
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_walk_gpe_list
*
* PARAMETERS: gpe_walk_callback - Routine called for each GPE block
*
* RETURN: Status
*
* DESCRIPTION: Walk the GPE lists.
* FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
acpi_status
acpi_ev_walk_gpe_list (
ACPI_GPE_CALLBACK gpe_walk_callback)
{
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE ("ev_walk_gpe_list");
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
/* Walk the interrupt level descriptor list */
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
while (gpe_xrupt_info) {
/* Walk all Gpe Blocks attached to this interrupt level */
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
/* One callback per GPE block */
status = gpe_walk_callback (gpe_xrupt_info, gpe_block);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
gpe_block = gpe_block->next;
}
gpe_xrupt_info = gpe_xrupt_info->next;
}
unlock_and_exit:
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
return_ACPI_STATUS (status);
}
/******************************************************************************* /*******************************************************************************
...@@ -131,11 +228,12 @@ acpi_ev_save_method_info ( ...@@ -131,11 +228,12 @@ acpi_ev_save_method_info (
/* Ensure that we have a valid GPE number for this GPE block */ /* Ensure that we have a valid GPE number for this GPE block */
if ((gpe_number < gpe_block->block_base_number) || if ((gpe_number < gpe_block->block_base_number) ||
(gpe_number >= (gpe_block->register_count * 8))) { (gpe_number >= (gpe_block->block_base_number + (gpe_block->register_count * 8)))) {
/* Not valid, all we can do here is ignore it */ /*
* Not valid for this GPE block, just ignore it
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, * However, it may be valid for a different GPE block, since GPE0 and GPE1
"GPE number associated with method %s is not valid\n", name)); * methods both appear under \_GPE.
*/
return (AE_OK); return (AE_OK);
} }
...@@ -145,7 +243,7 @@ acpi_ev_save_method_info ( ...@@ -145,7 +243,7 @@ acpi_ev_save_method_info (
*/ */
gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
gpe_event_info->type = type; gpe_event_info->flags = type;
gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle; gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
/* /*
...@@ -156,17 +254,92 @@ acpi_ev_save_method_info ( ...@@ -156,17 +254,92 @@ acpi_ev_save_method_info (
return (status); return (status);
} }
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %2.2X\n", ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Registered GPE method %s as GPE number 0x%.2X\n",
name, gpe_number)); name, gpe_number));
return (AE_OK); return (AE_OK);
} }
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_xrupt_block
*
* PARAMETERS: interrupt_level - Interrupt for a GPE block
*
* RETURN: A GPE interrupt block
*
* DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
* block per unique interrupt level used for GPEs.
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
*
******************************************************************************/
struct acpi_gpe_xrupt_info *
acpi_ev_get_gpe_xrupt_block (
u32 interrupt_level)
{
struct acpi_gpe_xrupt_info *next_gpe_xrupt;
struct acpi_gpe_xrupt_info *gpe_xrupt;
acpi_status status;
/* No need for spin lock since we are not changing any list elements here */
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt) {
if (next_gpe_xrupt->interrupt_level == interrupt_level) {
return (next_gpe_xrupt);
}
next_gpe_xrupt = next_gpe_xrupt->next;
}
/* Not found, must allocate a new xrupt descriptor */
gpe_xrupt = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_xrupt_info));
if (!gpe_xrupt) {
return (NULL);
}
gpe_xrupt->interrupt_level = interrupt_level;
/* Install new interrupt descriptor with spin lock */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
if (acpi_gbl_gpe_xrupt_list_head) {
next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
while (next_gpe_xrupt->next) {
next_gpe_xrupt = next_gpe_xrupt->next;
}
next_gpe_xrupt->next = gpe_xrupt;
gpe_xrupt->previous = next_gpe_xrupt;
}
else {
acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
}
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) {
status = acpi_os_install_interrupt_handler (interrupt_level,
acpi_ev_gpe_xrupt_handler, gpe_xrupt);
}
return (gpe_xrupt);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ev_install_gpe_block * FUNCTION: acpi_ev_install_gpe_block
* *
* PARAMETERS: gpe_block - New GPE block * PARAMETERS: gpe_block - New GPE block
* interrupt_level - Level to be associated with this GPE block
* *
* RETURN: Status * RETURN: Status
* *
...@@ -176,9 +349,11 @@ acpi_ev_save_method_info ( ...@@ -176,9 +349,11 @@ acpi_ev_save_method_info (
acpi_status acpi_status
acpi_ev_install_gpe_block ( acpi_ev_install_gpe_block (
struct acpi_gpe_block_info *gpe_block) struct acpi_gpe_block_info *gpe_block,
u32 interrupt_level)
{ {
struct acpi_gpe_block_info *next_gpe_block; struct acpi_gpe_block_info *next_gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_block;
acpi_status status; acpi_status status;
...@@ -187,10 +362,17 @@ acpi_ev_install_gpe_block ( ...@@ -187,10 +362,17 @@ acpi_ev_install_gpe_block (
return (status); return (status);
} }
/* Install the new block at the end of the global list */ gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block (interrupt_level);
if (!gpe_xrupt_block) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
/* Install the new block at the end of the list for this interrupt with lock */
if (acpi_gbl_gpe_block_list_head) { acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
next_gpe_block = acpi_gbl_gpe_block_list_head; if (gpe_xrupt_block->gpe_block_list_head) {
next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
while (next_gpe_block->next) { while (next_gpe_block->next) {
next_gpe_block = next_gpe_block->next; next_gpe_block = next_gpe_block->next;
} }
...@@ -199,9 +381,11 @@ acpi_ev_install_gpe_block ( ...@@ -199,9 +381,11 @@ acpi_ev_install_gpe_block (
gpe_block->previous = next_gpe_block; gpe_block->previous = next_gpe_block;
} }
else { else {
acpi_gbl_gpe_block_list_head = gpe_block; gpe_xrupt_block->gpe_block_list_head = gpe_block;
} }
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
unlock_and_exit:
status = acpi_ut_release_mutex (ACPI_MTX_EVENTS); status = acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return (status); return (status);
} }
...@@ -259,12 +443,16 @@ acpi_ev_create_gpe_info_blocks ( ...@@ -259,12 +443,16 @@ acpi_ev_create_gpe_info_blocks (
goto error_exit; goto error_exit;
} }
/* Save the new Info arrays in the GPE block */
gpe_block->register_info = gpe_register_info;
gpe_block->event_info = gpe_event_info;
/* /*
* Initialize the GPE Register and Event structures. A goal of these * Initialize the GPE Register and Event structures. A goal of these
* tables is to hide the fact that there are two separate GPE register sets * tables is to hide the fact that there are two separate GPE register sets
* in a given gpe hardware block, the status registers occupy the first half, * in a given gpe hardware block, the status registers occupy the first half,
* and the enable registers occupy the second half. Another goal is to hide * and the enable registers occupy the second half.
* the fact that there may be multiple GPE hardware blocks.
*/ */
this_register = gpe_register_info; this_register = gpe_register_info;
this_event = gpe_event_info; this_event = gpe_event_info;
...@@ -319,14 +507,10 @@ acpi_ev_create_gpe_info_blocks ( ...@@ -319,14 +507,10 @@ acpi_ev_create_gpe_info_blocks (
this_register++; this_register++;
} }
gpe_block->register_info = gpe_register_info;
gpe_block->event_info = gpe_event_info;
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
error_exit: error_exit:
if (gpe_register_info) { if (gpe_register_info) {
ACPI_MEM_FREE (gpe_register_info); ACPI_MEM_FREE (gpe_register_info);
} }
...@@ -334,7 +518,7 @@ acpi_ev_create_gpe_info_blocks ( ...@@ -334,7 +518,7 @@ acpi_ev_create_gpe_info_blocks (
ACPI_MEM_FREE (gpe_event_info); ACPI_MEM_FREE (gpe_event_info);
} }
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (status);
} }
...@@ -356,7 +540,8 @@ acpi_ev_create_gpe_block ( ...@@ -356,7 +540,8 @@ acpi_ev_create_gpe_block (
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,
u32 interrupt_level) u32 interrupt_level,
struct acpi_gpe_block_info **return_gpe_block)
{ {
struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_block_info *gpe_block;
acpi_status status; acpi_status status;
...@@ -400,9 +585,8 @@ acpi_ev_create_gpe_block ( ...@@ -400,9 +585,8 @@ acpi_ev_create_gpe_block (
} }
/* Install the new block in the global list(s) */ /* Install the new block in the global list(s) */
/* TBD: Install block in the interrupt handler list */
status = acpi_ev_install_gpe_block (gpe_block); status = acpi_ev_install_gpe_block (gpe_block, interrupt_level);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_MEM_FREE (gpe_block); ACPI_MEM_FREE (gpe_block);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
...@@ -415,7 +599,7 @@ acpi_ev_create_gpe_block ( ...@@ -415,7 +599,7 @@ acpi_ev_create_gpe_block (
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)));
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block defined as GPE%d to GPE%d\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,
(u32) (gpe_block->block_base_number + (u32) (gpe_block->block_base_number +
((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)))); ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1))));
...@@ -426,6 +610,9 @@ acpi_ev_create_gpe_block ( ...@@ -426,6 +610,9 @@ acpi_ev_create_gpe_block (
ACPI_UINT32_MAX, acpi_ev_save_method_info, ACPI_UINT32_MAX, acpi_ev_save_method_info,
gpe_block, NULL); gpe_block, NULL);
/* Return the new block */
(*return_gpe_block) = gpe_block;
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
} }
...@@ -448,6 +635,7 @@ acpi_ev_gpe_initialize (void) ...@@ -448,6 +635,7 @@ 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_status status;
ACPI_FUNCTION_TRACE ("ev_gpe_initialize"); ACPI_FUNCTION_TRACE ("ev_gpe_initialize");
...@@ -474,6 +662,7 @@ acpi_ev_gpe_initialize (void) ...@@ -474,6 +662,7 @@ acpi_ev_gpe_initialize (void)
* *
* Note: both GPE0 and GPE1 are optional, and either can exist without * Note: both GPE0 and GPE1 are optional, and either can exist without
* the other. * the other.
*
* If EITHER the register length OR the block address are zero, then that * If EITHER the register length OR the block address are zero, then that
* particular block is not supported. * particular block is not supported.
*/ */
...@@ -485,8 +674,15 @@ acpi_ev_gpe_initialize (void) ...@@ -485,8 +674,15 @@ acpi_ev_gpe_initialize (void)
gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
acpi_ev_create_gpe_block ("\\_GPE", &acpi_gbl_FADT->xgpe0_blk, /* Install GPE Block 0 */
register_count0, 0, acpi_gbl_FADT->sci_int);
status = acpi_ev_create_gpe_block ("\\_GPE", &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 ((
"Could not create GPE Block 0, %s\n",
acpi_format_exception (status)));
}
} }
if (acpi_gbl_FADT->gpe1_blk_len && if (acpi_gbl_FADT->gpe1_blk_len &&
...@@ -510,8 +706,16 @@ acpi_ev_gpe_initialize (void) ...@@ -510,8 +706,16 @@ acpi_ev_gpe_initialize (void)
register_count1 = 0; register_count1 = 0;
} }
else { else {
acpi_ev_create_gpe_block ("\\_GPE", &acpi_gbl_FADT->xgpe1_blk, /* Install GPE Block 1 */
register_count1, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->sci_int);
status = acpi_ev_create_gpe_block ("\\_GPE", &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)) {
ACPI_REPORT_ERROR ((
"Could not create GPE Block 1, %s\n",
acpi_format_exception (status)));
}
/* /*
* GPE0 and GPE1 do not have to be contiguous in the GPE number space, * GPE0 and GPE1 do not have to be contiguous in the GPE number space,
......
...@@ -525,7 +525,8 @@ acpi_ev_terminate (void) ...@@ -525,7 +525,8 @@ acpi_ev_terminate (void)
acpi_status status; acpi_status status;
struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_block_info *next_gpe_block; struct acpi_gpe_block_info *next_gpe_block;
struct acpi_gpe_event_info *gpe_event_info; 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");
...@@ -537,46 +538,29 @@ acpi_ev_terminate (void) ...@@ -537,46 +538,29 @@ acpi_ev_terminate (void)
* In all cases, on error, print a message but obviously we don't abort. * In all cases, on error, print a message but obviously we don't abort.
*/ */
/* /* Disable all fixed events */
* Disable all fixed events
*/
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
status = acpi_disable_event ((u32) i, ACPI_EVENT_FIXED, 0); status = acpi_disable_event ((u32) i, 0);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable fixed event %d\n", (u32) i)); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable fixed event %d\n", (u32) i));
} }
} }
/* /* Disable all GPEs in all GPE blocks */
* Disable all GPEs
*/
gpe_block = acpi_gbl_gpe_block_list_head;
while (gpe_block) {
gpe_event_info = gpe_block->event_info;
for (i = 0; i < (gpe_block->register_count * 8); i++) {
status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable GPE %d\n", (u32) i));
}
gpe_event_info++;
}
gpe_block = gpe_block->next; status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block);
}
/* Remove SCI handler */
/*
* Remove SCI handler
*/
status = acpi_ev_remove_sci_handler (); status = acpi_ev_remove_sci_handler ();
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not remove SCI handler\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not remove SCI handler\n"));
} }
} }
/* /* Return to original mode if necessary */
* Return to original mode if necessary
*/
if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
status = acpi_disable (); status = acpi_disable ();
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
...@@ -584,19 +568,23 @@ acpi_ev_terminate (void) ...@@ -584,19 +568,23 @@ acpi_ev_terminate (void)
} }
} }
/* /* Free global GPE blocks and related info structures */
* Free global GPE blocks and related info structures
*/ gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
gpe_block = acpi_gbl_gpe_block_list_head; while (gpe_xrupt_info) {
while (gpe_block) { gpe_block = gpe_xrupt_info->gpe_block_list_head;
next_gpe_block = gpe_block->next; while (gpe_block) {
ACPI_MEM_FREE (gpe_block->event_info); next_gpe_block = gpe_block->next;
ACPI_MEM_FREE (gpe_block->register_info); ACPI_MEM_FREE (gpe_block->event_info);
ACPI_MEM_FREE (gpe_block); ACPI_MEM_FREE (gpe_block->register_info);
ACPI_MEM_FREE (gpe_block);
gpe_block = next_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;
} }
...@@ -52,26 +52,26 @@ ...@@ -52,26 +52,26 @@
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ev_sci_handler * FUNCTION: acpi_ev_sci_xrupt_handler
* *
* PARAMETERS: Context - Calling Context * PARAMETERS: Context - Calling Context
* *
* RETURN: Status code indicates whether interrupt was handled. * RETURN: Status code indicates whether interrupt was handled.
* *
* DESCRIPTION: Interrupt handler that will figure out what function or * DESCRIPTION: Interrupt handler that will figure out what function or
* control method to call to deal with a SCI. Installed * control method to call to deal with a SCI.
* using BU interrupt support.
* *
******************************************************************************/ ******************************************************************************/
static u32 ACPI_SYSTEM_XFACE static u32 ACPI_SYSTEM_XFACE
acpi_ev_sci_handler ( acpi_ev_sci_xrupt_handler (
void *context) void *context)
{ {
struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED; u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE("ev_sci_handler"); ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler");
/* /*
...@@ -85,11 +85,51 @@ acpi_ev_sci_handler ( ...@@ -85,11 +85,51 @@ acpi_ev_sci_handler (
*/ */
interrupt_handled |= acpi_ev_fixed_event_detect (); interrupt_handled |= acpi_ev_fixed_event_detect ();
/* TBD: What if there are no GPEs defined? */
/*
* GPEs:
* Check for and dispatch any GPEs that have occurred
*/
interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
return_VALUE (interrupt_handled);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_xrupt_handler
*
* PARAMETERS: Context - Calling Context
*
* RETURN: Status code indicates whether interrupt was handled.
*
* DESCRIPTION: Handler for GPE Block Device interrupts
*
******************************************************************************/
u32 ACPI_SYSTEM_XFACE
acpi_ev_gpe_xrupt_handler (
void *context)
{
struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler");
/*
* We are guaranteed by the ACPI CA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
*/
/* /*
* GPEs: * GPEs:
* Check for and dispatch any GPEs that have occurred * Check for and dispatch any GPEs that have occurred
*/ */
interrupt_handled |= acpi_ev_gpe_detect (); interrupt_handled |= acpi_ev_gpe_detect (gpe_xrupt_list);
return_VALUE (interrupt_handled); return_VALUE (interrupt_handled);
} }
...@@ -117,7 +157,7 @@ acpi_ev_install_sci_handler (void) ...@@ -117,7 +157,7 @@ acpi_ev_install_sci_handler (void)
status = acpi_os_install_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, status = acpi_os_install_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
acpi_ev_sci_handler, NULL); acpi_ev_sci_xrupt_handler, acpi_gbl_gpe_xrupt_list_head);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -153,7 +193,7 @@ acpi_ev_remove_sci_handler (void) ...@@ -153,7 +193,7 @@ acpi_ev_remove_sci_handler (void)
/* Just let the OS remove the handler and disable the level */ /* Just let the OS remove the handler and disable the level */
status = acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, status = acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int,
acpi_ev_sci_handler); acpi_ev_sci_xrupt_handler);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
......
...@@ -102,7 +102,7 @@ acpi_install_fixed_event_handler ( ...@@ -102,7 +102,7 @@ acpi_install_fixed_event_handler (
acpi_gbl_fixed_event_handlers[event].handler = handler; acpi_gbl_fixed_event_handlers[event].handler = handler;
acpi_gbl_fixed_event_handlers[event].context = context; acpi_gbl_fixed_event_handlers[event].context = context;
status = acpi_enable_event (event, ACPI_EVENT_FIXED, 0); status = acpi_enable_event (event, 0);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n")); ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
...@@ -160,7 +160,7 @@ acpi_remove_fixed_event_handler ( ...@@ -160,7 +160,7 @@ acpi_remove_fixed_event_handler (
/* Disable the event before removing the handler */ /* Disable the event before removing the handler */
status = acpi_disable_event(event, ACPI_EVENT_FIXED, 0); status = acpi_disable_event (event, 0);
/* Always Remove the handler */ /* Always Remove the handler */
...@@ -471,8 +471,8 @@ acpi_remove_notify_handler ( ...@@ -471,8 +471,8 @@ acpi_remove_notify_handler (
* *
* FUNCTION: acpi_install_gpe_handler * FUNCTION: acpi_install_gpe_handler
* *
* PARAMETERS: gpe_number - The GPE number. The numbering scheme is * PARAMETERS: gpe_number - The GPE number within the GPE block
* bank 0 first, then bank 1. * gpe_block - GPE block (NULL == FADT GPEs)
* Type - Whether this GPE should be treated as an * Type - Whether this GPE should be treated as an
* edge- or level-triggered interrupt. * edge- or level-triggered interrupt.
* Handler - Address of the handler * Handler - Address of the handler
...@@ -486,6 +486,7 @@ acpi_remove_notify_handler ( ...@@ -486,6 +486,7 @@ acpi_remove_notify_handler (
acpi_status acpi_status
acpi_install_gpe_handler ( acpi_install_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number, u32 gpe_number,
u32 type, u32 type,
acpi_gpe_handler handler, acpi_gpe_handler handler,
...@@ -504,42 +505,45 @@ acpi_install_gpe_handler ( ...@@ -504,42 +505,45 @@ acpi_install_gpe_handler (
return_ACPI_STATUS (AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
} }
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info (gpe_number);
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
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_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure that there isn't a handler there already */ /* Make sure that there isn't a handler there already */
if (gpe_event_info->handler) { if (gpe_event_info->handler) {
status = AE_ALREADY_EXISTS; status = AE_ALREADY_EXISTS;
goto cleanup; goto unlock_and_exit;
} }
/* Install the handler */ /* Install the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
gpe_event_info->handler = handler; gpe_event_info->handler = handler;
gpe_event_info->context = context; gpe_event_info->context = context;
gpe_event_info->type = (u8) type; gpe_event_info->flags = (u8) type;
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
/* Clear the GPE (of stale events), the enable it */ /* Clear the GPE (of stale events), the enable it */
status = acpi_hw_clear_gpe (gpe_event_info); status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
goto cleanup; goto unlock_and_exit;
} }
status = acpi_hw_enable_gpe (gpe_event_info); status = acpi_hw_enable_gpe (gpe_event_info);
cleanup: unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -550,6 +554,7 @@ acpi_install_gpe_handler ( ...@@ -550,6 +554,7 @@ acpi_install_gpe_handler (
* FUNCTION: acpi_remove_gpe_handler * FUNCTION: acpi_remove_gpe_handler
* *
* PARAMETERS: gpe_number - The event to remove a handler * PARAMETERS: gpe_number - The event to remove a handler
* gpe_block - GPE block (NULL == FADT GPEs)
* Handler - Address of the handler * Handler - Address of the handler
* *
* RETURN: Status * RETURN: Status
...@@ -560,6 +565,7 @@ acpi_install_gpe_handler ( ...@@ -560,6 +565,7 @@ acpi_install_gpe_handler (
acpi_status acpi_status
acpi_remove_gpe_handler ( acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number, u32 gpe_number,
acpi_gpe_handler handler) acpi_gpe_handler handler)
{ {
...@@ -576,23 +582,24 @@ acpi_remove_gpe_handler ( ...@@ -576,23 +582,24 @@ acpi_remove_gpe_handler (
return_ACPI_STATUS (AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
} }
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 */
gpe_event_info = acpi_ev_get_gpe_event_info (gpe_number); gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
if (!gpe_event_info) { if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER); status = AE_BAD_PARAMETER;
goto unlock_and_exit;
} }
/* Disable the GPE before removing the handler */ /* Disable the GPE before removing the handler */
status = acpi_hw_disable_gpe (gpe_event_info); status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); goto unlock_and_exit;
}
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
} }
/* Make sure that the installed handler is the same */ /* Make sure that the installed handler is the same */
...@@ -600,16 +607,18 @@ acpi_remove_gpe_handler ( ...@@ -600,16 +607,18 @@ acpi_remove_gpe_handler (
if (gpe_event_info->handler != handler) { if (gpe_event_info->handler != handler) {
(void) acpi_hw_enable_gpe (gpe_event_info); (void) acpi_hw_enable_gpe (gpe_event_info);
status = AE_BAD_PARAMETER; status = AE_BAD_PARAMETER;
goto cleanup; goto unlock_and_exit;
} }
/* Remove the handler */ /* Remove the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
gpe_event_info->handler = NULL; gpe_event_info->handler = NULL;
gpe_event_info->context = NULL; gpe_event_info->context = NULL;
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
cleanup: unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS); (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
......
...@@ -145,94 +145,114 @@ acpi_disable (void) ...@@ -145,94 +145,114 @@ acpi_disable (void)
* *
* FUNCTION: acpi_enable_event * FUNCTION: acpi_enable_event
* *
* PARAMETERS: Event - The fixed event or GPE to be enabled * PARAMETERS: Event - The fixed eventto be enabled
* Type - The type of event * Flags - Reserved
* Flags - Just enable, or also wake enable?
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Enable an ACPI event (fixed and general purpose) * DESCRIPTION: Enable an ACPI event (fixed)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_enable_event ( acpi_enable_event (
u32 event, u32 event,
u32 type,
u32 flags) u32 flags)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
u32 value; u32 value;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_enable_event"); ACPI_FUNCTION_TRACE ("acpi_enable_event");
/* The Type must be either Fixed Event or GPE */ /* Decode the Fixed Event */
switch (type) { if (event > ACPI_EVENT_MAX) {
case ACPI_EVENT_FIXED: return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */ /*
* Enable the requested fixed event (by writing a one to the
* enable register bit)
*/
status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
1, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (event > ACPI_EVENT_MAX) { /* Make sure that the hardware responded */
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
* Enable the requested fixed event (by writing a one to the &value, ACPI_MTX_LOCK);
* enable register bit) if (ACPI_FAILURE (status)) {
*/ return_ACPI_STATUS (status);
status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, }
1, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Make sure that the hardware responded */ if (value != 1) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Could not enable %s event\n", acpi_ut_get_event_name (event)));
return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
}
status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, return_ACPI_STATUS (status);
&value, ACPI_MTX_LOCK); }
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (value != 1) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Could not enable %s event\n", acpi_ut_get_event_name (event)));
return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
}
break;
/*******************************************************************************
*
* FUNCTION: acpi_enable_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable?
*
* RETURN: Status
*
* DESCRIPTION: Enable an ACPI event (general purpose)
*
******************************************************************************/
case ACPI_EVENT_GPE: acpi_status
acpi_enable_gpe (
acpi_handle gpe_device,
u32 gpe_number,
u32 flags)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info (event); ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Enable the requested GPE number */
status = acpi_hw_enable_gpe (gpe_event_info); status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
if (flags & ACPI_EVENT_WAKE_ENABLE) { /* Ensure that we have a valid GPE number */
acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
}
break;
gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
default: /* Enable the requested GPE number */
status = AE_BAD_PARAMETER; status = acpi_hw_enable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
} }
if (flags & ACPI_EVENT_WAKE_ENABLE) {
acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
}
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -241,92 +261,112 @@ acpi_enable_event ( ...@@ -241,92 +261,112 @@ acpi_enable_event (
* *
* FUNCTION: acpi_disable_event * FUNCTION: acpi_disable_event
* *
* PARAMETERS: Event - The fixed event or GPE to be enabled * PARAMETERS: Event - The fixed eventto be enabled
* Type - The type of event, fixed or general purpose * Flags - Reserved
* Flags - Wake disable vs. non-wake disable
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Disable an ACPI event (fixed and general purpose) * DESCRIPTION: Disable an ACPI event (fixed)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_disable_event ( acpi_disable_event (
u32 event, u32 event,
u32 type,
u32 flags) u32 flags)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
u32 value; u32 value;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_disable_event"); ACPI_FUNCTION_TRACE ("acpi_disable_event");
/* The Type must be either Fixed Event or GPE */ /* Decode the Fixed Event */
switch (type) { if (event > ACPI_EVENT_MAX) {
case ACPI_EVENT_FIXED: return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */ /*
* Disable the requested fixed event (by writing a zero to the
* enable register bit)
*/
status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
0, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (event > ACPI_EVENT_MAX) { status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
return_ACPI_STATUS (AE_BAD_PARAMETER); &value, ACPI_MTX_LOCK);
} if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* if (value != 0) {
* Disable the requested fixed event (by writing a zero to the ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
* enable register bit) "Could not disable %s events\n", acpi_ut_get_event_name (event)));
*/ return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id, }
0, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id, return_ACPI_STATUS (status);
&value, ACPI_MTX_LOCK); }
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (value != 0) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Could not disable %s events\n", acpi_ut_get_event_name (event)));
return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
}
break;
/*******************************************************************************
*
* FUNCTION: acpi_disable_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable?
*
* RETURN: Status
*
* DESCRIPTION: Disable an ACPI event (general purpose)
*
******************************************************************************/
case ACPI_EVENT_GPE: acpi_status
acpi_disable_gpe (
acpi_handle gpe_device,
u32 gpe_number,
u32 flags)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info (event); ACPI_FUNCTION_TRACE ("acpi_disable_gpe");
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/*
* Only disable the requested GPE number for wake if specified.
* Otherwise, turn it totally off
*/
if (flags & ACPI_EVENT_WAKE_DISABLE) { status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
acpi_hw_disable_gpe_for_wakeup (gpe_event_info); if (ACPI_FAILURE (status)) {
} return_ACPI_STATUS (status);
else { }
status = acpi_hw_disable_gpe (gpe_event_info);
}
break;
/* Ensure that we have a valid GPE number */
default: gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER; status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/*
* Only disable the requested GPE number for wake if specified.
* Otherwise, turn it totally off
*/
if (flags & ACPI_EVENT_WAKE_DISABLE) {
acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
}
else {
status = acpi_hw_disable_gpe (gpe_event_info);
} }
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -335,65 +375,83 @@ acpi_disable_event ( ...@@ -335,65 +375,83 @@ acpi_disable_event (
* *
* FUNCTION: acpi_clear_event * FUNCTION: acpi_clear_event
* *
* PARAMETERS: Event - The fixed event or GPE to be cleared * PARAMETERS: Event - The fixed event to be cleared
* Type - The type of event
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Clear an ACPI event (fixed and general purpose) * DESCRIPTION: Clear an ACPI event (fixed)
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_clear_event ( acpi_clear_event (
u32 event, u32 event)
u32 type)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_clear_event"); ACPI_FUNCTION_TRACE ("acpi_clear_event");
/* The Type must be either Fixed Event or GPE */ /* Decode the Fixed Event */
switch (type) { if (event > ACPI_EVENT_MAX) {
case ACPI_EVENT_FIXED: return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */ /*
* Clear the requested fixed event (By writing a one to the
* status register bit)
*/
status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
1, ACPI_MTX_LOCK);
if (event > ACPI_EVENT_MAX) { return_ACPI_STATUS (status);
return_ACPI_STATUS (AE_BAD_PARAMETER); }
}
/*
* Clear the requested fixed event (By writing a one to the
* status register bit)
*/
status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
1, ACPI_MTX_LOCK);
break;
/*******************************************************************************
*
* FUNCTION: acpi_clear_gpe
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
* DESCRIPTION: Clear an ACPI event (general purpose)
*
******************************************************************************/
case ACPI_EVENT_GPE: acpi_status
acpi_clear_gpe (
acpi_handle gpe_device,
u32 gpe_number)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info (event); ACPI_FUNCTION_TRACE ("acpi_clear_gpe");
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
status = acpi_hw_clear_gpe (gpe_event_info);
break;
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
default: /* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER; status = AE_BAD_PARAMETER;
goto unlock_and_exit;
} }
status = acpi_hw_clear_gpe (gpe_event_info);
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -402,9 +460,8 @@ acpi_clear_event ( ...@@ -402,9 +460,8 @@ acpi_clear_event (
* *
* FUNCTION: acpi_get_event_status * FUNCTION: acpi_get_event_status
* *
* PARAMETERS: Event - The fixed event or GPE * PARAMETERS: Event - The fixed event
* Type - The type of event * Event Status - Where the current status of the event will
* Status - Where the current status of the event will
* be returned * be returned
* *
* RETURN: Status * RETURN: Status
...@@ -413,15 +470,12 @@ acpi_clear_event ( ...@@ -413,15 +470,12 @@ acpi_clear_event (
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_get_event_status ( acpi_get_event_status (
u32 event, u32 event,
u32 type,
acpi_event_status *event_status) acpi_event_status *event_status)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_get_event_status"); ACPI_FUNCTION_TRACE ("acpi_get_event_status");
...@@ -431,44 +485,68 @@ acpi_get_event_status ( ...@@ -431,44 +485,68 @@ acpi_get_event_status (
return_ACPI_STATUS (AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
} }
/* Decode the Fixed Event */
/* The Type must be either Fixed Event or GPE */ if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
switch (type) { }
case ACPI_EVENT_FIXED:
/* Decode the Fixed Event */ /* Get the status of the requested fixed event */
if (event > ACPI_EVENT_MAX) { status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id,
return_ACPI_STATUS (AE_BAD_PARAMETER); event_status, ACPI_MTX_LOCK);
}
/* Get the status of the requested fixed event */ return_ACPI_STATUS (status);
}
status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id,
event_status, ACPI_MTX_LOCK);
break;
/*******************************************************************************
*
* FUNCTION: acpi_get_gpe_status
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Event Status - Where the current status of the event will
* be returned
*
* RETURN: Status
*
* DESCRIPTION: Get status of an event (general purpose)
*
******************************************************************************/
case ACPI_EVENT_GPE: acpi_status
acpi_get_gpe_status (
acpi_handle gpe_device,
u32 gpe_number,
acpi_event_status *event_status)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info (event); ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Obtain status on the requested GPE number */
status = acpi_hw_get_gpe_status (event, event_status); status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
break; if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Ensure that we have a valid GPE number */
default: gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER; status = AE_BAD_PARAMETER;
goto unlock_and_exit;
} }
/* Obtain status on the requested GPE number */
status = acpi_hw_get_gpe_status (gpe_event_info, event_status);
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
......
...@@ -266,13 +266,12 @@ acpi_hw_clear_gpe ( ...@@ -266,13 +266,12 @@ acpi_hw_clear_gpe (
acpi_status acpi_status
acpi_hw_get_gpe_status ( acpi_hw_get_gpe_status (
u32 gpe_number, struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status) acpi_event_status *event_status)
{ {
u32 in_byte; u32 in_byte;
u8 bit_mask; u8 bit_mask;
struct acpi_gpe_register_info *gpe_register_info; struct acpi_gpe_register_info *gpe_register_info;
struct acpi_gpe_event_info *gpe_event_info;
acpi_status status; acpi_status status;
acpi_event_status local_event_status = 0; acpi_event_status local_event_status = 0;
...@@ -284,11 +283,6 @@ acpi_hw_get_gpe_status ( ...@@ -284,11 +283,6 @@ acpi_hw_get_gpe_status (
return (AE_BAD_PARAMETER); return (AE_BAD_PARAMETER);
} }
gpe_event_info = acpi_ev_get_gpe_event_info (gpe_number);
if (!gpe_event_info) {
return (AE_BAD_PARAMETER);
}
/* Get the info block for the entire GPE register */ /* Get the info block for the entire GPE register */
gpe_register_info = gpe_event_info->register_info; gpe_register_info = gpe_event_info->register_info;
...@@ -301,7 +295,7 @@ acpi_hw_get_gpe_status ( ...@@ -301,7 +295,7 @@ acpi_hw_get_gpe_status (
status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address, 0); status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address, 0);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return (status); goto unlock_and_exit;
} }
if (bit_mask & in_byte) { if (bit_mask & in_byte) {
...@@ -318,7 +312,7 @@ acpi_hw_get_gpe_status ( ...@@ -318,7 +312,7 @@ acpi_hw_get_gpe_status (
status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address, 0); status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address, 0);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return (status); goto unlock_and_exit;
} }
if (bit_mask & in_byte) { if (bit_mask & in_byte) {
...@@ -328,6 +322,150 @@ acpi_hw_get_gpe_status ( ...@@ -328,6 +322,150 @@ acpi_hw_get_gpe_status (
/* Set return value */ /* Set return value */
(*event_status) = local_event_status; (*event_status) = local_event_status;
unlock_and_exit:
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_disable_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Disable all GPEs within a GPE block
*
******************************************************************************/
acpi_status
acpi_hw_disable_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
{
u32 i;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
status = acpi_hw_low_level_write (8, 0x00,
&gpe_block->register_info[i].enable_address, (u32) i);
if (ACPI_FAILURE (status)) {
return (status);
}
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_clear_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Clear all GPEs within a GPE block
*
******************************************************************************/
acpi_status
acpi_hw_clear_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
{
u32 i;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
status = acpi_hw_low_level_write (8, 0xFF,
&gpe_block->register_info[i].status_address, (u32) i);
if (ACPI_FAILURE (status)) {
return (status);
}
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_disable_non_wakeup_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Disable all GPEs except wakeup GPEs in a GPE block
*
******************************************************************************/
acpi_status
acpi_hw_disable_non_wakeup_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
{
u32 i;
struct acpi_gpe_register_info *gpe_register_info;
u32 in_value;
acpi_status status;
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/*
* Read the enabled status of all GPEs. We
* will be using it to restore all the GPEs later.
*/
status = acpi_hw_low_level_read (8, &in_value,
&gpe_register_info->enable_address, 0);
if (ACPI_FAILURE (status)) {
return (status);
}
gpe_register_info->enable = (u8) in_value;
/*
* Disable all GPEs except wakeup GPEs.
*/
status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
&gpe_register_info->enable_address, 0);
if (ACPI_FAILURE (status)) {
return (status);
}
gpe_register_info++;
}
return (AE_OK); return (AE_OK);
} }
...@@ -341,7 +479,7 @@ acpi_hw_get_gpe_status ( ...@@ -341,7 +479,7 @@ acpi_hw_get_gpe_status (
* RETURN: None * RETURN: None
* *
* DESCRIPTION: Disable all non-wakeup GPEs * DESCRIPTION: Disable all non-wakeup GPEs
* Call with interrupts disabled. The interrupt handler also * Called with interrupts disabled. The interrupt handler also
* modifies gpe_register_info->Enable, so it should not be * modifies gpe_register_info->Enable, so it should not be
* given the chance to run until after non-wake GPEs are * given the chance to run until after non-wake GPEs are
* re-enabled. * re-enabled.
...@@ -351,54 +489,65 @@ acpi_hw_get_gpe_status ( ...@@ -351,54 +489,65 @@ acpi_hw_get_gpe_status (
acpi_status acpi_status
acpi_hw_disable_non_wakeup_gpes ( acpi_hw_disable_non_wakeup_gpes (
void) void)
{
acpi_status status;
ACPI_FUNCTION_ENTRY ();
status = acpi_ev_walk_gpe_list (acpi_hw_disable_non_wakeup_gpe_block);
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_non_wakeup_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Enable a single GPE.
*
******************************************************************************/
acpi_status
acpi_hw_enable_non_wakeup_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
{ {
u32 i; u32 i;
struct acpi_gpe_register_info *gpe_register_info; struct acpi_gpe_register_info *gpe_register_info;
u32 in_value;
acpi_status status; acpi_status status;
struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_ENTRY (); /* This callback processes one entire GPE block */
/* Get the register info for the entire GPE block */
gpe_block = acpi_gbl_gpe_block_list_head; gpe_register_info = gpe_block->register_info;
while (gpe_block) {
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info; /* Examine each GPE register within the block */
if (!gpe_register_info) {
return (AE_BAD_PARAMETER);
}
for (i = 0; i < gpe_block->register_count; i++) { for (i = 0; i < gpe_block->register_count; i++) {
/* /*
* Read the enabled status of all GPEs. We * We previously stored the enabled status of all GPEs.
* will be using it to restore all the GPEs later. * Blast them back in.
*/ */
status = acpi_hw_low_level_read (8, &in_value, status = acpi_hw_low_level_write (8, gpe_register_info->enable,
&gpe_register_info->enable_address, 0); &gpe_register_info->enable_address, 0);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
return (status); return (status);
}
gpe_register_info->enable = (u8) in_value;
/*
* Disable all GPEs except wakeup GPEs.
*/
status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
&gpe_register_info->enable_address, 0);
if (ACPI_FAILURE (status)) {
return (status);
}
gpe_register_info++;
} }
gpe_block = gpe_block->next; gpe_register_info++;
} }
return (AE_OK); return (AE_OK);
} }
...@@ -419,40 +568,13 @@ acpi_status ...@@ -419,40 +568,13 @@ acpi_status
acpi_hw_enable_non_wakeup_gpes ( acpi_hw_enable_non_wakeup_gpes (
void) void)
{ {
u32 i;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status; acpi_status status;
struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_ENTRY (); ACPI_FUNCTION_ENTRY ();
gpe_block = acpi_gbl_gpe_block_list_head; status = acpi_ev_walk_gpe_list (acpi_hw_enable_non_wakeup_gpe_block);
while (gpe_block) {
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info; return (status);
if (!gpe_register_info) {
return (AE_BAD_PARAMETER);
}
for (i = 0; i < gpe_block->register_count; i++) {
/*
* We previously stored the enabled status of all GPEs.
* Blast them back in.
*/
status = acpi_hw_low_level_write (8, gpe_register_info->enable,
&gpe_register_info->enable_address, 0);
if (ACPI_FAILURE (status)) {
return (status);
}
gpe_register_info++;
}
gpe_block = gpe_block->next;
}
return (AE_OK);
} }
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <acpi/acnamesp.h> #include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_HARDWARE #define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME ("hwregs") ACPI_MODULE_NAME ("hwregs")
...@@ -66,9 +67,7 @@ ...@@ -66,9 +67,7 @@
acpi_status acpi_status
acpi_hw_clear_acpi_status (void) acpi_hw_clear_acpi_status (void)
{ {
acpi_native_uint i;
acpi_status status; acpi_status status;
struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_TRACE ("hw_clear_acpi_status"); ACPI_FUNCTION_TRACE ("hw_clear_acpi_status");
...@@ -102,18 +101,7 @@ acpi_hw_clear_acpi_status (void) ...@@ -102,18 +101,7 @@ acpi_hw_clear_acpi_status (void)
/* Clear the GPE Bits in all GPE registers in all GPE blocks */ /* Clear the GPE Bits in all GPE registers in all GPE blocks */
gpe_block = acpi_gbl_gpe_block_list_head; status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
while (gpe_block) {
for (i = 0; i < gpe_block->register_count; i++) {
status = acpi_hw_low_level_write (8, 0xFF,
&gpe_block->register_info[i].status_address, (u32) i);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
}
gpe_block = gpe_block->next;
}
unlock_and_exit: unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE); (void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
......
...@@ -73,6 +73,7 @@ acpi_ns_root_initialize (void) ...@@ -73,6 +73,7 @@ acpi_ns_root_initialize (void)
const struct acpi_predefined_names *init_val = NULL; const struct acpi_predefined_names *init_val = NULL;
struct acpi_namespace_node *new_node; struct acpi_namespace_node *new_node;
union acpi_operand_object *obj_desc; union acpi_operand_object *obj_desc;
acpi_string val = NULL;
ACPI_FUNCTION_TRACE ("ns_root_initialize"); ACPI_FUNCTION_TRACE ("ns_root_initialize");
...@@ -119,9 +120,7 @@ acpi_ns_root_initialize (void) ...@@ -119,9 +120,7 @@ acpi_ns_root_initialize (void)
* initial value, create the initial value. * initial value, create the initial value.
*/ */
if (init_val->val) { if (init_val->val) {
acpi_string val; status = acpi_os_predefined_override (init_val, &val);
status = acpi_os_predefined_override(init_val, &val);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not override predefined %s\n", ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not override predefined %s\n",
init_val->name)); init_val->name));
......
...@@ -164,6 +164,7 @@ acpi_ns_walk_namespace ( ...@@ -164,6 +164,7 @@ acpi_ns_walk_namespace (
void **return_value) void **return_value)
{ {
acpi_status status; acpi_status status;
acpi_status mutex_status;
struct acpi_namespace_node *child_node; struct acpi_namespace_node *child_node;
struct acpi_namespace_node *parent_node; struct acpi_namespace_node *parent_node;
acpi_object_type child_type; acpi_object_type child_type;
...@@ -211,9 +212,9 @@ acpi_ns_walk_namespace ( ...@@ -211,9 +212,9 @@ acpi_ns_walk_namespace (
* callback function * callback function
*/ */
if (unlock_before_callback) { if (unlock_before_callback) {
status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); mutex_status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (mutex_status)) {
return_ACPI_STATUS (status); return_ACPI_STATUS (mutex_status);
} }
} }
...@@ -221,9 +222,9 @@ acpi_ns_walk_namespace ( ...@@ -221,9 +222,9 @@ acpi_ns_walk_namespace (
context, return_value); context, return_value);
if (unlock_before_callback) { if (unlock_before_callback) {
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); mutex_status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (mutex_status)) {
return_ACPI_STATUS (status); return_ACPI_STATUS (mutex_status);
} }
} }
......
...@@ -581,24 +581,32 @@ acpi_os_derive_pci_id ( ...@@ -581,24 +581,32 @@ acpi_os_derive_pci_id (
acpi_status acpi_status
acpi_os_write_pci_configuration ( acpi_os_write_pci_configuration (
acpi_pci_id *pci_id, struct acpi_pci_id *pci_id,
u32 reg, u32 reg,
acpi_integer value, acpi_integer value,
u32 width) u32 width)
{ {
return (AE_SUPPORT); return (AE_SUPPORT);
} }
acpi_status acpi_status
acpi_os_read_pci_configuration ( acpi_os_read_pci_configuration (
acpi_pci_id *pci_id, struct acpi_pci_id *pci_id,
u32 reg, u32 reg,
void *value, void *value,
u32 width) u32 width)
{ {
return (AE_SUPPORT); return (AE_SUPPORT);
} }
void
acpi_os_derive_pci_id (
acpi_handle rhandle, /* upper bound */
acpi_handle chandle, /* current node */
struct acpi_pci_id **id)
{
}
#endif /*CONFIG_ACPI_PCI*/ #endif /*CONFIG_ACPI_PCI*/
static void static void
...@@ -669,6 +677,92 @@ acpi_os_queue_for_execution( ...@@ -669,6 +677,92 @@ acpi_os_queue_for_execution(
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
/*
* Allocate the memory for a spinlock and initialize it.
*/
acpi_status
acpi_os_create_lock (
acpi_handle *out_handle)
{
spinlock_t *lock_ptr;
ACPI_FUNCTION_TRACE ("os_create_lock");
lock_ptr = acpi_os_allocate(sizeof(spinlock_t));
spin_lock_init(lock_ptr);
ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr));
*out_handle = lock_ptr;
return_ACPI_STATUS (AE_OK);
}
/*
* Deallocate the memory for a spinlock.
*/
void
acpi_os_delete_lock (
acpi_handle handle)
{
ACPI_FUNCTION_TRACE ("os_create_lock");
ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
acpi_os_free(handle);
return_VOID;
}
/*
* Acquire a spinlock.
*
* handle is a pointer to the spinlock_t.
* flags is *not* the result of save_flags - it is an ACPI-specific flag variable
* that indicates whether we are at interrupt level.
*/
void
acpi_os_acquire_lock (
acpi_handle handle,
u32 flags)
{
ACPI_FUNCTION_TRACE ("os_acquire_lock");
ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Acquiring spinlock[%p] from %s level\n", handle,
((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
if (flags & ACPI_NOT_ISR)
ACPI_DISABLE_IRQS();
spin_lock(handle);
return_VOID;
}
/*
* Release a spinlock. See above.
*/
void
acpi_os_release_lock (
acpi_handle handle,
u32 flags)
{
ACPI_FUNCTION_TRACE ("os_release_lock");
ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Releasing spinlock[%p] from %s level\n", handle,
((flags & ACPI_NOT_ISR) ? "non-interrupt" : "interrupt")));
spin_unlock(handle);
if (flags & ACPI_NOT_ISR)
ACPI_ENABLE_IRQS();
return_VOID;
}
acpi_status acpi_status
acpi_os_create_semaphore( acpi_os_create_semaphore(
......
...@@ -639,7 +639,7 @@ acpi_processor_get_power_info ( ...@@ -639,7 +639,7 @@ acpi_processor_get_power_info (
/* /*
* C2 latency must be less than or equal to 100 microseconds. * C2 latency must be less than or equal to 100 microseconds.
*/ */
if (acpi_fadt.plvl2_lat >= ACPI_PROCESSOR_MAX_C2_LATENCY) if (acpi_fadt.plvl2_lat > ACPI_PROCESSOR_MAX_C2_LATENCY)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C2 latency too large [%d]\n", "C2 latency too large [%d]\n",
acpi_fadt.plvl2_lat)); acpi_fadt.plvl2_lat));
...@@ -673,7 +673,7 @@ acpi_processor_get_power_info ( ...@@ -673,7 +673,7 @@ acpi_processor_get_power_info (
/* /*
* C3 latency must be less than or equal to 1000 microseconds. * C3 latency must be less than or equal to 1000 microseconds.
*/ */
if (acpi_fadt.plvl3_lat >= ACPI_PROCESSOR_MAX_C3_LATENCY) if (acpi_fadt.plvl3_lat > ACPI_PROCESSOR_MAX_C3_LATENCY)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"C3 latency too large [%d]\n", "C3 latency too large [%d]\n",
acpi_fadt.plvl3_lat)); acpi_fadt.plvl3_lat));
......
...@@ -240,12 +240,13 @@ acpi_walk_resources ( ...@@ -240,12 +240,13 @@ acpi_walk_resources (
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
struct acpi_resource *resource; struct acpi_resource *resource;
ACPI_FUNCTION_TRACE ("acpi_walk_resources"); ACPI_FUNCTION_TRACE ("acpi_walk_resources");
if (!device_handle || if (!device_handle ||
(ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) && (ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) &&
ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) { ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) {
return_ACPI_STATUS (AE_BAD_PARAMETER); return_ACPI_STATUS (AE_BAD_PARAMETER);
} }
...@@ -290,10 +291,10 @@ acpi_walk_resources ( ...@@ -290,10 +291,10 @@ acpi_walk_resources (
cleanup: cleanup:
acpi_os_free (buffer.pointer); acpi_os_free (buffer.pointer);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_set_current_resources * FUNCTION: acpi_set_current_resources
...@@ -337,6 +338,7 @@ acpi_set_current_resources ( ...@@ -337,6 +338,7 @@ acpi_set_current_resources (
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
#define COPY_FIELD(out, in, field) out->field = in->field #define COPY_FIELD(out, in, field) out->field = in->field
#define COPY_ADDRESS(out, in) \ #define COPY_ADDRESS(out, in) \
COPY_FIELD(out, in, resource_type); \ COPY_FIELD(out, in, resource_type); \
...@@ -352,48 +354,53 @@ acpi_set_current_resources ( ...@@ -352,48 +354,53 @@ acpi_set_current_resources (
COPY_FIELD(out, in, address_length); \ COPY_FIELD(out, in, address_length); \
COPY_FIELD(out, in, resource_source); COPY_FIELD(out, in, resource_source);
/******************************************************************************* /******************************************************************************
* *
* FUNCTION: acpi_resource_to_address64 * FUNCTION: acpi_resource_to_address64
* *
* PARAMETERS: resource - Pointer to a resource * PARAMETERS: resource - Pointer to a resource
* out - Pointer to the users's return * out - Pointer to the users's return
* buffer (a struct * buffer (a struct
* struct acpi_resource_address64) * struct acpi_resource_address64)
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: If the resource is an address16, address32, or address64, * DESCRIPTION: If the resource is an address16, address32, or address64,
* copy it to the address64 return buffer. This saves the * copy it to the address64 return buffer. This saves the
* caller from having to duplicate code for different-sized * caller from having to duplicate code for different-sized
* addresses. * addresses.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_resource_to_address64 ( acpi_resource_to_address64 (
struct acpi_resource *resource, struct acpi_resource *resource,
struct acpi_resource_address64 *out) struct acpi_resource_address64 *out)
{ {
struct acpi_resource_address16 *address16; struct acpi_resource_address16 *address16;
struct acpi_resource_address32 *address32; struct acpi_resource_address32 *address32;
struct acpi_resource_address64 *address64; struct acpi_resource_address64 *address64;
switch (resource->id) { switch (resource->id) {
case ACPI_RSTYPE_ADDRESS16: case ACPI_RSTYPE_ADDRESS16:
address16 = (struct acpi_resource_address16 *) &resource->data; address16 = (struct acpi_resource_address16 *) &resource->data;
COPY_ADDRESS(out, address16); COPY_ADDRESS(out, address16);
break; break;
case ACPI_RSTYPE_ADDRESS32: case ACPI_RSTYPE_ADDRESS32:
address32 = (struct acpi_resource_address32 *) &resource->data; address32 = (struct acpi_resource_address32 *) &resource->data;
COPY_ADDRESS(out, address32); COPY_ADDRESS(out, address32);
break; break;
case ACPI_RSTYPE_ADDRESS64: case ACPI_RSTYPE_ADDRESS64:
address64 = (struct acpi_resource_address64 *) &resource->data; address64 = (struct acpi_resource_address64 *) &resource->data;
COPY_ADDRESS(out, address64); COPY_ADDRESS(out, address64);
break; break;
default: default:
return (AE_BAD_PARAMETER); return (AE_BAD_PARAMETER);
} }
return (AE_OK); return (AE_OK);
} }
...@@ -228,7 +228,7 @@ acpi_tb_get_required_tables ( ...@@ -228,7 +228,7 @@ acpi_tb_get_required_tables (
* any SSDTs. * any SSDTs.
*/ */
for (i = 0; i < acpi_gbl_rsdt_table_count; i++) { for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
/* Get the table addresss from the common internal XSDT */ /* Get the table address from the common internal XSDT */
address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i]; address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i];
......
...@@ -731,7 +731,9 @@ acpi_ut_init_globals ( ...@@ -731,7 +731,9 @@ acpi_ut_init_globals (
/* GPE support */ /* GPE support */
acpi_gbl_gpe_block_list_head = NULL; acpi_gbl_gpe_xrupt_list_head = NULL;
acpi_gbl_gpe_fadt_blocks[0] = NULL;
acpi_gbl_gpe_fadt_blocks[1] = NULL;
/* Global notify handlers */ /* Global notify handlers */
......
...@@ -556,6 +556,9 @@ acpi_ut_mutex_initialize ( ...@@ -556,6 +556,9 @@ acpi_ut_mutex_initialize (
} }
} }
status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
} }
...@@ -589,6 +592,7 @@ acpi_ut_mutex_terminate ( ...@@ -589,6 +592,7 @@ acpi_ut_mutex_terminate (
(void) acpi_ut_delete_mutex (i); (void) acpi_ut_delete_mutex (i);
} }
(void) acpi_os_delete_lock (acpi_gbl_gpe_lock);
return_VOID; return_VOID;
} }
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
/* Version string */ /* Version string */
#define ACPI_CA_VERSION 0x20030228 #define ACPI_CA_VERSION 0x20030321
/* Version of ACPI supported */ /* Version of ACPI supported */
......
...@@ -109,8 +109,17 @@ acpi_ev_notify_dispatch ( ...@@ -109,8 +109,17 @@ acpi_ev_notify_dispatch (
* Evgpe - GPE handling and dispatch * Evgpe - GPE handling and dispatch
*/ */
acpi_status
acpi_ev_walk_gpe_list (
ACPI_GPE_CALLBACK gpe_walk_callback);
u8
acpi_ev_valid_gpe_event (
struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_event_info * struct acpi_gpe_event_info *
acpi_ev_get_gpe_event_info ( acpi_ev_get_gpe_event_info (
acpi_handle gpe_device,
u32 gpe_number); u32 gpe_number);
acpi_status acpi_status
...@@ -119,11 +128,12 @@ acpi_ev_gpe_initialize ( ...@@ -119,11 +128,12 @@ acpi_ev_gpe_initialize (
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,
u32 gpe_number);
u32 u32
acpi_ev_gpe_detect ( acpi_ev_gpe_detect (
void); struct acpi_gpe_xrupt_info *gpe_xrupt_list);
/* /*
* Evregion - Address Space handling * Evregion - Address Space handling
...@@ -216,6 +226,10 @@ acpi_ev_initialize_region ( ...@@ -216,6 +226,10 @@ acpi_ev_initialize_region (
* Evsci - SCI (System Control Interrupt) handling/dispatch * Evsci - SCI (System Control Interrupt) handling/dispatch
*/ */
u32 ACPI_SYSTEM_XFACE
acpi_ev_gpe_xrupt_handler (
void *context);
u32 u32
acpi_ev_install_sci_handler ( acpi_ev_install_sci_handler (
void); void);
......
...@@ -234,7 +234,9 @@ ACPI_EXTERN u8 acpi_gbl_sleep_type_b; ...@@ -234,7 +234,9 @@ ACPI_EXTERN u8 acpi_gbl_sleep_type_b;
extern struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS]; extern struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS];
ACPI_EXTERN struct acpi_fixed_event_handler acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS]; ACPI_EXTERN struct acpi_fixed_event_handler acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS];
ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_block_list_head; ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock;
/***************************************************************************** /*****************************************************************************
......
...@@ -127,6 +127,11 @@ acpi_status ...@@ -127,6 +127,11 @@ acpi_status
acpi_hw_disable_gpe ( acpi_hw_disable_gpe (
struct acpi_gpe_event_info *gpe_event_info); struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_disable_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
void void
acpi_hw_disable_gpe_for_wakeup ( acpi_hw_disable_gpe_for_wakeup (
struct acpi_gpe_event_info *gpe_event_info); struct acpi_gpe_event_info *gpe_event_info);
...@@ -135,9 +140,14 @@ acpi_status ...@@ -135,9 +140,14 @@ acpi_status
acpi_hw_clear_gpe ( acpi_hw_clear_gpe (
struct acpi_gpe_event_info *gpe_event_info); struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_clear_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
acpi_status acpi_status
acpi_hw_get_gpe_status ( acpi_hw_get_gpe_status (
u32 gpe_number, struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status); acpi_event_status *event_status);
acpi_status acpi_status
......
...@@ -308,19 +308,19 @@ struct acpi_create_field_info ...@@ -308,19 +308,19 @@ struct acpi_create_field_info
* *
****************************************************************************/ ****************************************************************************/
/* Information about each particular GPE level */ /* Information about a GPE, one per each GPE in an array */
struct acpi_gpe_event_info struct acpi_gpe_event_info
{ {
struct acpi_namespace_node *method_node; /* Method node for this GPE level */ struct acpi_namespace_node *method_node; /* Method node for this GPE level */
acpi_gpe_handler handler; /* Address of handler, if any */ acpi_gpe_handler handler; /* Address of handler, if any */
void *context; /* Context to be passed to handler */ void *context; /* Context to be passed to handler */
struct acpi_gpe_register_info *register_info; struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
u8 type; /* Level or Edge */ u8 flags; /* Level or Edge */
u8 bit_mask; u8 bit_mask; /* This GPE within the register */
}; };
/* Information about a particular GPE register pair */ /* Information about a GPE register pair, one per each status/enable pair in an array */
struct acpi_gpe_register_info struct acpi_gpe_register_info
{ {
...@@ -332,25 +332,36 @@ struct acpi_gpe_register_info ...@@ -332,25 +332,36 @@ struct acpi_gpe_register_info
u8 base_gpe_number; /* Base GPE number for this register */ u8 base_gpe_number; /* Base GPE number for this register */
}; };
/*
#define ACPI_GPE_LEVEL_TRIGGERED 1 * Information about a GPE register block, one per each installed block --
#define ACPI_GPE_EDGE_TRIGGERED 2 * GPE0, GPE1, and one per each installed GPE Block Device.
*/
/* Information about each GPE register block */
struct acpi_gpe_block_info 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_block_info *next_on_interrupt; struct acpi_gpe_register_info *register_info; /* One per GPE register pair */
struct acpi_gpe_register_info *register_info; struct acpi_gpe_event_info *event_info; /* One for each GPE */
struct acpi_gpe_event_info *event_info; struct acpi_generic_address block_address; /* Base address of the block */
struct acpi_generic_address block_address; u32 register_count; /* Number of register pairs in block */
u32 register_count; u8 block_base_number;/* Base GPE number for this block */
u8 block_base_number;
}; };
/* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
struct acpi_gpe_xrupt_info
{
struct acpi_gpe_xrupt_info *previous;
struct acpi_gpe_xrupt_info *next;
struct acpi_gpe_block_info *gpe_block_list_head; /* List of GPE blocks for this xrupt */
u32 interrupt_level; /* System interrupt level */
};
typedef acpi_status (*ACPI_GPE_CALLBACK) (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
/* Information about each particular fixed event */ /* Information about each particular fixed event */
...@@ -360,7 +371,6 @@ struct acpi_fixed_event_handler ...@@ -360,7 +371,6 @@ struct acpi_fixed_event_handler
void *context; /* Context to be passed to handler */ void *context; /* Context to be passed to handler */
}; };
struct acpi_fixed_event_info struct acpi_fixed_event_info
{ {
u8 status_register_id; u8 status_register_id;
......
...@@ -239,6 +239,7 @@ struct acpi_object_device ...@@ -239,6 +239,7 @@ struct acpi_object_device
{ {
ACPI_OBJECT_COMMON_HEADER ACPI_OBJECT_COMMON_HEADER
ACPI_COMMON_NOTIFY_INFO ACPI_COMMON_NOTIFY_INFO
struct acpi_gpe_block_info *gpe_block;
}; };
......
...@@ -147,6 +147,27 @@ acpi_os_signal_semaphore ( ...@@ -147,6 +147,27 @@ acpi_os_signal_semaphore (
acpi_handle handle, acpi_handle handle,
u32 units); u32 units);
acpi_status
acpi_os_create_lock (
acpi_handle *out_handle);
void
acpi_os_delete_lock (
acpi_handle handle);
void
acpi_os_acquire_lock (
acpi_handle handle,
u32 flags);
void
acpi_os_release_lock (
acpi_handle handle,
u32 flags);
#define ACPI_NOT_ISR 1
#define ACPI_ISR 0
/* /*
* Memory allocation and mapping * Memory allocation and mapping
......
...@@ -293,6 +293,7 @@ acpi_remove_address_space_handler ( ...@@ -293,6 +293,7 @@ acpi_remove_address_space_handler (
acpi_status acpi_status
acpi_install_gpe_handler ( acpi_install_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number, u32 gpe_number,
u32 type, u32 type,
acpi_gpe_handler handler, acpi_gpe_handler handler,
...@@ -309,30 +310,50 @@ acpi_release_global_lock ( ...@@ -309,30 +310,50 @@ acpi_release_global_lock (
acpi_status acpi_status
acpi_remove_gpe_handler ( acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number, u32 gpe_number,
acpi_gpe_handler handler); acpi_gpe_handler handler);
acpi_status acpi_status
acpi_enable_event ( acpi_enable_event (
u32 acpi_event, u32 event,
u32 type,
u32 flags); u32 flags);
acpi_status acpi_status
acpi_disable_event ( acpi_disable_event (
u32 acpi_event, u32 event,
u32 type,
u32 flags); u32 flags);
acpi_status acpi_status
acpi_clear_event ( acpi_clear_event (
u32 acpi_event, u32 event);
u32 type);
acpi_status acpi_status
acpi_get_event_status ( acpi_get_event_status (
u32 acpi_event, u32 event,
u32 type, acpi_event_status *event_status);
acpi_status
acpi_enable_gpe (
acpi_handle gpe_device,
u32 gpe_number,
u32 flags);
acpi_status
acpi_disable_gpe (
acpi_handle gpe_device,
u32 gpe_number,
u32 flags);
acpi_status
acpi_clear_gpe (
acpi_handle gpe_device,
u32 gpe_number);
acpi_status
acpi_get_gpe_status (
acpi_handle gpe_device,
u32 gpe_number,
acpi_event_status *event_status); acpi_event_status *event_status);
/* /*
......
...@@ -520,9 +520,6 @@ typedef u32 acpi_object_type; ...@@ -520,9 +520,6 @@ typedef u32 acpi_object_type;
*/ */
typedef u32 acpi_event_type; typedef u32 acpi_event_type;
#define ACPI_EVENT_FIXED 0
#define ACPI_EVENT_GPE 1
/* /*
* Fixed events * Fixed events
*/ */
......
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