diff --git a/drivers/video/rockchip/rve/include/rve_drv.h b/drivers/video/rockchip/rve/include/rve_drv.h index a8d818f43bdd..592c1087ba67 100644 --- a/drivers/video/rockchip/rve/include/rve_drv.h +++ b/drivers/video/rockchip/rve/include/rve_drv.h @@ -74,7 +74,7 @@ #define DRIVER_MAJOR_VERSION 1 #define DRIVER_MINOR_VERSION 0 -#define DRIVER_REVISION_VERSION 0 +#define DRIVER_REVISION_VERSION 1 #define DRIVER_VERSION (STR(DRIVER_MAJOR_VERSION) "." STR(DRIVER_MINOR_VERSION) \ "." STR(DRIVER_REVISION_VERSION)) @@ -88,6 +88,7 @@ #define RVE_MAX_SCHEDULER 1 #define RVE_MAX_BUS_CLK 10 +#define RVE_MAX_PID_INFO 10 extern struct rve_drvdata_t *rve_drvdata; @@ -154,6 +155,27 @@ struct rve_timer { u32 busy_time_record; }; +struct rve_sche_pid_info_t { + pid_t pid; + /* hw total use time, per hrtimer */ + u32 hw_time_total; +}; + +struct rve_sche_session_info_t { + struct rve_sche_pid_info_t pid_info[RVE_MAX_PID_INFO]; + + int pd_refcount; + + /* the bandwidth of total read bytes, per hrtimer */ + uint32_t rd_bandwidth; + /* the bandwidth of total write bytes, per hrtimer */ + uint32_t wr_bandwidth; + /* the total running cycle of current frame, per hrtimer */ + uint32_t cycle_cnt; + /* total interrupt count */ + uint64_t total_int_cnt; +}; + struct rve_scheduler_t { struct device *dev; void __iomem *rve_base; @@ -161,8 +183,6 @@ struct rve_scheduler_t { struct clk *clks[RVE_MAX_BUS_CLK]; int num_clks; - int pd_refcount; - struct rve_job *running_job; struct list_head todo_list; spinlock_t irq_lock; @@ -175,24 +195,25 @@ struct rve_scheduler_t { int core; struct rve_timer timer; - uint64_t total_int_cnt; + + struct rve_sche_session_info_t session; }; struct rve_cmd_reg_array_t { uint32_t cmd_reg[58]; }; -struct rve_debug_info_t { +struct rve_ctx_debug_info_t { pid_t pid; - ktime_t timestamp; - ktime_t hw_time_total; - ktime_t last_job_use_time; - ktime_t last_job_hw_use_time; - ktime_t max_cost_time_per_sec; - - uint32_t rd_bandwidth; - uint32_t wr_bandwidth; - uint32_t cycle_cnt; + u32 timestamp; + /* hw total use time, per hrtimer */ + u32 hw_time_total; + /* last job use time, per hrtimer*/ + u32 last_job_use_time; + /* last job hardware use time, per hrtimer*/ + u32 last_job_hw_use_time; + /* the most time-consuming job, per hrtimer */ + u32 max_cost_time_per_sec; }; struct rve_internal_ctx_t { @@ -218,13 +239,13 @@ struct rve_internal_ctx_t { struct kref refcount; /* debug info */ - struct rve_debug_info_t debug_info; + struct rve_ctx_debug_info_t debug_info; /* TODO: add some common work */ }; struct rve_pending_ctx_manager { - struct mutex lock; + spinlock_t lock; /* * @ctx_id_idr: diff --git a/drivers/video/rockchip/rve/include/rve_reg.h b/drivers/video/rockchip/rve/include/rve_reg.h index f61987e75952..7a68e3b1097c 100644 --- a/drivers/video/rockchip/rve/include/rve_reg.h +++ b/drivers/video/rockchip/rve/include/rve_reg.h @@ -71,13 +71,18 @@ #define RVE_CFG_REG 0x200 #define RVE_MMU_REG 0x300 +/* mode value */ +#define RVE_LLP_MODE 0x8000 +#define RVE_LLP_DONE 0x11 +#define RVE_CLEAR_UP_REG6_WROK_STA 0xff0000 + void rve_soft_reset(struct rve_scheduler_t *scheduler); int rve_set_reg(struct rve_job *job, struct rve_scheduler_t *scheduler); int rve_init_reg(struct rve_job *job); int rve_get_version(struct rve_scheduler_t *scheduler); void rve_dump_read_back_reg(struct rve_scheduler_t *scheduler); -void rve_get_monitor_info(struct rve_internal_ctx_t *ctx, struct rve_scheduler_t *scheduler); +void rve_get_monitor_info(struct rve_scheduler_t *scheduler); #endif diff --git a/drivers/video/rockchip/rve/rve_debugger.c b/drivers/video/rockchip/rve/rve_debugger.c index 5c8d15bc7671..00476911bf0f 100644 --- a/drivers/video/rockchip/rve/rve_debugger.c +++ b/drivers/video/rockchip/rve/rve_debugger.c @@ -149,6 +149,7 @@ static int rve_version_show(struct seq_file *m, void *data) static int rve_load_show(struct seq_file *m, void *data) { struct rve_scheduler_t *scheduler = NULL; + struct rve_sche_pid_info_t *pid_info = NULL; unsigned long flags; int i; int load; @@ -157,21 +158,24 @@ static int rve_load_show(struct seq_file *m, void *data) seq_printf(m, "num of scheduler = %d\n", rve_drvdata->num_of_scheduler); seq_printf(m, "================= load ==================\n"); - for (i = 0; i < rve_drvdata->num_of_scheduler; i++) { - scheduler = rve_drvdata->scheduler[i]; + scheduler = rve_drvdata->scheduler[0]; - seq_printf(m, "scheduler[%d]: %s\n", - i, dev_driver_string(scheduler->dev)); + seq_printf(m, "scheduler[0]: %s\n", dev_driver_string(scheduler->dev)); - spin_lock_irqsave(&scheduler->irq_lock, flags); + spin_lock_irqsave(&scheduler->irq_lock, flags); - busy_time_total = scheduler->timer.busy_time_record; + busy_time_total = scheduler->timer.busy_time_record; + pid_info = scheduler->session.pid_info; - spin_unlock_irqrestore(&scheduler->irq_lock, flags); + spin_unlock_irqrestore(&scheduler->irq_lock, flags); - load = (busy_time_total * 100000 / RVE_LOAD_INTERVAL); - seq_printf(m, "\t load = %d\n", load); - seq_printf(m, "-----------------------------------\n"); + load = (busy_time_total * 100000 / RVE_LOAD_INTERVAL); + seq_printf(m, "\t load = %d\n", load); + seq_printf(m, "-----------------------------------\n"); + + for (i = 0; i < RVE_MAX_PID_INFO; i++) { + seq_printf(m, "\t [pid: %d] hw_time_total = %llu us\n", + pid_info[i].pid, ktime_to_us(pid_info[i].hw_time_total)); } return 0; } @@ -180,6 +184,11 @@ static int rve_scheduler_show(struct seq_file *m, void *data) { struct rve_scheduler_t *scheduler = NULL; int i; + unsigned long flags; + + int pd_refcount; + uint64_t total_int_cnt; + uint32_t rd_bandwidth, wr_bandwidth, cycle_cnt; seq_printf(m, "num of scheduler = %d\n", rve_drvdata->num_of_scheduler); seq_printf(m, "===================================\n"); @@ -187,10 +196,23 @@ static int rve_scheduler_show(struct seq_file *m, void *data) for (i = 0; i < rve_drvdata->num_of_scheduler; i++) { scheduler = rve_drvdata->scheduler[i]; + spin_lock_irqsave(&scheduler->irq_lock, flags); + + pd_refcount = scheduler->session.pd_refcount; + total_int_cnt = scheduler->session.total_int_cnt; + rd_bandwidth = scheduler->session.rd_bandwidth; + wr_bandwidth = scheduler->session.wr_bandwidth; + cycle_cnt = scheduler->session.cycle_cnt; + + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + seq_printf(m, "scheduler[%d]: %s\n", i, dev_driver_string(scheduler->dev)); seq_printf(m, "-----------------------------------\n"); - seq_printf(m, "pd_ref = %d\n", scheduler->pd_refcount); - seq_printf(m, "total_int_cnt = %llu\n", scheduler->total_int_cnt); + seq_printf(m, "pd_ref = %d\n", pd_refcount); + seq_printf(m, "total_int_cnt = %llu\n", total_int_cnt); + seq_printf(m, "rd_bandwidth: %u bytes/s\t wr_bandwidth: %u bytes/s\n", + rd_bandwidth, wr_bandwidth); + seq_printf(m, "cycle_cnt/s: %u\n", cycle_cnt); } return 0; @@ -207,22 +229,23 @@ static int rve_ctx_manager_show(struct seq_file *m, void *data) bool status = false; pid_t pid; - ktime_t last_job_hw_use_time; - ktime_t last_job_use_time; - ktime_t hw_time_total; - ktime_t max_cost_time_per_sec; - uint32_t rd_bandwidth, wr_bandwidth, cycle_cnt; + u32 last_job_hw_use_time; + u32 last_job_use_time; + u32 hw_time_total; + u32 max_cost_time_per_sec; ctx_manager = rve_drvdata->pend_ctx_manager; seq_puts(m, "rve internal ctx dump:\n"); seq_printf(m, "ctx count = %d\n", ctx_manager->ctx_count); - mutex_lock(&ctx_manager->lock); + spin_lock_irqsave(&ctx_manager->lock, flags); idr_for_each_entry(&ctx_manager->ctx_id_idr, ctx, id) { seq_printf(m, "================= ctx id: %d =================\n", ctx->id); + spin_unlock_irqrestore(&ctx_manager->lock, flags); + spin_lock_irqsave(&ctx->lock, flags); cmd_num = ctx->cmd_num; @@ -233,9 +256,6 @@ static int rve_ctx_manager_show(struct seq_file *m, void *data) last_job_use_time = ctx->debug_info.last_job_use_time; hw_time_total = ctx->debug_info.hw_time_total; max_cost_time_per_sec = ctx->debug_info.max_cost_time_per_sec; - rd_bandwidth = ctx->debug_info.rd_bandwidth; - wr_bandwidth = ctx->debug_info.wr_bandwidth; - cycle_cnt = ctx->debug_info.cycle_cnt; spin_unlock_irqrestore(&ctx->lock, flags); @@ -243,19 +263,18 @@ static int rve_ctx_manager_show(struct seq_file *m, void *data) seq_printf(m, "\t [pid: %d] status: %s\n", pid, status ? "active" : "pending"); seq_printf(m, "\t set cmd num: %d\t finish job sum: %d\n", cmd_num, finished_job_count); - seq_printf(m, "\t last_job_use_time: %llu us\t last_job_hw_use_time: %llu us", - ktime_to_us(last_job_use_time), ktime_to_us(last_job_hw_use_time)); - seq_printf(m, "\t hw_time_total: %llu us\t max_cost_time_per_sec: %llu us", - ktime_to_us(hw_time_total), ktime_to_us(max_cost_time_per_sec)); - seq_printf(m, "\t rd_bandwidth: %u bytes\t wr_bandwidth: %u bytes", - rd_bandwidth, wr_bandwidth); - seq_printf(m, "\t cycle_cnt: %u\t", cycle_cnt); + seq_printf(m, "\t last_job_use_time: %u us\t last_job_hw_use_time: %u us", + last_job_use_time, last_job_hw_use_time); + seq_printf(m, "\t hw_time_total: %u us\t max_cost_time_per_sec: %u us", + hw_time_total, max_cost_time_per_sec); seq_printf(m, "----------------- RVE INVOKE INFO -----------------\n"); /* TODO: */ + + spin_lock_irqsave(&ctx_manager->lock, flags); } - mutex_unlock(&ctx_manager->lock); + spin_unlock_irqrestore(&ctx_manager->lock, flags); return 0; } @@ -269,8 +288,6 @@ struct rve_debugger_list rve_debugger_root_list[] = { {"ctx_manager", rve_ctx_manager_show, NULL, NULL}, }; -#ifdef CONFIG_ROCKCHIP_RVE_DEBUG_FS - static ssize_t rve_debugger_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) { @@ -283,6 +300,8 @@ static ssize_t rve_debugger_write(struct file *file, const char __user *ubuf, return len; } +#ifdef CONFIG_ROCKCHIP_RVE_DEBUG_FS + static int rve_debugfs_open(struct inode *inode, struct file *file) { struct rve_debugger_node *node = inode->i_private; @@ -420,25 +439,12 @@ static int rve_procfs_open(struct inode *inode, struct file *file) return single_open(file, node->info_ent->show, node); } -static ssize_t rve_fops_write_u32(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - int rc; - struct seq_file *priv = file->private_data; - - rc = kstrtou32_from_user(buf, count, 0, priv->private); - if (rc) - return rc; - - return count; -} - static const struct proc_ops rve_procfs_fops = { .proc_open = rve_procfs_open, .proc_read = seq_read, .proc_lseek = seq_lseek, .proc_release = single_release, - .proc_write = rve_fops_write_u32, + .proc_write = rve_debugger_write, }; static int rve_procfs_remove_files(struct rve_debugger *debugger) diff --git a/drivers/video/rockchip/rve/rve_drv.c b/drivers/video/rockchip/rve/rve_drv.c index eafb36cde48a..ef43adec1565 100644 --- a/drivers/video/rockchip/rve/rve_drv.c +++ b/drivers/video/rockchip/rve/rve_drv.c @@ -25,10 +25,26 @@ static const struct rve_backend_ops rve_ops = { .soft_reset = rve_soft_reset }; +static int rve_ctx_set_debuf_info_cb(int id, void *ptr, void *data) +{ + struct rve_internal_ctx_t *ctx = ptr; + unsigned long flags; + + spin_lock_irqsave(&ctx->lock, flags); + + ctx->debug_info.max_cost_time_per_sec = 0; + ctx->debug_info.hw_time_total = 0; + + spin_unlock_irqrestore(&ctx->lock, flags); + + return 0; +} + static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer) { struct rve_drvdata_t *rve = rve_drvdata; struct rve_scheduler_t *scheduler = NULL; + struct rve_pending_ctx_manager *ctx_manager; struct rve_job *job = NULL; unsigned long flags; int i; @@ -50,11 +66,23 @@ static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer) scheduler->timer.busy_time_record = scheduler->timer.busy_time; scheduler->timer.busy_time = 0; + for (i = 0; i < RVE_MAX_PID_INFO; i++) { + if (scheduler->session.pid_info[i].pid > 0) + scheduler->session.pid_info[i].hw_time_total = 0; + } + spin_unlock_irqrestore(&scheduler->irq_lock, flags); + ctx_manager = rve_drvdata->pend_ctx_manager; + + spin_lock_irqsave(&ctx_manager->lock, flags); + + idr_for_each(&ctx_manager->ctx_id_idr, &rve_ctx_set_debuf_info_cb, ctx_manager); + + spin_unlock_irqrestore(&ctx_manager->lock, flags); + /* monitor */ - if (job && job->ctx) - rve_get_monitor_info(job->ctx, scheduler); + rve_get_monitor_info(scheduler); } hrtimer_forward_now(timer, kt); @@ -64,9 +92,12 @@ static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer) static void rve_init_timer(void) { kt = ktime_set(0, RVE_LOAD_INTERVAL); + hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - hrtimer_start(&timer, kt, HRTIMER_MODE_REL); + timer.function = hrtimer_handler; + + hrtimer_start(&timer, kt, HRTIMER_MODE_REL); } static void rve_cancel_timer(void) @@ -101,7 +132,7 @@ err_enable_clk: pm_relax(scheduler->dev); pm_runtime_put_sync_suspend(scheduler->dev); - scheduler->pd_refcount++; + scheduler->session.pd_refcount++; return ret; } @@ -117,7 +148,7 @@ int rve_power_disable(struct rve_scheduler_t *scheduler) pm_relax(scheduler->dev); pm_runtime_put_sync_suspend(scheduler->dev); - scheduler->pd_refcount--; + scheduler->session.pd_refcount--; return 0; } @@ -355,30 +386,32 @@ static int rve_open(struct inode *inode, struct file *file) static int rve_release(struct inode *inode, struct file *file) { - pid_t pid; - int ctx_id; struct rve_pending_ctx_manager *ctx_manager; struct rve_internal_ctx_t *ctx; + pid_t pid; + int ctx_id; + unsigned long flags; pid = current->pid; ctx_manager = rve_drvdata->pend_ctx_manager; - mutex_lock(&ctx_manager->lock); + spin_lock_irqsave(&ctx_manager->lock, flags); idr_for_each_entry(&ctx_manager->ctx_id_idr, ctx, ctx_id) { - mutex_unlock(&ctx_manager->lock); + spin_unlock_irqrestore(&ctx_manager->lock, flags); if (pid == ctx->debug_info.pid) { - pr_err("[pid:%d] destroy ctx[%d] when the user exits", pid, ctx->id); + 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); } - mutex_lock(&ctx_manager->lock); + spin_lock_irqsave(&ctx_manager->lock, flags); } - mutex_unlock(&ctx_manager->lock); + spin_unlock_irqrestore(&ctx_manager->lock, flags); return 0; } @@ -414,19 +447,18 @@ static irqreturn_t rve_irq_thread(int irq, void *data) u32 error_flag; job = scheduler->running_job; - scheduler->total_int_cnt++; + scheduler->session.total_int_cnt++; if (!job) { pr_err("running job is invalid on irq thread\n"); return IRQ_HANDLED; } + error_flag = rve_read(RVE_SWREG6_IVE_WORK_STA, scheduler); + if (DEBUGGER_EN(INT_FLAG)) { - error_flag = rve_read(RVE_SWREG6_IVE_WORK_STA, scheduler); - - if (error_flag & 0x1) { - pr_err("irq thread work_status[%x]\n", error_flag); - + pr_err("irq thread work_status[%x]\n", error_flag); + if (error_flag & 0x6) { if (error_flag & 0x2) pr_err("irq: bus error"); else if (error_flag & 0x4) @@ -434,8 +466,17 @@ static irqreturn_t rve_irq_thread(int irq, void *data) } } + /* if llp mode*/ + if ((error_flag & RVE_LLP_MODE) && + (!(error_flag & RVE_LLP_DONE))) { + if (DEBUGGER_EN(INT_FLAG)) + pr_err("irq: llp mode need to skip rve_job_done"); + goto skip_job_done; + } + rve_job_done(scheduler, 0); +skip_job_done: return IRQ_HANDLED; } diff --git a/drivers/video/rockchip/rve/rve_job.c b/drivers/video/rockchip/rve/rve_job.c index 52135021716b..d66c6c975fd4 100644 --- a/drivers/video/rockchip/rve/rve_job.c +++ b/drivers/video/rockchip/rve/rve_job.c @@ -111,14 +111,15 @@ static struct rve_internal_ctx_t * rve_internal_ctx_lookup(struct rve_pending_ctx_manager *ctx_manager, uint32_t id) { struct rve_internal_ctx_t *ctx = NULL; + unsigned long flags; - mutex_lock(&ctx_manager->lock); + spin_lock_irqsave(&ctx_manager->lock, flags); ctx = idr_find(&ctx_manager->ctx_id_idr, id); if (ctx == NULL) pr_err("can not find internal ctx from id[%d]", id); - mutex_unlock(&ctx_manager->lock); + spin_unlock_irqrestore(&ctx_manager->lock, flags); return ctx; } @@ -139,16 +140,17 @@ static int rve_internal_ctx_free_remove_idr_cb(int id, void *ptr, void *data) static int rve_internal_ctx_free_remove_idr(struct rve_internal_ctx_t *ctx) { struct rve_pending_ctx_manager *ctx_manager; + unsigned long flags; ctx_manager = rve_drvdata->pend_ctx_manager; - mutex_lock(&ctx_manager->lock); + spin_lock_irqsave(&ctx_manager->lock, flags); ctx_manager->ctx_count--; idr_remove(&ctx_manager->ctx_id_idr, ctx->id); kfree(ctx); - mutex_unlock(&ctx_manager->lock); + spin_unlock_irqrestore(&ctx_manager->lock, flags); return 0; } @@ -319,6 +321,44 @@ static void rve_job_finish_and_next(struct rve_job *job, int ret) #endif } +static void rve_scheduler_set_pid_info(struct rve_job *job, ktime_t now) +{ + struct rve_scheduler_t *scheduler; + bool pid_match_flag = false; + ktime_t tmp = 0; + int pid_mark = 0, i; + + scheduler = rve_job_get_scheduler(job); + + for (i = 0; i < RVE_MAX_PID_INFO; i++) { + if (scheduler->session.pid_info[i].pid == 0) + scheduler->session.pid_info[i].pid = job->pid; + + if (scheduler->session.pid_info[i].pid == job->pid) { + pid_match_flag = true; + scheduler->session.pid_info[i].hw_time_total += + (job->hw_running_time - now); + break; + } + } + + if (!pid_match_flag) { + for (i = 0; i < RVE_MAX_PID_INFO; i++) { + if (i == 0) { + tmp = scheduler->session.pid_info[i].hw_time_total; + continue; + } + + if (tmp > scheduler->session.pid_info[i].hw_time_total) + pid_mark = i; + } + + scheduler->session.pid_info[pid_mark].pid = job->pid; + scheduler->session.pid_info[pid_mark].hw_time_total += + ktime_us_delta(now, job->hw_running_time); + } +} + void rve_job_done(struct rve_scheduler_t *scheduler, int ret) { struct rve_job *job; @@ -336,6 +376,8 @@ void rve_job_done(struct rve_scheduler_t *scheduler, int ret) scheduler->timer.busy_time += ktime_us_delta(now, job->hw_recoder_time); + rve_scheduler_set_pid_info(job, now); + spin_unlock_irqrestore(&scheduler->irq_lock, flags); spin_lock_irqsave(&job->ctx->lock, flags); @@ -343,9 +385,9 @@ void rve_job_done(struct rve_scheduler_t *scheduler, int ret) job->ctx->debug_info.max_cost_time_per_sec = max(job->ctx->debug_info.last_job_hw_use_time, job->ctx->debug_info.max_cost_time_per_sec); - job->ctx->debug_info.last_job_hw_use_time = job->hw_running_time - now; + job->ctx->debug_info.last_job_hw_use_time = ktime_us_delta(now, job->hw_running_time); job->ctx->debug_info.hw_time_total += job->ctx->debug_info.last_job_hw_use_time; - job->ctx->debug_info.last_job_use_time = job->timestamp - now; + job->ctx->debug_info.last_job_use_time = ktime_us_delta(now, job->timestamp); spin_unlock_irqrestore(&job->ctx->lock, flags); @@ -359,6 +401,9 @@ void rve_job_done(struct rve_scheduler_t *scheduler, int ret) if (DEBUGGER_EN(MSG)) pr_err("irq thread work_status[%.8x]\n", error_flag); + /* disable llp enable, TODO: support pause mode */ + rve_write(0, RVE_SWLTB3_ENABLE, scheduler); + rve_job_finish_and_next(job, ret); } @@ -527,6 +572,7 @@ int rve_internal_ctx_alloc_to_get_idr_id(void) { struct rve_pending_ctx_manager *ctx_manager; struct rve_internal_ctx_t *ctx; + unsigned long flags; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (ctx == NULL) { @@ -537,8 +583,7 @@ int rve_internal_ctx_alloc_to_get_idr_id(void) ctx_manager = rve_drvdata->pend_ctx_manager; if (ctx_manager == NULL) { pr_err("rve_pending_ctx_manager is null!\n"); - kfree(ctx); - return -EFAULT; + goto failed; } spin_lock_init(&ctx->lock); @@ -548,21 +593,33 @@ int rve_internal_ctx_alloc_to_get_idr_id(void) * allocation under our spinlock. */ - mutex_lock(&ctx_manager->lock); - idr_preload(GFP_KERNEL); - ctx->id = idr_alloc(&ctx_manager->ctx_id_idr, ctx, 1, 0, GFP_KERNEL); - idr_preload_end(); + + spin_lock_irqsave(&ctx_manager->lock, flags); + + ctx->id = idr_alloc(&ctx_manager->ctx_id_idr, ctx, 1, 0, GFP_ATOMIC); + if (ctx->id < 0) { + pr_err("idr_alloc failed"); + spin_unlock_irqrestore(&ctx_manager->lock, flags); + goto failed; + } ctx_manager->ctx_count++; - kref_init(&ctx->refcount); ctx->debug_info.pid = current->pid; ctx->debug_info.timestamp = ktime_get(); - mutex_unlock(&ctx_manager->lock); + spin_unlock_irqrestore(&ctx_manager->lock, flags); + + idr_preload_end(); + + kref_init(&ctx->refcount); return ctx->id; + +failed: + kfree(ctx); + return -EFAULT; } int rve_job_config_by_user_ctx(struct rve_user_ctx_t *user_ctx) @@ -897,7 +954,7 @@ int rve_ctx_manager_init(struct rve_pending_ctx_manager **ctx_manager_session) ctx_manager = *ctx_manager_session; - mutex_init(&ctx_manager->lock); + spin_lock_init(&ctx_manager->lock); idr_init_base(&ctx_manager->ctx_id_idr, 1); @@ -907,13 +964,14 @@ 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) { struct rve_pending_ctx_manager *ctx_manager = *ctx_manager_session; + unsigned long flags; - mutex_lock(&ctx_manager->lock); + spin_lock_irqsave(&ctx_manager->lock, flags); idr_for_each(&ctx_manager->ctx_id_idr, &rve_internal_ctx_free_remove_idr_cb, ctx_manager); idr_destroy(&ctx_manager->ctx_id_idr); - mutex_unlock(&ctx_manager->lock); + spin_unlock_irqrestore(&ctx_manager->lock, flags); kfree(*ctx_manager_session); diff --git a/drivers/video/rockchip/rve/rve_reg.c b/drivers/video/rockchip/rve/rve_reg.c index a5f2c1342e2b..adaadc9a880a 100644 --- a/drivers/video/rockchip/rve/rve_reg.c +++ b/drivers/video/rockchip/rve/rve_reg.c @@ -130,7 +130,6 @@ int rve_set_reg(struct rve_job *job, struct rve_scheduler_t *scheduler) uint32_t *cmd_reg; int i; - /* TODO: dump regcmd_data */ cmd_reg = job->regcmd_data->cmd_reg; if (DEBUGGER_EN(REG)) { @@ -145,8 +144,6 @@ int rve_set_reg(struct rve_job *job, struct rve_scheduler_t *scheduler) /* clean up irq status reg */ rve_write(0x00000, RVE_SWREG6_IVE_WORK_STA, scheduler); - /* TODO: llp mode */ - if (DEBUGGER_EN(MSG)) { pr_info("idle_ctrl = %x, idle_prc_sta = %x", rve_read(RVE_SWREG5_IVE_IDLE_CTRL, scheduler), @@ -165,18 +162,27 @@ int rve_set_reg(struct rve_job *job, struct rve_scheduler_t *scheduler) for (i = 0; i < 8; i++) rve_write(cmd_reg[i], RVE_SYS_REG + i * 4, scheduler); - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { + /* skip start reg */ + if (i == 2) + continue; + rve_write(cmd_reg[8 + i], RVE_LTB_REG + i * 4, scheduler); + } /* 0x200(start)(40 - 1 = 39) need config after reg ready */ for (i = 0; i < 39; i++) rve_write(cmd_reg[19 + i], RVE_CFG_REG + (i + 1) * 4, scheduler); - //TODO: + //TODO: ddr config rve_write(0x30000, RVE_SWCFG5_CTRL, scheduler); rve_write(0xf4240, RVE_SWCFG6_TIMEOUT_THRESH, scheduler); rve_write(0x1f0001, RVE_SWCFG7_DDR_CTRL, scheduler); + /* reset RVE_SWREG6_IVE_WORK_STA */ + rve_write(RVE_CLEAR_UP_REG6_WROK_STA, RVE_SWREG6_IVE_WORK_STA, scheduler); + + /* enable monitor */ if (DEBUGGER_EN(MONITOR)) rve_write(1, RVE_SWCFG32_MONITOR_CTRL0, scheduler); @@ -185,7 +191,12 @@ int rve_set_reg(struct rve_job *job, struct rve_scheduler_t *scheduler) rve_dump_read_back_reg(scheduler); } - rve_write(cmd_reg[18], RVE_SWCFG0_EN, scheduler); + /* if llp mode enable, skip to enable slave mode */ + if (cmd_reg[11] != 1) + rve_write(1, RVE_SWCFG0_EN, scheduler); + else + /* llp config done, to start hw */ + rve_write(cmd_reg[10], RVE_SWLTB2_CFG_DONE, scheduler); if (DEBUGGER_EN(REG)) { pr_err("after config:"); @@ -221,7 +232,7 @@ int rve_get_version(struct rve_scheduler_t *scheduler) return 0; } -void rve_get_monitor_info(struct rve_internal_ctx_t *ctx, struct rve_scheduler_t *scheduler) +void rve_get_monitor_info(struct rve_scheduler_t *scheduler) { unsigned long flags; uint32_t rd_bandwidth, wr_bandwidth, cycle_cnt; @@ -235,13 +246,12 @@ void rve_get_monitor_info(struct rve_internal_ctx_t *ctx, struct rve_scheduler_t /* reset per htimer occur */ rve_write(2, RVE_SWCFG32_MONITOR_CTRL0, scheduler); - spin_lock_irqsave(&ctx->lock, flags); + spin_lock_irqsave(&scheduler->irq_lock, flags); - ctx->debug_info.max_cost_time_per_sec = 0; - ctx->debug_info.rd_bandwidth = rd_bandwidth; - ctx->debug_info.wr_bandwidth = wr_bandwidth; - ctx->debug_info.cycle_cnt = cycle_cnt; + scheduler->session.rd_bandwidth = rd_bandwidth; + scheduler->session.wr_bandwidth = wr_bandwidth; + scheduler->session.cycle_cnt = cycle_cnt; - spin_unlock_irqrestore(&ctx->lock, flags); + spin_unlock_irqrestore(&scheduler->irq_lock, flags); } }