From 77de161fdeae9fe954c0e37c0d3623d186da14a8 Mon Sep 17 00:00:00 2001 From: Yu Qiaowei Date: Wed, 15 Jun 2022 18:31:35 +0800 Subject: [PATCH] video: rockchip: rga3: batch mode supports asynchronous calls Signed-off-by: Yu Qiaowei Change-Id: I0d38d9a478a77a79d85cac0eb91906ebfae59544 --- .../video/rockchip/rga3/include/rga_fence.h | 4 +- drivers/video/rockchip/rga3/rga_drv.c | 20 ++++-- drivers/video/rockchip/rga3/rga_fence.c | 6 +- drivers/video/rockchip/rga3/rga_job.c | 65 +++++++++++-------- 4 files changed, 58 insertions(+), 37 deletions(-) diff --git a/drivers/video/rockchip/rga3/include/rga_fence.h b/drivers/video/rockchip/rga3/include/rga_fence.h index 9fc7f45f5dd9..61c43904aa58 100644 --- a/drivers/video/rockchip/rga3/include/rga_fence.h +++ b/drivers/video/rockchip/rga3/include/rga_fence.h @@ -25,7 +25,7 @@ struct rga_fence_waiter { int rga_fence_context_init(struct rga_fence_context **ctx); void rga_fence_context_remove(struct rga_fence_context **ctx); -struct dma_fence *rga_dma_fence_alloc(spinlock_t *lock); +struct dma_fence *rga_dma_fence_alloc(void); int rga_dma_fence_get_fd(struct dma_fence *fence); struct dma_fence *rga_get_dma_fence_from_fd(int fence_fd); int rga_dma_fence_wait(struct dma_fence *fence); @@ -50,7 +50,7 @@ static inline int rga_dma_fence_get_status(struct dma_fence *fence) } #else -static inline struct dma_fence *rga_dma_fence_alloc(spinlock_t *lock) +static inline struct dma_fence *rga_dma_fence_alloc(void) { return NULL; } diff --git a/drivers/video/rockchip/rga3/rga_drv.c b/drivers/video/rockchip/rga3/rga_drv.c index a317eef77196..4fe2ba73540f 100644 --- a/drivers/video/rockchip/rga3/rga_drv.c +++ b/drivers/video/rockchip/rga3/rga_drv.c @@ -729,11 +729,18 @@ static long rga_ioctl_request_submit(unsigned long arg, bool run_enbale) return -EFAULT; } - if (request->sync_mode == RGA_BLIT_SYNC) { - mutex_lock(&request_manager->lock); - rga_request_put(request); - mutex_unlock(&request_manager->lock); + if (request->sync_mode == RGA_BLIT_ASYNC) { + user_request.release_fence_fd = request->release_fence_fd; + if (copy_to_user((struct rga_req *)arg, + &user_request, sizeof(user_request))) { + pr_err("copy_to_user failed\n"); + return -EFAULT; + } } + + mutex_lock(&request_manager->lock); + rga_request_put(request); + mutex_unlock(&request_manager->lock); } return 0; @@ -813,12 +820,14 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg) memset(&request, 0x0, sizeof(request)); request.sync_mode = cmd; + request.acquire_fence_fd = req_rga.in_fence_fd; request.use_batch_mode = false; + request.is_running = false; request.session = session; request.task_list = &req_rga; request.task_count = 1; - ret = rga_request_commit(&request); + ret = rga_request_submit(&request); if (ret < 0) { if (ret == -ERESTARTSYS) { if (DEBUGGER_EN(MSG)) @@ -830,6 +839,7 @@ static long rga_ioctl(struct file *file, uint32_t cmd, unsigned long arg) break; } + req_rga.out_fence_fd = request.release_fence_fd; if (copy_to_user((struct rga_req *)arg, &req_rga, sizeof(struct rga_req))) { pr_err("copy_to_user failed\n"); diff --git a/drivers/video/rockchip/rga3/rga_fence.c b/drivers/video/rockchip/rga3/rga_fence.c index f25a4cd382c3..0e1f58fed9c1 100644 --- a/drivers/video/rockchip/rga3/rga_fence.c +++ b/drivers/video/rockchip/rga3/rga_fence.c @@ -51,7 +51,7 @@ void rga_fence_context_remove(struct rga_fence_context **ctx) *ctx = NULL; } -struct dma_fence *rga_dma_fence_alloc(spinlock_t *lock) +struct dma_fence *rga_dma_fence_alloc(void) { struct rga_fence_context *fence_ctx = rga_drvdata->fence_ctx; struct dma_fence *fence = NULL; @@ -65,8 +65,8 @@ struct dma_fence *rga_dma_fence_alloc(spinlock_t *lock) if (!fence) return ERR_PTR(-ENOMEM); - dma_fence_init(fence, &rga_fence_ops, lock, - fence_ctx->context, ++fence_ctx->seqno); + dma_fence_init(fence, &rga_fence_ops, &fence_ctx->spinlock, + fence_ctx->context, ++fence_ctx->seqno); return fence; } diff --git a/drivers/video/rockchip/rga3/rga_job.c b/drivers/video/rockchip/rga3/rga_job.c index 3370754d955e..d6eb80c76d8e 100644 --- a/drivers/video/rockchip/rga3/rga_job.c +++ b/drivers/video/rockchip/rga3/rga_job.c @@ -112,8 +112,6 @@ static void rga_job_put_current_mm(struct rga_job *job) static void rga_job_free(struct rga_job *job) { - rga_dma_fence_put(job->out_fence); - if (~job->flags & RGA_JOB_USE_HANDLE) rga_job_put_current_mm(job); @@ -581,11 +579,11 @@ static inline int rga_job_wait(struct rga_job *job) return ret; } -static int rga_job_alloc_release_fence(struct dma_fence **release_fence, spinlock_t *lock) +static int rga_job_alloc_release_fence(struct dma_fence **release_fence) { struct dma_fence *fence; - fence = rga_dma_fence_alloc(lock); + fence = rga_dma_fence_alloc(); if (IS_ERR(fence)) { pr_err("Can not alloc release fence!\n"); return IS_ERR(fence); @@ -606,9 +604,10 @@ static int rga_job_add_acquire_fence_callback(int acquire_fence_fd, void *privat pr_info("acquire_fence_fd = %d", acquire_fence_fd); acquire_fence = rga_get_dma_fence_from_fd(acquire_fence_fd); - if (IS_ERR(acquire_fence)) { - pr_err("%s: failed to get acquire dma_fence\n", __func__); - return PTR_ERR(acquire_fence); + if (IS_ERR_OR_NULL(acquire_fence)) { + pr_err("%s: failed to get acquire dma_fence from[%d]\n", + __func__, acquire_fence_fd); + return -EINVAL; } /* close acquire fence fd */ ksys_close(acquire_fence_fd); @@ -645,6 +644,7 @@ struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_requ job->use_batch_mode = request->use_batch_mode; job->request_id = request->id; job->session = request->session; + job->out_fence = request->release_fence; if (!(job->flags & RGA_JOB_USE_HANDLE)) { ret = rga_mm_get_external_buffer(job); @@ -804,16 +804,6 @@ int rga_request_commit(struct rga_request *request) int i = 0; struct rga_job *job = NULL; - if (request->sync_mode == RGA_BLIT_ASYNC) { - ret = rga_job_alloc_release_fence(&request->release_fence, &request->fence_lock); - if (ret < 0) { - pr_err("Failed to alloc release fence fd!\n"); - return ret; - } - - request->release_fence_fd = ret; - } - if (request->use_batch_mode) { for (i = 0; i < request->task_count; i++) { job = rga_job_commit(&(request->task_list[i]), request); @@ -958,10 +948,12 @@ struct rga_request *rga_request_config(struct rga_user_request *user_request) spin_lock_irqsave(&request->lock, flags); + request->use_batch_mode = true; request->task_list = task_list; request->task_count = user_request->task_num; request->sync_mode = user_request->sync_mode; request->mpi_config_flags = user_request->mpi_config_flags; + request->acquire_fence_fd = user_request->acquire_fence_fd; spin_unlock_irqrestore(&request->lock, flags); @@ -990,30 +982,47 @@ int rga_request_submit(struct rga_request *request) return -EINVAL; } - request->use_batch_mode = true; request->is_running = true; spin_unlock_irqrestore(&request->lock, flags); - if (request->sync_mode == RGA_BLIT_ASYNC && request->acquire_fence_fd > 0) { - ret = rga_job_add_acquire_fence_callback(request->acquire_fence_fd, - (void *)request, - rga_request_acquire_fence_signaled_cb); - if (ret == 1) { - goto request_commit; - } else { - pr_err("Failed to wait acquire fence fd[%d]!\n", request->acquire_fence_fd); + if (request->sync_mode == RGA_BLIT_ASYNC) { + ret = rga_job_alloc_release_fence(&request->release_fence); + if (ret < 0) { + pr_err("Failed to alloc release fence fd!\n"); return ret; } + request->release_fence_fd = ret; + + if (request->acquire_fence_fd > 0) { + ret = rga_job_add_acquire_fence_callback( + request->acquire_fence_fd, + (void *)request, + rga_request_acquire_fence_signaled_cb); + if (ret == 0) { + return ret; + } else if (ret == 1) { + goto request_commit; + } else { + pr_err("Failed to add callback with acquire fence fd[%d]!\n", + request->acquire_fence_fd); + goto error_release_fence_put; + } + } + } request_commit: ret = rga_request_commit(request); if (ret < 0) { pr_err("rga request commit failed!\n"); - return ret; + goto error_release_fence_put; } + return 0; + +error_release_fence_put: + rga_dma_fence_put(request->release_fence); return ret; } @@ -1067,6 +1076,8 @@ static void rga_request_kref_release(struct kref *ref) spin_lock_irqsave(&request->lock, flags); + rga_dma_fence_put(request->release_fence); + if (!request->is_running || request->finished_task_count >= request->task_count) { spin_unlock_irqrestore(&request->lock, flags); goto free_request;