aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaudio Foellmi <claudio.foellmi@ergon.ch>2017-10-05 08:44:14 -0400
committerWolfram Sang <wsa@the-dreams.de>2017-10-28 16:56:50 -0400
commit1f35b8653687b9c08c8d58489c1b5cb9cf961c17 (patch)
treef078d095f01fa9792a3ce8e8849cf5a1e70e0c4d
parent3ded0512e96fcd654c45d8245f6d7ea2e435a8c9 (diff)
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>
-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)
205 */ 205 */
206 while (i++ < RECOVERY_CLK_CNT * 2) { 206 while (i++ < RECOVERY_CLK_CNT * 2) {
207 if (val) { 207 if (val) {
208 /* Break if SDA is high */
209 if (bri->get_sda && bri->get_sda(adap))
210 break;
211 /* SCL shouldn't be low here */ 208 /* SCL shouldn't be low here */
212 if (!bri->get_scl(adap)) { 209 if (!bri->get_scl(adap)) {
213 dev_err(&adap->dev, 210 dev_err(&adap->dev,
@@ -215,6 +212,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
215 ret = -EBUSY; 212 ret = -EBUSY;
216 break; 213 break;
217 } 214 }
215 /* Break if SDA is high */
216 if (bri->get_sda && bri->get_sda(adap))
217 break;
218 } 218 }
219 219
220 val = !val; 220 val = !val;
@@ -222,6 +222,10 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)
222 ndelay(RECOVERY_NDELAY); 222 ndelay(RECOVERY_NDELAY);
223 } 223 }
224 224
225 /* check if recovery actually succeeded */
226 if (bri->get_sda && !bri->get_sda(adap))
227 ret = -EBUSY;
228
225 if (bri->unprepare_recovery) 229 if (bri->unprepare_recovery)
226 bri->unprepare_recovery(adap); 230 bri->unprepare_recovery(adap);
227 231