]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
i2c: stm32f7: reinit_completion() per transfer not per msg
authorMarek Vasut <marex@nabladev.com>
Sat, 2 May 2026 15:31:54 +0000 (17:31 +0200)
committerWolfram Sang <wsa+renesas@sang-engineering.com>
Mon, 4 May 2026 08:22:00 +0000 (10:22 +0200)
Currently, the driver may repeatedly call reinit_completion() during
transfer which contains multiple messages, while another thread is
waiting for the completion.

This happens during transfer with more than 1 message, invoked via
stm32f7_i2c_xfer_core() -> stm32f7_i2c_xfer_msg(). After invoking the
stm32f7_i2c_xfer_msg() to start transfer, stm32f7_i2c_xfer_core()
calls wait_for_completion_timeout() to wait for completion of the
transfer of all messages. When the first message transfer completes,
the hard IRQ handler triggers, and detects transfer completion, which
leads to stm32f7_i2c_isr_event_thread() IRQ thread being started. The
stm32f7_i2c_isr_event_thread() calls stm32f7_i2c_xfer_msg() in case
there are more messages.

Without this change, the second and later stm32f7_i2c_xfer_msg() would
call reinit_completion() on the completion which is still being waited
for in stm32f7_i2c_xfer_core(). Fix this by moving the reinit_completion()
into stm32f7_i2c_xfer_core(), together with wait_for_completion_timeout().

Since stm32f7_i2c_xfer_core() now waits for completion of the entire
transfer, increase the default timeout. This fixes sporadic transfer
timeouts on STM32MP25xx during kernel boot.

Fixes: aeb068c57214 ("i2c: i2c-stm32f7: add driver")
Signed-off-by: Marek Vasut <marex@nabladev.com>
[wsa: reworded commit subject]
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
drivers/i2c/busses/i2c-stm32f7.c

index 70cb5822bf17bfe8b5c6949cd304759026f8677c..53d9df70ebe4de301f1f0329f774c23b556363db 100644 (file)
@@ -895,8 +895,6 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
        f7_msg->result = 0;
        f7_msg->stop = (i2c_dev->msg_id >= i2c_dev->msg_num - 1);
 
-       reinit_completion(&i2c_dev->complete);
-
        cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
        cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
 
@@ -1728,6 +1726,8 @@ static int stm32f7_i2c_xfer_core(struct i2c_adapter *i2c_adap,
        if (ret)
                goto pm_free;
 
+       reinit_completion(&i2c_dev->complete);
+
        stm32f7_i2c_xfer_msg(i2c_dev, msgs);
 
        if (!i2c_dev->atomic)
@@ -2253,7 +2253,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
        snprintf(adap->name, sizeof(adap->name), "STM32F7 I2C(%pa)",
                 &res->start);
        adap->owner = THIS_MODULE;
-       adap->timeout = 2 * HZ;
+       adap->timeout = 8 * HZ;
        adap->retries = 3;
        adap->algo = &stm32f7_i2c_algo;
        adap->dev.parent = &pdev->dev;