mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
video: rockchip: rga3: add 'reset' debug node
Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com> Change-Id: I5839cd60c4d5d95fc01a23fc9461f40a23b78fa8
This commit is contained in:
@@ -35,6 +35,7 @@ struct rga_request *rga_request_lookup(struct rga_pending_request_manager *reque
|
||||
uint32_t id);
|
||||
|
||||
int rga_request_commit(struct rga_request *user_request);
|
||||
void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler);
|
||||
void rga_request_session_destroy_abort(struct rga_session *session);
|
||||
int rga_request_put(struct rga_request *request);
|
||||
void rga_request_get(struct rga_request *request);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "rga_drv.h"
|
||||
#include "rga_mm.h"
|
||||
#include "rga_common.h"
|
||||
#include "rga_job.h"
|
||||
|
||||
#define RGA_DEBUGGER_ROOT_NAME "rkrga"
|
||||
|
||||
@@ -462,6 +464,65 @@ static int rga_hardware_show(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rga_reset_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct rga_scheduler_t *scheduler = NULL;
|
||||
int i;
|
||||
|
||||
seq_puts(m, "help:\n");
|
||||
seq_puts(m, " 'echo <core> > reset' to reset hardware.\n");
|
||||
|
||||
seq_puts(m, "core:\n");
|
||||
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
|
||||
scheduler = rga_drvdata->scheduler[i];
|
||||
|
||||
seq_printf(m, " %s core <%d>\n",
|
||||
dev_driver_string(scheduler->dev), scheduler->core);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rga_reset_write(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
char buf[14];
|
||||
int i, ret;
|
||||
int reset_core = 0;
|
||||
int reset_done = false;
|
||||
struct rga_scheduler_t *scheduler = NULL;
|
||||
|
||||
if (len > sizeof(buf) - 1)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(buf, ubuf, len))
|
||||
return -EFAULT;
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
ret = kstrtoint(buf, 10, &reset_core);
|
||||
if (ret < 0 || reset_core <= 0) {
|
||||
pr_err("invalid core! failed to reset hardware, data = %s len = %zu.\n", buf, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
|
||||
scheduler = rga_drvdata->scheduler[i];
|
||||
|
||||
if (scheduler->core == reset_core) {
|
||||
reset_done = true;
|
||||
pr_info("reset hardware core[%d]!\n", reset_core);
|
||||
|
||||
rga_request_scheduler_abort(scheduler);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reset_done)
|
||||
pr_err("cannot find core[%d]\n", reset_core);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct rga_debugger_list rga_debugger_root_list[] = {
|
||||
{"debug", rga_debug_show, rga_debug_write, NULL},
|
||||
{"driver_version", rga_version_show, NULL, NULL},
|
||||
@@ -474,6 +535,7 @@ static struct rga_debugger_list rga_debugger_root_list[] = {
|
||||
{"dump_image", rga_dump_image_show, rga_dump_image_write, NULL},
|
||||
#endif
|
||||
{"hardware", rga_hardware_show, NULL, NULL},
|
||||
{"reset", rga_reset_show, rga_reset_write, NULL},
|
||||
};
|
||||
|
||||
static ssize_t rga_debugger_write(struct file *file, const char __user *ubuf,
|
||||
|
||||
@@ -651,6 +651,46 @@ struct rga_request *rga_request_lookup(struct rga_pending_request_manager *manag
|
||||
return request;
|
||||
}
|
||||
|
||||
void rga_request_scheduler_abort(struct rga_scheduler_t *scheduler)
|
||||
{
|
||||
struct rga_job *job;
|
||||
unsigned long flags;
|
||||
|
||||
rga_power_enable(scheduler);
|
||||
|
||||
spin_lock_irqsave(&scheduler->irq_lock, flags);
|
||||
|
||||
job = scheduler->running_job;
|
||||
if (job) {
|
||||
scheduler->running_job = NULL;
|
||||
scheduler->status = RGA_SCHEDULER_ABORT;
|
||||
scheduler->ops->soft_reset(scheduler);
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
|
||||
rga_mm_unmap_job_info(job);
|
||||
|
||||
job->ret = -EBUSY;
|
||||
rga_request_release_signal(scheduler, job);
|
||||
|
||||
rga_job_next(scheduler);
|
||||
|
||||
/*
|
||||
* Since the running job was abort, turn off the power here that
|
||||
* should have been turned off after job done (corresponds to
|
||||
* power_enable in rga_job_run()).
|
||||
*/
|
||||
rga_power_disable(scheduler);
|
||||
} else {
|
||||
scheduler->status = RGA_SCHEDULER_ABORT;
|
||||
scheduler->ops->soft_reset(scheduler);
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
}
|
||||
|
||||
rga_power_disable(scheduler);
|
||||
}
|
||||
|
||||
static int rga_request_scheduler_job_abort(struct rga_request *request)
|
||||
{
|
||||
int i;
|
||||
|
||||
Reference in New Issue
Block a user