Commit 0ee0d349 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

ACPICA: Store GPE register enable masks upfront

It is reported that ACPI interrupts do not work any more on
Dell Latitude D600 after commit c50f13c6 (ACPICA: Save
current masks of enabled GPEs after enable register writes).
The problem turns out to be related to the fact that the
enable_mask and enable_for_run GPE bit masks are not in
sync (in the absence of any system suspend/resume events)
for at least one GPE register on that machine.

Address this problem by writing the enable_for_run mask into
enable_mask as soon as enable_for_run is updated instead of
doing that only after the subsequent register write has
succeeded.  For consistency, update acpi_hw_gpe_enable_write()
to store the bit mask to be written into the GPE register
in enable_mask unconditionally before the write.

Since the ACPI_GPE_SAVE_MASK flag is not necessary any more after
that, drop it along with the symbols depending on it.
Reported-and-tested-by: default avatarJim Bos <jim876@xs4all.nl>
Fixes: c50f13c6 (ACPICA: Save current masks of enabled GPEs after enable register writes)
Cc: 3.19+ <stable@vger.kernel.org> # 3.19+
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 2b5083e5
...@@ -92,6 +92,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info) ...@@ -92,6 +92,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
ACPI_SET_BIT(gpe_register_info->enable_for_run, ACPI_SET_BIT(gpe_register_info->enable_for_run,
(u8)register_bit); (u8)register_bit);
} }
gpe_register_info->enable_mask = gpe_register_info->enable_for_run;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
...@@ -123,7 +124,7 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) ...@@ -123,7 +124,7 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Enable the requested GPE */ /* Enable the requested GPE */
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE_SAVE); status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
...@@ -202,7 +203,7 @@ acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info) ...@@ -202,7 +203,7 @@ acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
status = status =
acpi_hw_low_set_gpe(gpe_event_info, acpi_hw_low_set_gpe(gpe_event_info,
ACPI_GPE_DISABLE_SAVE); ACPI_GPE_DISABLE);
} }
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
......
...@@ -89,6 +89,8 @@ u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info) ...@@ -89,6 +89,8 @@ u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: Enable or disable a single GPE in the parent enable register. * DESCRIPTION: Enable or disable a single GPE in the parent enable register.
* The enable_mask field of the involved GPE register must be
* updated by the caller if necessary.
* *
******************************************************************************/ ******************************************************************************/
...@@ -119,7 +121,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) ...@@ -119,7 +121,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
/* Set or clear just the bit that corresponds to this GPE */ /* Set or clear just the bit that corresponds to this GPE */
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info); register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
switch (action & ~ACPI_GPE_SAVE_MASK) { switch (action) {
case ACPI_GPE_CONDITIONAL_ENABLE: case ACPI_GPE_CONDITIONAL_ENABLE:
/* Only enable if the corresponding enable_mask bit is set */ /* Only enable if the corresponding enable_mask bit is set */
...@@ -149,9 +151,6 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action) ...@@ -149,9 +151,6 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
/* Write the updated enable mask */ /* Write the updated enable mask */
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
if (ACPI_SUCCESS(status) && (action & ACPI_GPE_SAVE_MASK)) {
gpe_register_info->enable_mask = (u8)enable_mask;
}
return (status); return (status);
} }
...@@ -297,10 +296,8 @@ acpi_hw_gpe_enable_write(u8 enable_mask, ...@@ -297,10 +296,8 @@ acpi_hw_gpe_enable_write(u8 enable_mask,
{ {
acpi_status status; acpi_status status;
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
if (ACPI_SUCCESS(status)) {
gpe_register_info->enable_mask = enable_mask; gpe_register_info->enable_mask = enable_mask;
} status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
return (status); return (status);
} }
......
...@@ -759,10 +759,6 @@ typedef u32 acpi_event_status; ...@@ -759,10 +759,6 @@ typedef u32 acpi_event_status;
#define ACPI_GPE_ENABLE 0 #define ACPI_GPE_ENABLE 0
#define ACPI_GPE_DISABLE 1 #define ACPI_GPE_DISABLE 1
#define ACPI_GPE_CONDITIONAL_ENABLE 2 #define ACPI_GPE_CONDITIONAL_ENABLE 2
#define ACPI_GPE_SAVE_MASK 4
#define ACPI_GPE_ENABLE_SAVE (ACPI_GPE_ENABLE | ACPI_GPE_SAVE_MASK)
#define ACPI_GPE_DISABLE_SAVE (ACPI_GPE_DISABLE | ACPI_GPE_SAVE_MASK)
/* /*
* GPE info flags - Per GPE * GPE info flags - Per GPE
......
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