Skip to contentSkip to conversation

i2c: timeouts off by 1

PATCH In review Roel Kluin 4 participants 6 messages Feb 25, 2009 – Apr 29, 2009 5 messages not in the archive

Subsystems (2)
lore
Share & tools
lore

Roel Kluin

author
#0 lore raw

PATCH 1/1 i2c: timeouts off by 1

with while (timeout++ < MAX_TIMEOUT); timeout reaches MAX_TIMEOUT + 1 after the loop, so the tests below are off by one.

---
 drivers/i2c/busses/i2c-ali1535.c |    2 +-
 drivers/i2c/busses/i2c-ali15x3.c |    2 +-
 drivers/i2c/busses/i2c-amd756.c  |    4 ++--
 drivers/i2c/busses/i2c-i801.c    |    8 ++++----
 drivers/i2c/busses/i2c-isch.c    |    2 +-
 drivers/i2c/busses/i2c-nforce2.c |    2 +-
 drivers/i2c/busses/i2c-pxa.c     |    4 ++--
 drivers/i2c/busses/i2c-sis5595.c |    2 +-
 drivers/i2c/busses/i2c-sis630.c  |    2 +-
 drivers/i2c/busses/i2c-sis96x.c  |    2 +-
 10 files changed, 15 insertions(+), 15 deletions(-)
drivers/i2c/busses/i2c-ali1535.c +1 -1
index 981e080..d108450 100644
@@ -284,7 +284,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
 		 && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		result = -ETIMEDOUT;
 		dev_err(&adap->dev, "SMBus Timeout!\n");
 	}
drivers/i2c/busses/i2c-ali15x3.c +1 -1
index 39066de..d627fce 100644
@@ -306,7 +306,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
 		 && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		result = -ETIMEDOUT;
 		dev_err(&adap->dev, "SMBus Timeout!\n");
 	}
drivers/i2c/busses/i2c-amd756.c +2 -2
index 220f4a1..f7d6fe9 100644
@@ -126,7 +126,7 @@ static int amd756_transaction(struct i2c_adapter *adap)
 		} while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
 		         (timeout++ < MAX_TIMEOUT));
 		/* If the SMBus is still busy, we give up */
-		if (timeout >= MAX_TIMEOUT) {
+		if (timeout > MAX_TIMEOUT) {
 			dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp);
 			goto abort;
 		}
@@ -143,7 +143,7 @@ static int amd756_transaction(struct i2c_adapter *adap)
 	} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		dev_dbg(&adap->dev, "Completion timeout!\n");
 		goto abort;
 	}
drivers/i2c/busses/i2c-i801.c +4 -4
index 230238d..79cacd3 100644
@@ -236,7 +236,7 @@ static int i801_transaction(int xact)
 		status = inb_p(SMBHSTSTS);
 	} while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
 
-	result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+	result = i801_check_post(status, timeout > MAX_TIMEOUT);
 	if (result < 0)
 		return result;
 
@@ -256,9 +256,9 @@ static void i801_wait_hwpec(void)
 	} while ((!(status & SMBHSTSTS_INTR))
 		 && (timeout++ < MAX_TIMEOUT));
 
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT)
 		dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
-	}
+
 	outb_p(status, SMBHSTSTS);
 }
 
@@ -343,7 +343,7 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
 		while ((!(status & SMBHSTSTS_BYTE_DONE))
 		       && (timeout++ < MAX_TIMEOUT));
 
-		result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+		result = i801_check_post(status, timeout > MAX_TIMEOUT);
 		if (result < 0)
 			return result;
 
drivers/i2c/busses/i2c-isch.c +1 -1
index b9c01aa..9f6b8e0 100644
@@ -112,7 +112,7 @@ static int sch_transaction(void)
 	} while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
 		result = -ETIMEDOUT;
 	}
drivers/i2c/busses/i2c-nforce2.c +1 -1
index 05af6cd..d3da45c 100644
@@ -169,7 +169,7 @@ static int nforce2_check_status(struct i2c_adapter *adap)
 		temp = inb_p(NVIDIA_SMB_STS);
 	} while ((!temp) && (timeout++ < MAX_TIMEOUT));
 
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		dev_dbg(&adap->dev, "SMBus Timeout!\n");
 		if (smbus->can_abort)
 			nforce2_abort(adap);
drivers/i2c/busses/i2c-pxa.c +2 -2
index bdb1f75..8a95642 100644
@@ -264,10 +264,10 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
 		show_state(i2c);
 	}
 
-	if (timeout <= 0)
+	if (timeout < 0)
 		show_state(i2c);
 
-	return timeout <= 0 ? I2C_RETRY : 0;
+	return timeout < 0 ? I2C_RETRY : 0;
 }
 
 static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
drivers/i2c/busses/i2c-sis5595.c +1 -1
index f320ab2..139f0c7 100644
@@ -256,7 +256,7 @@ static int sis5595_transaction(struct i2c_adapter *adap)
 	} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		dev_dbg(&adap->dev, "SMBus Timeout!\n");
 		result = -ETIMEDOUT;
 	}
