]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/i915/dp_tunnel: Fix error handling when clearing stream BW in atomic state
authorImre Deak <imre.deak@intel.com>
Fri, 20 Mar 2026 09:29:00 +0000 (11:29 +0200)
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Tue, 24 Mar 2026 06:00:00 +0000 (08:00 +0200)
Clearing the DP tunnel stream BW in the atomic state involves getting
the tunnel group state, which can fail. Handle the error accordingly.

This fixes at least one issue where drm_dp_tunnel_atomic_set_stream_bw()
failed to get the tunnel group state returning -EDEADLK, which wasn't
handled. This lead to the ctx->contended warn later in modeset_lock()
while taking a WW mutex for another object in the same atomic state, and
thus within the same already contended WW context.

Moving intel_crtc_state_alloc() later would avoid freeing saved_state on
the error path; this stable patch leaves that simplification for a
follow-up.

Cc: Uma Shankar <uma.shankar@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: <stable@vger.kernel.org> # v6.9+
Fixes: a4efae87ecb2 ("drm/i915/dp: Compute DP tunnel BW during encoder state computation")
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/7617
Reviewed-by: Michał Grzelak <michal.grzelak@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patch.msgid.link/20260320092900.13210-1-imre.deak@intel.com
(cherry picked from commit fb69d0076e687421188bc8103ab0e8e5825b1df1)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_dp_tunnel.c
drivers/gpu/drm/i915/display/intel_dp_tunnel.h

index c4246481fc2fe942213f3db1bb13f753e42e2550..0f82bf771a92da82d72d166a812f49fca5042e77 100644 (file)
@@ -4602,6 +4602,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
        struct intel_crtc_state *crtc_state =
                intel_atomic_get_new_crtc_state(state, crtc);
        struct intel_crtc_state *saved_state;
+       int err;
 
        saved_state = intel_crtc_state_alloc(crtc);
        if (!saved_state)
@@ -4610,7 +4611,12 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
        /* free the old crtc_state->hw members */
        intel_crtc_free_hw_state(crtc_state);
 
-       intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state);
+       err = intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state);
+       if (err) {
+               kfree(saved_state);
+
+               return err;
+       }
 
        /* FIXME: before the switch to atomic started, a new pipe_config was
         * kzalloc'd. Code that depends on any field being zero should be
index 83865c02d477cdab4b3075d93aad1e61a9333f6f..55b423fd6b6f4c74bed36e19cf9c110f82c05625 100644 (file)
@@ -621,19 +621,27 @@ int intel_dp_tunnel_atomic_compute_stream_bw(struct intel_atomic_state *state,
  *
  * Clear any DP tunnel stream BW requirement set by
  * intel_dp_tunnel_atomic_compute_stream_bw().
+ *
+ * Returns 0 in case of success, a negative error code otherwise.
  */
-void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
-                                           struct intel_crtc_state *crtc_state)
+int intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
+                                          struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       int err;
 
        if (!crtc_state->dp_tunnel_ref.tunnel)
-               return;
+               return 0;
+
+       err = drm_dp_tunnel_atomic_set_stream_bw(&state->base,
+                                                crtc_state->dp_tunnel_ref.tunnel,
+                                                crtc->pipe, 0);
+       if (err)
+               return err;
 
-       drm_dp_tunnel_atomic_set_stream_bw(&state->base,
-                                          crtc_state->dp_tunnel_ref.tunnel,
-                                          crtc->pipe, 0);
        drm_dp_tunnel_ref_put(&crtc_state->dp_tunnel_ref);
+
+       return 0;
 }
 
 /**
index 7f0f720e8dcadfc88dbb9f56be1a4692bd323d9d..10ab9eebcef69491acef427b80e9f990b697fe64 100644 (file)
@@ -40,8 +40,8 @@ int intel_dp_tunnel_atomic_compute_stream_bw(struct intel_atomic_state *state,
                                             struct intel_dp *intel_dp,
                                             const struct intel_connector *connector,
                                             struct intel_crtc_state *crtc_state);
-void intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
-                                           struct intel_crtc_state *crtc_state);
+int intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
+                                          struct intel_crtc_state *crtc_state);
 
 int intel_dp_tunnel_atomic_add_state_for_crtc(struct intel_atomic_state *state,
                                              struct intel_crtc *crtc);
@@ -88,9 +88,12 @@ intel_dp_tunnel_atomic_compute_stream_bw(struct intel_atomic_state *state,
        return 0;
 }
 
-static inline void
+static inline int
 intel_dp_tunnel_atomic_clear_stream_bw(struct intel_atomic_state *state,
-                                      struct intel_crtc_state *crtc_state) {}
+                                      struct intel_crtc_state *crtc_state)
+{
+       return 0;
+}
 
 static inline int
 intel_dp_tunnel_atomic_add_state_for_crtc(struct intel_atomic_state *state,