mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
video: rockchip: rve: update to 1.0.1
1. support llp mode. 2. improve debugger module. Signed-off-by: Li Huang <putin.li@rock-chips.com> Change-Id: I8478804419b1d5f9582fb8b926711ae5418c2e86
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user