Re: [PATCH] i2c: designware: Do not allow i2c_dw_xfer() calls while suspended

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 09/23/2018 05:00 PM, Hans de Goede wrote:
On most Intel Bay- and Cherry-Trail systems the PMIC is connected over I2C
and the PMIC is accessed through various means by the _PS0 and _PS3 ACPI
methods (power on / off methods) of various devices.

This leads to suspend/resume ordering problems where a device may be
resumed and get its _PS0 method executed before the I2C controller is
resumed. On Cherry Trail this leads to errors like these:

      i2c_designware 808622C1:06: controller timed out
      ACPI Error: AE_ERROR, Returned by Handler for [UserDefinedRegion]
      ACPI Error: Method parse/execution failed \_SB.P18W._ON, AE_ERROR
      video LNXVIDEO:00: Failed to change power state to D0

But on Bay Trail this caused I2C reads to seem to succeed, but they end
up returning wrong data, which ends up getting written back by the typical
read-modify-write cycle done to turn on various power-resources.

Debugging the problems caused by this silent data corruption is quite
nasty. This commit adds a check which disallows i2c_dw_xfer() calls to
happen until the controller's resume method has completed.

Which turns the silent data corruption into getting these errors in
dmesg instead:

     i2c_designware 80860F41:04: Error i2c_dw_xfer call while suspended
     ACPI Error: AE_ERROR, Returned by Handler for [UserDefinedRegion]
     ACPI Error: Method parse/execution failed \_SB.PCI0.GFX0._PS0, AE_ERROR

Which is much better.

Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
---
  drivers/i2c/busses/i2c-designware-core.h    | 2 ++
  drivers/i2c/busses/i2c-designware-master.c  | 6 ++++++
  drivers/i2c/busses/i2c-designware-pcidrv.c  | 7 ++++++-
  drivers/i2c/busses/i2c-designware-platdrv.c | 3 +++
  4 files changed, 17 insertions(+), 1 deletion(-)

...
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 2a630ac35ba2..77a1ab33a3d4 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -424,6 +424,12 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
pm_runtime_get_sync(dev->dev); + if (dev->suspended) {
+		dev_err(dev->dev, "Error %s call while suspended\n", __func__);
+		ret = -EIO;

I don't know for sure but would the -EBUSY be more correct here?

--
Jarkko



[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux