All of lore.kernel.org
 help / color / mirror / Atom feed
From: clock@twibright.com (Karel Kulhavy)
To: lm-sensors@vger.kernel.org
Subject: [lm-sensors] Patch to check return values in i2c-algo-bit.c
Date: Sat, 11 Jun 2005 16:12:32 +0000	[thread overview]
Message-ID: <20050611141135.GA25547@kestrel> (raw)
In-Reply-To: <20050611110823.GA21311@kestrel>

Hello

When you use a parallel port adapter that supports SCL readback and have
the kernel configured to use it and are using also some additional
driver on top of it (PCFxxx or whatever) and the adapter is accidentally
pulled out, you get a big (90 second) delay on system startup.

This is because SCL readback times out, generates -ETIMEDOUT, but the
caller functions don't check this and continue repeating operations
again and again.

I have made a patch to fix this problem. However was unable to check it
because don't have suitable hardware.

Please ideologicallt check it and try it someone. I hope the changes are
not so complicated it could cause some bug.

CL<

--- /usr/src/linux/drivers/i2c/algos/i2c-algo-bit.c	2005-06-10 20:06:26.000000000 +0200
+++ i2c-algo-bit.c	2005-06-10 20:10:20.000000000 +0200
@@ -115,26 +115,36 @@
 	scllo(adap);
 }
 
-static void i2c_repstart(struct i2c_algo_bit_data *adap) 
+/* Return value: 0 OK, <0 error */
+static int i2c_repstart(struct i2c_algo_bit_data *adap) 
 {
+	int retval;
 	/* scl, sda may not be high */
 	DEBPROTO(printk(" Sr "));
 	setsda(adap,1);
-	sclhi(adap);
+	if ((retval = sclhi(adap)) < 0)
+		return retval; 
 	udelay(adap->udelay);
 	
 	sdalo(adap);
 	scllo(adap);
+	return 0;
 }
 
 
-static void i2c_stop(struct i2c_algo_bit_data *adap) 
+/* Returns 0 on OK and -ETIMEDOUT on timeout. */
+static int i2c_stop(struct i2c_algo_bit_data *adap) 
 {
+	int retval;
+
 	DEBPROTO(printk("P\n"));
+
 	/* assert: scl is low */
 	sdalo(adap);
-	sclhi(adap); 
+	if ((retval = sclhi(adap)) < 0)
+		return retval;
 	sdahi(adap);
+	return 0;
 }
 
 
@@ -218,8 +228,9 @@
  * Sanity check for the adapter hardware - check the reaction of
  * the bus lines only if it seems to be idle.
  */
-static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
-	int scl,sda;
+static int test_bus(struct i2c_algo_bit_data *adap, char* name)
+{
+	int scl, sda, retval;
 
 	if (adap->getscl=NULL)
 		printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, "
@@ -275,7 +286,10 @@
 		goto bailout;
 	}
 	
-	sclhi(adap);
+	retval = sclhi(adap);
+	if (retval < 0)
+		return retval;
+
 	sda=getsda(adap);
 	scl=(adap->getscl=NULL?1:getscl(adap));
 	printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda);
@@ -292,7 +306,11 @@
 	return 0;
 bailout:
 	sdahi(adap);
-	sclhi(adap);
+	
+	retval = sclhi(adap);
+	if (retval < 0)
+		return retval;
+
 	return -ENODEV;
 }
 
