video: rockchip: rga3: Add support for rga load by hrtimer

Add debugger node to show rga load

Signed-off-by: Li Huang <putin.li@rock-chips.com>
Change-Id: Ie7f5facc94db7ccaef2f61490b6951d0c614cb30
This commit is contained in:
Li Huang
2021-12-29 11:58:56 +08:00
committed by Tao Huang
parent 2777810757
commit 2b456d3acd
6 changed files with 112 additions and 17 deletions

View File

@@ -51,14 +51,15 @@
#include <linux/iova.h>
#include <linux/dma-iommu.h>
#include <linux/dma-map-ops.h>
#include <linux/hrtimer.h>
#include "rga.h"
#include "rga_debugger.h"
#define RGA_CORE_REG_OFFSET 0x10000
/* sample interval: 100ms */
#define RGA_LOAD_INTERVAL 100000
/* sample interval: 1000ms */
#define RGA_LOAD_INTERVAL 1000000000
#if ((defined(CONFIG_RK_IOMMU) || defined(CONFIG_ROCKCHIP_IOMMU)) \
&& defined(CONFIG_ION_ROCKCHIP))
@@ -246,6 +247,7 @@ struct rga_job {
struct dma_fence *in_fence;
spinlock_t fence_lock;
ktime_t timestamp;
ktime_t running_time;
unsigned int flags;
int job_id;
int priority;
@@ -262,6 +264,11 @@ struct rga_backend_ops {
void (*soft_reset)(struct rga_scheduler_t *scheduler);
};
struct rga_timer {
u32 busy_time;
u32 busy_time_record;
};
struct rga_scheduler_t {
struct device *dev;
void __iomem *rga_base;
@@ -281,7 +288,8 @@ struct rga_scheduler_t {
int irq;
struct rga_version_t version;
int core;
unsigned int core_offset;
struct rga_timer timer;
};
struct rga_drvdata_t {

View File

@@ -2487,13 +2487,16 @@ int rga2_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
rga_write(rga_read(RGA2_INT, scheduler) | (0x1 << 10) | (0x1 << 9) |
(0x1 << 8), RGA2_INT, scheduler);
if (RGA_DEBUG_MSG) {
if (RGA_DEBUG_TIME) {
pr_err("sys_ctrl = %x, int = %x, set cmd use time = %lld\n",
rga_read(RGA2_SYS_CTRL, scheduler),
rga_read(RGA2_INT, scheduler),
ktime_to_us(ktime_sub(now, job->timestamp)));
ktime_to_us(ktime_sub(now, job->running_time)));
}
job->timestamp = now;
job->running_time = now;
rga_write(1, RGA2_CMD_CTRL, scheduler);
#if CONFIG_ROCKCHIP_RGA_DEBUGGER

View File

@@ -2084,12 +2084,17 @@ int rga3_set_reg(struct rga_job *job, struct rga_scheduler_t *scheduler)
rga_read(RGA3_INT_EN, scheduler),
rga_read(RGA3_INT_RAW, scheduler));
pr_err("status0 = %x, status1 = %x, set cmd use time = %lld\n",
pr_err("status0 = %x, status1 = %x\n",
rga_read(RGA3_STATUS0, scheduler),
rga_read(RGA3_STATUS1, scheduler),
ktime_to_us(ktime_sub(now, job->timestamp)));
rga_read(RGA3_STATUS1, scheduler));
}
if (RGA_DEBUG_TIME)
pr_err("set cmd use time = %lld\n", ktime_to_us(ktime_sub(now, job->running_time)));
job->timestamp = now;
job->running_time = now;
rga_write(1, RGA3_SYS_CTRL, scheduler);
#if CONFIG_ROCKCHIP_RGA_DEBUGGER

View File

@@ -138,8 +138,31 @@ static int rga_version_show(struct seq_file *m, void *data)
static int rga_load_show(struct seq_file *m, void *data)
{
seq_printf(m, "%s: v%s\n", DRIVER_DESC, DRIVER_VERSION);
struct rga_scheduler_t *rga_scheduler = NULL;
unsigned long flags;
int i;
int load;
u32 busy_time_total;
seq_printf(m, "num of scheduler = %d\n", rga_drvdata->num_of_scheduler);
seq_printf(m, "================= load ==================\n");
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
rga_scheduler = rga_drvdata->rga_scheduler[i];
seq_printf(m, "scheduler[%d]: %s\n",
i, dev_driver_string(rga_scheduler->dev));
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
busy_time_total = rga_scheduler->timer.busy_time_record;
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
load = (busy_time_total * 100000 / RGA_LOAD_INTERVAL);
seq_printf(m, "load = %d", load);
seq_printf(m, "-----------------------------------\n");
}
return 0;
}
@@ -154,8 +177,8 @@ static int rga_scheduler_show(struct seq_file *m, void *data)
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
rga_scheduler = rga_drvdata->rga_scheduler[i];
seq_printf(m, "scheduler[%d]: core = %d\n",
i, rga_scheduler->core);
seq_printf(m, "scheduler[%d]: %s\n",
i, dev_driver_string(rga_scheduler->dev));
seq_printf(m, "-----------------------------------\n");
seq_printf(m, "pd_ref = %d\n", rga_scheduler->pd_refcount);
}
@@ -535,4 +558,4 @@ void rga_cmd_print_debug_info(struct rga_req *req)
pr_info("yuv2rgb mode is %x\n", req->yuv2rgb_mode);
pr_info("set core = %d, priority = %d, in_fence_fd = %d\n",
req->core, req->priority, req->in_fence_fd);
}
}

