aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2007-05-01 23:26:28 +0200
committerJean Delvare <khali@hyperion.delvare>2007-05-01 23:26:28 +0200
commit1ecac07abaca1a4084d0259d4a15b55188852a2e (patch)
tree369572a568a1162ed4ce7e3ef656f36e7e379a6b /drivers/i2c
parentef2c8321f5a27ff9ecdae1ee587430cafa495586 (diff)
downloadkernel_samsung_espresso10-1ecac07abaca1a4084d0259d4a15b55188852a2e.zip
kernel_samsung_espresso10-1ecac07abaca1a4084d0259d4a15b55188852a2e.tar.gz
kernel_samsung_espresso10-1ecac07abaca1a4084d0259d4a15b55188852a2e.tar.bz2
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')
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c27
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)