lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 11 Nov 2018 19:49:05 +0000
From:   Ben Hutchings <ben@...adent.org.uk>
To:     linux-kernel@...r.kernel.org, stable@...r.kernel.org
CC:     akpm@...ux-foundation.org, "Hans de Goede" <hdegoede@...hat.com>,
        "Thierry Reding" <thierry.reding@...il.com>,
        "Andy Shevchenko" <andriy.shevchenko@...ux.intel.com>
Subject: [PATCH 3.16 121/366] pwm: lpss: platform: Save/restore the ctrl
 register over a suspend/resume

3.16.61-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Hans de Goede <hdegoede@...hat.com>

commit 1d375b58c12f08d8570b30b865def4734517f04f upstream.

On some devices the contents of the ctrl register get lost over a
suspend/resume and the PWM comes back up disabled after the resume.

This is seen on some Bay Trail devices with the PWM in ACPI enumerated
mode, so it shows up as a platform device instead of a PCI device.

If we still think it is enabled and then try to change the duty-cycle
after this, we end up with a "PWM_SW_UPDATE was not cleared" error and
the PWM is stuck in that state from then on.

This commit adds suspend and resume pm callbacks to the pwm-lpss-platform
code, which save/restore the ctrl register over a suspend/resume, fixing
this.

Note that:

1) There is no need to do this over a runtime suspend, since we
only runtime suspend when disabled and then we properly set the enable
bit and reprogram the timings when we re-enable the PWM.

2) This may be happening on more systems then we realize, but has been
covered up sofar by a bug in the acpi-lpss.c code which was save/restoring
the regular device registers instead of the lpss private registers due to
lpss_device_desc.prv_offset not being set. This is fixed by a later patch
in this series.

Signed-off-by: Hans de Goede <hdegoede@...hat.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@...ux.intel.com>
Signed-off-by: Thierry Reding <thierry.reding@...il.com>
[bwh: Backported to 3.16:
 - pwm-lpss is a single module, so make the new functions static
 - Only one PWM per chip is supported; remove the npwm assertion and loops
 - Adjust filenames, context]
Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
---
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -39,6 +39,7 @@ struct pwm_lpss_chip {
 	void __iomem *regs;
 	struct clk *clk;
 	unsigned long clk_rate;
+	u32 saved_ctrl;
 };
 
 struct pwm_lpss_boardinfo {
@@ -177,6 +178,24 @@ static int pwm_lpss_remove(struct pwm_lp
 	return pwmchip_remove(&lpwm->chip);
 }
 
+static int pwm_lpss_suspend(struct device *dev)
+{
+	struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
+
+	lpwm->saved_ctrl = readl(lpwm->regs + PWM);
+
+	return 0;
+}
+
+static int pwm_lpss_resume(struct device *dev)
+{
+	struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
+
+	writel(lpwm->saved_ctrl, lpwm->regs + PWM);
+
+	return 0;
+}
+
 static int pwm_lpss_probe_pci(struct pci_dev *pdev,
 			      const struct pci_device_id *id)
 {
@@ -241,6 +260,10 @@ static int pwm_lpss_remove_platform(stru
 	return pwm_lpss_remove(lpwm);
 }
 
+static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops,
+			 pwm_lpss_suspend,
+			 pwm_lpss_resume);
+
 static const struct acpi_device_id pwm_lpss_acpi_match[] = {
 	{ "80860F09", 0 },
 	{ },
@@ -251,6 +274,7 @@ static struct platform_driver pwm_lpss_d
 	.driver = {
 		.name = "pwm-lpss",
 		.acpi_match_table = pwm_lpss_acpi_match,
+		.pm = &pwm_lpss_platform_pm_ops,
 	},
 	.probe = pwm_lpss_probe_platform,
 	.remove = pwm_lpss_remove_platform,

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