View File

@@ -23,6 +23,10 @@ struct rga2_mmu_info_t rga2_mmu_info;
struct rga_drvdata_t *rga_drvdata;
/* set hrtimer */
static struct hrtimer timer;
static ktime_t kt;
static const struct rga_backend_ops rga3_ops = {
.get_version = rga3_get_version,
.set_reg = rga3_set_reg,
@@ -71,6 +75,51 @@ int rga_kernel_commit(struct rga_req *cmd)
}
EXPORT_SYMBOL_GPL(rga_kernel_commit);
static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)
{
struct rga_drvdata_t *rga = rga_drvdata;
struct rga_scheduler_t *scheduler = NULL;
struct rga_job *job = NULL;
unsigned long flags;
int i;
ktime_t now = ktime_get();
for (i = 0; i < rga->num_of_scheduler; i++) {
scheduler = rga->rga_scheduler[i];
spin_lock_irqsave(&scheduler->irq_lock, flags);
/* if timer action on job running */
job = scheduler->running_job;
if (job) {
scheduler->timer.busy_time += ktime_us_delta(now, job->timestamp);
job->timestamp = now;
}
scheduler->timer.busy_time_record = scheduler->timer.busy_time;
scheduler->timer.busy_time = 0;
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
}
hrtimer_forward_now(timer, kt);
return HRTIMER_RESTART;
}
static void rga_init_timer(void)
{
kt = ktime_set(0, RGA_LOAD_INTERVAL);
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer_start(&timer, kt, HRTIMER_MODE_REL);
timer.function = hrtimer_handler;
}
static void rga_cancel_timer(void)
{
hrtimer_cancel(&timer);
}
#ifndef CONFIG_ROCKCHIP_FPGA
int rga_power_enable(struct rga_scheduler_t *rga_scheduler)
{
@@ -901,6 +950,8 @@ static int __init rga_init(void)
return ret;
}
rga_init_timer();
rga_drvdata->fence_ctx = rga_fence_context_alloc();
if (IS_ERR(rga_drvdata->fence_ctx)) {
pr_err("failed to allocate fence context for RGA\n");
@@ -941,6 +992,8 @@ static void __exit rga_exit(void)
rga_fence_context_free(rga_drvdata->fence_ctx);
rga_cancel_timer();
platform_driver_unregister(&rga3_core0_driver);
platform_driver_unregister(&rga3_core1_driver);
platform_driver_unregister(&rga2_driver);

View File

@@ -89,6 +89,7 @@ static struct rga_job *rga_job_alloc(struct rga_req *rga_command_base)
INIT_LIST_HEAD(&job->head);
job->timestamp = ktime_get();
job->running_time = ktime_get();
job->rga_command_base = *rga_command_base;
@@ -267,23 +268,25 @@ void rga_job_done(struct rga_scheduler_t *rga_scheduler, int ret)
struct rga_job *job;
unsigned long flags;
ktime_t now;
ktime_t now = ktime_get();
spin_lock_irqsave(&rga_scheduler->irq_lock, flags);
job = rga_scheduler->running_job;
rga_scheduler->running_job = NULL;
rga_scheduler->timer.busy_time += ktime_us_delta(now, job->timestamp);
spin_unlock_irqrestore(&rga_scheduler->irq_lock, flags);
job->flags |= RGA_JOB_DONE;
job->ret = ret;
now = ktime_get();
if (RGA_DEBUG_TIME)
pr_err("%s use time = %lld\n", __func__,
ktime_to_us(ktime_sub(now, job->timestamp)));
ktime_us_delta(now, job->running_time));
job->running_time = now;
if (job->core == RGA2_SCHEDULER_CORE0)
rga2_dma_flush_cache_for_virtual_address(&job->vir_page_table,
@@ -446,7 +449,7 @@ static inline int rga_job_wait(struct rga_scheduler_t *rga_scheduler,
if (RGA_DEBUG_TIME)
pr_err("%s use time = %lld\n", __func__,
ktime_to_us(ktime_sub(now, job->timestamp)));
ktime_to_us(ktime_sub(now, job->running_time)));
return ret;
}