// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) Rockchip Electronics Co., Ltd. * * Author: Huang Lee */ #define pr_fmt(fmt) "rve_fence: " fmt #include #include #include #include "rve_fence.h" static const char *rve_fence_get_name(struct dma_fence *fence) { return DRIVER_NAME; } static const struct dma_fence_ops rve_fence_ops = { .get_driver_name = rve_fence_get_name, .get_timeline_name = rve_fence_get_name, }; struct rve_fence_context *rve_fence_context_alloc(void) { struct rve_fence_context *fence_ctx = NULL; fence_ctx = kzalloc(sizeof(*fence_ctx), GFP_KERNEL); if (!fence_ctx) return ERR_PTR(-ENOMEM); fence_ctx->context = dma_fence_context_alloc(1); spin_lock_init(&fence_ctx->spinlock); return fence_ctx; } void rve_fence_context_free(struct rve_fence_context *fence_ctx) { kfree(fence_ctx); } int rve_out_fence_alloc(struct rve_job *job) { struct rve_fence_context *fence_ctx = rve_drvdata->fence_ctx; struct dma_fence *fence = NULL; fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (!fence) return -ENOMEM; dma_fence_init(fence, &rve_fence_ops, &job->fence_lock, fence_ctx->context, ++fence_ctx->seqno); job->out_fence = fence; return 0; } int rve_out_fence_get_fd(struct rve_job *job) { struct sync_file *sync_file = NULL; int fence_fd = -1; if (!job->out_fence) return -EINVAL; fence_fd = get_unused_fd_flags(O_CLOEXEC); if (fence_fd < 0) return fence_fd; sync_file = sync_file_create(job->out_fence); if (!sync_file) return -ENOMEM; fd_install(fence_fd, sync_file->file); return fence_fd; } struct dma_fence *rve_get_input_fence(int in_fence_fd) { struct dma_fence *in_fence; in_fence = sync_file_get_fence(in_fence_fd); if (!in_fence) pr_err("can not get in-fence from fd\n"); return in_fence; } int rve_wait_input_fence(struct dma_fence *in_fence) { int ret = 0; ret = dma_fence_wait(in_fence, true); dma_fence_put(in_fence); return ret; } int rve_add_dma_fence_callback(struct rve_job *job, struct dma_fence *in_fence, dma_fence_func_t func) { struct rve_fence_waiter *waiter; int ret; waiter = kmalloc(sizeof(*waiter), GFP_KERNEL); if (!waiter) { pr_err("%s: Failed to allocate waiter\n", __func__); return -ENOMEM; } waiter->job = job; ret = dma_fence_add_callback(in_fence, &waiter->waiter, func); if (ret == -ENOENT) { pr_err("'input fence' has been already signaled."); goto err_free_waiter; } else if (ret == -EINVAL) { pr_err ("%s: failed to add callback to dma_fence, err: %d\n", __func__, ret); goto err_free_waiter; } return ret; err_free_waiter: kfree(waiter); return ret; }