mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
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:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user