Linux I2C development
 help / color / mirror / Atom feed
* [PATCH 27/28] i2c: cgbc: Propagate hardware errors when polling read status
       [not found] <20261021121245.3111563-1-lee@kernel.org>
@ 2026-10-21 12:09 ` Lee Jones
  2026-10-23  8:43   ` Thomas Richard (congatec GmbH)
  0 siblings, 1 reply; 3+ messages in thread
From: Lee Jones @ 2026-10-21 12:09 UTC (permalink / raw)
  To: lee, Thomas Richard, Andi Shyti, linux-i2c, linux-kernel; +Cc: stable

In cgbc_i2c_xfer_msg(), read_poll_timeout() uses the same ret variable
to store the polled return value of cgbc_i2c_get_status() and the
timeout result of the macro itself.  When cgbc_i2c_get_status() returns
a negative error code (such as -EIO on an I2C NACK), the loop condition
ret != CGBC_I2C_STAT_BUSY evaluates to true and read_poll_timeout()
overwrites ret with 0.  The driver then issues CGBC_I2C_CMD_DATA, which
completes with CGBC_STATUS_CMD_READY without populating msg->buf,
leaving uninitialised heap memory in the caller's read buffer.

Store the polled status in a separate variable, verify that it equals
CGBC_I2C_STAT_DAT, and check that CGBC_I2C_CMD_DATA returns the expected
number of bytes.

Fixes: 6894f640b8f3 ("i2c: Congatec Board Controller i2c bus driver")
Closes: https://sashiko.dev/#/bug/linux-66cbf4b1-a219-4012-969d-236417bf419a
Cc: stable@vger.kernel.org
Signed-off-by: Lee Jones <lee@kernel.org>
---
 drivers/i2c/busses/i2c-cgbc.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-cgbc.c b/drivers/i2c/busses/i2c-cgbc.c
index 25a74fa51aa0..9909c25f0b18 100644
--- a/drivers/i2c/busses/i2c-cgbc.c
+++ b/drivers/i2c/busses/i2c-cgbc.c
@@ -205,9 +205,9 @@ static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
 	struct cgbc_device_data *cgbc = i2c->cgbc;
 	struct i2c_msg *msg = i2c->msg;
 	u8 cmd[CGBC_I2C_CMD_SIZE];
-	int ret, max_len, len, i;
+	int ret, status, max_len, len, i;
 	unsigned int cmd_len;
-	u8 cmd_data;
+	u8 cmd_data, data_len;
 
 	struct cgbc_i2c_transfer xfer = {
 		.bus_id = algo_data->bus_id,
@@ -266,17 +266,32 @@ static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
 		if (ret)
 			goto err;
 
-		ret = read_poll_timeout(cgbc_i2c_get_status, ret,
-					ret != CGBC_I2C_STAT_BUSY, 0,
+		ret = read_poll_timeout(cgbc_i2c_get_status, status,
+					status != CGBC_I2C_STAT_BUSY, 0,
 					2 * algo_data->read_maxtime_us, false, adap);
-		if (ret < 0)
+		if (ret)
 			goto err;
 
+		if (status < 0) {
+			ret = status;
+			goto err;
+		}
+
+		if (status != CGBC_I2C_STAT_DAT) {
+			ret = -EIO;
+			goto err;
+		}
+
 		cmd_data = CGBC_I2C_CMD_DATA | algo_data->bus_id;
 		ret = cgbc_command(cgbc, &cmd_data, sizeof(cmd_data),
-				   msg->buf + i2c->pos, len, NULL);
+				   msg->buf + i2c->pos, len, &data_len);
 		if (ret)
 			goto err;
+
+		if (data_len != len) {
+			ret = -EIO;
+			goto err;
+		}
 	}
 
 	if (len == (msg->len - i2c->pos)) {
-- 
2.56.0.218.g1ec904b173-goog


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

* Re: [PATCH 27/28] i2c: cgbc: Propagate hardware errors when polling read status
  2026-10-21 12:09 ` [PATCH 27/28] i2c: cgbc: Propagate hardware errors when polling read status Lee Jones
@ 2026-10-23  8:43   ` Thomas Richard (congatec GmbH)
  2026-10-26 14:53     ` Lee Jones
  0 siblings, 1 reply; 3+ messages in thread
From: Thomas Richard (congatec GmbH) @ 2026-10-23  8:43 UTC (permalink / raw)
  To: Lee Jones; +Cc: Thomas Richard, Andi Shyti, linux-i2c, linux-kernel, stable

> In cgbc_i2c_xfer_msg(), read_poll_timeout() uses the same ret variable
> to store the polled return value of cgbc_i2c_get_status() and the
> timeout result of the macro itself.  When cgbc_i2c_get_status() returns
> a negative error code (such as -EIO on an I2C NACK), the loop condition
> ret != CGBC_I2C_STAT_BUSY evaluates to true and read_poll_timeout()
> overwrites ret with 0.  The driver then issues CGBC_I2C_CMD_DATA, which
> completes with CGBC_STATUS_CMD_READY without populating msg->buf,
> leaving uninitialised heap memory in the caller's read buffer.
> 
> Store the polled status in a separate variable, verify that it equals
> CGBC_I2C_STAT_DAT, and check that CGBC_I2C_CMD_DATA returns the expected
> number of bytes.
> 
> Fixes: 6894f640b8f3 ("i2c: Congatec Board Controller i2c bus driver")
> Closes: https://sashiko.dev/#/bug/linux-66cbf4b1-a219-4012-969d-236417bf419a
> Cc: stable@vger.kernel.org
> Signed-off-by: Lee Jones <lee@kernel.org>
>
> diff --git a/drivers/i2c/busses/i2c-cgbc.c b/drivers/i2c/busses/i2c-cgbc.c
> index 682ba639d887..3226838cca46 100644
> --- a/drivers/i2c/busses/i2c-cgbc.c
> +++ b/drivers/i2c/busses/i2c-cgbc.c
> @@ -198,9 +198,9 @@ static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
>  	struct cgbc_device_data *cgbc = i2c->cgbc;
>  	struct i2c_msg *msg = i2c->msg;
>  	u8 cmd[CGBC_I2C_CMD_SIZE];
> -	int ret, max_len, len, i;
> +	int ret, status, max_len, len, i;
>  	unsigned int cmd_len;
> -	u8 cmd_data;
> +	u8 cmd_data, data_len;
>  
>  	struct cgbc_i2c_transfer xfer = {
>  		.bus_id = i2c->bus_id,
> @@ -259,17 +259,32 @@ static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
>  		if (ret)
>  			goto err;
>  
> -		ret = read_poll_timeout(cgbc_i2c_get_status, ret,
> -					ret != CGBC_I2C_STAT_BUSY, 0,
> +		ret = read_poll_timeout(cgbc_i2c_get_status, status,
> +					status != CGBC_I2C_STAT_BUSY, 0,
>  					2 * i2c->read_maxtime_us, false, adap);
> -		if (ret < 0)
> +		if (ret)
> +			goto err;
> +
> +		if (status < 0) {
> +			ret = status;
>  			goto err;
> +		}
> +
> +		if (status != CGBC_I2C_STAT_DAT) {
> +			ret = -EIO;
> +			goto err;
> +		}

We could save a goto and make code more readable IMO

if (ret)
	goto err;

if (status != CGBC_I2C_STAT_DAT) {
	ret = (status < 0) ? status : -EIO;
	goto err;
}

>  
>  		cmd_data = CGBC_I2C_CMD_DATA | i2c->bus_id;
>  		ret = cgbc_command(cgbc, &cmd_data, sizeof(cmd_data),
> -				   msg->buf + i2c->pos, len, NULL);
> +				   msg->buf + i2c->pos, len, &data_len);
>  		if (ret)
>  			goto err;
> +
> +		if (data_len != len) {
> +			ret = -EIO;
> +			goto err;
> +		}
>  	}
>  
>  	if (len == (msg->len - i2c->pos)) {

Otherwise looks good to me.

Reviewed-by: Thomas Richard (congatec GmbH) <thomas.richard@bootlin.com>
Tested-by: Thomas Richard (congatec GmbH) <thomas.richard@bootlin.com>

Best Regards,
Thomas

-- 
Thomas Richard (congatec GmbH) <thomas.richard@bootlin.com>

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

* Re: [PATCH 27/28] i2c: cgbc: Propagate hardware errors when polling read status
  2026-10-23  8:43   ` Thomas Richard (congatec GmbH)
@ 2026-10-26 14:53     ` Lee Jones
  0 siblings, 0 replies; 3+ messages in thread
From: Lee Jones @ 2026-10-26 14:53 UTC (permalink / raw)
  To: Thomas Richard (congatec GmbH)
  Cc: Andi Shyti, linux-i2c, linux-kernel, stable

On Fri, 23 Oct 2026, Thomas Richard (congatec GmbH) wrote:

> > In cgbc_i2c_xfer_msg(), read_poll_timeout() uses the same ret variable
> > to store the polled return value of cgbc_i2c_get_status() and the
> > timeout result of the macro itself.  When cgbc_i2c_get_status() returns
> > a negative error code (such as -EIO on an I2C NACK), the loop condition
> > ret != CGBC_I2C_STAT_BUSY evaluates to true and read_poll_timeout()
> > overwrites ret with 0.  The driver then issues CGBC_I2C_CMD_DATA, which
> > completes with CGBC_STATUS_CMD_READY without populating msg->buf,
> > leaving uninitialised heap memory in the caller's read buffer.
> > 
> > Store the polled status in a separate variable, verify that it equals
> > CGBC_I2C_STAT_DAT, and check that CGBC_I2C_CMD_DATA returns the expected
> > number of bytes.
> > 
> > Fixes: 6894f640b8f3 ("i2c: Congatec Board Controller i2c bus driver")
> > Closes: https://sashiko.dev/#/bug/linux-66cbf4b1-a219-4012-969d-236417bf419a
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Lee Jones <lee@kernel.org>
> >
> > diff --git a/drivers/i2c/busses/i2c-cgbc.c b/drivers/i2c/busses/i2c-cgbc.c
> > index 682ba639d887..3226838cca46 100644
> > --- a/drivers/i2c/busses/i2c-cgbc.c
> > +++ b/drivers/i2c/busses/i2c-cgbc.c
> > @@ -198,9 +198,9 @@ static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
> >  	struct cgbc_device_data *cgbc = i2c->cgbc;
> >  	struct i2c_msg *msg = i2c->msg;
> >  	u8 cmd[CGBC_I2C_CMD_SIZE];
> > -	int ret, max_len, len, i;
> > +	int ret, status, max_len, len, i;
> >  	unsigned int cmd_len;
> > -	u8 cmd_data;
> > +	u8 cmd_data, data_len;
> >  
> >  	struct cgbc_i2c_transfer xfer = {
> >  		.bus_id = i2c->bus_id,
> > @@ -259,17 +259,32 @@ static int cgbc_i2c_xfer_msg(struct i2c_adapter *adap)
> >  		if (ret)
> >  			goto err;
> >  
> > -		ret = read_poll_timeout(cgbc_i2c_get_status, ret,
> > -					ret != CGBC_I2C_STAT_BUSY, 0,
> > +		ret = read_poll_timeout(cgbc_i2c_get_status, status,
> > +					status != CGBC_I2C_STAT_BUSY, 0,
> >  					2 * i2c->read_maxtime_us, false, adap);
> > -		if (ret < 0)
> > +		if (ret)
> > +			goto err;
> > +
> > +		if (status < 0) {
> > +			ret = status;
> >  			goto err;
> > +		}
> > +
> > +		if (status != CGBC_I2C_STAT_DAT) {
> > +			ret = -EIO;
> > +			goto err;
> > +		}
> 
> We could save a goto and make code more readable IMO
> 
> if (ret)
> 	goto err;
> 
> if (status != CGBC_I2C_STAT_DAT) {
> 	ret = (status < 0) ? status : -EIO;

Ternary operators certainly do not make the code _more_ readable.

Concise, yes.  Readable, no.  The current code is preferable.

> }
> 
> >  
> >  		cmd_data = CGBC_I2C_CMD_DATA | i2c->bus_id;
> >  		ret = cgbc_command(cgbc, &cmd_data, sizeof(cmd_data),
> > -				   msg->buf + i2c->pos, len, NULL);
> > +				   msg->buf + i2c->pos, len, &data_len);
> >  		if (ret)
> >  			goto err;
> > +
> > +		if (data_len != len) {
> > +			ret = -EIO;
> > +			goto err;
> > +		}
> >  	}
> >  
> >  	if (len == (msg->len - i2c->pos)) {
> 
> Otherwise looks good to me.
> 
> Reviewed-by: Thomas Richard (congatec GmbH) <thomas.richard@bootlin.com>
> Tested-by: Thomas Richard (congatec GmbH) <thomas.richard@bootlin.com>

Thanks for these.  Much appreciated.

-- 
Lee Jones

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

end of thread, other threads:[~2026-10-26 14:53 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20261021121245.3111563-1-lee@kernel.org>
2026-10-21 12:09 ` [PATCH 27/28] i2c: cgbc: Propagate hardware errors when polling read status Lee Jones
2026-10-23  8:43   ` Thomas Richard (congatec GmbH)
2026-10-26 14:53     ` Lee Jones

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox