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) |
