diff options
author | Jean Delvare <khali@linux-fr.org> | 2007-05-01 17:26:28 -0400 |
---|---|---|
committer | Jean Delvare <khali@hyperion.delvare> | 2007-05-01 17:26:28 -0400 |
commit | 1ecac07abaca1a4084d0259d4a15b55188852a2e (patch) | |
tree | 369572a568a1162ed4ce7e3ef656f36e7e379a6b /drivers/i2c/algos | |
parent | ef2c8321f5a27ff9ecdae1ee587430cafa495586 (diff) |
i2c-algo-bit: Always send a stop condition before leaving
The i2c-algo-bit driver doesn't behave well on read errors: it'll
bail out without even sending a stop condition on the bus, so the bus
will be stuck. So make sure that we always send a stop condition on
the bus before we leave. The best way to make sure is to always send
it at the end of function bit_xfer.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/algos')
-rw-r--r-- | drivers/i2c/algos/i2c-algo-bit.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 95aa5395a5be..28b7e25ca79c 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c | |||
@@ -312,12 +312,10 @@ static int try_address(struct i2c_adapter *i2c_adap, | |||
312 | int i,ret = -1; | 312 | int i,ret = -1; |
313 | for (i=0;i<=retries;i++) { | 313 | for (i=0;i<=retries;i++) { |
314 | ret = i2c_outb(i2c_adap,addr); | 314 | ret = i2c_outb(i2c_adap,addr); |
315 | if (ret==1) | 315 | if (ret == 1 || i == retries) |
316 | break; /* success! */ | 316 | break; |
317 | i2c_stop(adap); | 317 | i2c_stop(adap); |
318 | udelay(5/*adap->udelay*/); | 318 | udelay(5/*adap->udelay*/); |
319 | if (i==retries) /* no success */ | ||
320 | break; | ||
321 | i2c_start(adap); | 319 | i2c_start(adap); |
322 | udelay(adap->udelay); | 320 | udelay(adap->udelay); |
323 | } | 321 | } |
@@ -331,7 +329,6 @@ static int try_address(struct i2c_adapter *i2c_adap, | |||
331 | 329 | ||
332 | static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) | 330 | static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) |
333 | { | 331 | { |
334 | struct i2c_algo_bit_data *adap = i2c_adap->algo_data; | ||
335 | char c; | 332 | char c; |
336 | const char *temp = msg->buf; | 333 | const char *temp = msg->buf; |
337 | int count = msg->len; | 334 | int count = msg->len; |
@@ -349,7 +346,6 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) | |||
349 | wrcount++; | 346 | wrcount++; |
350 | } else { /* arbitration or no acknowledge */ | 347 | } else { /* arbitration or no acknowledge */ |
351 | dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); | 348 | dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); |
352 | i2c_stop(adap); | ||
353 | return (retval<0)? retval : -EFAULT; | 349 | return (retval<0)? retval : -EFAULT; |
354 | /* got a better one ?? */ | 350 | /* got a better one ?? */ |
355 | } | 351 | } |
@@ -480,27 +476,34 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, | |||
480 | if ((ret != 0) && !nak_ok) { | 476 | if ((ret != 0) && !nak_ok) { |
481 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n" | 477 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n" |
482 | ,msgs[i].addr,i)); | 478 | ,msgs[i].addr,i)); |
483 | return (ret<0) ? ret : -EREMOTEIO; | 479 | goto bailout; |
484 | } | 480 | } |
485 | } | 481 | } |
486 | if (pmsg->flags & I2C_M_RD ) { | 482 | if (pmsg->flags & I2C_M_RD ) { |
487 | /* read bytes into buffer*/ | 483 | /* read bytes into buffer*/ |
488 | ret = readbytes(i2c_adap, pmsg); | 484 | ret = readbytes(i2c_adap, pmsg); |
489 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); | 485 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); |
490 | if (ret < pmsg->len ) { | 486 | if (ret < pmsg->len) { |
491 | return (ret<0)? ret : -EREMOTEIO; | 487 | if (ret >= 0) |
488 | ret = -EREMOTEIO; | ||
489 | goto bailout; | ||
492 | } | 490 | } |
493 | } else { | 491 | } else { |
494 | /* write bytes from buffer */ | 492 | /* write bytes from buffer */ |
495 | ret = sendbytes(i2c_adap, pmsg); | 493 | ret = sendbytes(i2c_adap, pmsg); |
496 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); | 494 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); |
497 | if (ret < pmsg->len ) { | 495 | if (ret < pmsg->len) { |
498 | return (ret<0) ? ret : -EREMOTEIO; | 496 | if (ret >= 0) |
497 | ret = -EREMOTEIO; | ||
498 | goto bailout; | ||
499 | } | 499 | } |
500 | } | 500 | } |
501 | } | 501 | } |
502 | ret = i; | ||
503 | |||
504 | bailout: | ||
502 | i2c_stop(adap); | 505 | i2c_stop(adap); |
503 | return num; | 506 | return ret; |
504 | } | 507 | } |
505 | 508 | ||
506 | static u32 bit_func(struct i2c_adapter *adap) | 509 | static u32 bit_func(struct i2c_adapter *adap) |