Re: [PATCH v6 1/2] drm/atomic: attempt full modeset on page flip timeout

Ville Syrjälä
2026-05-06T18:47:16Z

On Tue, May 05, 2026 at 02:20:57PM -0400, Hamza Mahfooz wrote:
> We should try to recover from page flip timeouts. Forcing
> a full modeset should be generic across all atomic KMS drivers,
> so try that first.
>
> Signed-off-by: Hamza Mahfooz <someguy@effective-light.com>
> ---
> drivers/gpu/drm/drm_atomic_helper.c | 49 +++++++++++++++++++++++++++--
> 1 file changed, 46 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index a768398a1884..7ee9d52f63c5 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1926,6 +1926,43 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
> }
> EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
>
> +static int force_full_modeset(struct drm_crtc *crtc)
> +{
> + struct drm_modeset_acquire_ctx ctx;
> + struct drm_crtc_state *crtc_state;
> + struct drm_atomic_state *state;
> + int ret;
> + int err;
> +
> + if (drm_atomic_crtc_needs_modeset(crtc->state))
> + return -EBUSY;
> +
> + DRM_MODESET_LOCK_ALL_BEGIN(crtc->dev, ctx, 0, err);
> + state = drm_atomic_state_alloc(crtc->dev);
> + if (!state)
> + return -ENOMEM;
> +
> + state->acquire_ctx = &ctx;
> +
> + crtc_state = drm_atomic_get_crtc_state(state, crtc);
> + if (IS_ERR(crtc_state)) {
> + ret = PTR_ERR(crtc_state);
> + goto out;
> + }
> +
> + crtc_state->mode_changed = true;
> +
> + drm_info(crtc->dev,
> + "[CRTC:%d:%s] Attempting force full modeset...\n",
> + crtc->base.id, crtc->name);
> +
> + ret = drm_atomic_commit(state);
> +out:
> + drm_atomic_state_put(state);
> + DRM_MODESET_LOCK_ALL_END(crtc->dev, ctx, err);
> + return ret;
> +}
> +
> /**
> * drm_atomic_helper_wait_for_flip_done - wait for all page flips to be done
> * @dev: DRM device
> @@ -1949,17 +1986,23 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
>
> for (i = 0; i < dev->mode_config.num_crtc; i++) {
> struct drm_crtc_commit *commit = state->crtcs[i].commit;
> - int ret;
>
> crtc = state->crtcs[i].ptr;
>
> if (!crtc || !commit)
> continue;
>
> - ret = wait_for_completion_timeout(&commit->flip_done, 10 * HZ);
> - if (ret == 0)
> + if (!wait_for_completion_timeout(&commit->flip_done, 10 * HZ)) {
> + int ret;
> drm_err(dev, "[CRTC:%d:%s] flip_done timed out\n",
> crtc->base.id, crtc->name);
> +
> + ret = force_full_modeset(crtc);

This looks like some kind of ugly hack to paper over a driver bug.
I really don't want this for i915/xe because all it'll end up doing
is make it harder to debug any real issues.

> + if (ret)
> + drm_err(dev,
> + "[CRTC:%d:%s] force full modeset failed! ret=%d\n",
> + crtc->base.id, crtc->name, ret);
> + }
> }
>
> if (state->fake_commit)
> --
> 2.54.0

--
Ville Syrjälä
Intel