diff options
author | Jean Delvare <khali@linux-fr.org> | 2007-05-01 23:26:28 +0200 |
---|---|---|
committer | Jean Delvare <khali@hyperion.delvare> | 2007-05-01 23:26:28 +0200 |
commit | 1ecac07abaca1a4084d0259d4a15b55188852a2e (patch) | |
tree | 369572a568a1162ed4ce7e3ef656f36e7e379a6b /drivers | |
parent | ef2c8321f5a27ff9ecdae1ee587430cafa495586 (diff) | |
download | op-kernel-dev-1ecac07abaca1a4084d0259d4a15b55188852a2e.zip op-kernel-dev-1ecac07abaca1a4084d0259d4a15b55188852a2e.tar.gz |
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')
-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 95aa539..28b7e25 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, int i,ret = -1; for (i=0;i<=retries;i++) { ret = i2c_outb(i2c_adap,addr); - if (ret==1) - break; /* success! */ + if (ret == 1 || i == retries) + break; i2c_stop(adap); udelay(5/*adap->udelay*/); - if (i==retries) /* no success */ - break; i2c_start(adap); udelay(adap->udelay); } @@ -331,7 +329,6 @@ static int try_address(struct i2c_adapter *i2c_adap, static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; char c; const char *temp = msg->buf; int count = msg->len; @@ -349,7 +346,6 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) wrcount++; } else { /* arbitration or no acknowledge */ dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); - i2c_stop(adap); return (retval<0)? retval : -EFAULT; /* got a better one ?? */ } @@ -480,27 +476,34 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, if ((ret != 0) && !nak_ok) { DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n" ,msgs[i].addr,i)); - return (ret<0) ? ret : -EREMOTEIO; + goto bailout; } } if (pmsg->flags & I2C_M_RD ) { /* read bytes into buffer*/ ret = readbytes(i2c_adap, pmsg); DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); - if (ret < pmsg->len ) { - return (ret<0)? ret : -EREMOTEIO; + if (ret < pmsg->len) { + if (ret >= 0) + ret = -EREMOTEIO; + goto bailout; } } else { /* write bytes from buffer */ ret = sendbytes(i2c_adap, pmsg); DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); - if (ret < pmsg->len ) { - return (ret<0) ? ret : -EREMOTEIO; + if (ret < pmsg->len) { + if (ret >= 0) + ret = -EREMOTEIO; + goto bailout; } } } + ret = i; + +bailout: i2c_stop(adap); - return num; + return ret; } static u32 bit_func(struct i2c_adapter *adap) |