summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-06-13 07:17:26 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-06-14 03:57:56 -0400
commita09c591306881dfb04387c6ee7b7e2e4683fa531 (patch)
treee5ede692c136d09f0989d68b602fd860d27abb4c /drivers/acpi
parentd290ef9305ebaaac884ae0350bfc243dd01d354d (diff)
ACPI / LPSS: Avoid PM quirks on suspend and resume from S3
It is reported that commit a192aa923b66a (ACPI / LPSS: Consolidate runtime PM and system sleep handling) introduced a system suspend regression on some machines, but the only functional change made by it was to cause the PM quirks in the LPSS to also be used during system suspend and resume. While that should always work for suspend-to-idle, it turns out to be problematic for S3 (suspend-to-RAM). To address that issue restore the previous S3 suspend and resume behavior of the LPSS to avoid applying PM quirks then. Fixes: a192aa923b66a (ACPI / LPSS: Consolidate runtime PM and system sleep handling) Link: https://bugs.launchpad.net/bugs/1774950 Reported-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Cc: 4.15+ <stable@vger.kernel.org> # 4.15+
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpi_lpss.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index cb6ac5c65c2e..55e4577b504c 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -22,6 +22,7 @@
22#include <linux/pm_domain.h> 22#include <linux/pm_domain.h>
23#include <linux/pm_runtime.h> 23#include <linux/pm_runtime.h>
24#include <linux/pwm.h> 24#include <linux/pwm.h>
25#include <linux/suspend.h>
25#include <linux/delay.h> 26#include <linux/delay.h>
26 27
27#include "internal.h" 28#include "internal.h"
@@ -944,9 +945,10 @@ static void lpss_iosf_exit_d3_state(void)
944 mutex_unlock(&lpss_iosf_mutex); 945 mutex_unlock(&lpss_iosf_mutex);
945} 946}
946 947
947static int acpi_lpss_suspend(struct device *dev, bool wakeup) 948static int acpi_lpss_suspend(struct device *dev, bool runtime)
948{ 949{
949 struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); 950 struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
951 bool wakeup = runtime || device_may_wakeup(dev);
950 int ret; 952 int ret;
951 953
952 if (pdata->dev_desc->flags & LPSS_SAVE_CTX) 954 if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
@@ -959,13 +961,14 @@ static int acpi_lpss_suspend(struct device *dev, bool wakeup)
959 * wrong status for devices being about to be powered off. See 961 * wrong status for devices being about to be powered off. See
960 * lpss_iosf_enter_d3_state() for further information. 962 * lpss_iosf_enter_d3_state() for further information.
961 */ 963 */
962 if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) 964 if ((runtime || !pm_suspend_via_firmware()) &&
965 lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
963 lpss_iosf_enter_d3_state(); 966 lpss_iosf_enter_d3_state();
964 967
965 return ret; 968 return ret;
966} 969}
967 970
968static int acpi_lpss_resume(struct device *dev) 971static int acpi_lpss_resume(struct device *dev, bool runtime)
969{ 972{
970 struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); 973 struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
971 int ret; 974 int ret;
@@ -974,7 +977,8 @@ static int acpi_lpss_resume(struct device *dev)
974 * This call is kept first to be in symmetry with 977 * This call is kept first to be in symmetry with
975 * acpi_lpss_runtime_suspend() one. 978 * acpi_lpss_runtime_suspend() one.
976 */ 979 */
977 if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) 980 if ((runtime || !pm_resume_via_firmware()) &&
981 lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
978 lpss_iosf_exit_d3_state(); 982 lpss_iosf_exit_d3_state();
979 983
980 ret = acpi_dev_resume(dev); 984 ret = acpi_dev_resume(dev);
@@ -998,12 +1002,12 @@ static int acpi_lpss_suspend_late(struct device *dev)
998 return 0; 1002 return 0;
999 1003
1000 ret = pm_generic_suspend_late(dev); 1004 ret = pm_generic_suspend_late(dev);
1001 return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev)); 1005 return ret ? ret : acpi_lpss_suspend(dev, false);
1002} 1006}
1003 1007
1004static int acpi_lpss_resume_early(struct device *dev) 1008static int acpi_lpss_resume_early(struct device *dev)
1005{ 1009{
1006 int ret = acpi_lpss_resume(dev); 1010 int ret = acpi_lpss_resume(dev, false);
1007 1011
1008 return ret ? ret : pm_generic_resume_early(dev); 1012 return ret ? ret : pm_generic_resume_early(dev);
1009} 1013}
@@ -1018,7 +1022,7 @@ static int acpi_lpss_runtime_suspend(struct device *dev)
1018 1022
1019static int acpi_lpss_runtime_resume(struct device *dev) 1023static int acpi_lpss_runtime_resume(struct device *dev)
1020{ 1024{
1021 int ret = acpi_lpss_resume(dev); 1025 int ret = acpi_lpss_resume(dev, true);
1022 1026
1023 return ret ? ret : pm_generic_runtime_resume(dev); 1027 return ret ? ret : pm_generic_runtime_resume(dev);
1024} 1028}