mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
video: rockchip: rve: support rve session
Signed-off-by: Li Huang <putin.li@rock-chips.com> Change-Id: Ic141815933c5cdd4832b0581ceab1f6c69aa315f
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user