Commit 1ecac07a authored by Jean Delvare's avatar Jean Delvare Committed by Jean Delvare

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: default avatarJean Delvare <khali@linux-fr.org>
parent ef2c8321
...@@ -312,12 +312,10 @@ static int try_address(struct i2c_adapter *i2c_adap, ...@@ -312,12 +312,10 @@ static int try_address(struct i2c_adapter *i2c_adap,
int i,ret = -1; int i,ret = -1;
for (i=0;i<=retries;i++) { for (i=0;i<=retries;i++) {
ret = i2c_outb(i2c_adap,addr); ret = i2c_outb(i2c_adap,addr);
if (ret==1) if (ret == 1 || i == retries)
break; /* success! */ break;
i2c_stop(adap); i2c_stop(adap);
udelay(5/*adap->udelay*/); udelay(5/*adap->udelay*/);
if (i==retries) /* no success */
break;
i2c_start(adap); i2c_start(adap);
udelay(adap->udelay); udelay(adap->udelay);
} }
...@@ -331,7 +329,6 @@ static int try_address(struct i2c_adapter *i2c_adap, ...@@ -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) static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
{ {
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
char c; char c;
const char *temp = msg->buf; const char *temp = msg->buf;
int count = msg->len; int count = msg->len;
...@@ -349,7 +346,6 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) ...@@ -349,7 +346,6 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
wrcount++; wrcount++;
} else { /* arbitration or no acknowledge */ } else { /* arbitration or no acknowledge */
dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
i2c_stop(adap);
return (retval<0)? retval : -EFAULT; return (retval<0)? retval : -EFAULT;
/* got a better one ?? */ /* got a better one ?? */
} }
...@@ -480,27 +476,34 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, ...@@ -480,27 +476,34 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
if ((ret != 0) && !nak_ok) { if ((ret != 0) && !nak_ok) {
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n" DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n"
,msgs[i].addr,i)); ,msgs[i].addr,i));
return (ret<0) ? ret : -EREMOTEIO; goto bailout;
} }
} }
if (pmsg->flags & I2C_M_RD ) { if (pmsg->flags & I2C_M_RD ) {
/* read bytes into buffer*/ /* read bytes into buffer*/
ret = readbytes(i2c_adap, pmsg); ret = readbytes(i2c_adap, pmsg);
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret));
if (ret < pmsg->len ) { if (ret < pmsg->len) {
return (ret<0)? ret : -EREMOTEIO; if (ret >= 0)
ret = -EREMOTEIO;
goto bailout;
} }
} else { } else {
/* write bytes from buffer */ /* write bytes from buffer */
ret = sendbytes(i2c_adap, pmsg); ret = sendbytes(i2c_adap, pmsg);
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret));
if (ret < pmsg->len ) { if (ret < pmsg->len) {
return (ret<0) ? ret : -EREMOTEIO; if (ret >= 0)
ret = -EREMOTEIO;
goto bailout;
} }
} }
} }
ret = i;
bailout:
i2c_stop(adap); i2c_stop(adap);
return num; return ret;
} }
static u32 bit_func(struct i2c_adapter *adap) static u32 bit_func(struct i2c_adapter *adap)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment