drm/gma500: return errors from Oaktrail HDMI I2C reads

xfer_read() waits for the HDMI I2C transaction to reach
I2C_TRANSACTION_DONE, but it ignores both timeout and signal returns from
wait_for_completion_interruptible_timeout().  If the interrupt never
advances the transaction state, the loop can wait forever.

Return -ETIMEDOUT when the completion wait expires, propagate interrupted
waits, and make the I2C master_xfer callback return the first transfer
error instead of reporting a successful message count.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Link: https://patch.msgid.link/20260625003240.6923-1-pengpeng@iscas.ac.cn
This commit is contained in:
Pengpeng Hou 2026-06-25 08:32:40 +08:00 committed by Patrik Jakobsson
parent 7dc3680b7f
commit 9b5ce5c496

View File

@ -98,6 +98,7 @@ static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
u32 temp;
int ret;
i2c_dev->status = I2C_STAT_INIT;
i2c_dev->msg = pmsg;
@ -109,9 +110,14 @@ static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
HDMI_WRITE(HDMI_HI2CHCR, temp);
HDMI_READ(HDMI_HI2CHCR);
while (i2c_dev->status != I2C_TRANSACTION_DONE)
wait_for_completion_interruptible_timeout(&i2c_dev->complete,
while (i2c_dev->status != I2C_TRANSACTION_DONE) {
ret = wait_for_completion_interruptible_timeout(&i2c_dev->complete,
10 * HZ);
if (ret < 0)
return ret;
if (!ret)
return -ETIMEDOUT;
}
return 0;
}
@ -130,7 +136,7 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
{
struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
int i;
int i, ret = 0;
mutex_lock(&i2c_dev->i2c_lock);
@ -142,9 +148,11 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
for (i = 0; i < num; i++) {
if (pmsg->len && pmsg->buf) {
if (pmsg->flags & I2C_M_RD)
xfer_read(adap, pmsg);
ret = xfer_read(adap, pmsg);
else
xfer_write(adap, pmsg);
ret = xfer_write(adap, pmsg);
if (ret)
break;
}
pmsg++; /* next message */
}
@ -154,6 +162,9 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
mutex_unlock(&i2c_dev->i2c_lock);
if (ret)
return ret;
return i;
}