]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.19/acpi-ec-pm-disable-non-wakeup-gpes-for-suspend-to-id.patch
70b8228a28565c2d73e7a91ef4f9fefb5b3dd54f
[thirdparty/kernel/stable-queue.git] / queue-4.19 / acpi-ec-pm-disable-non-wakeup-gpes-for-suspend-to-id.patch
1 From eeeff38cb7cbcd5fec7553e2eb853698c94f4aaf Mon Sep 17 00:00:00 2001
2 From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
3 Date: Mon, 17 Dec 2018 12:21:55 +0100
4 Subject: ACPI: EC / PM: Disable non-wakeup GPEs for suspend-to-idle
5
6 [ Upstream commit f941d3e41da7f86bdb9dcc1977c2bcc6b89bfe47 ]
7
8 There are systems in which non-wakeup GPEs fire during the "noirq"
9 suspend stage of suspending devices and that effectively prevents the
10 system that tries to suspend to idle from entering any low-power
11 state at all. If the offending GPE fires regularly and often enough,
12 the system appears to be suspended, but in fact it is in a tight loop
13 over "noirq" suspend and "noirq" resume of devices all the time.
14
15 To prevent that from happening, disable all non-wakeup GPEs except
16 for the EC GPE for suspend-to-idle (the EC GPE is special, because
17 on some systems it has to be enabled for power button wakeup events
18 to be generated as expected).
19
20 Fixes: 147a7d9d25ca (ACPI / PM: Do not reconfigure GPEs for suspend-to-idle)
21 Link: https://bugzilla.kernel.org/show_bug.cgi?id=201987
22 Reported-by: Zhang Rui <rui.zhang@intel.com>
23 Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
24 Tested-by: Zhang Rui <rui.zhang@intel.com>
25 Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
26 Signed-off-by: Sasha Levin <sashal@kernel.org>
27 ---
28 drivers/acpi/ec.c | 12 ++++++++++++
29 drivers/acpi/internal.h | 2 ++
30 drivers/acpi/sleep.c | 11 +++++++++++
31 3 files changed, 25 insertions(+)
32
33 diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
34 index d4e5610e09c5..9d66a47d32fb 100644
35 --- a/drivers/acpi/ec.c
36 +++ b/drivers/acpi/ec.c
37 @@ -1034,6 +1034,18 @@ void acpi_ec_unblock_transactions(void)
38 acpi_ec_start(first_ec, true);
39 }
40
41 +void acpi_ec_mark_gpe_for_wake(void)
42 +{
43 + if (first_ec && !ec_no_wakeup)
44 + acpi_mark_gpe_for_wake(NULL, first_ec->gpe);
45 +}
46 +
47 +void acpi_ec_set_gpe_wake_mask(u8 action)
48 +{
49 + if (first_ec && !ec_no_wakeup)
50 + acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action);
51 +}
52 +
53 void acpi_ec_dispatch_gpe(void)
54 {
55 if (first_ec)
56 diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
57 index 530a3f675490..f59d0b9e2683 100644
58 --- a/drivers/acpi/internal.h
59 +++ b/drivers/acpi/internal.h
60 @@ -188,6 +188,8 @@ int acpi_ec_ecdt_probe(void);
61 int acpi_ec_dsdt_probe(void);
62 void acpi_ec_block_transactions(void);
63 void acpi_ec_unblock_transactions(void);
64 +void acpi_ec_mark_gpe_for_wake(void);
65 +void acpi_ec_set_gpe_wake_mask(u8 action);
66 void acpi_ec_dispatch_gpe(void);
67 int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
68 acpi_handle handle, acpi_ec_query_func func,
69 diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
70 index 754d59f95500..74c489047f57 100644
71 --- a/drivers/acpi/sleep.c
72 +++ b/drivers/acpi/sleep.c
73 @@ -940,6 +940,8 @@ static int lps0_device_attach(struct acpi_device *adev,
74
75 acpi_handle_debug(adev->handle, "_DSM function mask: 0x%x\n",
76 bitmask);
77 +
78 + acpi_ec_mark_gpe_for_wake();
79 } else {
80 acpi_handle_debug(adev->handle,
81 "_DSM function 0 evaluation failed\n");
82 @@ -968,11 +970,16 @@ static int acpi_s2idle_prepare(void)
83 if (lps0_device_handle) {
84 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
85 acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
86 +
87 + acpi_ec_set_gpe_wake_mask(ACPI_GPE_ENABLE);
88 }
89
90 if (acpi_sci_irq_valid())
91 enable_irq_wake(acpi_sci_irq);
92
93 + /* Change the configuration of GPEs to avoid spurious wakeup. */
94 + acpi_enable_all_wakeup_gpes();
95 + acpi_os_wait_events_complete();
96 return 0;
97 }
98
99 @@ -1017,10 +1024,14 @@ static void acpi_s2idle_sync(void)
100
101 static void acpi_s2idle_restore(void)
102 {
103 + acpi_enable_all_runtime_gpes();
104 +
105 if (acpi_sci_irq_valid())
106 disable_irq_wake(acpi_sci_irq);
107
108 if (lps0_device_handle) {
109 + acpi_ec_set_gpe_wake_mask(ACPI_GPE_DISABLE);
110 +
111 acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
112 acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
113 }
114 --
115 2.19.1
116