Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 193493
b: refs/heads/master
c: 0f849d2
h: refs/heads/master
i:
  193491: 3f85346
v: v3
  • Loading branch information
Lin Ming authored and Len Brown committed Apr 20, 2010
1 parent 1774dd7 commit 4eecbca
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 263 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aa2110cb1a7510f9b834adfb39b05d4843a35d35
refs/heads/master: 0f849d2cc6863c7874889ea60a871fb71399dd3f
7 changes: 4 additions & 3 deletions trunk/drivers/acpi/acpica/acevents.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ acpi_status acpi_ev_disable_gpe(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);

struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
struct acpi_gpe_block_info
*gpe_block);

/*
* evgpeblk
*/
Expand Down Expand Up @@ -118,9 +122,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,

u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);

acpi_status
acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);

acpi_status acpi_ev_gpe_initialize(void);

/*
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/acpi/acpica/aclocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,8 @@ struct acpi_gpe_event_info {
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
u8 flags; /* Misc info about this GPE */
u8 gpe_number; /* This GPE */
u8 runtime_count;
u8 wakeup_count;
u8 runtime_count; /* References to a run GPE */
u8 wakeup_count; /* References to a wake GPE */
};

/* Information about a GPE register pair, one per each status/enable pair in an array */
Expand All @@ -454,6 +454,7 @@ struct acpi_gpe_block_info {
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 */
u16 gpe_count; /* Number of individual GPEs in block */
u8 block_base_number; /* Base GPE number for this block */
};

Expand Down
153 changes: 109 additions & 44 deletions trunk/drivers/acpi/acpica/evgpe.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
*
* RETURN: Status
*
* DESCRIPTION: Updates GPE register enable masks based on the GPE type
* DESCRIPTION: Updates GPE register enable masks based upon whether there are
* references (either wake or run) to this GPE
*
******************************************************************************/

Expand All @@ -81,14 +82,20 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
(1 <<
(gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));

/* Clear the wake/run bits up front */

ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit);
ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);

if (gpe_event_info->runtime_count)
/* Set the mask bits only if there are references to this GPE */

if (gpe_event_info->runtime_count) {
ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
}

if (gpe_event_info->wakeup_count)
if (gpe_event_info->wakeup_count) {
ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
}

return_ACPI_STATUS(AE_OK);
}
Expand All @@ -101,28 +108,47 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
*
* RETURN: Status
*
* DESCRIPTION: Enable a GPE based on the GPE type
* DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
* of type or number of references.
*
* Note: The GPE lock should be already acquired when this function is called.
*
******************************************************************************/

acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;


ACPI_FUNCTION_TRACE(ev_enable_gpe);

/* Make sure HW enable masks are updated */

/*
* We will only allow a GPE to be enabled if it has either an
* associated method (_Lxx/_Exx) or a handler. Otherwise, the
* GPE will be immediately disabled by acpi_ev_gpe_dispatch the
* first time it fires.
*/
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
return_ACPI_STATUS(AE_NO_HANDLER);
}

/* Ensure the HW enable masks are current */

status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_FAILURE(status))
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

/* Clear the GPE (of stale events) */

/* Clear the GPE (of stale events), then enable it */
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status))
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

/* Enable the requested GPE */

status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
return_ACPI_STATUS(status);
}
Expand All @@ -135,7 +161,10 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
*
* RETURN: Status
*
* DESCRIPTION: Disable a GPE based on the GPE type
* DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
* regardless of the type or number of references.
*
* Note: The GPE lock should be already acquired when this function is called.
*
******************************************************************************/

Expand All @@ -145,24 +174,71 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)

ACPI_FUNCTION_TRACE(ev_disable_gpe);

/* Make sure HW enable masks are updated */

/*
* Note: Always disable the GPE, even if we think that that it is already
* disabled. It is possible that the AML or some other code has enabled
* the GPE behind our back.
*/

/* Ensure the HW enable masks are current */

status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_FAILURE(status))
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}

/*
* Even if we don't know the GPE type, make sure that we always
* disable it. low_disable_gpe will just clear the enable bit for this
* GPE and write it. It will not write out the current GPE enable mask,
* since this may inadvertently enable GPEs too early, if a rogue GPE has
* come in during ACPICA initialization - possibly as a result of AML or
* other code that has enabled the GPE.
* Always H/W disable this GPE, even if we don't know the GPE type.
* Simply clear the enable bit for this particular GPE, but do not
* write out the current GPE enable mask since this may inadvertently
* enable GPEs too early. An example is a rogue GPE that has arrived
* during ACPICA initialization - possibly because AML or other code
* has enabled the GPE.
*/
status = acpi_hw_low_disable_gpe(gpe_event_info);
return_ACPI_STATUS(status);
}


/*******************************************************************************
*
* FUNCTION: acpi_ev_low_get_gpe_info
*
* PARAMETERS: gpe_number - Raw GPE number
* gpe_block - A GPE info block
*
* RETURN: A GPE event_info struct. NULL if not a valid GPE (The gpe_number
* is not within the specified GPE block)
*
* DESCRIPTION: Returns the event_info struct associated with this GPE. This is
* the low-level implementation of ev_get_gpe_event_info.
*
******************************************************************************/

struct acpi_gpe_event_info *acpi_ev_low_get_gpe_info(u32 gpe_number,
struct acpi_gpe_block_info
*gpe_block)
{
u32 gpe_index;

/*
* Validate that the gpe_number is within the specified gpe_block.
* (Two steps)
*/
if (!gpe_block || (gpe_number < gpe_block->block_base_number)) {
return (NULL);
}

gpe_index = gpe_number - gpe_block->block_base_number;
if (gpe_index >= gpe_block->gpe_count) {
return (NULL);
}

return (&gpe_block->event_info[gpe_index]);
}


/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_event_info
Expand All @@ -184,7 +260,7 @@ 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;
struct acpi_gpe_event_info *gpe_info;
u32 i;

ACPI_FUNCTION_ENTRY();
Expand All @@ -196,17 +272,11 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
/* Examine GPE Block 0 and 1 (These blocks are permanent) */

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]);
}
gpe_info = acpi_ev_low_get_gpe_info(gpe_number,
acpi_gbl_gpe_fadt_blocks
[i]);
if (gpe_info) {
return (gpe_info);
}
}

Expand All @@ -223,16 +293,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
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]);
}

return (NULL);
return (acpi_ev_low_get_gpe_info
(gpe_number, obj_desc->device.gpe_block));
}

/*******************************************************************************
Expand Down Expand Up @@ -389,7 +451,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
return_VOID;
}

/* Set the GPE flags for return to enabled state */
/* Update the GPE register masks for return to enabled state */

(void)acpi_ev_update_gpe_enable_masks(gpe_event_info);

Expand Down Expand Up @@ -569,15 +631,18 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)

default:

/* No handler or method to run! */

/*
* No handler or method to run!
* 03/2010: This case should no longer be possible. We will not allow
* a GPE to be enabled if it has no handler or method.
*/
ACPI_ERROR((AE_INFO,
"No handler or method for GPE[0x%2X], disabling event",
gpe_number));

/*
* Disable the GPE. The GPE will remain disabled until the ACPICA
* Core Subsystem is restarted, or a handler is installed.
* Disable the GPE. The GPE will remain disabled a handler
* is installed or ACPICA is restarted.
*/
status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
Expand Down
Loading

0 comments on commit 4eecbca

Please sign in to comment.