]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amdgpu: fix resource leak on ACP reset timeout
authorCe Sun <cesun102@amd.com>
Mon, 22 Jun 2026 15:05:09 +0000 (23:05 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2026 17:00:19 +0000 (13:00 -0400)
When ACP soft reset poll times out, original code returns early without cleanup,
leaking MFD child devices, genpd links and all ACP heap allocations.

Replace direct early return with goto out to force run all cleanup logic
regardless of reset success, preserve timeout error code for caller.

Signed-off-by: Ce Sun <cesun102@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 98073e4328d7a8d75d03696ab27f6de70ef1aeda)
Cc: stable@vger.kernel.org
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c

index 4c732e0f776e1269399469dd3d66369bfe5062be..f04b2d63c59a7420e04b3bfaf12418b2209067a4 100644 (file)
@@ -508,6 +508,7 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
        u32 val = 0;
        u32 count = 0;
        struct amdgpu_device *adev = ip_block->adev;
+       int ret = 0;
 
        /* return early if no ACP */
        if (!adev->acp.acp_genpd) {
@@ -529,7 +530,8 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
                        break;
                if (--count == 0) {
                        dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
-                       return -ETIMEDOUT;
+                       ret = -ETIMEDOUT;
+                       goto out;
                }
                udelay(100);
        }
@@ -546,11 +548,12 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
                        break;
                if (--count == 0) {
                        dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
-                       return -ETIMEDOUT;
+                       ret = -ETIMEDOUT;
+                       goto out;
                }
                udelay(100);
        }
-
+out:
        device_for_each_child(adev->acp.parent, NULL,
                              acp_genpd_remove_device);
 
@@ -560,7 +563,7 @@ static int acp_hw_fini(struct amdgpu_ip_block *ip_block)
        kfree(adev->acp.acp_genpd);
        kfree(adev->acp.acp_cell);
 
-       return 0;
+       return ret;
 }
 
 static int acp_suspend(struct amdgpu_ip_block *ip_block)