All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] i2c: xlp9xx: Fix case where SSIF read transaction completes early
@ 2018-07-23  5:18 George Cherian
  2018-07-31 21:05 ` Wolfram Sang
  0 siblings, 1 reply; 3+ messages in thread
From: George Cherian @ 2018-07-23  5:18 UTC (permalink / raw)
  To: linux-i2c, linux-kernel; +Cc: jglauber, george.cherian, wsa

During ipmi stress tests we see occasional failure of transactions
at the boot time. This happens in the case of a I2C_M_RECV_LEN
transactions, when the read transfer completes (with the initial
read length of 34) before the driver gets a chance to handle interrupts.

The current driver code expects at least 2 interrupts for I2C_M_RECV_LEN
transactions. The length is updated during the first interrupt, and  the
buffer contents are only copied during subsequent interrupts. In case of
just one interrupt, we will complete the transaction without copying
out the bytes from RX fifo.

Update the code to drain the RX fifo after the length update,
so that the transaction completes correctly in all cases.

Signed-off-by: George Cherian <george.cherian@cavium.com>
---
 drivers/i2c/busses/i2c-xlp9xx.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
index 1f41a4f..01fa04d 100644
--- a/drivers/i2c/busses/i2c-xlp9xx.c
+++ b/drivers/i2c/busses/i2c-xlp9xx.c
@@ -191,28 +191,30 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
 	if (priv->len_recv) {
 		/* read length byte */
 		rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
+		len--;
 		if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) {
 			rlen = 0;	/*abort transfer */
 			priv->msg_buf_remaining = 0;
 			priv->msg_len = 0;
-		} else {
-			*buf++ = rlen;
-			if (priv->client_pec)
-				++rlen; /* account for error check byte */
-			/* update remaining bytes and message length */
-			priv->msg_buf_remaining = rlen;
-			priv->msg_len = rlen + 1;
+			xlp9xx_i2c_update_rlen(priv);
+			return;
 		}
+
+		*buf++ = rlen;
+		if (priv->client_pec)
+			++rlen; /* account for error check byte */
+		/* update remaining bytes and message length */
+		priv->msg_buf_remaining = rlen;
+		priv->msg_len = rlen + 1;
 		xlp9xx_i2c_update_rlen(priv);
 		priv->len_recv = false;
-	} else {
-		len = min(priv->msg_buf_remaining, len);
-		for (i = 0; i < len; i++, buf++)
-			*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
-
-		priv->msg_buf_remaining -= len;
 	}
 
+	len = min(priv->msg_buf_remaining, len);
+	for (i = 0; i < len; i++, buf++)
+		*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
+
+	priv->msg_buf_remaining -= len;
 	priv->msg_buf = buf;
 
 	if (priv->msg_buf_remaining)
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] i2c: xlp9xx: Fix case where SSIF read transaction completes early
  2018-07-23  5:18 [PATCH] i2c: xlp9xx: Fix case where SSIF read transaction completes early George Cherian
@ 2018-07-31 21:05 ` Wolfram Sang
  2018-08-03  4:49   ` George Cherian
  0 siblings, 1 reply; 3+ messages in thread
From: Wolfram Sang @ 2018-07-31 21:05 UTC (permalink / raw)
  To: George Cherian; +Cc: linux-i2c, linux-kernel, jglauber

[-- Attachment #1: Type: text/plain, Size: 568 bytes --]

> --- a/drivers/i2c/busses/i2c-xlp9xx.c
> +++ b/drivers/i2c/busses/i2c-xlp9xx.c
> @@ -191,28 +191,30 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
>  	if (priv->len_recv) {
>  		/* read length byte */
>  		rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
> +		len--;

I don't know the HW and assume the above line is correct because of
merging two interrupts into one. However, the line looks a bit stray,
and I wonder if we shouldn't add a comment somewhere explaining the
situation similar to the second paragraph of the commit message?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Re: [PATCH] i2c: xlp9xx: Fix case where SSIF read transaction completes early
  2018-07-31 21:05 ` Wolfram Sang
@ 2018-08-03  4:49   ` George Cherian
  0 siblings, 0 replies; 3+ messages in thread
From: George Cherian @ 2018-08-03  4:49 UTC (permalink / raw)
  To: Wolfram Sang, George Cherian; +Cc: linux-i2c, linux-kernel, jglauber

Hi Wolfran,

Thanks for the review.

I will update the patch with a small comment section above
len --;
so that there is no confusion.

On 08/01/2018 02:35 AM, Wolfram Sang wrote:
>> --- a/drivers/i2c/busses/i2c-xlp9xx.c
>> +++ b/drivers/i2c/busses/i2c-xlp9xx.c
>> @@ -191,28 +191,30 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
>>   	if (priv->len_recv) {
>>   		/* read length byte */
>>   		rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
>> +		len--;
> 
> I don't know the HW and assume the above line is correct because of
> merging two interrupts into one. However, the line looks a bit stray,
> and I wonder if we shouldn't add a comment somewhere explaining the
> situation similar to the second paragraph of the commit message?
> 

Regards,
-George

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-08-03  4:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-23  5:18 [PATCH] i2c: xlp9xx: Fix case where SSIF read transaction completes early George Cherian
2018-07-31 21:05 ` Wolfram Sang
2018-08-03  4:49   ` George Cherian

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.