78 lines
2.8 KiB
Diff
78 lines
2.8 KiB
Diff
From: Rafael J. Wysocki <rjw@sisk.pl>
|
|
Date: Tue, 8 Jun 2010 08:49:45 +0000 (+0200)
|
|
Subject: ACPI / ACPICA: Avoid writing full enable masks to GPE registers
|
|
X-Git-Tag: v2.6.35-rc4~72^2~6^2~2
|
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=c9a8bbb7704cbf515c0fc68970abbe4e91d68521
|
|
|
|
ACPI / ACPICA: Avoid writing full enable masks to GPE registers
|
|
|
|
ACPICA uses acpi_hw_write_gpe_enable_reg() to re-enable a GPE after
|
|
an event signaled by it has been handled. However, this function
|
|
writes the entire GPE enable mask to the GPE's enable register which
|
|
may not be correct. Namely, if one of the other GPEs in the same
|
|
register was previously enabled by acpi_enable_gpe() and subsequently
|
|
disabled using acpi_set_gpe(), acpi_hw_write_gpe_enable_reg() will
|
|
re-enable it along with the target GPE.
|
|
|
|
To fix this issue rework acpi_hw_write_gpe_enable_reg() so that it
|
|
calls acpi_hw_low_set_gpe() with a special action value,
|
|
ACPI_GPE_COND_ENABLE, that will make it only enable the GPE if the
|
|
corresponding bit in its register's enable_for_run mask is set.
|
|
|
|
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
|
|
Signed-off-by: Len Brown <len.brown@intel.com>
|
|
---
|
|
|
|
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
|
|
index 40388e2..3450309 100644
|
|
--- a/drivers/acpi/acpica/hwgpe.c
|
|
+++ b/drivers/acpi/acpica/hwgpe.c
|
|
@@ -118,6 +118,10 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
|
|
register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
|
|
gpe_register_info);
|
|
switch (action) {
|
|
+ case ACPI_GPE_COND_ENABLE:
|
|
+ if (!(register_bit & gpe_register_info->enable_for_run))
|
|
+ return (AE_BAD_PARAMETER);
|
|
+
|
|
case ACPI_GPE_ENABLE:
|
|
ACPI_SET_BIT(enable_mask, register_bit);
|
|
break;
|
|
@@ -154,23 +158,11 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
|
|
acpi_status
|
|
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
|
|
{
|
|
- struct acpi_gpe_register_info *gpe_register_info;
|
|
acpi_status status;
|
|
|
|
ACPI_FUNCTION_ENTRY();
|
|
|
|
- /* Get the info block for the entire GPE register */
|
|
-
|
|
- gpe_register_info = gpe_event_info->register_info;
|
|
- if (!gpe_register_info) {
|
|
- return (AE_NOT_EXIST);
|
|
- }
|
|
-
|
|
- /* Write the entire GPE (runtime) enable register */
|
|
-
|
|
- status = acpi_hw_write(gpe_register_info->enable_for_run,
|
|
- &gpe_register_info->enable_address);
|
|
-
|
|
+ status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
|
|
return (status);
|
|
}
|
|
|
|
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
|
|
index 6881f5b..15a4c68f 100644
|
|
--- a/include/acpi/actypes.h
|
|
+++ b/include/acpi/actypes.h
|
|
@@ -667,6 +667,7 @@ typedef u32 acpi_event_status;
|
|
|
|
#define ACPI_GPE_ENABLE 0
|
|
#define ACPI_GPE_DISABLE 1
|
|
+#define ACPI_GPE_COND_ENABLE 2
|
|
|
|
/* gpe_types for acpi_enable_gpe and acpi_disable_gpe */
|
|
|