summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/ipu-v3/ipu-pre.c
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2024-05-17 12:45:49 +0200
committerPhilipp Zabel <p.zabel@pengutronix.de>2024-06-26 17:43:54 +0200
commitd5316cdd15da9b37ddaa531f0739e4886ecd6faa (patch)
tree07cbe4d3a4fdb5e8a20f823f5f09921f0bcdd3a1 /drivers/gpu/ipu-v3/ipu-pre.c
parent4dbc7d5d61d5212bcfef794f47562ace58ac390b (diff)
downloadlinux-stable-d5316cdd15da9b37ddaa531f0739e4886ecd6faa.tar.gz
linux-stable-d5316cdd15da9b37ddaa531f0739e4886ecd6faa.tar.bz2
linux-stable-d5316cdd15da9b37ddaa531f0739e4886ecd6faa.zip
gpu: ipu-v3: pre: don't use fixed timeout when waiting for safe window
The timeout when waiting for the PRE safe window is rather short, as normally we would only need to wait a few dozen usecs for the problematic scanline region to pass and we don't want to spin too long in case something goes wrong. This however mixes badly with preemption, as we can easily get scheduled away from the CPU for a longer time than our timeout, in which case we would hit a spurious timeout and wrongly skip the PRE update. Instead of disabling preemption across the wait loop, potentially impacting the overall system latency, use a wait loop with a fixed max number of iterations, so time spent away from the CPU is not accounted against the timeout budget. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Link: https://lore.kernel.org/r/20240517104549.3648939-3-l.stach@pengutronix.de Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20240517104549.3648939-3-l.stach@pengutronix.de
Diffstat (limited to 'drivers/gpu/ipu-v3/ipu-pre.c')
-rw-r--r--drivers/gpu/ipu-v3/ipu-pre.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
index 0ec16282e3b4..624b76131560 100644
--- a/drivers/gpu/ipu-v3/ipu-pre.c
+++ b/drivers/gpu/ipu-v3/ipu-pre.c
@@ -5,6 +5,7 @@
#include <drm/drm_fourcc.h>
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/genalloc.h>
#include <linux/module.h>
@@ -256,10 +257,6 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
void ipu_pre_update(struct ipu_pre *pre, uint64_t modifier, unsigned int bufaddr)
{
- unsigned long timeout = jiffies + msecs_to_jiffies(5);
- unsigned short current_yblock;
- u32 val;
-
if (bufaddr == pre->cur.bufaddr &&
modifier == pre->cur.modifier)
return;
@@ -270,8 +267,11 @@ void ipu_pre_update(struct ipu_pre *pre, uint64_t modifier, unsigned int bufaddr
if (modifier != pre->cur.modifier)
ipu_pre_configure_modifier(pre, modifier);
- do {
- if (time_after(jiffies, timeout)) {
+ for (int i = 0;; i++) {
+ unsigned short current_yblock;
+ u32 val;
+
+ if (i > 500) {
dev_warn(pre->dev, "timeout waiting for PRE safe window\n");
return;
}
@@ -280,8 +280,14 @@ void ipu_pre_update(struct ipu_pre *pre, uint64_t modifier, unsigned int bufaddr
current_yblock =
(val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) &
IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK;
- } while (current_yblock == 0 ||
- current_yblock >= pre->cur.safe_window_end);
+
+ if (current_yblock != 0 &&
+ current_yblock < pre->cur.safe_window_end)
+ break;
+
+ udelay(10);
+ cpu_relax();
+ }
writel(pre->cur.ctrl | IPU_PRE_CTRL_SDW_UPDATE,
pre->regs + IPU_PRE_CTRL);