The issue takes place in several error handling paths in both cik_sdma_ib_test() and r600_dma_ib_test(). Take cik_sdma_ib_test() for an example. When radeon_fence_wait_timeout() returns a value equal or less than zero, the function simply returns an error code, forgetting to free the object "ib", which is requested by calling radeon_ib_get() earlier. This may result in memory leaks. Fix it by freeing "ib" in specific error handling paths. Fixes: 04db4caf5c83 ("drm/radeon: Avoid double gpu reset by adding a timeout on IB ring tests.") Signed-off-by: Xin Xiong <xiongx18@xxxxxxxxxxxx> Signed-off-by: Xin Tan <tanxin.ctf@xxxxxxxxx> --- V1 -> V2: Fix another function of similar pattern --- drivers/gpu/drm/radeon/cik_sdma.c | 9 +++++---- drivers/gpu/drm/radeon/r600_dma.c | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 919b14845c3c..d0e7323cdd42 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -732,18 +732,18 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) r = radeon_ib_schedule(rdev, &ib, NULL, false); if (r) { - radeon_ib_free(rdev, &ib); DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); - return r; + goto out; } r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( RADEON_USEC_IB_TEST_TIMEOUT)); if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); - return r; + goto out; } else if (r == 0) { DRM_ERROR("radeon: fence wait timed out.\n"); - return -ETIMEDOUT; + r = -ETIMEDOUT; + goto out; } r = 0; for (i = 0; i < rdev->usec_timeout; i++) { @@ -758,6 +758,7 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_ERROR("radeon: ib test failed (0x%08X)\n", tmp); r = -EINVAL; } +out: radeon_ib_free(rdev, &ib); return r; } diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index 89ca2738c5d4..75ed03886fc2 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -363,18 +363,18 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) r = radeon_ib_schedule(rdev, &ib, NULL, false); if (r) { - radeon_ib_free(rdev, &ib); DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); - return r; + goto out; } r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( RADEON_USEC_IB_TEST_TIMEOUT)); if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); - return r; + goto out; } else if (r == 0) { DRM_ERROR("radeon: fence wait timed out.\n"); - return -ETIMEDOUT; + r = -ETIMEDOUT; + goto out; } r = 0; for (i = 0; i < rdev->usec_timeout; i++) { @@ -389,6 +389,7 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_ERROR("radeon: ib test failed (0x%08X)\n", tmp); r = -EINVAL; } +out: radeon_ib_free(rdev, &ib); return r; } -- 2.25.1