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

Reply via email to