From 41e9ffebc838e020f0bf842123d55108a7363fe7 Mon Sep 17 00:00:00 2001 From: Felix Zeng Date: Sat, 23 Apr 2022 15:51:38 +0800 Subject: [PATCH] driver: rknpu: Update rknpu driver, version: 0.7.2 Signed-off-by: Felix Zeng Change-Id: I4959bf36fac74d590e651afdccba2dd2d8a856e9 --- drivers/rknpu/include/rknpu_debugger.h | 6 +- drivers/rknpu/include/rknpu_drv.h | 7 +- drivers/rknpu/include/rknpu_ioctl.h | 4 - drivers/rknpu/rknpu_debugger.c | 58 ++++++++++++ drivers/rknpu/rknpu_drv.c | 58 +++++++++--- drivers/rknpu/rknpu_gem.c | 11 ++- drivers/rknpu/rknpu_job.c | 126 ++++++------------------- drivers/rknpu/rknpu_mem.c | 69 +++++++++++--- 8 files changed, 199 insertions(+), 140 deletions(-) diff --git a/drivers/rknpu/include/rknpu_debugger.h b/drivers/rknpu/include/rknpu_debugger.h index ef1cd44d6ea3..61369706690b 100644 --- a/drivers/rknpu/include/rknpu_debugger.h +++ b/drivers/rknpu/include/rknpu_debugger.h @@ -48,8 +48,8 @@ struct rknpu_debugger_list { * rknpu_debugger_node corresponding to the instance of this info * on a given &struct rknpu_debugger. */ - ssize_t (*write)(struct file *file, const char __user *ubuf, - size_t len, loff_t *offp); + ssize_t (*write)(struct file *file, const char __user *ubuf, size_t len, + loff_t *offp); /* Procfs/Debugfs private data. */ void *data; }; @@ -78,9 +78,7 @@ struct rknpu_debugger_node { struct list_head list; }; - int rknpu_debugger_init(struct rknpu_device *rknpu_dev); int rknpu_debugger_remove(struct rknpu_device *rknpu_dev); - #endif /* __LINUX_RKNPU_FENCE_H_ */ diff --git a/drivers/rknpu/include/rknpu_drv.h b/drivers/rknpu/include/rknpu_drv.h index f9d776e4b11e..57979f9b9dfb 100644 --- a/drivers/rknpu/include/rknpu_drv.h +++ b/drivers/rknpu/include/rknpu_drv.h @@ -29,10 +29,10 @@ #define DRIVER_NAME "rknpu" #define DRIVER_DESC "RKNPU driver" -#define DRIVER_DATE "20220328" +#define DRIVER_DATE "20220428" #define DRIVER_MAJOR 0 #define DRIVER_MINOR 7 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_PATCHLEVEL 2 #define LOG_TAG "RKNPU" @@ -135,6 +135,7 @@ struct rknpu_device { struct device *genpd_dev_npu2; bool multiple_domains; atomic_t power_refcount; + atomic_t cmdline_power_refcount; struct delayed_work power_off_work; struct workqueue_struct *power_off_wq; bool is_powered; @@ -143,4 +144,6 @@ struct rknpu_device { ktime_t kt; }; +int rknpu_action(struct rknpu_device *rknpu_dev, struct rknpu_action *args); + #endif /* __LINUX_RKNPU_DRV_H_ */ diff --git a/drivers/rknpu/include/rknpu_ioctl.h b/drivers/rknpu/include/rknpu_ioctl.h index a8f727c23d75..43ab93d5ce83 100644 --- a/drivers/rknpu/include/rknpu_ioctl.h +++ b/drivers/rknpu/include/rknpu_ioctl.h @@ -287,8 +287,6 @@ struct rknpu_action { #define RKNPU_IOR(nr, type) _IOR(RKNPU_IOC_MAGIC, nr, type) #define RKNPU_IOWR(nr, type) _IOWR(RKNPU_IOC_MAGIC, nr, type) -#if defined(__arm__) || defined(__aarch64__) - #include #define DRM_IOCTL_RKNPU_ACTION \ @@ -314,5 +312,3 @@ struct rknpu_action { #define IOCTL_RKNPU_MEM_SYNC RKNPU_IOWR(RKNPU_MEM_SYNC, struct rknpu_mem_sync) #endif - -#endif diff --git a/drivers/rknpu/rknpu_debugger.c b/drivers/rknpu/rknpu_debugger.c index 74367817a283..585983bf2ce0 100644 --- a/drivers/rknpu/rknpu_debugger.c +++ b/drivers/rknpu/rknpu_debugger.c @@ -64,9 +64,67 @@ static int rknpu_load_show(struct seq_file *m, void *data) return 0; } +static int rknpu_power_show(struct seq_file *m, void *data) +{ + struct rknpu_debugger_node *node = m->private; + struct rknpu_debugger *debugger = node->debugger; + struct rknpu_device *rknpu_dev = + container_of(debugger, struct rknpu_device, debugger); + + if (rknpu_dev->is_powered) + seq_puts(m, "on\n"); + else + seq_puts(m, "off\n"); + + return 0; +} + +static ssize_t rknpu_power_set(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *priv = file->private_data; + struct rknpu_debugger_node *node = priv->private; + struct rknpu_debugger *debugger = node->debugger; + struct rknpu_device *rknpu_dev = + container_of(debugger, struct rknpu_device, debugger); + struct rknpu_action args; + char buf[10]; + + if (len > sizeof(buf) - 1) + return -EINVAL; + if (copy_from_user(buf, ubuf, len)) + return -EFAULT; + buf[len - 1] = '\0'; + + if (strcmp(buf, "on") == 0) { + atomic_inc(&rknpu_dev->cmdline_power_refcount); + args.flags = RKNPU_POWER_ON; + rknpu_action(rknpu_dev, &args); + LOG_INFO("rknpu power is on!"); + } else if (strcmp(buf, "off") == 0) { + if (rknpu_dev->is_powered && + atomic_dec_if_positive( + &rknpu_dev->cmdline_power_refcount) >= 0) { + atomic_sub( + atomic_read(&rknpu_dev->cmdline_power_refcount), + &rknpu_dev->power_refcount); + atomic_set(&rknpu_dev->cmdline_power_refcount, 0); + args.flags = RKNPU_POWER_OFF; + rknpu_action(rknpu_dev, &args); + } + if (!rknpu_dev->is_powered) + LOG_INFO("rknpu power is off!"); + } else { + LOG_ERROR("rknpu power node params is invalid!"); + } + + return len; +} + struct rknpu_debugger_list rknpu_debugger_root_list[] = { { "driver_version", rknpu_version_show, NULL, NULL }, { "load", rknpu_load_show, NULL, NULL }, + { "power", rknpu_power_show, rknpu_power_set, NULL } }; static ssize_t rknpu_debugger_write(struct file *file, const char __user *ubuf, diff --git a/drivers/rknpu/rknpu_drv.c b/drivers/rknpu/rknpu_drv.c index 6c9235f77439..b37a36eb6e7b 100644 --- a/drivers/rknpu/rknpu_drv.c +++ b/drivers/rknpu/rknpu_drv.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,9 @@ #include #include #include -#include #ifndef FPGA_PLATFORM +#include #include #include #include @@ -190,8 +191,7 @@ static void rknpu_power_off_delay_work(struct work_struct *power_off_work) mutex_unlock(&rknpu_dev->power_lock); } -static int rknpu_action(struct rknpu_device *rknpu_dev, - struct rknpu_action *args) +int rknpu_action(struct rknpu_device *rknpu_dev, struct rknpu_action *args) { int ret = -EINVAL; @@ -612,11 +612,15 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev) return ret; } +#ifndef FPGA_PLATFORM +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE rockchip_monitor_volt_adjust_lock(rknpu_dev->mdev_info); +#endif +#endif if (rknpu_dev->multiple_domains) { if (rknpu_dev->genpd_dev_npu0) { -#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE +#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE ret = pm_runtime_resume_and_get( rknpu_dev->genpd_dev_npu0); #else @@ -631,7 +635,7 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev) } } if (rknpu_dev->genpd_dev_npu1) { -#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE +#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE ret = pm_runtime_resume_and_get( rknpu_dev->genpd_dev_npu1); #else @@ -646,7 +650,7 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev) } } if (rknpu_dev->genpd_dev_npu2) { -#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE +#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE ret = pm_runtime_resume_and_get( rknpu_dev->genpd_dev_npu2); #else @@ -669,7 +673,11 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev) } out: +#ifndef FPGA_PLATFORM +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info); +#endif +#endif return ret; } @@ -677,13 +685,19 @@ out: static int rknpu_power_off(struct rknpu_device *rknpu_dev) { struct device *dev = rknpu_dev->dev; + +#ifndef FPGA_PLATFORM int ret; bool val; +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE rockchip_monitor_volt_adjust_lock(rknpu_dev->mdev_info); +#endif +#endif pm_runtime_put_sync(dev); +#ifndef FPGA_PLATFORM /* * Because IOMMU's runtime suspend callback is asynchronous, * So it may be executed after the NPU is turned off after PD/CLK/VD, @@ -693,16 +707,21 @@ static int rknpu_power_off(struct rknpu_device *rknpu_dev) * If pm runtime framework can handle this issue in the future, remove * this. */ - - ret = readx_poll_timeout(rockchip_iommu_is_enabled, dev, val, - !val, NPU_MMU_DISABLED_POLL_PERIOD_US, + ret = readx_poll_timeout(rockchip_iommu_is_enabled, dev, val, !val, + NPU_MMU_DISABLED_POLL_PERIOD_US, NPU_MMU_DISABLED_POLL_TIMEOUT_US); if (ret) { - dev_err(dev, "iommu still enabled\n"); + LOG_DEV_ERROR(dev, "iommu still enabled\n"); pm_runtime_get_sync(dev); +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info); +#endif return ret; } +#else + if (rknpu_dev->iommu_en) + msleep(20); +#endif if (rknpu_dev->multiple_domains) { if (rknpu_dev->genpd_dev_npu2) @@ -713,7 +732,11 @@ static int rknpu_power_off(struct rknpu_device *rknpu_dev) pm_runtime_put_sync(rknpu_dev->genpd_dev_npu0); } +#ifndef FPGA_PLATFORM +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info); +#endif +#endif clk_bulk_disable_unprepare(rknpu_dev->num_clks, rknpu_dev->clks); @@ -838,7 +861,8 @@ restore_freq: restore_rm: rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt, &target_rm); - rockchip_set_read_margin(dev, opp_info, opp_info->current_rm, is_set_rm); + rockchip_set_read_margin(dev, opp_info, opp_info->current_rm, + is_set_rm); restore_voltage: regulator_set_voltage(mem_reg, old_supply_mem->u_volt, INT_MAX); regulator_set_voltage(vdd_reg, old_supply_vdd->u_volt, INT_MAX); @@ -864,7 +888,9 @@ static int npu_devfreq_target(struct device *dev, unsigned long *freq, opp_volt = dev_pm_opp_get_voltage(opp); dev_pm_opp_put(opp); +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE rockchip_monitor_volt_adjust_lock(rknpu_dev->mdev_info); +#endif ret = dev_pm_opp_set_rate(dev, *freq); if (!ret) { rknpu_dev->current_freq = *freq; @@ -873,7 +899,9 @@ static int npu_devfreq_target(struct device *dev, unsigned long *freq, *freq; rknpu_dev->current_volt = opp_volt; } +#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info); +#endif return ret; } @@ -1015,7 +1043,8 @@ static int rk3588_npu_set_read_margin(struct device *dev, for (i = 0; i < 3; i++) { ret = regmap_read(opp_info->grf, offset, &val); if (ret < 0) { - dev_err(dev, "failed to get rm from 0x%x\n", offset); + LOG_DEV_ERROR(dev, "failed to get rm from 0x%x\n", + offset); return ret; } val &= ~0x1c; @@ -1526,9 +1555,10 @@ static int rknpu_probe(struct platform_device *pdev) } INIT_DEFERRABLE_WORK(&rknpu_dev->power_off_work, rknpu_power_off_delay_work); + rknpu_power_off(rknpu_dev); rknpu_dev->is_powered = false; atomic_set(&rknpu_dev->power_refcount, 0); - rknpu_power_off(rknpu_dev); + atomic_set(&rknpu_dev->cmdline_power_refcount, 0); rknpu_debugger_init(rknpu_dev); rknpu_init_timer(rknpu_dev); @@ -1647,7 +1677,7 @@ static struct platform_driver rknpu_driver = { .owner = THIS_MODULE, .name = "RKNPU", #ifndef FPGA_PLATFORM -#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE +#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE .pm = &rknpu_pm_ops, #endif #endif diff --git a/drivers/rknpu/rknpu_gem.c b/drivers/rknpu/rknpu_gem.c index 0fd8204268a7..5b7ff5267092 100644 --- a/drivers/rknpu/rknpu_gem.c +++ b/drivers/rknpu/rknpu_gem.c @@ -56,14 +56,13 @@ static int rknpu_gem_get_pages(struct rknpu_gem_object *rknpu_obj) goto free_sgt; } - dma_sync_sg_for_device(drm->dev, rknpu_obj->sgt->sgl, - rknpu_obj->sgt->nents, DMA_TO_DEVICE); - if (rknpu_obj->flags & RKNPU_MEM_KERNEL_MAPPING) { rknpu_obj->cookie = vmap(rknpu_obj->pages, rknpu_obj->num_pages, VM_MAP, PAGE_KERNEL); - if (!rknpu_obj->cookie) + if (!rknpu_obj->cookie) { + ret = -ENOMEM; goto unmap_sg; + } rknpu_obj->kv_addr = rknpu_obj->cookie; } @@ -97,8 +96,10 @@ static void rknpu_gem_put_pages(struct rknpu_gem_object *rknpu_obj) { struct drm_device *drm = rknpu_obj->base.dev; - if (rknpu_obj->flags & RKNPU_MEM_KERNEL_MAPPING) + if (rknpu_obj->flags & RKNPU_MEM_KERNEL_MAPPING) { vunmap(rknpu_obj->kv_addr); + rknpu_obj->kv_addr = NULL; + } dma_unmap_sg(drm->dev, rknpu_obj->sgt->sgl, rknpu_obj->sgt->nents, DMA_BIDIRECTIONAL); diff --git a/drivers/rknpu/rknpu_job.c b/drivers/rknpu/rknpu_job.c index 8d4de7322ecf..0232b4541b0b 100644 --- a/drivers/rknpu/rknpu_job.c +++ b/drivers/rknpu/rknpu_job.c @@ -39,9 +39,23 @@ static int rknpu_core_index(int core_mask) static int rknpu_core_mask(int core_index) { - int core_mask[3] = { RKNPU_CORE0_MASK, RKNPU_CORE1_MASK, - RKNPU_CORE2_MASK }; - return core_mask[core_index]; + int core_mask = RKNPU_CORE_AUTO_MASK; + + switch (core_index) { + case 0: + core_mask = RKNPU_CORE0_MASK; + break; + case 1: + core_mask = RKNPU_CORE1_MASK; + break; + case 2: + core_mask = RKNPU_CORE2_MASK; + break; + default: + break; + } + + return core_mask; } static int rknn_get_task_number(struct rknpu_job *job, int core_index) @@ -577,12 +591,9 @@ static void rknpu_job_timeout_clean(struct rknpu_device *rknpu_dev, } } -#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM -int rknpu_submit_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int rknpu_submit(struct rknpu_device *rknpu_dev, + struct rknpu_submit *args) { - struct rknpu_device *rknpu_dev = dev_get_drvdata(dev->dev); - struct rknpu_submit *args = data; struct rknpu_job *job = NULL; int ret = -EINVAL; @@ -676,13 +687,22 @@ int rknpu_submit_ioctl(struct drm_device *dev, void *data, return ret; } + +#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM +int rknpu_submit_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct rknpu_device *rknpu_dev = dev_get_drvdata(dev->dev); + struct rknpu_submit *args = data; + + return rknpu_submit(rknpu_dev, args); +} #endif #ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP int rknpu_submit_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) { struct rknpu_submit args; - struct rknpu_job *job = NULL; int ret = -EINVAL; if (unlikely(copy_from_user(&args, (struct rknpu_submit *)data, @@ -692,93 +712,7 @@ int rknpu_submit_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) return ret; } - if (args.task_number == 0) { - LOG_ERROR("invalid rknpu task number!\n"); - return -EINVAL; - } - - job = rknpu_job_alloc(rknpu_dev, &args); - if (!job) { - LOG_ERROR("failed to allocate rknpu job!\n"); - return -ENOMEM; - } - - if (args.flags & RKNPU_JOB_FENCE_IN) { -#ifdef CONFIG_ROCKCHIP_RKNPU_FENCE - struct dma_fence *in_fence; - - in_fence = sync_file_get_fence(args.fence_fd); - - if (!in_fence) { - LOG_ERROR("invalid fence in fd, fd = %d\n", - args.fence_fd); - return -EINVAL; - } - args.fence_fd = -1; - - /* - * Wait if the fence is from a foreign context, or if the fence - * array contains any fence from a foreign context. - */ - ret = 0; - if (!dma_fence_match_context(in_fence, - rknpu_dev->fence_ctx->context)) - ret = dma_fence_wait_timeout(in_fence, true, - args.timeout); - dma_fence_put(in_fence); - if (ret < 0) { - if (ret != -ERESTARTSYS) - LOG_ERROR("Error (%d) waiting for fence!\n", - ret); - - return ret; - } -#else - LOG_ERROR( - "failed to use rknpu fence, please enable rknpu fence config!\n"); - rknpu_job_free(job); - return -EINVAL; -#endif - } - - if (args.flags & RKNPU_JOB_FENCE_OUT) { -#ifdef CONFIG_ROCKCHIP_RKNPU_FENCE - ret = rknpu_fence_alloc(job); - if (ret) { - rknpu_job_free(job); - return ret; - } - job->args->fence_fd = rknpu_fence_get_fd(job); - args.fence_fd = job->args->fence_fd; -#else - LOG_ERROR( - "failed to use rknpu fence, please enable rknpu fence config!\n"); - rknpu_job_free(job); - return -EINVAL; -#endif - } - - if (args.flags & RKNPU_JOB_NONBLOCK) { - job->flags |= RKNPU_JOB_ASYNC; - rknpu_job_timeout_clean(rknpu_dev, job->args->core_mask); - rknpu_job_schedule(job); - ret = job->ret; - if (ret) { - rknpu_job_abort(job); - return ret; - } - } else { - rknpu_job_schedule(job); - if (args.flags & RKNPU_JOB_PC) - job->ret = rknpu_job_wait(job); - - args.task_counter = job->args->task_counter; - ret = job->ret; - if (!ret) - rknpu_job_cleanup(job); - else - rknpu_job_abort(job); - } + ret = rknpu_submit(rknpu_dev, &args); if (unlikely(copy_to_user((struct rknpu_submit *)data, &args, sizeof(struct rknpu_submit)))) { diff --git a/drivers/rknpu/rknpu_mem.c b/drivers/rknpu/rknpu_mem.c index 539d7c1ae6cf..b8ba36b27a29 100644 --- a/drivers/rknpu/rknpu_mem.c +++ b/drivers/rknpu/rknpu_mem.c @@ -40,13 +40,13 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) if (args.flags & RKNPU_MEM_NON_CONTIGUOUS) { LOG_ERROR("%s: malloc iommu memory unsupported in current!\n", __func__); - ret = -EFAULT; + ret = -EINVAL; return ret; } rknpu_obj = kzalloc(sizeof(*rknpu_obj), GFP_KERNEL); if (!rknpu_obj) - return PTR_ERR(rknpu_obj); + return -ENOMEM; if (args.handle > 0) { fd = args.handle; @@ -64,8 +64,10 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) dmabuf = rk_dma_heap_buffer_alloc(rknpu_dev->heap, args.size, O_CLOEXEC | O_RDWR, 0x0, dev_name(rknpu_dev->dev)); - if (IS_ERR(dmabuf)) - return PTR_ERR(dmabuf); + if (IS_ERR(dmabuf)) { + ret = PTR_ERR(dmabuf); + goto err_free_obj; + } rknpu_obj->dmabuf = dmabuf; rknpu_obj->owner = 1; @@ -85,6 +87,7 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) table = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL); if (IS_ERR(table)) { + dma_buf_detach(dmabuf, attachment); ret = PTR_ERR(table); goto err_free_dma_buf; } @@ -92,21 +95,26 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) for_each_sgtable_sg(table, sgl, i) { phys = sg_dma_address(sgl); page = sg_page(sgl); - LOG_DEBUG("%s, %d, phys = %pad, length = 0x%x\n", __func__, - __LINE__, &phys, sg_dma_len(sgl)); length = sg_dma_len(sgl); + LOG_DEBUG("%s, %d, phys = %pad, length = 0x%x\n", __func__, + __LINE__, &phys, length); } page_count = length >> PAGE_SHIFT; pages = kmalloc_array(page_count, sizeof(struct page), GFP_KERNEL); + if (!pages) { + ret = -ENOMEM; + goto err_detach_dma_buf; + } + for (i = 0; i < page_count; i++) pages[i] = &page[i]; rknpu_obj->kv_addr = vmap(pages, page_count, VM_MAP, PAGE_KERNEL); - kfree(pages); - - dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL); - dma_buf_detach(dmabuf, attachment); + if (!rknpu_obj->kv_addr) { + ret = -ENOMEM; + goto err_free_pages; + } rknpu_obj->size = PAGE_ALIGN(args.size); rknpu_obj->dma_addr = phys; @@ -126,18 +134,35 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) sizeof(struct rknpu_mem_create)))) { LOG_ERROR("%s: copy_to_user failed\n", __func__); ret = -EFAULT; - goto err_free_dma_buf; + goto err_unmap_kv_addr; } + + kfree(pages); + dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL); + dma_buf_detach(dmabuf, attachment); + return 0; +err_unmap_kv_addr: + vunmap(rknpu_obj->kv_addr); + rknpu_obj->kv_addr = NULL; + +err_free_pages: + kfree(pages); + +err_detach_dma_buf: + dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL); + dma_buf_detach(dmabuf, attachment); + err_free_dma_buf: - dma_buf_put(dmabuf); if (rknpu_obj->owner) rk_dma_heap_buffer_free(dmabuf); - return ret; + else + dma_buf_put(dmabuf); err_free_obj: kfree(rknpu_obj); + return ret; } @@ -156,8 +181,9 @@ int rknpu_mem_destroy_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) } if (!kern_addr_valid(args.obj_addr)) { - LOG_ERROR("%s: invalid params, unknown obj_addr\n", __func__); - ret = -EFAULT; + LOG_ERROR("%s: invalid obj_addr: %#llx\n", __func__, + (__u64)(uintptr_t)args.obj_addr); + ret = -EINVAL; return ret; } @@ -169,6 +195,12 @@ int rknpu_mem_destroy_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) (__u64)rknpu_obj->dma_addr); vunmap(rknpu_obj->kv_addr); + rknpu_obj->kv_addr = NULL; + + if (rknpu_obj->owner) + rk_dma_heap_buffer_free(dmabuf); + else + dma_buf_put(dmabuf); kfree(rknpu_obj); @@ -189,6 +221,13 @@ int rknpu_mem_sync_ioctl(struct rknpu_device *rknpu_dev, unsigned long data) return ret; } + if (!kern_addr_valid(args.obj_addr)) { + LOG_ERROR("%s: invalid obj_addr: %#llx\n", __func__, + (__u64)(uintptr_t)args.obj_addr); + ret = -EINVAL; + return ret; + } + rknpu_obj = (struct rknpu_mem_object *)(uintptr_t)args.obj_addr; dmabuf = rknpu_obj->dmabuf;