Commit 63fb9623 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds
Browse files

ACPI: PM: s2idle: Check fixed wakeup events in acpi_s2idle_wake()



Commit fdde0ff8 ("ACPI: PM: s2idle: Prevent spurious SCIs from
waking up the system") overlooked the fact that fixed events can wake
up the system too and broke RTC wakeup from suspend-to-idle as a
result.

Fix this issue by checking the fixed events in acpi_s2idle_wake() in
addition to checking wakeup GPEs and break out of the suspend-to-idle
loop if the status bits of any enabled fixed events are set then.

Fixes: fdde0ff8 ("ACPI: PM: s2idle: Prevent spurious SCIs from waking up the system")
Reported-and-tested-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: 5.4+ <stable@vger.kernel.org> # 5.4+
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ebe7acad
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -265,4 +265,49 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
		 handler) (acpi_gbl_fixed_event_handlers[event].context));
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_any_fixed_event_status_set
 *
 * PARAMETERS:  None
 *
 * RETURN:      TRUE or FALSE
 *
 * DESCRIPTION: Checks the PM status register for active fixed events
 *
 ******************************************************************************/

u32 acpi_any_fixed_event_status_set(void)
{
	acpi_status status;
	u32 in_status;
	u32 in_enable;
	u32 i;

	status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable);
	if (ACPI_FAILURE(status)) {
		return (FALSE);
	}

	status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status);
	if (ACPI_FAILURE(status)) {
		return (FALSE);
	}

	/*
	 * Check for all possible Fixed Events and dispatch those that are active
	 */
	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {

		/* Both the status and enable bits must be on for this event */

		if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
		    (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
			return (TRUE);
		}
	}

	return (FALSE);
}

#endif				/* !ACPI_REDUCED_HARDWARE */
+7 −0
Original line number Diff line number Diff line
@@ -1005,6 +1005,13 @@ static bool acpi_s2idle_wake(void)
		if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
			return true;

		/*
		 * If the status bit of any enabled fixed event is set, the
		 * wakeup is regarded as valid.
		 */
		if (acpi_any_fixed_event_status_set())
			return true;

		/*
		 * If there are no EC events to process and at least one of the
		 * other enabled GPEs is active, the wakeup is regarded as a
+1 −0
Original line number Diff line number Diff line
@@ -753,6 +753,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_gpe_status_set(void))
ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_fixed_event_status_set(void))

ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
				acpi_get_gpe_device(u32 gpe_index,