1 |
From: "Rafael J. Wysocki" <rjw@rjwysocki.net> |
2 |
Subject: [PATCH] ACPI / LPSS: Avoid PM quirks on suspend and resume from S3 |
3 |
Date: Wed, 13 Jun 2018 13:17:26 +0200 |
4 |
|
5 |
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
6 |
|
7 |
It is reported that commit a192aa923b66a (ACPI / LPSS: Consolidate |
8 |
runtime PM and system sleep handling) introduced a system suspend |
9 |
regression on some machines, but the only functional change made by |
10 |
it was to cause the PM quirks in the LPSS to also be used during |
11 |
system suspend and resume. While that should always work for |
12 |
suspend-to-idle, it turns out to be problematic for S3 |
13 |
(suspend-to-RAM). |
14 |
|
15 |
To address that issue restore the previous S3 suspend and resume |
16 |
behavior of the LPSS to avoid applying PM quirks then. |
17 |
|
18 |
Fixes: a192aa923b66a (ACPI / LPSS: Consolidate runtime PM and system sleep handling) |
19 |
Link: https://bugs.launchpad.net/bugs/1774950 |
20 |
Reported-by: Kai-Heng Feng <kai.heng.feng@canonical.com> |
21 |
Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com> |
22 |
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
23 |
--- |
24 |
drivers/acpi/acpi_lpss.c | 18 +++++++++++------- |
25 |
1 file changed, 11 insertions(+), 7 deletions(-) |
26 |
|
27 |
Index: linux-pm/drivers/acpi/acpi_lpss.c |
28 |
=================================================================== |
29 |
--- linux-pm.orig/drivers/acpi/acpi_lpss.c |
30 |
+++ linux-pm/drivers/acpi/acpi_lpss.c |
31 |
@@ -22,6 +22,7 @@ |
32 |
#include <linux/pm_domain.h> |
33 |
#include <linux/pm_runtime.h> |
34 |
#include <linux/pwm.h> |
35 |
+#include <linux/suspend.h> |
36 |
#include <linux/delay.h> |
37 |
|
38 |
#include "internal.h" |
39 |
@@ -940,9 +941,10 @@ static void lpss_iosf_exit_d3_state(void |
40 |
mutex_unlock(&lpss_iosf_mutex); |
41 |
} |
42 |
|
43 |
-static int acpi_lpss_suspend(struct device *dev, bool wakeup) |
44 |
+static int acpi_lpss_suspend(struct device *dev, bool runtime) |
45 |
{ |
46 |
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
47 |
+ bool wakeup = runtime || device_may_wakeup(dev); |
48 |
int ret; |
49 |
|
50 |
if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
51 |
@@ -955,13 +957,14 @@ static int acpi_lpss_suspend(struct devi |
52 |
* wrong status for devices being about to be powered off. See |
53 |
* lpss_iosf_enter_d3_state() for further information. |
54 |
*/ |
55 |
- if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) |
56 |
+ if ((runtime || !pm_suspend_via_firmware()) && |
57 |
+ lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) |
58 |
lpss_iosf_enter_d3_state(); |
59 |
|
60 |
return ret; |
61 |
} |
62 |
|
63 |
-static int acpi_lpss_resume(struct device *dev) |
64 |
+static int acpi_lpss_resume(struct device *dev, bool runtime) |
65 |
{ |
66 |
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
67 |
int ret; |
68 |
@@ -970,7 +973,8 @@ static int acpi_lpss_resume(struct devic |
69 |
* This call is kept first to be in symmetry with |
70 |
* acpi_lpss_runtime_suspend() one. |
71 |
*/ |
72 |
- if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) |
73 |
+ if ((runtime || !pm_resume_via_firmware()) && |
74 |
+ lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) |
75 |
lpss_iosf_exit_d3_state(); |
76 |
|
77 |
ret = acpi_dev_resume(dev); |
78 |
@@ -994,12 +998,12 @@ static int acpi_lpss_suspend_late(struct |
79 |
return 0; |
80 |
|
81 |
ret = pm_generic_suspend_late(dev); |
82 |
- return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); |
83 |
+ return ret ? ret : acpi_lpss_suspend(dev, false); |
84 |
} |
85 |
|
86 |
static int acpi_lpss_resume_early(struct device *dev) |
87 |
{ |
88 |
- int ret = acpi_lpss_resume(dev); |
89 |
+ int ret = acpi_lpss_resume(dev, false); |
90 |
|
91 |
return ret ? ret : pm_generic_resume_early(dev); |
92 |
} |
93 |
@@ -1014,7 +1018,7 @@ static int acpi_lpss_runtime_suspend(str |
94 |
|
95 |
static int acpi_lpss_runtime_resume(struct device *dev) |
96 |
{ |
97 |
- int ret = acpi_lpss_resume(dev); |
98 |
+ int ret = acpi_lpss_resume(dev, true); |
99 |
|
100 |
return ret ? ret : pm_generic_runtime_resume(dev); |
101 |
} |
102 |
|
103 |
|