]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/gma500: return errors from Oaktrail HDMI I2C reads
authorPengpeng Hou <pengpeng@iscas.ac.cn>
Thu, 25 Jun 2026 00:32:40 +0000 (08:32 +0800)
committerPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
Wed, 22 Jul 2026 20:46:27 +0000 (22:46 +0200)
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
drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c

index 2a7916ca59075a9ed5073687350146a573def4f8..a780643f25aa46f7a42aa1d784478ea19ff10123 100644 (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;
 }