video: rockchip: rve: support rve session

Signed-off-by: Li Huang <putin.li@rock-chips.com>
Change-Id: Ic141815933c5cdd4832b0581ceab1f6c69aa315f
This commit is contained in:
Li Huang 2022-04-20 16:55:57 +08:00 committed by Tao Huang
parent 31443cb761
commit cc9f3d2606
4 changed files with 204 additions and 35 deletions

View File

@ -116,9 +116,16 @@ struct rve_fence_waiter {
struct rve_scheduler_t;
struct rve_internal_ctx_t;
struct rve_session {
int id;
pid_t tgid;
};
struct rve_job {
struct list_head head;
struct rve_scheduler_t *scheduler;
struct rve_session *session;
struct rve_cmd_reg_array_t *regcmd_data;
@ -220,6 +227,7 @@ struct rve_ctx_debug_info_t {
struct rve_internal_ctx_t {
struct rve_scheduler_t *scheduler;
struct rve_session *session;
struct rve_cmd_reg_array_t *regcmd_data;
uint32_t cmd_num;
@ -260,6 +268,14 @@ struct rve_pending_ctx_manager {
int ctx_count;
};
struct rve_session_manager {
struct mutex lock;
struct idr ctx_id_idr;
int session_cnt;
};
struct rve_drvdata_t {
struct rve_fence_context *fence_ctx;
@ -277,6 +293,8 @@ struct rve_drvdata_t {
/* rve_job pending manager, import by RVE_IOC_START_CONFIG */
struct rve_pending_ctx_manager *pend_ctx_manager;
struct rve_session_manager *session_manager;
#ifdef CONFIG_ROCKCHIP_RVE_DEBUGGER
struct rve_debugger *debugger;
#endif

View File

@ -27,16 +27,18 @@ struct rve_internal_ctx_t *rve_job_get_internal_ctx(struct rve_job *job);
void rve_job_done(struct rve_scheduler_t *rve_scheduler, int ret);
int rve_job_commit(struct rve_internal_ctx_t *ctx);
int rve_ctx_manager_init(struct rve_pending_ctx_manager **ctx_manager_session);
int rve_ctx_manager_remove(struct rve_pending_ctx_manager **ctx_manager_session);
int rve_internal_ctx_alloc_to_get_idr_id(void);
void rve_internal_ctx_kref_release(struct kref *ref);
int rve_job_config_by_user_ctx(struct rve_user_ctx_t *user_ctx);
int rve_job_commit_by_user_ctx(struct rve_user_ctx_t *user_ctx);
int rve_job_cancel_by_user_ctx(uint32_t ctx_id);
void rve_job_session_destroy(struct rve_session *session);
int rve_ctx_manager_init(struct rve_pending_ctx_manager **ctx_manager_session);
int rve_ctx_manager_remove(struct rve_pending_ctx_manager **ctx_manager_session);
int rve_internal_ctx_alloc_to_get_idr_id(struct rve_session *session);
void rve_internal_ctx_kref_release(struct kref *ref);
struct rve_job *
rve_scheduler_get_pending_job_list(struct rve_scheduler_t *scheduler);

View File

@ -157,12 +157,140 @@ int rve_power_disable(struct rve_scheduler_t *scheduler)
#endif //RVE_PD_AWAYS_ON
static long rve_ioctl_cmd_start(unsigned long arg)
static int rve_session_manager_init(struct rve_session_manager **session_manager_ptr)
{
struct rve_session_manager *session_manager = NULL;
*session_manager_ptr = kzalloc(sizeof(struct rve_session_manager), GFP_KERNEL);
if (*session_manager_ptr == NULL) {
pr_err("can not kzalloc for rve_session_manager\n");
return -ENOMEM;
}
session_manager = *session_manager_ptr;
mutex_init(&session_manager->lock);
idr_init_base(&session_manager->ctx_id_idr, 1);
return 0;
}
/*
* Called at driver close to release the rve session's id references.
*/
static int rve_session_free_remove_idr_cb(int id, void *ptr, void *data)
{
struct rve_session *session = ptr;
idr_remove(&rve_drvdata->session_manager->ctx_id_idr, session->id);
kfree(session);
return 0;
}
static int rve_session_free_remove_idr(struct rve_session *session)
{
struct rve_session_manager *session_manager;
session_manager = rve_drvdata->session_manager;
mutex_lock(&session_manager->lock);
session_manager->session_cnt--;
idr_remove(&session_manager->ctx_id_idr, session->id);
mutex_unlock(&session_manager->lock);
return 0;
}
static int rve_session_manager_remove(struct rve_session_manager **session_manager_ptr)
{
struct rve_session_manager *session_manager = *session_manager_ptr;
mutex_lock(&session_manager->lock);
idr_for_each(&session_manager->ctx_id_idr, &rve_session_free_remove_idr_cb, session_manager);
idr_destroy(&session_manager->ctx_id_idr);
mutex_unlock(&session_manager->lock);
kfree(*session_manager_ptr);
*session_manager_ptr = NULL;
return 0;
}
static struct rve_session *rve_session_init(void)
{
struct rve_session_manager *session_manager = NULL;
struct rve_session *session = kzalloc(sizeof(*session), GFP_KERNEL);
session_manager = rve_drvdata->session_manager;
if (session_manager == NULL) {
pr_err("rve_session_manager is null!\n");
kfree(session);
return NULL;
}
mutex_lock(&session_manager->lock);
idr_preload(GFP_KERNEL);
session->id = idr_alloc(&session_manager->ctx_id_idr, session, 1, 0, GFP_ATOMIC);
session_manager->session_cnt++;
idr_preload_end();
mutex_unlock(&session_manager->lock);
session->tgid = current->tgid;
return session;
}
static int rve_session_deinit(struct rve_session *session)
{
pid_t pid;
int ctx_id;
struct rve_pending_ctx_manager *ctx_manager;
struct rve_internal_ctx_t *ctx;
unsigned long flags;
pid = current->pid;
ctx_manager = rve_drvdata->pend_ctx_manager;
spin_lock_irqsave(&ctx_manager->lock, flags);
idr_for_each_entry(&ctx_manager->ctx_id_idr, ctx, ctx_id) {
spin_unlock_irqrestore(&ctx_manager->lock, flags);
if (session == ctx->session) {
pr_err("[pid:%d] destroy ctx[%d] when the user exits", pid, ctx->id);
kref_put(&ctx->refcount, rve_internal_ctx_kref_release);
}
spin_lock_irqsave(&ctx_manager->lock, flags);
}
spin_unlock_irqrestore(&ctx_manager->lock, flags);
rve_job_session_destroy(session);
rve_session_free_remove_idr(session);
kfree(session);
return 0;
}
static long rve_ioctl_cmd_start(unsigned long arg, struct rve_session *session)
{
int rve_user_ctx_id;
int ret = 0;
rve_user_ctx_id = rve_internal_ctx_alloc_to_get_idr_id();
rve_user_ctx_id = rve_internal_ctx_alloc_to_get_idr_id(session);
if (copy_to_user((void *)arg, &rve_user_ctx_id, sizeof(int)))
ret = -EFAULT;
@ -269,6 +397,7 @@ static long rve_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
int i = 0;
struct rve_version_t driver_version;
struct rve_hw_versions_t hw_versions;
struct rve_session *session = file->private_data;
if (!rve) {
pr_err("rve_drvdata is null, rve is not init\n");
@ -312,7 +441,7 @@ static long rve_ioctl(struct file *file, uint32_t cmd, unsigned long arg)
break;
case RVE_IOC_START_CONFIG:
ret = rve_ioctl_cmd_start(arg);
ret = rve_ioctl_cmd_start(arg, session);
break;
@ -383,37 +512,22 @@ static int rve_debugger_remove(struct rve_debugger **debugger_p)
static int rve_open(struct inode *inode, struct file *file)
{
struct rve_session *session = NULL;
session = rve_session_init();
if (!session)
return -ENOMEM;
file->private_data = (void *)session;
return nonseekable_open(inode, file);
}
static int rve_release(struct inode *inode, struct file *file)
{
struct rve_pending_ctx_manager *ctx_manager;
struct rve_internal_ctx_t *ctx;
pid_t pid;
int ctx_id;
unsigned long flags;
struct rve_session *session = file->private_data;
pid = current->pid;
ctx_manager = rve_drvdata->pend_ctx_manager;
spin_lock_irqsave(&ctx_manager->lock, flags);
idr_for_each_entry(&ctx_manager->ctx_id_idr, ctx, ctx_id) {
spin_unlock_irqrestore(&ctx_manager->lock, flags);
if (pid == ctx->debug_info.pid) {
if (DEBUGGER_EN(MSG))
pr_info("[pid:%d] destroy ctx[%d] when the user exits", pid, ctx->id);
kref_put(&ctx->refcount, rve_internal_ctx_kref_release);
}
spin_lock_irqsave(&ctx_manager->lock, flags);
}
spin_unlock_irqrestore(&ctx_manager->lock, flags);
rve_session_deinit(session);
return 0;
}
@ -733,6 +847,8 @@ static int __init rve_init(void)
rve_ctx_manager_init(&rve_drvdata->pend_ctx_manager);
rve_session_manager_init(&rve_drvdata->session_manager);
rve_init_timer();
#ifdef CONFIG_ROCKCHIP_RVE_DEBUGGER
@ -752,6 +868,8 @@ static void __exit rve_exit(void)
rve_ctx_manager_remove(&rve_drvdata->pend_ctx_manager);
rve_session_manager_remove(&rve_drvdata->session_manager);
wake_lock_destroy(&rve_drvdata->wake_lock);
#ifdef CONFIG_SYNC_FILE

View File

@ -75,6 +75,35 @@ static int rve_job_cleanup(struct rve_job *job)
return 0;
}
void rve_job_session_destroy(struct rve_session *session)
{
struct rve_scheduler_t *scheduler = NULL;
struct rve_job *job_pos, *job_q;
int i;
unsigned long flags;
for (i = 0; i < rve_drvdata->num_of_scheduler; i++) {
scheduler = rve_drvdata->scheduler[i];
spin_lock_irqsave(&scheduler->irq_lock, flags);
list_for_each_entry_safe(job_pos, job_q, &scheduler->todo_list, head) {
if (session == job_pos->session) {
list_del(&job_pos->head);
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
rve_job_free(job_pos);
spin_lock_irqsave(&scheduler->irq_lock, flags);
}
}
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
}
}
static struct rve_job *rve_job_alloc(struct rve_internal_ctx_t *ctx)
{
struct rve_job *job = NULL;
@ -96,6 +125,7 @@ static struct rve_job *rve_job_alloc(struct rve_internal_ctx_t *ctx)
job->core = rve_drvdata->scheduler[0]->core;
job->ctx = ctx;
ctx->scheduler = job->scheduler;
job->session = ctx->session;
if (ctx->priority > 0) {
if (ctx->priority > RVE_SCHED_PRIORITY_MAX)
@ -570,7 +600,7 @@ static void rve_input_fence_signaled(struct dma_fence *fence,
}
#endif
int rve_internal_ctx_alloc_to_get_idr_id(void)
int rve_internal_ctx_alloc_to_get_idr_id(struct rve_session *session)
{
struct rve_pending_ctx_manager *ctx_manager;
struct rve_internal_ctx_t *ctx;
@ -610,6 +640,7 @@ int rve_internal_ctx_alloc_to_get_idr_id(void)
ctx->debug_info.pid = current->pid;
ctx->debug_info.timestamp = ktime_get();
ctx->session = session;
spin_unlock_irqrestore(&ctx_manager->lock, flags);