drivers/i2c/busses/i2c-sis630.c +1 -1
index 50c3610..70ca41e 100644
@@ -173,7 +173,7 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
 	} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		dev_dbg(&adap->dev, "SMBus Timeout!\n");
 		result = -ETIMEDOUT;
 	}
drivers/i2c/busses/i2c-sis96x.c +1 -1
index 7e1594b..8295885 100644
@@ -132,7 +132,7 @@ static int sis96x_transaction(int size)
 	} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
 
 	/* If the SMBus is still busy, we give up */
-	if (timeout >= MAX_TIMEOUT) {
+	if (timeout > MAX_TIMEOUT) {
 		dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
 		result = -ETIMEDOUT;
 	}

A message that is not in the archive (sent off-list or not yet received): [email protected]

#2 lore raw

Hi Roel,

Sorry for the late reply, I overlooked your patch.

Quoted 2 lines · Roel Kluin

with while (timeout++ < MAX_TIMEOUT); timeout reaches MAX_TIMEOUT + 1 after the loop, so the tests below are off by one.

This is correct. It just shows how all PC SMBus master drivers have been copied from each other ;)

Quoted 20 lines
---
 drivers/i2c/busses/i2c-ali1535.c |    2 +-
 drivers/i2c/busses/i2c-ali15x3.c |    2 +-
 drivers/i2c/busses/i2c-amd756.c  |    4 ++--
 drivers/i2c/busses/i2c-i801.c    |    8 ++++----
 drivers/i2c/busses/i2c-isch.c    |    2 +-
 drivers/i2c/busses/i2c-nforce2.c |    2 +-
 drivers/i2c/busses/i2c-pxa.c     |    4 ++--
 drivers/i2c/busses/i2c-sis5595.c |    2 +-
 drivers/i2c/busses/i2c-sis630.c  |    2 +-
 drivers/i2c/busses/i2c-sis96x.c  |    2 +-
 10 files changed, 15 insertions(+), 15 deletions(-)
drivers/i2c/busses/i2c-pxa.c +0 -0
@@ -264,10 +264,10 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
 		show_state(i2c);

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) · line 272

Quoted 10 lines
drivers/i2c/busses/i2c-pxa.c +2 -2
 	}
 
-	if (timeout <= 0)
+	if (timeout < 0)
 		show_state(i2c);
 
-	return timeout <= 0 ? I2C_RETRY : 0;
+	return timeout < 0 ? I2C_RETRY : 0;
 }
 

This one is different and doesn't match the description. I'm excluding it from this patch, for this reason and also because there may be other i2c-pxa patches pending on the arm side. Can you please submit a separate patch for i2c-pxa? Thanks.

Signature · 1 line
Jean Delvare

A message that is not in the archive (sent off-list or not yet received): [email protected]

author
#4 lore raw

PATCH 1/1 i2c-pxa.c: timeouts off by 1

Quoted 21 lines · Jean Delvare

Hi Roel,

Sorry for the late reply, I overlooked your patch.

Quoted 2 lines · Roel Kluin

with while (timeout++ < MAX_TIMEOUT); timeout reaches MAX_TIMEOUT + 1 after the loop, so the tests below are off by one.

This is correct. It just shows how all PC SMBus master drivers have been copied from each other ;)

Quoted 10 lines
drivers/i2c/busses/i2c-pxa.c +1 -1
@@ -264,10 +264,10 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
 		show_state(i2c);
 	}
 
-	if (timeout <= 0)
+	if (timeout < 0)
 		show_state(i2c);
 
Quoted 9 lines

drivers/i2c/busses/i2c-pxa.c static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) · line 272

Quoted 4 lines
drivers/i2c/busses/i2c-pxa.c +1 -1
-	return timeout <= 0 ? I2C_RETRY : 0;
+	return timeout < 0 ? I2C_RETRY : 0;
 }
 

This one is different and doesn't match the description. I'm excluding it from this patch, for this reason and also because there may be other i2c-pxa patches pending on the arm side. Can you please submit a separate patch for i2c-pxa? Thanks.

Ok, here's for drivers/i2c/busses/i2c-pxa.c. Note that I found another, the last hunk. --------------------------->8-------------8<------------------------------ With `while (timeout--)' timeout reaches -1 after the loop, so the tests below are off by one.

---

drivers/i2c/busses/i2c-pxa.c +3 -3
index c1405c8..acc7143 100644
@@ -265,10 +265,10 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
 		show_state(i2c);
 	}
 
-	if (timeout <= 0)
+	if (timeout < 0)
 		show_state(i2c);
 
-	return timeout <= 0 ? I2C_RETRY : 0;
+	return timeout < 0 ? I2C_RETRY : 0;
 }
 
 static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
@@ -612,7 +612,7 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
 		show_state(i2c);
 	}
 
