From: Claude Code Review Bot <claude-review@example.com>
To: dri-devel-reviews@example.com
Subject: Claude review: drm/vblank: Introduce deferred vblank enable/disable
Date: Wed, 25 Mar 2026 07:22:01 +1000 [thread overview]
Message-ID: <review-patch2-20260323202755.315929-3-sunpeng.li@amd.com> (raw)
In-Reply-To: <20260323202755.315929-3-sunpeng.li@amd.com>
Patch Review
This is the core patch and has the most issues:
**1. Workqueue allocated unconditionally (wasteful)**
```c
dev->deferred_vblank_wq = alloc_workqueue("drm_vblank_deferred_wq",
WQ_HIGHPRI | WQ_UNBOUND,
0);
```
This allocates a workqueue for *every* DRM device regardless of whether any CRTC uses deferred vblank. This wastes resources for the vast majority of drivers. Consider lazily allocating it (e.g., in `drm_crtc_init_with_planes` when the funcs have deferred callbacks) or at least guarding it behind a check.
**2. Race between deferred enable and drm_crtc_vblank_off()**
`drm_vblank_get()` queues the enable worker, then releases `vbl_lock`. If `drm_crtc_vblank_off()` runs before the worker executes, the worker will call `drm_vblank_enable()` → `crtc->funcs->enable_vblank()` on hardware that's being torn down. The worker does:
```c
spin_lock_irqsave(&dev->vbl_lock, irqflags);
ret = drm_vblank_enable(dev, vblank->pipe);
```
But `drm_crtc_vblank_off()` sets `vblank->inmodeset` under `vbl_lock`, which would make `drm_vblank_enable()` fail with `-EINVAL` (because the refcount was already decremented by `vblank_off`). However, the `pre_enable_vblank()` callback runs *before* this lock is taken, so the driver's blocking pre-work could still execute against torn-down hardware. Consider cancelling pending enable work in `drm_crtc_vblank_off()` before proceeding, or checking `vblank->inmodeset` inside the worker before calling the pre-hook.
**3. Race between deferred disable and deferred enable**
If a deferred disable is pending (delayed work) and a new `drm_vblank_get()` triggers a deferred enable, the pending disable isn't cancelled. The `queue_work()` for enable is non-delayed, so it may execute first, but there's no explicit cancellation of the pending `disable_work`. After enable completes, the stale disable could fire. The regular (non-deferred) path handles this via the `disable_timer` being re-armed, but the deferred path should cancel `disable_work` when queueing `enable_work`.
**4. drm_wait_vblank_ioctl ordering bug**
```c
ret = drm_vblank_get(dev, pipe);
drm_crtc_vblank_wait_deferred_enable(drm_crtc_from_index(dev, pipe));
if (ret) {
```
The `drm_crtc_vblank_wait_deferred_enable()` is called *before* checking `ret`. If `drm_vblank_get()` returned an error, this waits on a potentially stale/completed completion. It should be inside the success path:
```c
ret = drm_vblank_get(dev, pipe);
if (ret) {
...error handling...
}
drm_crtc_vblank_wait_deferred_enable(drm_crtc_from_index(dev, pipe));
```
**5. Missing `cancel_work_sync` / `cancel_delayed_work_sync` in cleanup paths**
In `drm_dev_init_release()`, only `flush_workqueue` + `destroy_workqueue` is done. But `drm_vblank_init_release()` (per-CRTC cleanup via `timer_delete_sync`) doesn't cancel the per-CRTC `enable_work` and `disable_work`. These should be cancelled in `drm_vblank_init_release()`:
```c
cancel_work_sync(&vblank->enable_work);
cancel_delayed_work_sync(&vblank->disable_work);
```
**6. `try_wait_for_completion` used outside lock for racy check**
```c
bool deferred_enable_pending =
needs_deferred_enable &&
!try_wait_for_completion(&vblank->enable_done);
```
`try_wait_for_completion()` actually *consumes* the completion if it's done. Inside `drm_vblank_get()` under `vbl_lock`, this consumption could cause a subsequent `wait_for_completion_timeout` (from `drm_crtc_vblank_wait_deferred_enable`) to block even though enable already completed. Using `completion_done()` instead would be non-destructive.
**7. `WQ_UNBOUND` with `max_active=0`**
The workqueue is created with `WQ_UNBOUND` and `max_active=0` (unlimited). The commit message says "single-threaded worker" but the workqueue is not single-threaded. Enable and disable workers for different CRTCs (or even the same CRTC) could run concurrently. If single-threaded semantics are intended, use `alloc_ordered_workqueue()`.
---
Generated by Claude Code Patch Reviewer
next prev parent reply other threads:[~2026-03-24 21:22 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-23 20:27 [PATCH v2 0/5] drm/vblank: Deferred Enable and Disable sunpeng.li
2026-03-23 20:27 ` [PATCH v2 1/5] drm/vblank: Add drm_crtc_vblank_is_off() helper sunpeng.li
2026-03-24 20:20 ` Mario Limonciello
2026-03-24 21:22 ` Claude review: " Claude Code Review Bot
2026-03-23 20:27 ` [PATCH v2 2/5] drm/vblank: Introduce deferred vblank enable/disable sunpeng.li
2026-03-24 21:22 ` Claude Code Review Bot [this message]
2026-03-23 20:27 ` [PATCH v2 3/5] drm/amd/display: Refactor amdgpu_dm_crtc_set_vblank sunpeng.li
2026-03-24 21:22 ` Claude review: " Claude Code Review Bot
2026-03-23 20:27 ` [PATCH v2 4/5] drm/amd/display: Implement deferred vblanks on IPS platforms sunpeng.li
2026-03-24 21:22 ` Claude review: " Claude Code Review Bot
2026-03-23 20:27 ` [PATCH v2 5/5] drm/vblank: Add some debugging trace events sunpeng.li
2026-03-24 21:22 ` Claude review: " Claude Code Review Bot
2026-03-24 21:22 ` Claude review: drm/vblank: Deferred Enable and Disable Claude Code Review Bot
-- strict thread matches above, loose matches on Subject: below --
2026-02-24 21:26 [PATCH 0/5] " sunpeng.li
2026-02-24 21:26 ` [PATCH 2/5] drm/vblank: Introduce deferred vblank enable/disable sunpeng.li
2026-02-27 4:40 ` Claude review: " Claude Code Review Bot
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=review-patch2-20260323202755.315929-3-sunpeng.li@amd.com \
--to=claude-review@example.com \
--cc=dri-devel-reviews@example.com \
/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