summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorClaudio Foellmi <claudio.foellmi@ergon.ch>2017-10-05 15:44:14 +0300
committerWolfram Sang <wsa@the-dreams.de>2017-10-28 23:56:50 +0300
commit1f35b8653687b9c08c8d58489c1b5cb9cf961c17 (patch)
treef078d095f01fa9792a3ce8e8849cf5a1e70e0c4d /drivers
parent3ded0512e96fcd654c45d8245f6d7ea2e435a8c9 (diff)
downloadlinux-1f35b8653687b9c08c8d58489c1b5cb9cf961c17.tar.xz
i2c: generic recovery: check SCL before SDA
Move the check for a stuck SCL before the check for a high SDA. This prevent false positives in the specific case that SDA is fine and SCL is stuck, which previously returned 0. Also check SDA again after the loop, if we can. Together, these changes should lead to a lot more failed recoveries being caught and returning error codes. Signed-off-by: Claudio Foellmi <claudio.foellmi@ergon.ch> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/i2c-core-base.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 875d6cacaa17..db6558e5f657 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -205,9 +205,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
*/
while (i++ < RECOVERY_CLK_CNT * 2) {
if (val) {
- /* Break if SDA is high */
- if (bri->get_sda && bri->get_sda(adap))
- break;
/* SCL shouldn't be low here */
if (!bri->get_scl(adap)) {
dev_err(&adap->dev,
@@ -215,6 +212,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
ret = -EBUSY;
break;
}
+ /* Break if SDA is high */
+ if (bri->get_sda && bri->get_sda(adap))
+ break;
}
val = !val;
@@ -222,6 +222,10 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
ndelay(RECOVERY_NDELAY);
}
+ /* check if recovery actually succeeded */
+ if (bri->get_sda && !bri->get_sda(adap))
+ ret = -EBUSY;
+
if (bri->unprepare_recovery)
bri->unprepare_recovery(adap);