* [PATCH RFC 1/2] gpu: host1x: add uninterruptible syncpoint wait variant
2026-11-08 5:21 [PATCH RFC 0/2] Uninterruptible host1x syncpoint wait for Tegra video capture DelaySystem via B4 Relay
@ 2026-11-08 5:21 ` DelaySystem via B4 Relay
2026-11-08 5:21 ` [PATCH RFC 2/2] staging: media: tegra-video: uninterruptible syncpt wait for tegra20 DelaySystem via B4 Relay
2026-11-09 3:27 ` [PATCH RFC 0/2] Uninterruptible host1x syncpoint wait for Tegra video capture Mikko Perttunen
2 siblings, 0 replies; 4+ messages in thread
From: DelaySystem via B4 Relay @ 2026-11-08 5:21 UTC (permalink / raw)
To: mperttunen, thierry.reding
Cc: DelaySystem, dri-devel, luca.ceresoli, gregkh, mchehab,
linux-staging, linux-kernel, clamor95, jonathanh, linux-tegra,
skomatineni, linux-media
From: DelaySystem <DelaySystem@tubot.lat>
host1x_syncpt_wait() is unconditionally interruptible: any signal
aborts the wait with -ERESTARTSYS. Kernel threads that wait on
syncpoints, such as the Tegra video capture threads, then need
retry loops to survive spurious wakeups.
Refactor the implementation into __host1x_syncpt_wait() with an
interruptible flag, keep host1x_syncpt_wait() behavior-identical for
its existing callers (including two DRM ioctls that must stay
interruptible), and add host1x_syncpt_wait_uninterruptible() for
in-kernel users that must not fail spuriously. The wait stays
bounded by the caller's timeout in both cases.
Signed-off-by: DelaySystem <DelaySystem@tubot.lat>
---
drivers/gpu/host1x/syncpt.c | 46 +++++++++++++++++++++++++++++++++++----------
include/linux/host1x.h | 2 ++
2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 5cc3cd46d321..393f50d3be33 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -215,15 +215,8 @@ int host1x_syncpt_incr(struct host1x_syncpt *sp)
}
EXPORT_SYMBOL(host1x_syncpt_incr);
-/**
- * host1x_syncpt_wait() - wait for a syncpoint to reach a given value
- * @sp: host1x syncpoint
- * @thresh: threshold
- * @timeout: maximum time to wait for the syncpoint to reach the given value
- * @value: return location for the syncpoint value
- */
-int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
- u32 *value)
+static int __host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh,
+ long timeout, u32 *value, bool intr)
{
struct dma_fence *fence;
long wait_err;
@@ -246,7 +239,7 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
if (IS_ERR(fence))
return PTR_ERR(fence);
- wait_err = dma_fence_wait_timeout(fence, true, timeout);
+ wait_err = dma_fence_wait_timeout(fence, intr, timeout);
if (wait_err == 0)
host1x_fence_cancel(fence);
dma_fence_put(fence);
@@ -271,8 +264,41 @@ int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
return 0;
}
}
+
+/**
+ * host1x_syncpt_wait() - wait for a syncpoint to reach a given value
+ * @sp: host1x syncpoint
+ * @thresh: threshold
+ * @timeout: maximum time to wait for the syncpoint to reach the given value
+ * @value: return location for the syncpoint value
+ *
+ * The wait is interruptible: a signal aborts it with -ERESTARTSYS.
+ */
+int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
+ u32 *value)
+{
+ return __host1x_syncpt_wait(sp, thresh, timeout, value, true);
+}
EXPORT_SYMBOL(host1x_syncpt_wait);
+/**
+ * host1x_syncpt_wait_uninterruptible() - wait for a syncpoint, uninterruptibly
+ * @sp: host1x syncpoint
+ * @thresh: threshold
+ * @timeout: maximum time to wait for the syncpoint to reach the given value
+ * @value: return location for the syncpoint value
+ *
+ * Like host1x_syncpt_wait(), but signals do not abort the wait. For use by
+ * kernel threads that must not fail spuriously with -ERESTARTSYS, such as
+ * the Tegra video capture threads. The wait is still bounded by @timeout.
+ */
+int host1x_syncpt_wait_uninterruptible(struct host1x_syncpt *sp, u32 thresh,
+ long timeout, u32 *value)
+{
+ return __host1x_syncpt_wait(sp, thresh, timeout, value, false);
+}
+EXPORT_SYMBOL(host1x_syncpt_wait_uninterruptible);
+
/*
* Returns true if syncpoint is expired, false if we may need to wait
*/
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index e7ba601b2afb..40d4024ca04e 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -221,6 +221,8 @@ int host1x_syncpt_incr(struct host1x_syncpt *sp);
u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
u32 *value);
+int host1x_syncpt_wait_uninterruptible(struct host1x_syncpt *sp, u32 thresh,
+ long timeout, u32 *value);
struct host1x_syncpt *host1x_syncpt_request(struct host1x_client *client,
unsigned long flags);
void host1x_syncpt_put(struct host1x_syncpt *sp);
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH RFC 2/2] staging: media: tegra-video: uninterruptible syncpt wait for tegra20
2026-11-08 5:21 [PATCH RFC 0/2] Uninterruptible host1x syncpoint wait for Tegra video capture DelaySystem via B4 Relay
2026-11-08 5:21 ` [PATCH RFC 1/2] gpu: host1x: add uninterruptible syncpoint wait variant DelaySystem via B4 Relay
@ 2026-11-08 5:21 ` DelaySystem via B4 Relay
2026-11-09 3:27 ` [PATCH RFC 0/2] Uninterruptible host1x syncpoint wait for Tegra video capture Mikko Perttunen
2 siblings, 0 replies; 4+ messages in thread
From: DelaySystem via B4 Relay @ 2026-11-08 5:21 UTC (permalink / raw)
To: mperttunen, thierry.reding
Cc: DelaySystem, dri-devel, luca.ceresoli, gregkh, mchehab,
linux-staging, linux-kernel, clamor95, jonathanh, linux-tegra,
skomatineni, linux-media
From: DelaySystem <DelaySystem@tubot.lat>
The Tegra20 capture path runs in a kernel thread and retries
host1x_syncpt_wait() in a do/while loop to survive the -ERESTARTSYS
its unconditionally interruptible wait returns spuriously at high
resolutions and framerates.
Now that host1x provides host1x_syncpt_wait_uninterruptible(), use it
for both the frame-start and MW-ACK waits and drop the retry loops,
fulfilling the TODO above the frame-start wait. Timeouts still fail
the capture as before; only the spurious signal failures go away.
Signed-off-by: DelaySystem <DelaySystem@tubot.lat>
---
drivers/staging/media/tegra-video/tegra20.c | 37 ++++++++---------------------
1 file changed, 10 insertions(+), 27 deletions(-)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index cdadff98eae7..e618d1722841 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -589,28 +589,14 @@ static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan,
CSI_PP_START_MARKER_FRAME_MAX(0xf) |
CSI_PP_SINGLE_SHOT | CSI_PP_ENABLE);
- /*
- * ERESTARTSYS workaround for syncpoints is used because host1x_syncpt_wait
- * is unconditionally interruptible. This is not an issue with single shots
- * or low resolution capture, but -ERESTARTSYS occurs quite often with high
- * resolution or high framerate captures and if not addressed here will
- * cause capture to fail entirely.
- *
- * TODO: once uninterruptible version of host1x_syncpt_wait is available,
- * host1x_syncpt_wait should be swapped and ERESTARTSYS workaround can be
- * removed.
- */
-
val = host1x_syncpt_read(chan->frame_start_sp[0]);
- do {
- err = host1x_syncpt_wait(chan->frame_start_sp[0],
- val + 1, TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
- } while (err == -ERESTARTSYS);
-
+ err = host1x_syncpt_wait_uninterruptible(chan->frame_start_sp[0],
+ val + 1,
+ TEGRA_VI_SYNCPT_WAIT_TIMEOUT,
+ NULL);
if (err) {
- if (err != -ERESTARTSYS)
- dev_err_ratelimited(&chan->video.dev,
- "frame start syncpt timeout: %d\n", err);
+ dev_err_ratelimited(&chan->video.dev,
+ "frame start syncpt timeout: %d\n", err);
tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
CSI_PP_START_MARKER_FRAME_MAX(0xf) | CSI_PP_RESET);
@@ -625,14 +611,11 @@ static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan,
}
val = host1x_syncpt_read(chan->mw_ack_sp[0]);
- do {
- err = host1x_syncpt_wait(chan->mw_ack_sp[0], val + 1,
- TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
- } while (err == -ERESTARTSYS);
-
+ err = host1x_syncpt_wait_uninterruptible(chan->mw_ack_sp[0], val + 1,
+ TEGRA_VI_SYNCPT_WAIT_TIMEOUT,
+ NULL);
if (err) {
- if (err != -ERESTARTSYS)
- dev_err_ratelimited(&chan->video.dev, "mw ack syncpt timeout: %d\n", err);
+ dev_err_ratelimited(&chan->video.dev, "mw ack syncpt timeout: %d\n", err);
goto exit;
}
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH RFC 0/2] Uninterruptible host1x syncpoint wait for Tegra video capture
2026-11-08 5:21 [PATCH RFC 0/2] Uninterruptible host1x syncpoint wait for Tegra video capture DelaySystem via B4 Relay
2026-11-08 5:21 ` [PATCH RFC 1/2] gpu: host1x: add uninterruptible syncpoint wait variant DelaySystem via B4 Relay
2026-11-08 5:21 ` [PATCH RFC 2/2] staging: media: tegra-video: uninterruptible syncpt wait for tegra20 DelaySystem via B4 Relay
@ 2026-11-09 3:27 ` Mikko Perttunen
2 siblings, 0 replies; 4+ messages in thread
From: Mikko Perttunen @ 2026-11-09 3:27 UTC (permalink / raw)
To: thierry.reding, linux-staging
Cc: DelaySystem, dri-devel, luca.ceresoli, gregkh, mchehab,
linux-staging, linux-kernel, clamor95, jonathanh, linux-tegra,
skomatineni, linux-media, DelaySystem
On Sunday, November 8, 2026 2:21 PM DelaySystem via B4 Relay wrote:
> Signed-off-by: DelaySystem <DelaySystem@tubot.lat>
> The Tegra20 video capture path runs in a kernel thread and waits on
> host1x syncpoints with host1x_syncpt_wait(), which is unconditionally
> interruptible: any signal aborts the wait with -ERESTARTSYS. At high
> resolutions and framerates these spurious failures are common, so the
> driver wraps both waits in do/while retry loops, with a TODO asking
> for an uninterruptible variant of the wait.
>
> This series proposes one: patch 1 refactors host1x_syncpt_wait() so
> the interruptible behavior is preserved exactly for existing callers
> (including two DRM ioctls that are userspace ABI and must stay
> interruptible) and adds host1x_syncpt_wait_uninterruptible() for
> in-kernel users. Patch 2 converts the Tegra20 capture waits and drops
> the retry loops and the TODO.
>
> This is sent as an RFC because the API shape and the scope need
> agreement before a final series:
>
> 1. Is a separate _uninterruptible() variant the shape host1x wants,
> or would the maintainers prefer something else (for example an
> internal helper with a flag, or a different name)?
> 2. Tegra210's two waits (tegra210.c) have no retry loop: a spurious
> -ERESTARTSYS currently fails the buffer. Should they convert to
> the uninterruptible wait as well, or is failing on signal
> intentional there?
> 3. drivers/crypto/tegra/tegra-se-main.c also waits with
> MAX_SCHEDULE_TIMEOUT; left out of scope here, but flagging in
> case its maintainer wants the same treatment.
>
> drivers/staging/media/tegra-video with VIDEO_TEGRA=m, zero warnings).
> The tegra20.c change itself has no compile coverage here: that object
> builds only for 32-bit ARM (ARCH_TEGRA_2x_SOC/_3x_SOC) and no ARM
> toolchain is available, and there is no Tegra hardware for runtime
> testing. Hardware testing help is needed before any final series.
nak
>
> Testing: compile-tested only (arm64: drivers/gpu/host1x and
> ---
> DelaySystem (2):
> gpu: host1x: add uninterruptible syncpoint wait variant
> staging: media: tegra-video: uninterruptible syncpt wait for tegra20
>
> drivers/gpu/host1x/syncpt.c | 46 ++++++++++++++++++++++-------
> drivers/staging/media/tegra-video/tegra20.c | 37 +++++++----------------
> include/linux/host1x.h | 2 ++
> 3 files changed, 48 insertions(+), 37 deletions(-)
> ---
> base-commit: fa4ad798f6f681031775266044ba1b0cf3c670bd
> change-id: 20261107-batch1-b1-host1x-wait-3cb3b92e9199
>
> Best regards,
> --
> DelaySystem <DelaySystem@tubot.lat>
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread