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 @@
#include <linux/acpi.h>
#include <asm/pgalloc.h>
#include <asm/apic.h>
#include <asm/io.h>
#include <asm/mpspec.h>
#if defined (CONFIG_X86_LOCAL_APIC)
......
......@@ -378,7 +378,7 @@ acpi_ec_gpe_query (
acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
end:
acpi_enable_event(ec->gpe_bit, ACPI_EVENT_GPE, 0);
acpi_enable_gpe(NULL, ec->gpe_bit, 0);
}
static void
......@@ -391,7 +391,7 @@ acpi_ec_gpe_handler (
if (!ec)
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,
acpi_ec_gpe_query, ec);
......@@ -589,12 +589,13 @@ acpi_ec_add (
acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
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);
}
/* 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);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
......@@ -714,7 +715,7 @@ acpi_ec_start (
/*
* 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);
if (ACPI_FAILURE(status)) {
return_VALUE(-ENODEV);
......@@ -724,7 +725,7 @@ acpi_ec_start (
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
&acpi_ec_space_setup, ec);
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);
}
......@@ -752,7 +753,7 @@ acpi_ec_stop (
if (ACPI_FAILURE(status))
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))
return_VALUE(-ENODEV);
......@@ -798,7 +799,7 @@ acpi_ec_ecdt_probe (void)
/*
* 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,
ec_ecdt);
if (ACPI_FAILURE(status)) {
......@@ -809,7 +810,7 @@ acpi_ec_ecdt_probe (void)
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
&acpi_ec_space_setup, ec_ecdt);
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);
goto error;
}
......
......@@ -78,9 +78,9 @@ acpi_ev_initialize (
}
/*
* Initialize the Fixed and General Purpose acpi_events prior. This is
* done prior to enabling SCIs to prevent interrupts from occurring
* before handers are installed.
* Initialize the Fixed and General Purpose Events. This is
* done prior to enabling SCIs to prevent interrupts from
* occurring before handers are installed.
*/
status = acpi_ev_fixed_event_initialize ();
if (ACPI_FAILURE (status)) {
......@@ -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);
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));
/*
......@@ -282,7 +282,7 @@ acpi_ev_fixed_event_dispatch (
0, ACPI_MTX_DO_NOT_LOCK);
ACPI_REPORT_ERROR (
("ev_gpe_dispatch: No installed handler for fixed event [%08X]\n",
("No installed handler for fixed event [%08X]\n",
event));
return (ACPI_INTERRUPT_NOT_HANDLED);
......
......@@ -53,44 +53,60 @@
*
* 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
* associated with this GPE.
* DESCRIPTION: Returns the event_info struct 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
* is implemented!
* Should be called only when the GPE lists are semaphore locked
* and not subject to change.
*
******************************************************************************/
struct acpi_gpe_event_info *
acpi_ev_get_gpe_event_info (
acpi_handle gpe_device,
u32 gpe_number)
{
union acpi_operand_object *obj_desc;
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_block) {
return (NULL);
}
if (!gpe_device) {
/* Examine GPE Block 0 and 1 (These blocks are permanent) */
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]);
}
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
gpe_block = acpi_gbl_gpe_fadt_blocks[i];
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);
}
gpe_block = obj_desc->device.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]);
......@@ -99,6 +115,7 @@ acpi_ev_get_gpe_event_info (
return (NULL);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_gpe_detect
......@@ -113,17 +130,19 @@ acpi_ev_get_gpe_event_info (
******************************************************************************/
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 i;
u32 j;
u8 enabled_status_byte;
u8 bit_mask;
struct acpi_gpe_register_info *gpe_register_info;
u32 in_value;
acpi_status status;
struct acpi_gpe_block_info *gpe_block;
u32 gpe_number;
u32 i;
u32 j;
ACPI_FUNCTION_NAME ("ev_gpe_detect");
......@@ -131,7 +150,8 @@ acpi_ev_gpe_detect (void)
/* 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) {
/*
* Read all of the 8-bit GPE status and enable registers
......@@ -143,18 +163,22 @@ acpi_ev_gpe_detect (void)
gpe_register_info = &gpe_block->register_info[i];
/* Read the Status Register */
status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
&gpe_register_info->status_address, 0);
gpe_register_info->status = (u8) in_value;
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,
&gpe_register_info->enable_address, 0);
gpe_register_info->enable = (u8) in_value;
if (ACPI_FAILURE (status)) {
return (ACPI_INTERRUPT_NOT_HANDLED);
goto unlock_and_exit;
}
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
......@@ -184,8 +208,11 @@ acpi_ev_gpe_detect (void)
* Found an active GPE. Dispatch the event to a handler
* or method.
*/
gpe_number = (i * ACPI_GPE_REGISTER_WIDTH) + j;
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)
gpe_block = gpe_block->next;
}
unlock_and_exit:
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
return (int_status);
}
......@@ -209,7 +239,7 @@ acpi_ev_gpe_detect (void)
* function is called from an invocation of acpi_os_queue_for_execution
* (and therefore does NOT execute at interrupt level) so that
* 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 (
struct acpi_gpe_event_info *gpe_event_info = (void *) context;
u32 gpe_number = 0;
acpi_status status;
struct acpi_gpe_event_info local_gpe_event_info;
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);
if (ACPI_FAILURE (status)) {
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);
if (ACPI_FAILURE (status)) {
return_VOID;
}
if (gpe_event_info->method_node) {
if (local_gpe_event_info.method_node) {
/*
* Invoke the GPE Method (_Lxx, _Exx):
* (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)) {
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),
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
* the event.
*/
status = acpi_hw_clear_gpe (gpe_event_info);
status = acpi_hw_clear_gpe (&local_gpe_event_info);
if (ACPI_FAILURE (status)) {
return_VOID;
}
......@@ -265,7 +305,7 @@ acpi_ev_asynch_execute_gpe_method (
/* Enable this GPE */
(void) acpi_hw_enable_gpe (gpe_event_info);
(void) acpi_hw_enable_gpe (&local_gpe_event_info);
return_VOID;
}
......@@ -274,21 +314,23 @@ acpi_ev_asynch_execute_gpe_method (
*
* 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
*
* DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
* or method (e.g. _Lxx/_Exx) handler. This function executes
* at interrupt level.
* or method (e.g. _Lxx/_Exx) handler.
*
* This function executes at interrupt level.
*
******************************************************************************/
u32
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;
......@@ -299,10 +341,10 @@ acpi_ev_gpe_dispatch (
* If edge-triggered, clear the GPE status bit now. Note that
* 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);
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));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
......@@ -327,19 +369,18 @@ acpi_ev_gpe_dispatch (
*/
status = acpi_hw_disable_gpe (gpe_event_info);
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));
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,
acpi_ev_asynch_execute_gpe_method,
gpe_event_info))) {
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));
}
}
......@@ -347,7 +388,7 @@ acpi_ev_gpe_dispatch (
/* No handler or method to run! */
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));
/*
......@@ -356,19 +397,18 @@ acpi_ev_gpe_dispatch (
*/
status = acpi_hw_disable_gpe (gpe_event_info);
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));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
/*
* It is now safe to clear level-triggered evnets.
*/
if (gpe_event_info->type & ACPI_EVENT_LEVEL_TRIGGERED) {
/* It is now safe to clear level-triggered events. */
if (gpe_event_info->flags & ACPI_EVENT_LEVEL_TRIGGERED) {
status = acpi_hw_clear_gpe (gpe_event_info);
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));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
......
......@@ -46,7 +46,104 @@
#include <acpi/acnamesp.h>
#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 (
/* Ensure that we have a valid GPE number for this GPE block */
if ((gpe_number < gpe_block->block_base_number) ||
(gpe_number >= (gpe_block->register_count * 8))) {
/* Not valid, all we can do here is ignore it */
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"GPE number associated with method %s is not valid\n", name));
(gpe_number >= (gpe_block->block_base_number + (gpe_block->register_count * 8)))) {
/*
* Not valid for this GPE block, just ignore it
* However, it may be valid for a different GPE block, since GPE0 and GPE1
* methods both appear under \_GPE.
*/
return (AE_OK);
}
......@@ -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->type = type;
gpe_event_info->flags = type;
gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
/*
......@@ -156,17 +254,92 @@ acpi_ev_save_method_info (
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));
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
*
* PARAMETERS: gpe_block - New GPE block
* PARAMETERS: gpe_block - New GPE block
* interrupt_level - Level to be associated with this GPE block
*
* RETURN: Status
*
......@@ -176,9 +349,11 @@ acpi_ev_save_method_info (
acpi_status
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_xrupt_info *gpe_xrupt_block;
acpi_status status;
......@@ -187,10 +362,17 @@ acpi_ev_install_gpe_block (
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) {
next_gpe_block = acpi_gbl_gpe_block_list_head;
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
if (gpe_xrupt_block->gpe_block_list_head) {
next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
while (next_gpe_block->next) {
next_gpe_block = next_gpe_block->next;
}
......@@ -199,9 +381,11 @@ acpi_ev_install_gpe_block (
gpe_block->previous = next_gpe_block;
}
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);
return (status);
}
......@@ -259,12 +443,16 @@ acpi_ev_create_gpe_info_blocks (
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
* 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,
* and the enable registers occupy the second half. Another goal is to hide
* the fact that there may be multiple GPE hardware blocks.
* and the enable registers occupy the second half.
*/
this_register = gpe_register_info;
this_event = gpe_event_info;
......@@ -319,14 +507,10 @@ acpi_ev_create_gpe_info_blocks (
this_register++;
}
gpe_block->register_info = gpe_register_info;
gpe_block->event_info = gpe_event_info;
return_ACPI_STATUS (AE_OK);
error_exit:
if (gpe_register_info) {
ACPI_MEM_FREE (gpe_register_info);
}
......@@ -334,7 +518,7 @@ acpi_ev_create_gpe_info_blocks (
ACPI_MEM_FREE (gpe_event_info);
}
return_ACPI_STATUS (AE_OK);
return_ACPI_STATUS (status);
}
......@@ -356,7 +540,8 @@ acpi_ev_create_gpe_block (
struct acpi_generic_address *gpe_block_address,
u32 register_count,
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;
acpi_status status;
......@@ -400,9 +585,8 @@ acpi_ev_create_gpe_block (
}
/* 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)) {
ACPI_MEM_FREE (gpe_block);
return_ACPI_STATUS (status);
......@@ -415,7 +599,7 @@ acpi_ev_create_gpe_block (
ACPI_HIDWORD (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,
(u32) (gpe_block->block_base_number +
((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1))));
......@@ -426,6 +610,9 @@ acpi_ev_create_gpe_block (
ACPI_UINT32_MAX, acpi_ev_save_method_info,
gpe_block, NULL);
/* Return the new block */
(*return_gpe_block) = gpe_block;
return_ACPI_STATUS (AE_OK);
}
......@@ -448,6 +635,7 @@ acpi_ev_gpe_initialize (void)
u32 register_count0 = 0;
u32 register_count1 = 0;
u32 gpe_number_max = 0;
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_gpe_initialize");
......@@ -474,6 +662,7 @@ acpi_ev_gpe_initialize (void)
*
* Note: both GPE0 and GPE1 are optional, and either can exist without
* the other.
*
* If EITHER the register length OR the block address are zero, then that
* particular block is not supported.
*/
......@@ -485,8 +674,15 @@ acpi_ev_gpe_initialize (void)
gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
acpi_ev_create_gpe_block ("\\_GPE", &acpi_gbl_FADT->xgpe0_blk,
register_count0, 0, acpi_gbl_FADT->sci_int);
/* Install GPE Block 0 */
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 &&
......@@ -510,8 +706,16 @@ acpi_ev_gpe_initialize (void)
register_count1 = 0;
}
else {
acpi_ev_create_gpe_block ("\\_GPE", &acpi_gbl_FADT->xgpe1_blk,
register_count1, acpi_gbl_FADT->gpe1_base, acpi_gbl_FADT->sci_int);
/* Install GPE Block 1 */
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,
......
......@@ -525,7 +525,8 @@ acpi_ev_terminate (void)
acpi_status status;
struct acpi_gpe_block_info *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");
......@@ -537,46 +538,29 @@ acpi_ev_terminate (void)
* 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++) {
status = acpi_disable_event ((u32) i, ACPI_EVENT_FIXED, 0);
status = acpi_disable_event ((u32) i, 0);
if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable fixed event %d\n", (u32) i));
}
}
/*
* 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++;
}
/* Disable all GPEs in all GPE blocks */
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 ();
if (ACPI_FAILURE(status)) {
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) {
status = acpi_disable ();
if (ACPI_FAILURE (status)) {
......@@ -584,19 +568,23 @@ acpi_ev_terminate (void)
}
}
/*
* Free global GPE blocks and related info structures
*/
gpe_block = acpi_gbl_gpe_block_list_head;
while (gpe_block) {
next_gpe_block = gpe_block->next;
ACPI_MEM_FREE (gpe_block->event_info);
ACPI_MEM_FREE (gpe_block->register_info);
ACPI_MEM_FREE (gpe_block);
gpe_block = next_gpe_block;
}
/* Free global GPE blocks and related info structures */
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
while (gpe_xrupt_info) {
gpe_block = gpe_xrupt_info->gpe_block_list_head;
while (gpe_block) {
next_gpe_block = gpe_block->next;
ACPI_MEM_FREE (gpe_block->event_info);
ACPI_MEM_FREE (gpe_block->register_info);
ACPI_MEM_FREE (gpe_block);
gpe_block = next_gpe_block;
}
next_gpe_xrupt_info = gpe_xrupt_info->next;
ACPI_MEM_FREE (gpe_xrupt_info);
gpe_xrupt_info = next_gpe_xrupt_info;
}
return_VOID;
}
......@@ -52,26 +52,26 @@
/*******************************************************************************
*
* FUNCTION: acpi_ev_sci_handler
* FUNCTION: acpi_ev_sci_xrupt_handler
*
* PARAMETERS: Context - Calling Context
*
* RETURN: Status code indicates whether interrupt was handled.
*
* DESCRIPTION: Interrupt handler that will figure out what function or
* control method to call to deal with a SCI. Installed
* using BU interrupt support.
* control method to call to deal with a SCI.
*
******************************************************************************/
static u32 ACPI_SYSTEM_XFACE
acpi_ev_sci_handler (
acpi_ev_sci_xrupt_handler (
void *context)
{
struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
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 (
*/
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:
* 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);
}
......@@ -117,7 +157,7 @@ acpi_ev_install_sci_handler (void)
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);
}
......@@ -153,7 +193,7 @@ acpi_ev_remove_sci_handler (void)
/* Just let the OS remove the handler and disable the level */
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);
}
......
......@@ -102,7 +102,7 @@ acpi_install_fixed_event_handler (
acpi_gbl_fixed_event_handlers[event].handler = handler;
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)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
......@@ -160,7 +160,7 @@ acpi_remove_fixed_event_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 */
......@@ -471,8 +471,8 @@ acpi_remove_notify_handler (
*
* FUNCTION: acpi_install_gpe_handler
*
* PARAMETERS: gpe_number - The GPE number. The numbering scheme is
* bank 0 first, then bank 1.
* PARAMETERS: gpe_number - The GPE number within the GPE block
* gpe_block - GPE block (NULL == FADT GPEs)
* Type - Whether this GPE should be treated as an
* edge- or level-triggered interrupt.
* Handler - Address of the handler
......@@ -486,6 +486,7 @@ acpi_remove_notify_handler (
acpi_status
acpi_install_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
u32 type,
acpi_gpe_handler handler,
......@@ -504,42 +505,45 @@ acpi_install_gpe_handler (
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);
if (ACPI_FAILURE (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 */
if (gpe_event_info->handler) {
status = AE_ALREADY_EXISTS;
goto cleanup;
goto unlock_and_exit;
}
/* Install the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
gpe_event_info->handler = handler;
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 */
status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
goto cleanup;
goto unlock_and_exit;
}
status = acpi_hw_enable_gpe (gpe_event_info);
cleanup:
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
return_ACPI_STATUS (status);
}
......@@ -550,6 +554,7 @@ acpi_install_gpe_handler (
* FUNCTION: acpi_remove_gpe_handler
*
* PARAMETERS: gpe_number - The event to remove a handler
* gpe_block - GPE block (NULL == FADT GPEs)
* Handler - Address of the handler
*
* RETURN: Status
......@@ -560,6 +565,7 @@ acpi_install_gpe_handler (
acpi_status
acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
acpi_gpe_handler handler)
{
......@@ -576,23 +582,24 @@ acpi_remove_gpe_handler (
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 */
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) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Disable the GPE before removing the handler */
status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
goto unlock_and_exit;
}
/* Make sure that the installed handler is the same */
......@@ -600,16 +607,18 @@ acpi_remove_gpe_handler (
if (gpe_event_info->handler != handler) {
(void) acpi_hw_enable_gpe (gpe_event_info);
status = AE_BAD_PARAMETER;
goto cleanup;
goto unlock_and_exit;
}
/* Remove the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
gpe_event_info->handler = 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);
return_ACPI_STATUS (status);
}
......
......@@ -145,94 +145,114 @@ acpi_disable (void)
*
* FUNCTION: acpi_enable_event
*
* PARAMETERS: Event - The fixed event or GPE to be enabled
* Type - The type of event
* Flags - Just enable, or also wake enable?
* PARAMETERS: Event - The fixed eventto be enabled
* Flags - Reserved
*
* RETURN: Status
*
* DESCRIPTION: Enable an ACPI event (fixed and general purpose)
* DESCRIPTION: Enable an ACPI event (fixed)
*
******************************************************************************/
acpi_status
acpi_enable_event (
u32 event,
u32 type,
u32 flags)
{
acpi_status status = AE_OK;
u32 value;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_enable_event");
/* The Type must be either Fixed Event or GPE */
/* Decode the Fixed Event */
switch (type) {
case ACPI_EVENT_FIXED:
if (event > ACPI_EVENT_MAX) {
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) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Make sure that the hardware responded */
/*
* 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);
}
status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
&value, 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,
&value, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (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);
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
/* Enable the requested GPE number */
status = acpi_hw_enable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (flags & ACPI_EVENT_WAKE_ENABLE) {
acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
}
break;
/* 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;
}
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);
}
......@@ -241,92 +261,112 @@ acpi_enable_event (
*
* FUNCTION: acpi_disable_event
*
* PARAMETERS: Event - The fixed event or GPE to be enabled
* Type - The type of event, fixed or general purpose
* Flags - Wake disable vs. non-wake disable
* PARAMETERS: Event - The fixed eventto be enabled
* Flags - Reserved
*
* RETURN: Status
*
* DESCRIPTION: Disable an ACPI event (fixed and general purpose)
* DESCRIPTION: Disable an ACPI event (fixed)
*
******************************************************************************/
acpi_status
acpi_disable_event (
u32 event,
u32 type,
u32 flags)
{
acpi_status status = AE_OK;
u32 value;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_disable_event");
/* The Type must be either Fixed Event or GPE */
/* Decode the Fixed Event */
switch (type) {
case ACPI_EVENT_FIXED:
if (event > ACPI_EVENT_MAX) {
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) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
&value, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/*
* 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 (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);
}
status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
&value, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (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);
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
ACPI_FUNCTION_TRACE ("acpi_disable_gpe");
/*
* 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);
}
break;
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
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;
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);
}
......@@ -335,65 +375,83 @@ acpi_disable_event (
*
* FUNCTION: acpi_clear_event
*
* PARAMETERS: Event - The fixed event or GPE to be cleared
* Type - The type of event
* PARAMETERS: Event - The fixed event to be cleared
*
* RETURN: Status
*
* DESCRIPTION: Clear an ACPI event (fixed and general purpose)
* DESCRIPTION: Clear an ACPI event (fixed)
*
******************************************************************************/
acpi_status
acpi_clear_event (
u32 event,
u32 type)
u32 event)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_clear_event");
/* The Type must be either Fixed Event or GPE */
/* Decode the Fixed Event */
switch (type) {
case ACPI_EVENT_FIXED:
if (event > ACPI_EVENT_MAX) {
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 (AE_BAD_PARAMETER);
}
return_ACPI_STATUS (status);
}
/*
* 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);
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
ACPI_FUNCTION_TRACE ("acpi_clear_gpe");
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;
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);
}
......@@ -402,9 +460,8 @@ acpi_clear_event (
*
* FUNCTION: acpi_get_event_status
*
* PARAMETERS: Event - The fixed event or GPE
* Type - The type of event
* Status - Where the current status of the event will
* PARAMETERS: Event - The fixed event
* Event Status - Where the current status of the event will
* be returned
*
* RETURN: Status
......@@ -413,15 +470,12 @@ acpi_clear_event (
*
******************************************************************************/
acpi_status
acpi_get_event_status (
u32 event,
u32 type,
acpi_event_status *event_status)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_get_event_status");
......@@ -431,44 +485,68 @@ acpi_get_event_status (
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */
/* The Type must be either Fixed Event or GPE */
switch (type) {
case ACPI_EVENT_FIXED:
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Decode the Fixed Event */
/* Get the status of the requested fixed event */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id,
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);
if (!gpe_event_info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
/* Obtain status on the requested GPE number */
status = acpi_hw_get_gpe_status (event, event_status);
break;
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
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;
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);
}
......
......@@ -266,13 +266,12 @@ acpi_hw_clear_gpe (
acpi_status
acpi_hw_get_gpe_status (
u32 gpe_number,
struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status)
{
u32 in_byte;
u8 bit_mask;
struct acpi_gpe_register_info *gpe_register_info;
struct acpi_gpe_event_info *gpe_event_info;
acpi_status status;
acpi_event_status local_event_status = 0;
......@@ -284,11 +283,6 @@ acpi_hw_get_gpe_status (
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 */
gpe_register_info = gpe_event_info->register_info;
......@@ -301,7 +295,7 @@ acpi_hw_get_gpe_status (
status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address, 0);
if (ACPI_FAILURE (status)) {
return (status);
goto unlock_and_exit;
}
if (bit_mask & in_byte) {
......@@ -318,7 +312,7 @@ acpi_hw_get_gpe_status (
status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address, 0);
if (ACPI_FAILURE (status)) {
return (status);
goto unlock_and_exit;
}
if (bit_mask & in_byte) {
......@@ -328,6 +322,150 @@ acpi_hw_get_gpe_status (
/* Set return value */
(*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);
}
......@@ -341,7 +479,7 @@ acpi_hw_get_gpe_status (
* RETURN: None
*
* 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
* given the chance to run until after non-wake GPEs are
* re-enabled.
......@@ -351,54 +489,65 @@ acpi_hw_get_gpe_status (
acpi_status
acpi_hw_disable_non_wakeup_gpes (
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;
struct acpi_gpe_register_info *gpe_register_info;
u32 in_value;
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;
while (gpe_block) {
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info;
gpe_register_info = gpe_block->register_info;
if (!gpe_register_info) {
return (AE_BAD_PARAMETER);
}
/* 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++;
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_block = gpe_block->next;
gpe_register_info++;
}
return (AE_OK);
}
......@@ -419,40 +568,13 @@ acpi_status
acpi_hw_enable_non_wakeup_gpes (
void)
{
u32 i;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_ENTRY ();
gpe_block = acpi_gbl_gpe_block_list_head;
while (gpe_block) {
/* Get the register info for the entire GPE block */
status = acpi_ev_walk_gpe_list (acpi_hw_enable_non_wakeup_gpe_block);
gpe_register_info = gpe_block->register_info;
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);
return (status);
}
......@@ -46,6 +46,7 @@
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME ("hwregs")
......@@ -66,9 +67,7 @@
acpi_status
acpi_hw_clear_acpi_status (void)
{
acpi_native_uint i;
acpi_status status;
struct acpi_gpe_block_info *gpe_block;
ACPI_FUNCTION_TRACE ("hw_clear_acpi_status");
......@@ -102,18 +101,7 @@ acpi_hw_clear_acpi_status (void)
/* Clear the GPE Bits in all GPE registers in all GPE blocks */
gpe_block = acpi_gbl_gpe_block_list_head;
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;
}
status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_HARDWARE);
......
......@@ -73,6 +73,7 @@ acpi_ns_root_initialize (void)
const struct acpi_predefined_names *init_val = NULL;
struct acpi_namespace_node *new_node;
union acpi_operand_object *obj_desc;
acpi_string val = NULL;
ACPI_FUNCTION_TRACE ("ns_root_initialize");
......@@ -119,9 +120,7 @@ acpi_ns_root_initialize (void)
* initial value, create the initial value.
*/
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)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not override predefined %s\n",
init_val->name));
......
......@@ -164,6 +164,7 @@ acpi_ns_walk_namespace (
void **return_value)
{
acpi_status status;
acpi_status mutex_status;
struct acpi_namespace_node *child_node;
struct acpi_namespace_node *parent_node;
acpi_object_type child_type;
......@@ -211,9 +212,9 @@ acpi_ns_walk_namespace (
* callback function
*/
if (unlock_before_callback) {
status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
mutex_status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (mutex_status)) {
return_ACPI_STATUS (mutex_status);
}
}
......@@ -221,9 +222,9 @@ acpi_ns_walk_namespace (
context, return_value);
if (unlock_before_callback) {
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
mutex_status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (mutex_status)) {
return_ACPI_STATUS (mutex_status);
}
}
......
......@@ -581,24 +581,32 @@ acpi_os_derive_pci_id (
acpi_status
acpi_os_write_pci_configuration (
acpi_pci_id *pci_id,
u32 reg,
acpi_integer value,
u32 width)
struct acpi_pci_id *pci_id,
u32 reg,
acpi_integer value,
u32 width)
{
return (AE_SUPPORT);
}
acpi_status
acpi_os_read_pci_configuration (
acpi_pci_id *pci_id,
u32 reg,
void *value,
u32 width)
struct acpi_pci_id *pci_id,
u32 reg,
void *value,
u32 width)
{
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*/
static void
......@@ -669,6 +677,92 @@ acpi_os_queue_for_execution(
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_os_create_semaphore(
......
......@@ -639,7 +639,7 @@ acpi_processor_get_power_info (
/*
* 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,
"C2 latency too large [%d]\n",
acpi_fadt.plvl2_lat));
......@@ -673,7 +673,7 @@ acpi_processor_get_power_info (
/*
* 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,
"C3 latency too large [%d]\n",
acpi_fadt.plvl3_lat));
......
......@@ -240,12 +240,13 @@ acpi_walk_resources (
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
struct acpi_resource *resource;
ACPI_FUNCTION_TRACE ("acpi_walk_resources");
if (!device_handle ||
(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);
}
......@@ -290,10 +291,10 @@ acpi_walk_resources (
cleanup:
acpi_os_free (buffer.pointer);
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_set_current_resources
......@@ -337,6 +338,7 @@ acpi_set_current_resources (
return_ACPI_STATUS (status);
}
#define COPY_FIELD(out, in, field) out->field = in->field
#define COPY_ADDRESS(out, in) \
COPY_FIELD(out, in, resource_type); \
......@@ -352,48 +354,53 @@ acpi_set_current_resources (
COPY_FIELD(out, in, address_length); \
COPY_FIELD(out, in, resource_source);
/*******************************************************************************
*
* FUNCTION: acpi_resource_to_address64
*
* PARAMETERS: resource - Pointer to a resource
* out - Pointer to the users's return
* buffer (a struct
* struct acpi_resource_address64)
*
* RETURN: Status
*
* DESCRIPTION: If the resource is an address16, address32, or address64,
* copy it to the address64 return buffer. This saves the
* caller from having to duplicate code for different-sized
* addresses.
*
******************************************************************************/
/******************************************************************************
*
* FUNCTION: acpi_resource_to_address64
*
* PARAMETERS: resource - Pointer to a resource
* out - Pointer to the users's return
* buffer (a struct
* struct acpi_resource_address64)
*
* RETURN: Status
*
* DESCRIPTION: If the resource is an address16, address32, or address64,
* copy it to the address64 return buffer. This saves the
* caller from having to duplicate code for different-sized
* addresses.
*
******************************************************************************/
acpi_status
acpi_resource_to_address64 (
struct acpi_resource *resource,
struct acpi_resource_address64 *out)
struct acpi_resource *resource,
struct acpi_resource_address64 *out)
{
struct acpi_resource_address16 *address16;
struct acpi_resource_address32 *address32;
struct acpi_resource_address64 *address64;
struct acpi_resource_address16 *address16;
struct acpi_resource_address32 *address32;
struct acpi_resource_address64 *address64;
switch (resource->id) {
case ACPI_RSTYPE_ADDRESS16:
address16 = (struct acpi_resource_address16 *) &resource->data;
COPY_ADDRESS(out, address16);
break;
case ACPI_RSTYPE_ADDRESS32:
address32 = (struct acpi_resource_address32 *) &resource->data;
COPY_ADDRESS(out, address32);
break;
case ACPI_RSTYPE_ADDRESS64:
address64 = (struct acpi_resource_address64 *) &resource->data;
COPY_ADDRESS(out, address64);
break;
default:
return (AE_BAD_PARAMETER);
}
return (AE_OK);
}
......@@ -228,7 +228,7 @@ acpi_tb_get_required_tables (
* any SSDTs.
*/
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];
......
......@@ -731,7 +731,9 @@ acpi_ut_init_globals (
/* 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 */
......
......@@ -556,6 +556,9 @@ acpi_ut_mutex_initialize (
}
}
status = acpi_os_create_lock (&acpi_gbl_gpe_lock);
return_ACPI_STATUS (AE_OK);
}
......@@ -589,6 +592,7 @@ acpi_ut_mutex_terminate (
(void) acpi_ut_delete_mutex (i);
}
(void) acpi_os_delete_lock (acpi_gbl_gpe_lock);
return_VOID;
}
......
......@@ -72,7 +72,7 @@
/* Version string */
#define ACPI_CA_VERSION 0x20030228
#define ACPI_CA_VERSION 0x20030321
/* Version of ACPI supported */
......
......@@ -109,8 +109,17 @@ acpi_ev_notify_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 *
acpi_ev_get_gpe_event_info (
acpi_handle gpe_device,
u32 gpe_number);
acpi_status
......@@ -119,11 +128,12 @@ acpi_ev_gpe_initialize (
u32
acpi_ev_gpe_dispatch (
struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_event_info *gpe_event_info,
u32 gpe_number);
u32
acpi_ev_gpe_detect (
void);
struct acpi_gpe_xrupt_info *gpe_xrupt_list);
/*
* Evregion - Address Space handling
......@@ -216,6 +226,10 @@ acpi_ev_initialize_region (
* Evsci - SCI (System Control Interrupt) handling/dispatch
*/
u32 ACPI_SYSTEM_XFACE
acpi_ev_gpe_xrupt_handler (
void *context);
u32
acpi_ev_install_sci_handler (
void);
......
......@@ -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];
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
acpi_hw_disable_gpe (
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
acpi_hw_disable_gpe_for_wakeup (
struct acpi_gpe_event_info *gpe_event_info);
......@@ -135,9 +140,14 @@ acpi_status
acpi_hw_clear_gpe (
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_hw_get_gpe_status (
u32 gpe_number,
struct acpi_gpe_event_info *gpe_event_info,
acpi_event_status *event_status);
acpi_status
......
......@@ -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_namespace_node *method_node; /* Method node for this GPE level */
acpi_gpe_handler handler; /* Address of handler, if any */
void *context; /* Context to be passed to handler */
struct acpi_gpe_register_info *register_info;
u8 type; /* Level or Edge */
u8 bit_mask;
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
u8 flags; /* Level or Edge */
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
{
......@@ -332,25 +332,36 @@ struct acpi_gpe_register_info
u8 base_gpe_number; /* Base GPE number for this register */
};
#define ACPI_GPE_LEVEL_TRIGGERED 1
#define ACPI_GPE_EDGE_TRIGGERED 2
/* Information about each GPE register block */
/*
* Information about a GPE register block, one per each installed block --
* GPE0, GPE1, and one per each installed GPE Block Device.
*/
struct acpi_gpe_block_info
{
struct acpi_gpe_block_info *previous;
struct acpi_gpe_block_info *next;
struct acpi_gpe_block_info *next_on_interrupt;
struct acpi_gpe_register_info *register_info;
struct acpi_gpe_event_info *event_info;
struct acpi_generic_address block_address;
u32 register_count;
u8 block_base_number;
struct acpi_gpe_register_info *register_info; /* One per GPE register pair */
struct acpi_gpe_event_info *event_info; /* One for each GPE */
struct acpi_generic_address block_address; /* Base address of the block */
u32 register_count; /* Number of register pairs in block */
u8 block_base_number;/* Base GPE number for this block */
};
/* 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 */
......@@ -360,7 +371,6 @@ struct acpi_fixed_event_handler
void *context; /* Context to be passed to handler */
};
struct acpi_fixed_event_info
{
u8 status_register_id;
......
......@@ -239,6 +239,7 @@ struct acpi_object_device
{
ACPI_OBJECT_COMMON_HEADER
ACPI_COMMON_NOTIFY_INFO
struct acpi_gpe_block_info *gpe_block;
};
......
......@@ -147,6 +147,27 @@ acpi_os_signal_semaphore (
acpi_handle handle,
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
......
......@@ -293,6 +293,7 @@ acpi_remove_address_space_handler (
acpi_status
acpi_install_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
u32 type,
acpi_gpe_handler handler,
......@@ -309,30 +310,50 @@ acpi_release_global_lock (
acpi_status
acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
acpi_gpe_handler handler);
acpi_status
acpi_enable_event (
u32 acpi_event,
u32 type,
u32 event,
u32 flags);
acpi_status
acpi_disable_event (
u32 acpi_event,
u32 type,
u32 event,
u32 flags);
acpi_status
acpi_clear_event (
u32 acpi_event,
u32 type);
u32 event);
acpi_status
acpi_get_event_status (
u32 acpi_event,
u32 type,
u32 event,
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);
/*
......
......@@ -520,9 +520,6 @@ typedef u32 acpi_object_type;
*/
typedef u32 acpi_event_type;
#define ACPI_EVENT_FIXED 0
#define ACPI_EVENT_GPE 1
/*
* 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