/* * Samsung Exynos SoC series VPU driver * * Copyright (c) 2015 Samsung Electronics Co., Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vision-config.h" #include "vision-dev.h" #include "vision-ioctl.h" #include "../npu/core/npu-log.h" /***************************************************************************** ***** wrapper function ***** *****************************************************************************/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,4,0) static unsigned long __npu_access_ok(const void __user *addr, unsigned long size) { return access_ok(addr, size); } #else static unsigned long __npu_access_ok(const void __user *addr, unsigned long size) { return access_ok(VERIFY_READ, addr, size); } #endif static int get_vs4l_ctrl64(struct vs4l_ctrl *kp, struct vs4l_ctrl __user *up) { int ret; if (!__npu_access_ok(up, sizeof(struct vs4l_ctrl))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err_ctrl; } ret = copy_from_user(kp, (void __user *)up, sizeof(struct vs4l_ctrl)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err_ctrl; } p_err_ctrl: return ret; } static void put_vs4l_ctrl64(struct vs4l_ctrl *kp, struct vs4l_ctrl __user *up) { int ret; ret = copy_to_user(up, kp, sizeof(struct vs4l_ctrl)); if (ret) vision_err("Failed to copy to user at ctrl.\n", ret); } static int get_vs4l_graph64(struct vs4l_graph *kp, struct vs4l_graph __user *up) { int ret; if (!__npu_access_ok(up, sizeof(struct vs4l_graph))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err_graph; } ret = copy_from_user(kp, (void __user *)up, sizeof(struct vs4l_graph)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err_graph; } p_err_graph: return ret; } static void put_vs4l_graph64(struct vs4l_graph *kp, struct vs4l_graph __user *up) { } static int get_vs4l_sched_param64(struct vs4l_sched_param *kp, struct vs4l_sched_param __user *up) { int ret; if (!__npu_access_ok(up, sizeof(struct vs4l_sched_param))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err; } ret = copy_from_user(kp, (void __user *)up, sizeof(struct vs4l_sched_param)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err; } p_err: return ret; } static void put_vs4l_sched_param64(struct vs4l_sched_param *kp, struct vs4l_sched_param __user *up) { } static int get_vs4l_format64(struct vs4l_format_list *kp, struct vs4l_format_list __user *up) { int ret = 0; size_t size = 0; struct vs4l_format *kformats_ptr; if (!__npu_access_ok(up, sizeof(struct vs4l_format_list))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err_format; } ret = copy_from_user((void *)kp, (void __user *)up, sizeof(struct vs4l_format_list)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err_format; } if (kp->count > VISION_MAX_BUFFER) { vision_err("kp->count(%u) cannot be greater to VISION_MAX_BUFFER(%d)\n", kp->count, VISION_MAX_BUFFER); ret = -EINVAL; goto p_err_format; } size = kp->count * sizeof(struct vs4l_format); if (!__npu_access_ok((void __user *)kp->formats, size)) { vision_err("acesss is fail\n"); ret = -EFAULT; goto p_err_format; } kformats_ptr = kmalloc(size, GFP_KERNEL); if (!kformats_ptr) { ret = -ENOMEM; goto p_err_format; } ret = copy_from_user(kformats_ptr, (void __user *)kp->formats, size); if (ret) { vision_err("copy_from_user failed(%d)\n", ret); kfree(kformats_ptr); ret = -EFAULT; goto p_err_format; } kp->formats = kformats_ptr; p_err_format: return ret; } static void put_vs4l_format64(struct vs4l_format_list *kp, struct vs4l_format_list __user *up) { kfree(kp->formats); } static int get_vs4l_param64(struct vs4l_param_list *kp, struct vs4l_param_list __user *up) { int ret; size_t size = 0; struct vs4l_param *kparams_ptr; if (!__npu_access_ok(up, sizeof(struct vs4l_param_list))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err_param; } ret = copy_from_user(kp, (void __user *)up, sizeof(struct vs4l_param_list)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err_param; } if (kp->count > VISION_MAX_BUFFER) { vision_err("kp->count(%u) cannot be greater to VISION_MAX_BUFFER(%d)\n", kp->count, VISION_MAX_BUFFER); ret = -EINVAL; goto p_err_param; } size = kp->count * sizeof(struct vs4l_param); if (!__npu_access_ok((void __user *)kp->params, size)) { vision_err("access failed\n"); ret = -EFAULT; goto p_err_param; } kparams_ptr = kmalloc(size, GFP_KERNEL); if (!kparams_ptr) { ret = -ENOMEM; goto p_err_param; } ret = copy_from_user(kparams_ptr, (void __user *)kp->params, size); if (ret) { vision_err("copy_from_user failed(%d)\n", ret); kfree(kparams_ptr); ret = -EFAULT; goto p_err_param; } kp->params = kparams_ptr; p_err_param: return ret; } static void put_vs4l_param64(struct vs4l_param_list *kp, struct vs4l_param_list __user *up) { kfree(kp->params); } static int get_vs4l_container64(struct vs4l_container_list *kp, struct vs4l_container_list __user *up) { int ret, i, free_buf_num; size_t size = 0; struct vs4l_container *kcontainer_ptr; struct vs4l_buffer *kbuffer_ptr = NULL; if (!__npu_access_ok(up, sizeof(struct vs4l_container_list))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err; } ret = copy_from_user(kp, (void __user *)up, sizeof(struct vs4l_container_list)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err; } /* container_list -> (vs4l_container)containers[count] -> (vs4l_buffer)buffers[count] */ if (kp->count > VISION_MAX_CONTAINERLIST) { vision_err("kp->count(%u) cannot be greater to VISION_MAX_CONTAINERLIST(%d)\n", kp->count, VISION_MAX_CONTAINERLIST); ret = -EINVAL; goto p_err; } size = kp->count * sizeof(struct vs4l_container); if (!__npu_access_ok((void __user *)kp->containers, size)) { vision_err("access to containers ptr failed (%pK)\n", kp->containers); ret = -EFAULT; goto p_err; } /* NOTE: hoon98.choi: check if devm_kzalloc() for memory management */ kcontainer_ptr = kzalloc(size, GFP_KERNEL); if (!kcontainer_ptr) { ret = -ENOMEM; goto p_err; } ret = copy_from_user(kcontainer_ptr, (void __user *)kp->containers, size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu)\n", ret, size); ret = -EFAULT; goto p_err_container; } kp->containers = kcontainer_ptr; /* fill each container from user's request */ for (i = 0, free_buf_num = 0; i < kp->count; i++, free_buf_num++) { size = kp->containers[i].count * sizeof(struct vs4l_buffer); if (!__npu_access_ok((void __user *) kp->containers[i].buffers, size)) { vision_err("access to containers ptr failed (%pK)\n", kp->containers[i].buffers); ret = -EFAULT; goto p_err_buffer; } kbuffer_ptr = kmalloc(size, GFP_KERNEL); if (!kbuffer_ptr) { ret = -ENOMEM; goto p_err_buffer; } ret = copy_from_user(kbuffer_ptr, (void __user *)kp->containers[i].buffers, size); if (ret) { vision_err("error from copy_from_user(idx: %d, ret: %d, size: %zu)\n", i, ret, size); ret = -EFAULT; goto p_err_buffer_malloc; } kp->containers[i].buffers = kbuffer_ptr; } return ret; p_err_buffer_malloc: kfree(kbuffer_ptr); kbuffer_ptr = NULL; p_err_buffer: for (i = 0; i < free_buf_num; i++) { kfree(kp->containers[i].buffers); kp->containers[i].buffers = NULL; } p_err_container: kfree(kcontainer_ptr); kp->containers = NULL; p_err: vision_err("Return with fail... (%d)\n", ret); return ret; } static void put_vs4l_container64(struct vs4l_container_list *kp, struct vs4l_container_list __user *up) { int i; if (!__npu_access_ok(up, sizeof(struct vs4l_container_list))) vision_err("Cannot access to user ptr(%pK)\n", up); if (put_user(kp->flags, &up->flags) || put_user(kp->index, &up->index) || put_user(kp->id, &up->id) || put_user(kp->timestamp[0].tv_sec, &up->timestamp[0].tv_sec) || put_user(kp->timestamp[0].tv_usec, &up->timestamp[0].tv_usec) || put_user(kp->timestamp[1].tv_sec, &up->timestamp[1].tv_sec) || put_user(kp->timestamp[1].tv_usec, &up->timestamp[1].tv_usec) || put_user(kp->timestamp[2].tv_sec, &up->timestamp[2].tv_sec) || put_user(kp->timestamp[2].tv_usec, &up->timestamp[2].tv_usec) || put_user(kp->timestamp[3].tv_sec, &up->timestamp[3].tv_sec) || put_user(kp->timestamp[3].tv_usec, &up->timestamp[3].tv_usec) || put_user(kp->timestamp[4].tv_sec, &up->timestamp[4].tv_sec) || put_user(kp->timestamp[4].tv_usec, &up->timestamp[4].tv_usec) || put_user(kp->timestamp[5].tv_sec, &up->timestamp[5].tv_sec) || put_user(kp->timestamp[5].tv_usec, &up->timestamp[5].tv_usec)) { vision_err("Copy_to_user failed (%pK -> %pK)\n", kp, up); } for (i = 0; i < kp->count; ++i) kfree(kp->containers[i].buffers); kfree(kp->containers); kp->containers = NULL; } static int get_vs4l_profiler(struct vs4l_profiler *kp, struct vs4l_profiler __user *up) { int ret; size_t size; struct vs4l_profiler_node *kprofiler_node = NULL; struct vs4l_profiler_node **kprofiler_child = NULL; struct vs4l_profiler_node *kprofiler_npu_child = NULL; struct vs4l_profiler_node *kprofiler_dsp_child = NULL; if (!__npu_access_ok(up, sizeof(struct vs4l_profiler))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err; } ret = copy_from_user(kp, (void __user *)up, sizeof(struct vs4l_profiler)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err; } if (kp->node != NULL) { // FW node size = sizeof(struct vs4l_profiler_node); if (!__npu_access_ok((void __user *)kp->node, size)) { vision_err("access to profiler node ptr failed (%pK)\n", kp->node); ret = -EFAULT; goto p_err; } kprofiler_node = kzalloc(size, GFP_KERNEL); if (!kprofiler_node) { ret = -ENOMEM; goto p_err_profiler_node; } ret = copy_from_user(kprofiler_node, (void __user *)kp->node, size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about profiler\n", ret, size); ret = -EFAULT; goto p_err_profiler_node; } kp->node = kprofiler_node; if (kp->node->child != NULL) { size = sizeof(struct vs4l_profiler_node *)*3; if (!__npu_access_ok((void __user *)kp->node->child, size)) { vision_err("access to profiler node ptr failed (%pK)\n", kp->node->child); ret = -EFAULT; goto p_err_profiler_node; } kprofiler_child = kzalloc(size, GFP_KERNEL); if (!kprofiler_child) { ret = -ENOMEM; goto p_err_profiler_child; } ret = copy_from_user(kprofiler_child, (void __user *)kp->node->child, size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about profiler\n", ret, size); ret = -EFAULT; goto p_err_profiler_child; } kp->node->child = kprofiler_child; if (kp->node->child[0] != NULL) { // NPU HW node size = sizeof(struct vs4l_profiler_node); if (!__npu_access_ok((void __user *)kp->node->child[0], size)) { vision_err("access to profiler node ptr failed (%pK)\n", kp->node->child[0]); ret = -EFAULT; goto p_err_profiler_child; } kprofiler_npu_child = kzalloc(size, GFP_KERNEL); if (!kprofiler_npu_child) { ret = -ENOMEM; goto p_err_profiler_npu_child; } ret = copy_from_user(kprofiler_npu_child, (void __user *)kp->node->child[0], size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about profiler\n", ret, size); ret = -EFAULT; goto p_err_profiler_npu_child; } kp->node->child[0] = kprofiler_npu_child; } if (kp->node->child[1] != NULL) { // DSP HW node size = sizeof(struct vs4l_profiler_node); if (!__npu_access_ok((void __user *)kp->node->child[1], size)) { vision_err("access to profiler node ptr failed (%pK)\n", kp->node->child[1]); ret = -EFAULT; goto p_err_profiler_npu_child; } kprofiler_dsp_child = kzalloc(size, GFP_KERNEL); if (!kprofiler_dsp_child) { ret = -ENOMEM; goto p_err_profiler_dsp_child; } ret = copy_from_user(kprofiler_dsp_child, (void __user *)kp->node->child[1], size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about profiler\n", ret, size); ret = -EFAULT; goto p_err_profiler_dsp_child; } kp->node->child[1] = kprofiler_dsp_child; } } } return ret; p_err_profiler_dsp_child: kfree(kprofiler_dsp_child); kp->node->child[1] = NULL; p_err_profiler_npu_child: kfree(kprofiler_npu_child); kp->node->child[0] = NULL; p_err_profiler_child: kfree(kprofiler_child); kp->node->child = NULL; p_err_profiler_node: kfree(kprofiler_node); kp->node = NULL; p_err: vision_err("Return with fail... (%d)\n", ret); return ret; } static int put_vs4l_profiler(struct vs4l_profiler *kp, struct vs4l_profiler __user *up) { int ret; size_t size; struct vs4l_profiler temp; struct vs4l_profiler_node **kprofiler_pchild; struct vs4l_profiler_node *kprofiler_node; if (!__npu_access_ok(up, sizeof(struct vs4l_profiler))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err; } ret = copy_from_user(&temp, (void __user *)up, sizeof(struct vs4l_profiler)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err; } if (kp->node != NULL) { size = sizeof(struct vs4l_profiler_node); if (!__npu_access_ok((void __user *)temp.node, size)) { vision_err("access to profiler node ptr failed (%pK)\n", temp.node); ret = -EFAULT; goto p_err; } // copy to user - Firmware duration put_user(kp->node->duration, &temp.node->duration); kprofiler_node = kzalloc(size, GFP_KERNEL); if (!kprofiler_node) { ret = -ENOMEM; goto p_err_profiler_node; } ret = copy_from_user(kprofiler_node, (void __user *)temp.node, size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about profiler\n", ret, size); ret = -EFAULT; goto p_err_profiler_node; } temp.node = kprofiler_node; if (temp.node->child != NULL) { size = sizeof(struct vs4l_profiler_node *)*3; if (!__npu_access_ok((void __user *)temp.node->child, size)) { vision_err("access to profiler node ptr failed (%pK)\n", temp.node->child); ret = -EFAULT; goto p_err_profiler_node; } kprofiler_pchild = kzalloc(size, GFP_KERNEL); if (!kprofiler_pchild) { ret = -ENOMEM; goto p_err_profiler_pchild; } ret = copy_from_user(kprofiler_pchild, (void __user *)temp.node->child, size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about profiler\n", ret, size); ret = -EFAULT; goto p_err_profiler_pchild; } temp.node->child = kprofiler_pchild; // copy to user - NPU HW duration if (kp->node->child[0] != NULL) put_user(kp->node->child[0]->duration, &temp.node->child[0]->duration); // copy to user - DSP HW duration if (kp->node->child[1] != NULL) put_user(kp->node->child[1]->duration, &temp.node->child[1]->duration); kfree(temp.node->child); temp.node->child = NULL; kfree(kp->node->child); kp->node->child = NULL; } kfree(temp.node); temp.node = NULL; kfree(kp->node); kp->node = NULL; } return ret; p_err_profiler_pchild: kfree(kprofiler_pchild); temp.node->child = NULL; p_err_profiler_node: kfree(kprofiler_node); temp.node = NULL; p_err: vision_err("Return with fail... (%d)\n", ret); return ret; } static int get_vs4l_version(struct vs4l_version *kp, struct vs4l_version __user *up) { int ret = 0; size_t size; char *fw_version; char *fw_hash; if (!__npu_access_ok(up, sizeof(struct vs4l_version))) { vision_err("access failed from user ptr(%pK)\n", up); ret = -EFAULT; goto p_err_version; } ret = copy_from_user(kp, (void __user *)up, sizeof(struct vs4l_version)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err_version; } size = sizeof(unsigned char *) * VISION_MAX_FW_VERSION_LEN; fw_version = kzalloc(size, GFP_KERNEL); if (!fw_version) { ret = -ENOMEM; goto p_err_version; } ret = copy_from_user(fw_version, (void __user *)kp->fw_version, size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about fw version\n", ret, size); ret = -EFAULT; kfree(fw_version); goto p_err_version; } kp->fw_version = fw_version; size = sizeof(unsigned char *) * VISION_MAX_FW_HASH_LEN; fw_hash = kzalloc(size, GFP_KERNEL); if (!fw_hash) { ret = -ENOMEM; goto p_err_version; } ret = copy_from_user(fw_hash, (void __user *)kp->fw_hash, size); if (ret) { vision_err("error from copy_from_user(%d), size(%zu) about fw hash\n", ret, size); ret = -EFAULT; kfree(fw_version); kfree(fw_hash); goto p_err_version; } kp->fw_hash = fw_hash; p_err_version: return ret; } static int put_vs4l_version(struct vs4l_version *kp, struct vs4l_version __user *up) { int ret = 0; struct vs4l_version temp; if (!__npu_access_ok(up, sizeof(struct vs4l_container_list))) vision_err("Cannot access to user ptr(%pK)\n", up); ret = copy_from_user(&temp, (void __user *)up, sizeof(struct vs4l_version)); if (ret) { vision_err("copy_from_user failed(%d) from %pK\n", ret, up); goto p_err_version; } ret = copy_to_user(temp.build_info, kp->build_info, strlen(kp->build_info) + 1); if (ret) { vision_err("Failed to copy to user at version.\n", ret); goto p_err_version; } ret = copy_to_user(temp.signature, kp->signature, strlen(kp->signature) + 1); if (ret) { vision_err("Failed to copy to user at version.\n", ret); goto p_err_version; } ret = copy_to_user(temp.driver_verion, kp->driver_verion, strlen(kp->driver_verion) + 1); if (ret) { vision_err("Failed to copy to user at version.\n", ret); goto p_err_version; } ret = copy_to_user(temp.fw_version, kp->fw_version, strlen(kp->fw_version)); if (ret) { vision_err("Failed to copy to user at version.\n", ret); goto p_err_version; } ret = copy_to_user(temp.fw_hash, kp->fw_hash, strlen(kp->fw_hash)); if (ret) { vision_err("Failed to copy to user at version.\n", ret); goto p_err_version; } put_user(kp->ncp_version, &up->ncp_version); put_user(kp->mailbox_version, &up->mailbox_version); put_user(kp->cmd_version, &up->cmd_version); put_user(kp->api_version, &up->api_version); kfree(kp->fw_version); kfree(kp->fw_hash); p_err_version: return ret; } static long __vertex_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { static s64 buf_time; s64 now; int get_time = 0; int ret = 0; static int p_flag; static int fw_time; static int npu_hw_time; static int dsp_hw_time; struct vision_device *vdev = vision_devdata(file); const struct vertex_ioctl_ops *ops = vdev->ioctl_ops; /* temp var to support each ioctl */ union { struct vs4l_graph vsg; struct vs4l_format_list vsf; struct vs4l_param_list vsp; struct vs4l_ctrl vsc; struct vs4l_sched_param vsprm; struct vs4l_container_list vscl; struct vs4l_profiler vspr; struct vs4l_version vsvs; } vs4l_kvar; now = ktime_to_ns(ktime_get_boottime()); npu_log_ioctl_set_date(cmd, 0); switch (cmd) { case VS4L_VERTEXIOC_S_GRAPH: ret = get_vs4l_graph64(&vs4l_kvar.vsg, (struct vs4l_graph __user *)arg); if (ret) { vision_err("get_vs4l_graph64 (%d)\n", ret); break; } ret = ops->vertexioc_s_graph(file, &vs4l_kvar.vsg); if (ret) vision_err("vertexioc_s_graph is fail(%d)\n", ret); put_vs4l_graph64(&vs4l_kvar.vsg, (struct vs4l_graph __user *)arg); break; case VS4L_VERTEXIOC_S_FORMAT: ret = get_vs4l_format64(&vs4l_kvar.vsf, (struct vs4l_format_list __user *)arg); if (ret) { vision_err("get_vs4l_format64 (%d)\n", ret); break; } ret = ops->vertexioc_s_format(file, &vs4l_kvar.vsf); if (ret) vision_err("vertexioc_s_format (%d)\n", ret); put_vs4l_format64(&vs4l_kvar.vsf, (struct vs4l_format_list __user *)arg); break; case VS4L_VERTEXIOC_S_PARAM: ret = get_vs4l_param64(&vs4l_kvar.vsp, (struct vs4l_param_list __user *)arg); if (ret) { vision_err("get_vs4l_param64 (%d)\n", ret); break; } ret = ops->vertexioc_s_param(file, &vs4l_kvar.vsp); if (ret) vision_err("vertexioc_s_param (%d)\n", ret); put_vs4l_param64(&vs4l_kvar.vsp, (struct vs4l_param_list __user *)arg); break; case VS4L_VERTEXIOC_S_CTRL: ret = get_vs4l_ctrl64(&vs4l_kvar.vsc, (struct vs4l_ctrl __user *)arg); if (ret) { vision_err("get_vs4l_ctrl64 (%d)\n", ret); break; } ret = ops->vertexioc_s_ctrl(file, &vs4l_kvar.vsc); if (ret) vision_err("vertexioc_s_ctrl is fail(%d)\n", ret); put_vs4l_ctrl64(&vs4l_kvar.vsc, (struct vs4l_ctrl __user *)arg); break; case VS4L_VERTEXIOC_STREAM_ON: ret = ops->vertexioc_streamon(file); if (ret) vision_err("vertexioc_streamon failed(%d)\n", ret); vdev->tpf = 0; break; #ifdef CONFIG_NPU_USE_BOOT_IOCTL case VS4L_VERTEXIOC_BOOTUP: ret = get_vs4l_ctrl64(&vs4l_kvar.vsc, (struct vs4l_ctrl __user *)arg); ret = ops->vertexioc_bootup(file, &vs4l_kvar.vsc); if (ret) vision_err("vertexioc_bootup failed(%d)\n", ret); put_vs4l_ctrl64(&vs4l_kvar.vsc, (struct vs4l_ctrl __user *)arg); break; #endif case VS4L_VERTEXIOC_STREAM_OFF: ret = ops->vertexioc_streamoff(file); if (ret) vision_err("vertexioc_streamoff failed(%d)\n", ret); break; case VS4L_VERTEXIOC_QBUF: ret = get_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); if (ret) break; if (vs4l_kvar.vscl.timestamp[0].tv_sec && vs4l_kvar.vscl.timestamp[0].tv_usec) buf_time = now; if (p_flag == 1) vs4l_kvar.vscl.timestamp[5].tv_usec = p_flag; ret = ops->vertexioc_qbuf(file, &vs4l_kvar.vscl); if (ret) vision_err("vertexioc_qbuf failed(%d)\n", ret); put_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); break; case VS4L_VERTEXIOC_DQBUF: ret = get_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); if (ret) break; if (vs4l_kvar.vscl.timestamp[0].tv_sec && vs4l_kvar.vscl.timestamp[0].tv_usec) get_time = 1; ret = ops->vertexioc_dqbuf(file, &vs4l_kvar.vscl); if (ret != 0 && ret != -EWOULDBLOCK) vision_err("vertexioc_dqbuf failed(%d)\n", ret); put_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); if (get_time) { now = ktime_to_ns(ktime_get_boottime()); vdev->tpf = now - buf_time; get_time = 0; if (p_flag == 1) { npu_hw_time = vs4l_kvar.vscl.timestamp[5].tv_sec; dsp_hw_time = vs4l_kvar.vscl.timestamp[4].tv_sec; fw_time = vs4l_kvar.vscl.timestamp[4].tv_usec; } } break; case VS4L_VERTEXIOC_PREPARE: ret = get_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); if (ret) break; ret = ops->vertexioc_prepare(file, &vs4l_kvar.vscl); if (ret) vision_err("vertexioc_prepare failed(%d)\n", ret); put_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); break; case VS4L_VERTEXIOC_UNPREPARE: ret = get_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); if (ret) break; ret = ops->vertexioc_unprepare(file, &vs4l_kvar.vscl); if (ret) vision_err("vertexioc_unprepare failed(%d)\n", ret); put_vs4l_container64(&vs4l_kvar.vscl, (struct vs4l_container_list __user *)arg); break; case VS4L_VERTEXIOC_SCHED_PARAM: ret = get_vs4l_sched_param64(&vs4l_kvar.vsprm, (struct vs4l_sched_param __user *)arg); if (ret) break; ret = ops->vertexioc_sched_param(file, &vs4l_kvar.vsprm); if (ret) vision_err("vertexioc_sched_param failed(%d)\n", ret); put_vs4l_sched_param64(&vs4l_kvar.vsprm, (struct vs4l_sched_param __user *)arg); break; case VS4L_VERTEXIOC_PROFILE_ON: ret = get_vs4l_profiler(&vs4l_kvar.vspr, (struct vs4l_profiler __user *)arg); p_flag = vs4l_kvar.vspr.level; fw_time = 0; npu_hw_time = 0; dsp_hw_time = 0; if (ret) { vision_err("get_vs4l_profiler failed(%d)\n", ret); break; } ret = ops->vertexioc_profileon(file, &vs4l_kvar.vspr); if (ret) { vision_err("vertexioc_profileon failed(%d)\n", ret); break; } ret = put_vs4l_profiler(&vs4l_kvar.vspr, (struct vs4l_profiler __user *)arg); if (ret) vision_err("put_vs4l_profiler failed(%d)\n", ret); break; case VS4L_VERTEXIOC_PROFILE_OFF: ret = get_vs4l_profiler(&vs4l_kvar.vspr, (struct vs4l_profiler __user *)arg); if (ret) { vision_err("get_vs4l_profiler failed(%d)\n", ret); break; } ret = ops->vertexioc_profileoff(file, &vs4l_kvar.vspr); if (ret) { vision_err("vertexioc_profileoff failed(%d)\n", ret); break; } if (vs4l_kvar.vspr.node) { (*vs4l_kvar.vspr.node).duration = fw_time; if ((*vs4l_kvar.vspr.node).child != NULL) { (*vs4l_kvar.vspr.node).child[0]->duration = npu_hw_time; #ifdef CONFIG_DSP_USE_VS4L if ((*vs4l_kvar.vspr.node).child[1] != NULL) (*vs4l_kvar.vspr.node).child[1]->duration = dsp_hw_time; #endif } } ret = put_vs4l_profiler(&vs4l_kvar.vspr, (struct vs4l_profiler __user *)arg); p_flag = 0; if (ret) vision_err("put_vs4l_profiler failed(%d)\n", ret); break; case VS4L_VERTEXIOC_VERSION: ret = get_vs4l_version(&vs4l_kvar.vsvs, (struct vs4l_version __user *)arg); if (ret) { vision_err("get_vs4l_version failed(%d)\n", ret); break; } ret = ops->vertexioc_version(file, &vs4l_kvar.vsvs); if (ret) { vision_err("vertexioc_version failed(%d)\n", ret); break; } ret = put_vs4l_version(&vs4l_kvar.vsvs, (struct vs4l_version __user *)arg); if (ret) vision_err("put_vs4l_version failed(%d)\n", ret); break; #ifdef CONFIG_NPU_USE_FENCE_SYNC case VS4L_VERTEXIOC_SYNC: ret = get_vs4l_ctrl64(&vs4l_kvar.vsc, (struct vs4l_ctrl __user *)arg); ret = ops->vertexioc_sync(file, &vs4l_kvar.vsc); if (ret) vision_err("vertexioc_sync failed(%d)\n", ret); put_vs4l_ctrl64(&vs4l_kvar.vsc, (struct vs4l_ctrl __user *)arg); break; #endif default: vision_err("ioctl(%u) is not supported(usr arg: %lx)\n", cmd, arg); break; } npu_log_ioctl_set_date(cmd, 1); return ret; } long vertex_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { if (unlikely(!file->private_data)) { return -EWOULDBLOCK; } return __vertex_ioctl(file, cmd, arg); }