mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
ACPICA: Store GPE register enable masks upfront
It is reported that ACPI interrupts do not work any more on Dell Latitude D600 after commitc50f13c672(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: Jim Bos <jim876@xs4all.nl> Fixes:c50f13c672(ACPICA: Save current masks of enabled GPEs after enable register writes) Cc: 3.19+ <stable@vger.kernel.org> # 3.19+ Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
@@ -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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
/* 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)
|
|||||||
/* 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,
|
|||||||
{
|
{
|
||||||
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;
|
|||||||
#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
|
||||||
|
|||||||
Reference in New Issue
Block a user