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