drm/i915: Flag purely internal commits to not clear crtc_state->inherited
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 28 Mar 2023 12:23:57 +0000 (15:23 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 13 Apr 2023 11:22:42 +0000 (14:22 +0300)
If we have to force the hardware to go through a full modeset
due to eg. cdclk reprogramming, we need to preserve
crtc_state->inherited for all crtcs that have not otherwise
gone through the whole compute_config() stuff after connectors
have been detected.

Otherwise eg. cdclk induced modeset glk_force_audio_cdclk()
will clear the inherited flag, and thus the first real commit
coming from userspace later on will not be forced through
the full .compute_config() path and so eg. audio state may
not get properly recomputed.

But instead of adding all kinds of ad-hoc crtc_state->inherited
preservation hacks all over, let's change things so that we
only clear it for the crtcs directly included in userspace/client
initiated commits.

Should be far less fragile since now we just need to remember
to flag the internal commits, and not worry about where new
crtcs might get pulled in.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5260
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230328122357.1697-1-ville.syrjala@linux.intel.com
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
drivers/gpu/drm/i915/display/i9xx_wm.c
drivers/gpu/drm/i915/display/intel_atomic.c
drivers/gpu/drm/i915/display/intel_audio.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_modeset_setup.c
drivers/gpu/drm/i915/display/intel_pipe_crc.c
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/display/intel_sprite_uapi.c

index caef72d387981d7b2dcf6d7324bf6fcaea058687..6288826a9497427cd07da9a9f9969d9279bbb2bb 100644 (file)
@@ -3447,9 +3447,10 @@ void ilk_wm_sanitize(struct drm_i915_private *dev_priv)
 
        drm_modeset_acquire_init(&ctx, 0);
 
-retry:
        state->acquire_ctx = &ctx;
+       to_intel_atomic_state(state)->internal = true;
 
+retry:
        /*
         * Hardware readout is the only time we don't want to calculate
         * intermediate watermarks (since we don't trust the current
index a9a3f3715279ddc5e875045461c7f4d0bfcf36cc..61011641f6ab8e07638cba9f82b2552c6596a1bf 100644 (file)
@@ -265,7 +265,6 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
        crtc_state->update_wm_post = false;
        crtc_state->fifo_changed = false;
        crtc_state->preload_luts = false;
-       crtc_state->inherited = false;
        crtc_state->wm.need_postvbl_update = false;
        crtc_state->do_async_flip = false;
        crtc_state->fb_bits = 0;
@@ -599,6 +598,8 @@ void intel_atomic_state_clear(struct drm_atomic_state *s)
        drm_atomic_state_default_clear(&state->base);
        intel_atomic_clear_global_state(state);
 
+       /* state->internal not reset on purpose */
+
        state->dpll_set = state->modeset = false;
 }
 
index 3d5a9bbc6fde370fcb40a73b72a55766d677716c..3d9c9b4f27f80268b16bb53b2f82764d9ca3c9e6 100644 (file)
@@ -1039,6 +1039,7 @@ static void glk_force_audio_cdclk(struct drm_i915_private *i915,
                return;
 
        state->acquire_ctx = &ctx;
+       to_intel_atomic_state(state)->internal = true;
 
 retry:
        ret = glk_force_audio_cdclk_commit(to_intel_atomic_state(state), crtc,
index d5652e3b2fdb6658ace049549bde10a7a5aee3eb..d6fb07821cffb4c9a29efab1e0a4acce6452d2ed 100644 (file)
@@ -3903,6 +3903,7 @@ static int modeset_pipe(struct drm_crtc *crtc,
                return -ENOMEM;
 
        state->acquire_ctx = ctx;
+       to_intel_atomic_state(state)->internal = true;
 
        crtc_state = drm_atomic_get_crtc_state(state, crtc);
        if (IS_ERR(crtc_state)) {
index 27b47680573a221ec5c9177f6328de8d7a5f283b..0334565cec8242f793fc37df1ba5717ad57550dd 100644 (file)
@@ -4137,7 +4137,10 @@ found:
        }
 
        state->acquire_ctx = ctx;
+       to_intel_atomic_state(state)->internal = true;
+
        restore_state->acquire_ctx = ctx;
+       to_intel_atomic_state(restore_state)->internal = true;
 
        connector_state = drm_atomic_get_connector_state(state, connector);
        if (IS_ERR(connector_state)) {
@@ -6585,6 +6588,13 @@ int intel_atomic_check(struct drm_device *dev,
 
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
                                            new_crtc_state, i) {
+               /*
+                * crtc's state no longer considered to be inherited
+                * after the first userspace/client initiated commit.
+                */
+               if (!state->internal)
+                       new_crtc_state->inherited = false;
+
                if (new_crtc_state->inherited != old_crtc_state->inherited)
                        new_crtc_state->uapi.mode_changed = true;
 
@@ -8285,9 +8295,10 @@ static int intel_initial_commit(struct drm_device *dev)
 
        drm_modeset_acquire_init(&ctx, 0);
 
-retry:
        state->acquire_ctx = &ctx;
+       to_intel_atomic_state(state)->internal = true;
 
+retry:
        for_each_intel_crtc(dev, crtc) {
                struct intel_crtc_state *crtc_state =
                        intel_atomic_get_crtc_state(state, crtc);
@@ -8300,15 +8311,6 @@ retry:
                if (crtc_state->hw.active) {
                        struct intel_encoder *encoder;
 
-                       /*
-                        * We've not yet detected sink capabilities
-                        * (audio,infoframes,etc.) and thus we don't want to
-                        * force a full state recomputation yet. We want that to
-                        * happen only for the first real commit from userspace.
-                        * So preserve the inherited flag for the time being.
-                        */
-                       crtc_state->inherited = true;
-
                        ret = drm_atomic_add_affected_planes(state, &crtc->base);
                        if (ret)
                                goto out;
index ed02399ee41dcaae5abdf507243a97fdade266d0..b28c8dc48e244763e23615fcfb41d4a1e220424e 100644 (file)
@@ -643,6 +643,9 @@ struct intel_atomic_state {
        struct __intel_global_objs_state *global_objs;
        int num_global_objs;
 
+       /* Internal commit, as opposed to userspace/client initiated one */
+       bool internal;
+
        bool dpll_set, modeset;
 
        struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS];
index bc0695c5bb6f81b7fb66e2c9c6832182ea3bd9bd..eefa4018dc0c288140e06971c5ff6fbf6a74a5ad 100644 (file)
@@ -69,6 +69,7 @@ static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
        }
 
        state->acquire_ctx = ctx;
+       to_intel_atomic_state(state)->internal = true;
 
        /* Everything's already locked, -EDEADLK can't happen. */
        temp_crtc_state = intel_atomic_get_crtc_state(state, crtc);
index 8d3ea8d7b737202af307143672d6050409374500..5a468ed6e26c71e862729724e3cba38aff4bf736 100644 (file)
@@ -293,6 +293,7 @@ intel_crtc_crc_setup_workarounds(struct intel_crtc *crtc, bool enable)
        }
 
        state->acquire_ctx = &ctx;
+       to_intel_atomic_state(state)->internal = true;
 
 retry:
        pipe_config = intel_atomic_get_crtc_state(state, crtc);
index 6badfff2b4a28a2c89fd68255079a96d5b9c509f..3e2d9998566c797319eb06f8c117bd70b97b0b2c 100644 (file)
@@ -2149,10 +2149,11 @@ static int intel_psr_fastset_force(struct drm_i915_private *dev_priv)
                return -ENOMEM;
 
        drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
+
        state->acquire_ctx = &ctx;
+       to_intel_atomic_state(state)->internal = true;
 
 retry:
-
        drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
        drm_for_each_connector_iter(conn, &conn_iter) {
                struct drm_connector_state *conn_state;
index 70a3910837519b6dc56ea64ef447a1581486566b..a76b48ebc2d31e437ff73869456681f9ffe6f8be 100644 (file)
@@ -86,6 +86,7 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
                goto out;
        }
        state->acquire_ctx = &ctx;
+       to_intel_atomic_state(state)->internal = true;
 
        while (1) {
                plane_state = drm_atomic_get_plane_state(state, plane);