From 1ecac07abaca1a4084d0259d4a15b55188852a2e Mon Sep 17 00:00:00 2001 From: Jean Delvare <khali@linux-fr.org> Date: Tue, 1 May 2007 23:26:28 +0200 Subject: 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> --- drivers/i2c/algos/i2c-algo-bit.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/i2c/algos/i2c-algo-bit.c') 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, 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) -- cgit v1.2.3