]>
Commit | Line | Data |
---|---|---|
d7d5500c GKH |
1 | From 12864ff8545f6b8144fdf1bb89b5663357f29ec4 Mon Sep 17 00:00:00 2001 |
2 | From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> | |
3 | Date: Thu, 26 Jul 2018 10:58:20 +0200 | |
4 | Subject: ACPI / LPSS: Avoid PM quirks on suspend and resume from hibernation | |
5 | ||
6 | From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | |
7 | ||
8 | commit 12864ff8545f6b8144fdf1bb89b5663357f29ec4 upstream. | |
9 | ||
10 | Commit a09c59130688 (ACPI / LPSS: Avoid PM quirks on suspend and | |
11 | resume from S3) modified the ACPI driver for Intel SoCs (LPSS) to | |
12 | avoid applying PM quirks on suspend and resume from S3 to address | |
13 | system-wide suspend and resume problems on some systems, but it is | |
14 | reported that the same issue also affects hibernation, so extend | |
15 | the approach used by that commit to cover hibernation as well. | |
16 | ||
17 | Fixes: a09c59130688 (ACPI / LPSS: Avoid PM quirks on suspend and resume from S3) | |
18 | Link: https://bugs.launchpad.net/bugs/1774950 | |
19 | Reported-by: Kai-Heng Feng <kai.heng.feng@canonical.com> | |
20 | Cc: 4.15+ <stable@vger.kernel.org> # 4.15+ | |
21 | Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> | |
22 | Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> | |
23 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
24 | ||
25 | --- | |
26 | drivers/acpi/acpi_lpss.c | 26 +++++++++++++++++--------- | |
27 | 1 file changed, 17 insertions(+), 9 deletions(-) | |
28 | ||
29 | --- a/drivers/acpi/acpi_lpss.c | |
30 | +++ b/drivers/acpi/acpi_lpss.c | |
31 | @@ -879,6 +879,7 @@ static void acpi_lpss_dismiss(struct dev | |
32 | #define LPSS_GPIODEF0_DMA_LLP BIT(13) | |
33 | ||
34 | static DEFINE_MUTEX(lpss_iosf_mutex); | |
35 | +static bool lpss_iosf_d3_entered; | |
36 | ||
37 | static void lpss_iosf_enter_d3_state(void) | |
38 | { | |
39 | @@ -921,6 +922,9 @@ static void lpss_iosf_enter_d3_state(voi | |
40 | ||
41 | iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, | |
42 | LPSS_IOSF_GPIODEF0, value1, mask1); | |
43 | + | |
44 | + lpss_iosf_d3_entered = true; | |
45 | + | |
46 | exit: | |
47 | mutex_unlock(&lpss_iosf_mutex); | |
48 | } | |
49 | @@ -935,6 +939,11 @@ static void lpss_iosf_exit_d3_state(void | |
50 | ||
51 | mutex_lock(&lpss_iosf_mutex); | |
52 | ||
53 | + if (!lpss_iosf_d3_entered) | |
54 | + goto exit; | |
55 | + | |
56 | + lpss_iosf_d3_entered = false; | |
57 | + | |
58 | iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE, | |
59 | LPSS_IOSF_GPIODEF0, value1, mask1); | |
60 | ||
61 | @@ -944,13 +953,13 @@ static void lpss_iosf_exit_d3_state(void | |
62 | iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE, | |
63 | LPSS_IOSF_PMCSR, value2, mask2); | |
64 | ||
65 | +exit: | |
66 | mutex_unlock(&lpss_iosf_mutex); | |
67 | } | |
68 | ||
69 | -static int acpi_lpss_suspend(struct device *dev, bool runtime) | |
70 | +static int acpi_lpss_suspend(struct device *dev, bool wakeup) | |
71 | { | |
72 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | |
73 | - bool wakeup = runtime || device_may_wakeup(dev); | |
74 | int ret; | |
75 | ||
76 | if (pdata->dev_desc->flags & LPSS_SAVE_CTX) | |
77 | @@ -963,14 +972,14 @@ static int acpi_lpss_suspend(struct devi | |
78 | * wrong status for devices being about to be powered off. See | |
79 | * lpss_iosf_enter_d3_state() for further information. | |
80 | */ | |
81 | - if ((runtime || !pm_suspend_via_firmware()) && | |
82 | + if (acpi_target_system_state() == ACPI_STATE_S0 && | |
83 | lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) | |
84 | lpss_iosf_enter_d3_state(); | |
85 | ||
86 | return ret; | |
87 | } | |
88 | ||
89 | -static int acpi_lpss_resume(struct device *dev, bool runtime) | |
90 | +static int acpi_lpss_resume(struct device *dev) | |
91 | { | |
92 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | |
93 | int ret; | |
94 | @@ -979,8 +988,7 @@ static int acpi_lpss_resume(struct devic | |
95 | * This call is kept first to be in symmetry with | |
96 | * acpi_lpss_runtime_suspend() one. | |
97 | */ | |
98 | - if ((runtime || !pm_resume_via_firmware()) && | |
99 | - lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) | |
100 | + if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) | |
101 | lpss_iosf_exit_d3_state(); | |
102 | ||
103 | ret = acpi_dev_resume(dev); | |
104 | @@ -1004,12 +1012,12 @@ static int acpi_lpss_suspend_late(struct | |
105 | return 0; | |
106 | ||
107 | ret = pm_generic_suspend_late(dev); | |
108 | - return ret ? ret : acpi_lpss_suspend(dev, false); | |
109 | + return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); | |
110 | } | |
111 | ||
112 | static int acpi_lpss_resume_early(struct device *dev) | |
113 | { | |
114 | - int ret = acpi_lpss_resume(dev, false); | |
115 | + int ret = acpi_lpss_resume(dev); | |
116 | ||
117 | return ret ? ret : pm_generic_resume_early(dev); | |
118 | } | |
119 | @@ -1024,7 +1032,7 @@ static int acpi_lpss_runtime_suspend(str | |
120 | ||
121 | static int acpi_lpss_runtime_resume(struct device *dev) | |
122 | { | |
123 | - int ret = acpi_lpss_resume(dev, true); | |
124 | + int ret = acpi_lpss_resume(dev); | |
125 | ||
126 | return ret ? ret : pm_generic_runtime_resume(dev); | |
127 | } |