Checked all the local variables in the function. Most of them are small numbers or pointers and use very little stack space. The only large item stored on the stack is struct drm_exec, and this is what pushes the stack size over the limit.
To fix this, struct drm_exec is now allocated with kmalloc() instead of being placed on the stack. All call sites were updated to use a pointer, and all cleanup paths now call drm_exec_fini() and kfree() to release the memory safely. This reduces stack usage, fixes the below: drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c:642:5: warning: stack frame size (1176) exceeds limit (1024) in 'amdgpu_userq_wait_ioctl' [-Wframe-larger-than] Cc: Alex Deucher <[email protected]> Cc: Christian König <[email protected]> Signed-off-by: Srinivasan Shanmugam <[email protected]> --- .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c index 25f178536469..b5839acde14a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c @@ -654,7 +654,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, struct dma_fence **fences = NULL; u16 num_points, num_fences = 0; int r, i, rentry, wentry, cnt; - struct drm_exec exec; + struct drm_exec *exec = NULL; num_read_bo_handles = wait_info->num_bo_read_handles; bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles), @@ -721,24 +721,26 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, } } - drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, + exec = kmalloc(sizeof(*exec), GFP_KERNEL); + if (!exec) { + r = -ENOMEM; + goto put_gobj_write; + } + + drm_exec_init(exec, DRM_EXEC_INTERRUPTIBLE_WAIT, (num_read_bo_handles + num_write_bo_handles)); /* Lock all BOs with retry handling */ - drm_exec_until_all_locked(&exec) { - r = drm_exec_prepare_array(&exec, gobj_read, num_read_bo_handles, 1); - drm_exec_retry_on_contention(&exec); - if (r) { - drm_exec_fini(&exec); - goto put_gobj_write; - } + drm_exec_until_all_locked(exec) { + r = drm_exec_prepare_array(exec, gobj_read, num_read_bo_handles, 1); + drm_exec_retry_on_contention(exec); + if (r) + goto exec_fini; - r = drm_exec_prepare_array(&exec, gobj_write, num_write_bo_handles, 1); - drm_exec_retry_on_contention(&exec); - if (r) { - drm_exec_fini(&exec); - goto put_gobj_write; - } + r = drm_exec_prepare_array(exec, gobj_write, num_write_bo_handles, 1); + drm_exec_retry_on_contention(exec); + if (r) + goto exec_fini; } if (!wait_info->num_fences) { @@ -966,7 +968,8 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, kfree(fence_info); } - drm_exec_fini(&exec); + drm_exec_fini(exec); + kfree(exec); for (i = 0; i < num_read_bo_handles; i++) drm_gem_object_put(gobj_read[i]); kfree(gobj_read); @@ -990,7 +993,10 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data, free_fence_info: kfree(fence_info); exec_fini: - drm_exec_fini(&exec); + if (exec) { + drm_exec_fini(exec); + kfree(exec); + } put_gobj_write: while (wentry-- > 0) drm_gem_object_put(gobj_write[wentry]); -- 2.34.1
