firmware: exynos-acpm: use ktime APIs for timeout detection
authorAndré Draszik <andre.draszik@linaro.org>
Tue, 25 Mar 2025 09:46:07 +0000 (09:46 +0000)
committerKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Mon, 7 Apr 2025 06:21:56 +0000 (08:21 +0200)
acpm_dequeue_by_polling() uses a loop counter and assumes that each
iteration of the loop takes 20us. It may take longer, though, because
usleep_range() may sleep a different amount.

Switch to using ktime_get() / ktime_before() to detect the timeout
condition more reliably.

This change also makes the code easier to follow and it allows us to
adjust the sleep if necessary, without having to adjust the loop
counter exit condition.

Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Signed-off-by: André Draszik <andre.draszik@linaro.org>
Link: https://lore.kernel.org/r/20250325-acpm-atomic-v3-1-c66aae7df925@linaro.org
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
drivers/firmware/samsung/exynos-acpm.c

index a85b2db..542eaff 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/firmware/samsung/exynos-acpm-protocol.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/ktime.h>
 #include <linux/mailbox/exynos-message.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
@@ -32,8 +33,7 @@
 
 #define ACPM_PROTOCOL_SEQNUM           GENMASK(21, 16)
 
-/* The unit of counter is 20 us. 5000 * 20 = 100 ms */
-#define ACPM_POLL_TIMEOUT              5000
+#define ACPM_POLL_TIMEOUT_US           (100 * USEC_PER_MSEC)
 #define ACPM_TX_TIMEOUT_US             500000
 
 #define ACPM_GS101_INITDATA_BASE       0xa000
@@ -284,12 +284,13 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
                                   const struct acpm_xfer *xfer)
 {
        struct device *dev = achan->acpm->dev;
-       unsigned int cnt_20us = 0;
+       ktime_t timeout;
        u32 seqnum;
        int ret;
 
        seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
 
+       timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
        do {
                ret = acpm_get_rx(achan, xfer);
                if (ret)
@@ -300,11 +301,10 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
 
                /* Determined experimentally. */
                usleep_range(20, 30);
-               cnt_20us++;
-       } while (cnt_20us < ACPM_POLL_TIMEOUT);
+       } while (ktime_before(ktime_get(), timeout));
 
-       dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx, cnt_20us = %d.\n",
-               achan->id, seqnum, achan->bitmap_seqnum[0], cnt_20us);
+       dev_err(dev, "Timeout! ch:%u s:%u bitmap:%lx.\n",
+               achan->id, seqnum, achan->bitmap_seqnum[0]);
 
        return -ETIME;
 }