drm/i915: Check vblank delay validity
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 10 Dec 2024 21:09:51 +0000 (23:09 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 15 Jan 2025 17:27:26 +0000 (19:27 +0200)
Make sure we have enough vblank for the computed vblank delay.
Supposedly we'd reject things anyway later if this gets violated,
but it seems nicer to do some basic sanity checks early just
so we can be sure the basic relationship vblank_end > vblank_start
always holds.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241210211007.5976-3-ville.syrjala@linux.intel.com
Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
drivers/gpu/drm/i915/display/intel_display.c

index 5530bcf32b87a3ed75c2f33ae58b4286d4208f79..f5d2eacce119b666bbdf0787c6e94a663990e5ba 100644 (file)
@@ -2633,17 +2633,40 @@ static int intel_crtc_vblank_delay(const struct intel_crtc_state *crtc_state)
        return vblank_delay;
 }
 
-static int intel_crtc_compute_config(struct intel_atomic_state *state,
-                                    struct intel_crtc *crtc)
+static int intel_crtc_compute_vblank_delay(struct intel_atomic_state *state,
+                                          struct intel_crtc *crtc)
 {
+       struct intel_display *display = to_intel_display(state);
        struct intel_crtc_state *crtc_state =
                intel_atomic_get_new_crtc_state(state, crtc);
        struct drm_display_mode *adjusted_mode =
                &crtc_state->hw.adjusted_mode;
+       int vblank_delay, max_vblank_delay;
+
+       vblank_delay = intel_crtc_vblank_delay(crtc_state);
+       max_vblank_delay = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start - 1;
+
+       if (vblank_delay > max_vblank_delay) {
+               drm_dbg_kms(display->drm, "[CRTC:%d:%s] vblank delay (%d) exceeds max (%d)\n",
+                           crtc->base.base.id, crtc->base.name, vblank_delay, max_vblank_delay);
+               return -EINVAL;
+       }
+
+       adjusted_mode->crtc_vblank_start += vblank_delay;
+
+       return 0;
+}
+
+static int intel_crtc_compute_config(struct intel_atomic_state *state,
+                                    struct intel_crtc *crtc)
+{
+       struct intel_crtc_state *crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
        int ret;
 
-       adjusted_mode->crtc_vblank_start +=
-               intel_crtc_vblank_delay(crtc_state);
+       ret = intel_crtc_compute_vblank_delay(state, crtc);
+       if (ret)
+               return ret;
 
        ret = intel_dpll_crtc_compute_clock(state, crtc);
        if (ret)