-	if (timeout <= 0) {
+	if (timeout < 0) {
 		show_state(i2c);
 		dev_err(&i2c->adap.dev,
 			"i2c_pxa: timeout waiting for bus free\n");

A message that is not in the archive (sent off-list or not yet received): [email protected]

#6 lore raw

Re: [PATCH] i2c-pxa.c: timeouts off by 1

Quoted 8 lines · Roel Kluin

Ok, here's for drivers/i2c/busses/i2c-pxa.c. Note that I found another, the last hunk. --------------------------->8-------------8<------------------------------ With `while (timeout--)' timeout reaches -1 after the loop, so the tests below are off by one.

---

Ben, Wolfram, I'll let you handle this one as it's an arm driver.

Quoted 27 lines
drivers/i2c/busses/i2c-pxa.c +3 -3
index c1405c8..acc7143 100644
@@ -265,10 +265,10 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
 		show_state(i2c);
 	}
 
-	if (timeout <= 0)
+	if (timeout < 0)
 		show_state(i2c);
 
-	return timeout <= 0 ? I2C_RETRY : 0;
+	return timeout < 0 ? I2C_RETRY : 0;
 }
 
 static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
@@ -612,7 +612,7 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
 		show_state(i2c);
 	}
 
-	if (timeout <= 0) {
+	if (timeout < 0) {
 		show_state(i2c);
 		dev_err(&i2c->adap.dev,
 			"i2c_pxa: timeout waiting for bus free\n");
Signature · 1 line
Jean Delvare

A message that is not in the archive (sent off-list or not yet received): [email protected]

#8 lore raw

Re: [PATCH] i2c-pxa.c: timeouts off by 1

Quoted 7 lines · On Thu, 23 Apr 2009 17:02:18 +0200 Jean Delvare…
Quoted 6 lines · Roel Kluin

Ok, here's for drivers/i2c/busses/i2c-pxa.c. Note that I found another, the last hunk. --------------------------->8-------------8<------------------------------ With `while (timeout--)' timeout reaches -1 after the loop, so the tests below are off by one.

Quoted 5 lines
Quoted 2 lines

---

Ben, Wolfram, I'll let you handle this one as it's an arm driver.

The patch looks OK, but the original code is weird.

: static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) : {
: int timeout = DEF_TIMEOUT;
:
: while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
: if ((readl(_ISR(i2c)) & ISR_SAD) != 0)
: timeout += 4;
:
: msleep(2);
: show_state(i2c);
: }
:
: if (timeout < 0)
: show_state(i2c);
:
: return timeout < 0 ? I2C_RETRY : 0;
: }

The timeout+=4 inside the loop makes my brain hurt. It makes the loop potentially almost-infinite. By effectively doing timeout+=3 each time we'll break out of the loop after we've wrapped through 0x100000000 three times. Or something. Help!

Also, i2c_pxa_pio_set_master() does

	long timeout = 2 * DEF_TIMEOUT;

whereas i2c_pxa_wait_bus_not_bus() does

	int timeout = DEF_TIMEOUT;

`int' seems an appropriate choice.

A message that is not in the archive (sent off-list or not yet received): 20090423163507.9588a73d.akpm-de/[email protected]

Acked-by
#10 lore raw

Re: [PATCH] i2c-pxa.c: timeouts off by 1

Quoted 10 lines · Andrew Morton
Quoted 7 lines · On Thu, 23 Apr 2009 17:02:18 +0200 Jean Delvare…
Quoted 6 lines · Roel Kluin

Ok, here's for drivers/i2c/busses/i2c-pxa.c. Note that I found another, the last hunk. --------------------------->8-------------8<------------------------------ With `while (timeout--)' timeout reaches -1 after the loop, so the tests below are off by one.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

---

Ben, Wolfram, I'll let you handle this one as it's an arm driver.

The patch looks OK,

Yup.

Quoted 19 lines

: static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) : {
: int timeout = DEF_TIMEOUT;
:
: while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
: if ((readl(_ISR(i2c)) & ISR_SAD) != 0)
: timeout += 4;
:
: msleep(2);
: show_state(i2c);
: }
:
: if (timeout < 0)
: show_state(i2c);
:
: return timeout < 0 ? I2C_RETRY : 0;
: }

Quoted 4 lines

The timeout+=4 inside the loop makes my brain hurt. It makes the loop potentially almost-infinite. By effectively doing timeout+=3 each time we'll break out of the loop after we've wrapped through 0x100000000 three times. Or something. Help!

Well, it only adds 4 if there was its own I2C-slave address detected. Without knowing the details, I assume there is a reason; I wouldn't dare changing it.

Quoted 10 lines

Also, i2c_pxa_pio_set_master() does

	long timeout = 2 * DEF_TIMEOUT;

whereas i2c_pxa_wait_bus_not_bus() does

	int timeout = DEF_TIMEOUT;

`int' seems an appropriate choice.

This driver seems to have quite some more potential for cleaning up :)

Regards,

Wolfram

Signature · 2 lines
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |