]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ACPI / ACPICA: Avoid writing full enable masks to GPE registers
authorRafael J. Wysocki <rjw@sisk.pl>
Tue, 8 Jun 2010 08:49:45 +0000 (10:49 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 2 Aug 2010 17:30:20 +0000 (10:30 -0700)
commit c9a8bbb7704cbf515c0fc68970abbe4e91d68521 upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/acpi/acpica/hwgpe.c
include/acpi/actypes.h

index 0070328466603fbaae5ebcf6ecaed9e0e8574d87..89e6cfd3c0a8d4aa1c9dffce4b10e6652c5f6cbb 100644 (file)
@@ -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);
 }
 
index 3f08e64962f872838ccc14ee635426fe9517f46d..8ac6ab948b6c281faa8e561a9a516b39b12a9e61 100644 (file)
@@ -665,6 +665,7 @@ typedef u32 acpi_event_status;
 
 #define ACPI_GPE_ENABLE                 0
 #define ACPI_GPE_DISABLE                1
+#define ACPI_GPE_COND_ENABLE            2
 
 /*
  * GPE info flags - Per GPE