nvdla: Fix build for CONFIG_FRAME_WARN=1024

Some 3rd party Linux distributions, set the kernel configuration option
"CONFIG_FRAME_WARN=1024" which will causes the compiler to generate
compilation errors when a functions stack frame size exceeds 1024 bytes.
When compiling the DLA driver on Fedora the compilation fails with the
following errors.

 drivers/video/tegra/host/nvdla/nvdla.o] Error 1
 drivers/video/tegra/host/nvdla/nvdla_ioctl.c: In function ‘nvdla_emu_task_submit’:
 build/drivers/video/tegra/host/nvdla/nvdla_ioctl.c:918:1: error: the frame size of
 	1456 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]

 drivers/video/tegra/host/nvdla/nvdla_ioctl.c: In function ‘nvdla_submit’:
 drivers/video/tegra/host/nvdla/nvdla_ioctl.c:1118:1: error: the frame size of 1440
 	bytes is larger than 1024 bytes [-Werror=frame-larger-than=]

Fix this by copying the user tasks from userspace one at a time and
allocating the structure nvdla_emu_task dynamically so that is it not
allocated on the stack.

Bug 3524939

Change-Id: If752423a170c46efd9b6cffc458a7c1db1984afe
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2694097
Tested-by: Amit Sharma (SW-TEGRA) <amisharma@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: Amit Sharma (SW-TEGRA) <amisharma@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Arvind M <am@nvidia.com>
Reviewed-by: Praveen K <kpraveen@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
Jon Hunter
2022-04-07 17:09:39 +01:00
committed by Laxman Dewangan
parent 0b7fd59dca
commit b67df49181

View File

@@ -832,10 +832,10 @@ static int nvdla_emu_task_submit(struct nvdla_private *priv, void *arg)
struct nvdla_submit_args *args =
(struct nvdla_submit_args *)arg;
struct nvdla_ioctl_emu_submit_task __user *user_tasks;
struct nvdla_ioctl_emu_submit_task local_tasks[MAX_NVDLA_TASKS_PER_SUBMIT];
struct nvdla_ioctl_emu_submit_task local_task;
struct platform_device *pdev;
struct nvdla_queue *queue;
struct nvdla_emu_task task;
struct nvdla_emu_task *task;
int err = 0, i = 0;
u32 num_tasks;
@@ -849,8 +849,6 @@ static int nvdla_emu_task_submit(struct nvdla_private *priv, void *arg)
nvdla_dbg_fn(pdev, "inside emulator task submit");
task.queue = queue;
user_tasks = (struct nvdla_ioctl_emu_submit_task __user *)
(uintptr_t)args->tasks;
if (!user_tasks)
@@ -862,40 +860,44 @@ static int nvdla_emu_task_submit(struct nvdla_private *priv, void *arg)
nvdla_dbg_info(pdev, "num of emulator tasks [%d]", num_tasks);
/* IOCTL copy descriptors*/
if (copy_from_user(local_tasks, (void __user *)user_tasks,
(num_tasks * sizeof(*user_tasks)))) {
err = -EFAULT;
goto exit;
}
nvdla_dbg_info(pdev, "copy of user tasks done");
task = kmalloc(sizeof(*task), GFP_KERNEL);
if (!task)
return -ENOMEM;
task->queue = queue;
for (i = 0; i < num_tasks; i++) {
/* IOCTL copy descriptor */
if (copy_from_user(&local_task, (void __user *)&user_tasks[i],
sizeof(*user_tasks))) {
err = -EFAULT;
goto exit;
}
nvdla_dbg_info(pdev, "submit [%d]th task", i + 1);
task.num_prefences = local_tasks[i].num_prefences;
task.num_postfences = local_tasks[i].num_postfences;
task->num_prefences = local_task.num_prefences;
task->num_postfences = local_task.num_postfences;
/* get pre fences */
if (copy_from_user(task.prefences,
(void __user *)local_tasks[i].prefences,
(task.num_prefences * sizeof(struct nvdev_fence)))) {
if (copy_from_user(task->prefences,
(void __user *)local_task.prefences,
(task->num_prefences * sizeof(struct nvdev_fence)))) {
err = -EFAULT;
nvdla_dbg_err(pdev, "failed to copy prefences");
goto exit;
}
/* get post fences */
if (copy_from_user(task.postfences,
(void __user *)local_tasks[i].postfences,
(task.num_postfences * sizeof(struct nvdev_fence)))) {
if (copy_from_user(task->postfences,
(void __user *)local_task.postfences,
(task->num_postfences * sizeof(struct nvdev_fence)))) {
err = -EFAULT;
nvdla_dbg_err(pdev, "failed to copy postfences");
goto exit;
}
err = nvdla_emulator_submit(queue, &task);
err = nvdla_emulator_submit(queue, task);
if (err) {
nvdla_dbg_err(pdev, "fail to submit task: %d", i + 1);
goto exit;
@@ -903,7 +905,7 @@ static int nvdla_emu_task_submit(struct nvdla_private *priv, void *arg)
nvdla_dbg_info(pdev, "task[%d] submitted", i + 1);
/* send signal fences to user */
err = nvdla_send_emu_signal_fences(&task, local_tasks + i);
err = nvdla_send_emu_signal_fences(task, &local_task);
if (err) {
nvdla_dbg_err(pdev, "fail to send sig fence%d", i + 1);
goto exit;
@@ -914,6 +916,8 @@ static int nvdla_emu_task_submit(struct nvdla_private *priv, void *arg)
nvdla_dbg_fn(pdev, "Emulator task submitted, done!");
exit:
kfree(task);
return 0;
}
@@ -986,7 +990,7 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
struct nvdla_submit_args *args =
(struct nvdla_submit_args *)arg;
struct nvdla_ioctl_submit_task __user *user_tasks;
struct nvdla_ioctl_submit_task local_tasks[MAX_NVDLA_TASKS_PER_SUBMIT];
struct nvdla_ioctl_submit_task local_task;
struct platform_device *pdev;
struct nvdla_queue *queue;
struct nvdla_buffers *buffers;
@@ -1020,15 +1024,14 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
bypass_exec = ((args->flags & NVDLA_SUBMIT_FLAGS_BYPASS_EXEC) != 0U);
nvdla_dbg_info(pdev, "submit flags [%u]", args->flags);
/* IOCTL copy descriptors*/
if (copy_from_user(local_tasks, (void __user *)user_tasks,
(num_tasks * sizeof(*user_tasks)))) {
err = -EFAULT;
goto fail_to_copy_task;
}
nvdla_dbg_info(pdev, "copy of user tasks done");
for (i = 0; i < num_tasks; i++) {
/* IOCTL copy descriptor */
if (copy_from_user(&local_task, (void __user *)&user_tasks[i],
sizeof(*user_tasks))) {
err = -EFAULT;
goto fail_to_copy_task;
}
nvdla_dbg_info(pdev, "submit [%d]th task", i + 1);
err = nvdla_get_task_mem(queue, &task);
@@ -1042,7 +1045,7 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
kref_init(&task->ref);
/* fill local task param from user args */
err = nvdla_fill_task(queue, buffers, local_tasks + i, task);
err = nvdla_fill_task(queue, buffers, &local_task, task);
if (err) {
nvdla_dbg_err(pdev, "failed to fill task[%d]", i + 1);
goto fail_to_fill_task;
@@ -1075,7 +1078,7 @@ static int nvdla_submit(struct nvdla_private *priv, void *arg)
nvdla_dbg_info(pdev, "task[%d] got fences", i + 1);
/* update fences to user */
err = nvdla_update_signal_fences(task, local_tasks + i);
err = nvdla_update_signal_fences(task, &local_task);
if (err) {
nvdla_dbg_err(pdev, "fail update postfence%d", i + 1);
goto fail_to_update_postfences;