On 5/5/26 13:20, 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 <[email protected]>
Reviewed-by: Mario Limonciello (AMD) <[email protected]>
---
  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);
+                       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)

Reply via email to