@@ -310,12 +328,20 @@
 		       unsigned char addr, int retries)
 {
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-	int i,ret = -1;
+	int i,ret = -1, retval;
 	for (i=0;i<=retries;i++) {
 		ret = i2c_outb(i2c_adap,addr);
 		if (ret=1)
 			break;	/* success! */
-		i2c_stop(adap);
+		if (ret < 0) return ret; /* Error */
+		
+		retval = i2c_stop(adap);
+		if (retval < 0)
+			return retval;
+		/* This can happen only when SCL readback doesn't work.
+	 	* We won't retry here because retry on sclhi doesn't
+		* make sense (the adapter is powered off or faulty) */
+
 		udelay(5/*adap->udelay*/);
 		if (i=retries)  /* no success */
 			break;
@@ -330,6 +356,7 @@
 	return ret;
 }
 
+/** Return value: */
 static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
@@ -337,7 +364,7 @@
 	const char *temp = msg->buf;
 	int count = msg->len;
 	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 
-	int retval;
+	int retval, retval_inner;
 	int wrcount=0;
 
 	while (count > 0) {
@@ -350,7 +377,10 @@
 			wrcount++;
 		} else { /* arbitration or no acknowledge */
 			dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
-			i2c_stop(adap);
+			retval_inner = i2c_stop(adap);
+			if (retval_inner < 0)
+				return retval_inner;
+
 			return (retval<0)? retval : -EFAULT;
 			        /* got a better one ?? */
 		}
@@ -430,22 +460,30 @@
 		DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
 		/* try extended address code...*/
 		ret = try_address(i2c_adap, addr, retries);
+		if (ret < 0) return ret;
 		if ((ret != 1) && !nak_ok)  {
 			printk(KERN_ERR "died at extended address code.\n");
 			return -EREMOTEIO;
 		}
 		/* the remaining 8 bit address */
 		ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
+		if (ret < 0) return ret;
 		if ((ret != 1) && !nak_ok) {
 			/* the chip did not ack / xmission error occurred */
 			printk(KERN_ERR "died at 2nd address code.\n");
 			return -EREMOTEIO;
 		}
 		if ( flags & I2C_M_RD ) {
-			i2c_repstart(adap);
+			int retval;
+
+			retval = i2c_repstart(adap);
+			if (retval < 0)
+				return retval;
+
 			/* okay, now switch into reading mode */
 			addr |= 0x01;
 			ret = try_address(i2c_adap, addr, retries);
+			if (ret < 0) return ret;
 			if ((ret!=1) && !nak_ok) {
 				printk(KERN_ERR "died at extended address code.\n");
 				return -EREMOTEIO;
@@ -458,6 +496,7 @@
 		if (flags & I2C_M_REV_DIR_ADDR )
 			addr ^= 1;
 		ret = try_address(i2c_adap, addr, retries);
+		if (ret < 0) return ret;
 		if ((ret!=1) && !nak_ok)
 			return -EREMOTEIO;
 	}
@@ -471,7 +510,7 @@
 	struct i2c_msg *pmsg;
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
 	
-	int i,ret;
+	int i,ret, retval;
 	unsigned short nak_ok;
 
 	i2c_start(adap);
@@ -480,13 +519,17 @@
 		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 
 		if (!(pmsg->flags & I2C_M_NOSTART)) {
 			if (i) {
-				i2c_repstart(adap);
+				int retval;
+
+				retval = i2c_repstart(adap);
+				if (retval < 0)
+					return retval;
 			}
 			ret = bit_doAddress(i2c_adap, pmsg);
 			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;
+			    return (ret < 0) ? ret : -EREMOTEIO;
 			}
 		}
 		if (pmsg->flags & I2C_M_RD ) {
@@ -494,18 +537,22 @@
 			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;
+				return (ret < 0)? ret : -EREMOTEIO;
 			}
 		} 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;
+				return (ret < 0) ? ret : -EREMOTEIO;
 			}
 		}
 	}
-	i2c_stop(adap);
+
+	retval = i2c_stop(adap);
+	if (retval < 0)
+		return retval;
+
 	return num;
 }
 
@@ -534,7 +581,7 @@
 
 	if (bit_test) {
 		int ret = test_bus(bit_adap, adap->name);
-		if (ret<0)
+		if (ret < 0)
 			return -ENODEV;
 	}
 

  reply	other threads:[~2005-06-11 16:12 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-06-11 13:09 [lm-sensors] Patch to check return values in i2c-algo-bit.c Karel Kulhavy
2005-06-11 16:12 ` Karel Kulhavy [this message]
2005-06-11 17:21 ` Jean Delvare
2005-06-12 10:39 ` Jean Delvare
2005-06-12 14:22 ` Karel Kulhavy
2005-06-12 14:34 ` Jean Delvare

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050611141135.GA25547@kestrel \
    --to=clock@twibright.com \
    --cc=lm-sensors@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.