From: sashiko-bot@kernel.org
To: "Jun Nie" <jun.nie@linaro.org>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH] drm/msm/dpu: delete timeout timer when encoder is not busy
Date: Thu, 03 Sep 2026 14:48:26 +0000 [thread overview]
Message-ID: <20260903144827.236AB1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260903143004.1026181-1-jun.nie@linaro.org>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] A Time-of-Check to Time-of-Use (TOCTOU) race condition in the lockless timer deletion allows an IRQ handler to inadvertently delete the watchdog timer for a newly started frame on another CPU.
- [Medium] The patch fails to address the root cause of the race condition and relies on a subsequent, unrelated IRQ to mask the bug, leaving the original false timeout issue unfixed in many scenarios.
Pre-existing issues:
- [High] Missing synchronization in `dpu_encoder_virt_atomic_disable` allows the driver to disable hardware resources while the timer callback is still executing, leading to crashes.
--
commit 91dd8b2e3a127693bc37ea9250d6d6a4bd503cf0
Author: Jun Nie <jun.nie@linaro.org>
drm/msm/dpu: delete timeout timer when encoder is not busy
This commit attempts to fix a spurious timeout error message during encoder
disable. It adds a check in the frame done IRQ callback to delete the
watchdog timer if the frame busy bits are cleared.
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 1f20695f81e35..d83d387973311 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -1573,6 +1573,21 @@ void dpu_encoder_frame_done_callback(
> | DPU_ENCODER_FRAME_EVENT_PANEL_DEAD)) {
>
> if (!dpu_enc->frame_busy_mask[0]) {
> + /*
> + * dpu_crtc_commit_kickoff calls dpu_encoder_kickoff to
> + * mark busy bits, starts the framedone timer next.
> + * It is possibile that irq happens between the 2
> + * operations. Thus timer is running with busy bits
> + * cleared by irq handler and timer will not be deleted
> + * anymore. Then false timeout introduces unnecessary
> + * confusion and visual defect.
> + * delete the timer here to fix it.
> + */
> + if (atomic_read(&dpu_enc->frame_done_timeout_ms)) {
> + atomic_set(&dpu_enc->frame_done_timeout_ms, 0);
> + timer_delete(&dpu_enc->frame_done_timer);
> + }
[Severity: Medium]
Does this patch rely on a subsequent IRQ to fix the false timeout in all
scenarios?
If no subsequent IRQ (like autorefresh or a TE interrupt) fires after the
timer is armed with an empty frame_busy_mask, the timer will expire normally.
When it expires, dpu_encoder_frame_done_timeout() returns early because
frame_busy_mask is empty, but it fails to clear frame_done_timeout_ms:
dpu_encoder_frame_done_timeout() {
...
if (!dpu_enc->frame_busy_mask[0] || !dpu_enc->crtc) {
return;
}
...
}
Later, dpu_encoder_virt_atomic_disable() checks frame_done_timeout_ms,
finds it non-zero, and still falsely prints the 'timeout pending' error.
Will this leave the bug unfixed for standard operations that do not trigger
extra IRQs?
[Severity: High]
Could this lockless timer deletion introduce a race condition with a new
commit?
CPU1 handling a spurious IRQ in dpu_encoder_frame_done_callback()
evaluates if (!dpu_enc->frame_busy_mask[0]) as true locklessly.
Concurrently, CPU2 starts a new commit:
dpu_encoder_kickoff() sets frame_busy_mask to 1.
dpu_encoder_start_frame_done_timer() arms the timer and sets
frame_done_timeout_ms to 500.
CPU1 continues execution, reads frame_done_timeout_ms (now 500 from CPU2),
sets it to 0, and calls timer_delete().
Does this silently delete the newly armed watchdog timer for CPU2's commit,
leaving it without watchdog protection if the hardware hangs?
[Severity: High]
This is a pre-existing issue, but does dpu_encoder_virt_atomic_disable()
lack synchronization when disabling hardware resources?
dpu_encoder_frame_done_timeout() clears frame_done_timeout_ms via
atomic_xchg() early in its execution:
dpu_encoder_frame_done_timeout() {
...
} else if (!atomic_xchg(&dpu_enc->frame_done_timeout_ms, 0)) {
return;
}
...
}
If dpu_encoder_virt_atomic_disable() runs concurrently, it checks:
if (atomic_xchg(&dpu_enc->frame_done_timeout_ms, 0)) {
timer_delete_sync(&dpu_enc->frame_done_timer);
}
If the timeout callback has already cleared the variable, the disable path
sees 0, skips timer_delete_sync(), and proceeds to disable clocks and power
domains. Meanwhile, the timeout callback is still executing and accesses
hardware registers, which can cause a synchronous external abort when clocks
are disabled. Should this path always synchronize with the timer callback?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903143004.1026181-1-jun.nie@linaro.org?part=1
prev parent reply other threads:[~2026-09-03 14:48 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 14:29 [PATCH] drm/msm/dpu: delete timeout timer when encoder is not busy Jun Nie
2026-09-03 14:39 ` Jun Nie
2026-09-03 14:48 ` sashiko-bot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903144827.236AB1F00A3A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=jun.nie@linaro.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox