]> git.dujemihanovic.xyz Git - linux.git/commitdiff
drm/amd/display: handle nulled pipe context in DCE110's set_drr()
authorTobias Jakobi <tjakobi@math.uni-bielefeld.de>
Mon, 16 Sep 2024 12:54:05 +0000 (14:54 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 18 Sep 2024 20:15:09 +0000 (16:15 -0400)
As set_drr() is called from IRQ context, it can happen that the
pipe context has been nulled by dc_state_destruct().

Apply the same protection here that is already present for
dcn35_set_drr() and dcn10_set_drr(). I.e. fetch the tg pointer
first (to avoid a race with dc_state_destruct()), and then
check the local copy before using it.

Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3142
Fixes: 06ad7e164256 ("drm/amd/display: Destroy DC context while keeping DML and DML2")
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c

index aa7479b318982b3cd1e922fc76de2f5fa3487236..4fbed0298adfa7cedfbb7ecda87b36a5fe54ba85 100644 (file)
@@ -2096,13 +2096,20 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
         * as well.
         */
        for (i = 0; i < num_pipes; i++) {
-               pipe_ctx[i]->stream_res.tg->funcs->set_drr(
-                       pipe_ctx[i]->stream_res.tg, &params);
-
-               if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
-                       pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
-                                       pipe_ctx[i]->stream_res.tg,
-                                       event_triggers, num_frames);
+               /* dc_state_destruct() might null the stream resources, so fetch tg
+                * here first to avoid a race condition. The lifetime of the pointee
+                * itself (the timing_generator object) is not a problem here.
+                */
+               struct timing_generator *tg = pipe_ctx[i]->stream_res.tg;
+
+               if ((tg != NULL) && tg->funcs) {
+                       if (tg->funcs->set_drr)
+                               tg->funcs->set_drr(tg, &params);
+                       if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
+                               if (tg->funcs->set_static_screen_control)
+                                       tg->funcs->set_static_screen_control(
+                                               tg, event_triggers, num_frames);
+               }
        }
 }