]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Avoid MPC infinite loop
authorJosip Pavic <Josip.Pavic@amd.com>
Thu, 21 Jul 2022 19:33:00 +0000 (15:33 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Sep 2022 08:27:46 +0000 (10:27 +0200)
[ Upstream commit 8de297dc046c180651c0500f8611663ae1c3828a ]

[why]
In some cases MPC tree bottom pipe ends up point to itself.  This causes
iterating from top to bottom to hang the system in an infinite loop.

[how]
When looping to next MPC bottom pipe, check that the pointer is not same
as current to avoid infinite loop.

Reviewed-by: Josip Pavic <Josip.Pavic@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Aric Cyr <aric.cyr@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c

index 8b2f29f6dabd202ca3cdfcf73fb6593904721021..068e79fa3490d2966ff181488d9e1cb44b08d9bf 100644 (file)
@@ -118,6 +118,12 @@ struct mpcc *mpc1_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id)
        while (tmp_mpcc != NULL) {
                if (tmp_mpcc->dpp_id == dpp_id)
                        return tmp_mpcc;
+
+               /* avoid circular linked list */
+               ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot);
+               if (tmp_mpcc == tmp_mpcc->mpcc_bot)
+                       break;
+
                tmp_mpcc = tmp_mpcc->mpcc_bot;
        }
        return NULL;
index 5a188b2bc033c92a340cdd2ae374f0a957d0e6d3..0a00bd8e00abc4e84c227751bde4c6faf93fcc94 100644 (file)
@@ -488,6 +488,12 @@ struct mpcc *mpc2_get_mpcc_for_dpp(struct mpc_tree *tree, int dpp_id)
        while (tmp_mpcc != NULL) {
                if (tmp_mpcc->dpp_id == 0xf || tmp_mpcc->dpp_id == dpp_id)
                        return tmp_mpcc;
+
+               /* avoid circular linked list */
+               ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot);
+               if (tmp_mpcc == tmp_mpcc->mpcc_bot)
+                       break;
+
                tmp_mpcc = tmp_mpcc->mpcc_bot;
        }
        return NULL;