video: rockchip: rga3: allow jobs in batch-mode to fail

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: Id2b67f8e77c4668423289fcbca67a2bf26b4fdc7
This commit is contained in:
Yu Qiaowei
2022-07-21 21:20:11 +08:00
committed by Tao Huang
parent 14c0e4eed3
commit b535c17671
3 changed files with 72 additions and 91 deletions

View File

@@ -92,8 +92,7 @@
"." STR(DRIVER_REVISION_VERSION))
/* time limit */
#define RGA_ASYNC_TIMEOUT_DELAY 500
#define RGA_SYNC_TIMEOUT_DELAY HZ
#define RGA_JOB_TIMEOUT_DELAY HZ
#define RGA_RESET_TIMEOUT 1000
#define RGA_MAX_SCHEDULER 3
@@ -320,9 +319,12 @@ struct rga_request {
struct rga_req *task_list;
int task_count;
uint32_t finished_task_count;
uint32_t failed_task_count;
bool use_batch_mode;
bool is_running;
bool is_done;
int ret;
uint32_t sync_mode;
int32_t acquire_fence_fd;

View File

@@ -319,7 +319,7 @@ static int rga_request_manager_show(struct seq_file *m, void *data)
struct rga_req *task_list;
unsigned long flags;
int task_count = 0;
int finished_task_count = 0;
int finished_task_count = 0, failed_task_count = 0;
request_manager = rga_drvdata->pend_request_manager;
@@ -336,6 +336,7 @@ static int rga_request_manager_show(struct seq_file *m, void *data)
task_count = request->task_count;
finished_task_count = request->finished_task_count;
failed_task_count = request->failed_task_count;
task_list = request->task_list;
spin_unlock_irqrestore(&request->lock, flags);
@@ -345,8 +346,8 @@ static int rga_request_manager_show(struct seq_file *m, void *data)
continue;
}
seq_printf(m, "\t set cmd num: %d, finish job sum: %d, flags = 0x%x, ref = %d\n",
task_count, finished_task_count,
seq_printf(m, "\t set cmd num: %d, finish job: %d, failed job: %d, flags = 0x%x, ref = %d\n",
task_count, finished_task_count, failed_task_count,
request->flags, kref_read(&request->refcount));
seq_puts(m, "\t cmd dump:\n\n");

View File

@@ -221,13 +221,13 @@ static int rga_job_run(struct rga_job *job, struct rga_scheduler_t *scheduler)
ret = scheduler->ops->init_reg(job);
if (ret < 0) {
pr_err("init reg failed");
goto failed;
goto err_put_buffer_info;
}
ret = scheduler->ops->set_reg(job, scheduler);
if (ret < 0) {
pr_err("set reg failed");
goto failed;
goto err_put_buffer_info;
}
/* for debug */
@@ -236,6 +236,14 @@ static int rga_job_run(struct rga_job *job, struct rga_scheduler_t *scheduler)
return ret;
err_put_buffer_info:
if (job->flags & RGA_JOB_USE_HANDLE) {
rga_mm_put_handle_info(job);
} else {
rga_mm_unmap_buffer_info(job);
rga_mm_put_external_buffer(job);
}
failed:
rga_power_disable(scheduler);
@@ -267,7 +275,6 @@ next_job:
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
job->ret = rga_job_run(job, scheduler);
/* If some error before hw run */
if (job->ret < 0) {
pr_err("some error on rga_job_run before hw start, %s(%d)\n",
@@ -279,13 +286,6 @@ next_job:
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
if (job->flags & RGA_JOB_USE_HANDLE) {
rga_mm_put_handle_info(job);
} else {
rga_mm_unmap_buffer_info(job);
rga_mm_put_external_buffer(job);
}
rga_request_release_signal(scheduler, job);
goto next_job;
@@ -341,7 +341,7 @@ void rga_job_done(struct rga_scheduler_t *scheduler, int ret)
rga_job_finish_and_next(scheduler, job, ret);
}
static void rga_job_timeout_clean(struct rga_scheduler_t *scheduler)
static void rga_job_scheduler_timeout_clean(struct rga_scheduler_t *scheduler)
{
unsigned long flags;
struct rga_job *job = NULL;
@@ -349,15 +349,18 @@ static void rga_job_timeout_clean(struct rga_scheduler_t *scheduler)
spin_lock_irqsave(&scheduler->irq_lock, flags);
if (scheduler->running_job == NULL) {
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
return;
}
job = scheduler->running_job;
if (job && (job->flags & RGA_JOB_ASYNC) &&
(ktime_ms_delta(now, job->hw_running_time) >= RGA_ASYNC_TIMEOUT_DELAY)) {
if (ktime_ms_delta(now, job->hw_running_time) >= RGA_JOB_TIMEOUT_DELAY) {
scheduler->running_job = NULL;
scheduler->ops->soft_reset(scheduler);
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
scheduler->ops->soft_reset(scheduler);
if (job->flags & RGA_JOB_USE_HANDLE) {
rga_mm_put_handle_info(job);
} else {
@@ -365,6 +368,7 @@ static void rga_job_timeout_clean(struct rga_scheduler_t *scheduler)
rga_mm_put_external_buffer(job);
}
job->ret = -EBUSY;
rga_request_release_signal(scheduler, job);
rga_power_disable(scheduler);
@@ -397,8 +401,7 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job)
return NULL;
}
/* Only async will timeout clean */
rga_job_timeout_clean(scheduler);
rga_job_scheduler_timeout_clean(scheduler);
spin_lock_irqsave(&scheduler->irq_lock, flags);
@@ -430,35 +433,11 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job)
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
rga_job_next(scheduler);
return scheduler;
}
static void rga_running_job_abort(struct rga_job *job,
struct rga_scheduler_t *scheduler)
{
unsigned long flags;
spin_lock_irqsave(&scheduler->irq_lock, flags);
/* invalid job */
if (job == scheduler->running_job)
scheduler->running_job = NULL;
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
rga_job_cleanup(job);
}
static void rga_invalid_job_abort(struct rga_job *job)
{
rga_job_cleanup(job);
}
struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_request *request)
{
int ret;
struct rga_job *job = NULL;
struct rga_scheduler_t *scheduler = NULL;
@@ -474,41 +453,32 @@ struct rga_job *rga_job_commit(struct rga_req *rga_command_base, struct rga_requ
job->mm = request->current_mm;
if (!(job->flags & RGA_JOB_USE_HANDLE)) {
ret = rga_mm_get_external_buffer(job);
if (ret < 0) {
job->ret = rga_mm_get_external_buffer(job);
if (job->ret < 0) {
pr_err("%s: failed to get external buffer from job_cmd!\n", __func__);
goto free_job;
goto err_free_job;
}
}
scheduler = rga_job_schedule(job);
if (scheduler == NULL) {
pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__);
ret = -EINVAL;
goto invalid_job;
job->ret = -EINVAL;
goto err_invalid_job;
}
ret = job->ret;
if (ret < 0) {
pr_err("some error on job, %s(%d)\n", __func__,
__LINE__);
goto running_job_abort;
}
rga_job_next(scheduler);
return job;
free_job:
rga_job_free(job);
return ERR_PTR(ret);
err_invalid_job:
if (!(job->flags & RGA_JOB_USE_HANDLE))
rga_mm_put_external_buffer(job);
invalid_job:
rga_invalid_job_abort(job);
return ERR_PTR(ret);
err_free_job:
rga_request_release_signal(scheduler, job);
/* only used by SYNC mode */
running_job_abort:
rga_running_job_abort(job, scheduler);
return ERR_PTR(ret);
return ERR_PTR(job->ret);
}
static bool rga_is_need_current_mm(struct rga_req *req)
@@ -672,9 +642,8 @@ static int rga_request_wait(struct rga_request *request)
int left_time;
int ret;
left_time = wait_event_timeout(request->finished_wq,
request->finished_task_count == request->task_count,
RGA_SYNC_TIMEOUT_DELAY * request->task_count);
left_time = wait_event_timeout(request->finished_wq, request->is_done,
RGA_JOB_TIMEOUT_DELAY * request->task_count);
switch (left_time) {
case 0:
@@ -685,7 +654,7 @@ static int rga_request_wait(struct rga_request *request)
ret = -ERESTARTSYS;
break;
default:
ret = 0;
ret = request->ret;
break;
}
@@ -696,15 +665,9 @@ int rga_request_commit(struct rga_request *request)
{
int ret;
int i = 0;
struct rga_job *job = NULL;
for (i = 0; i < request->task_count; i++) {
job = rga_job_commit(&(request->task_list[i]), request);
if (IS_ERR_OR_NULL(job)) {
pr_err("failed to commit job!\n");
return job ? PTR_ERR(job) : -EFAULT;
}
}
for (i = 0; i < request->task_count; i++)
rga_job_commit(&(request->task_list[i]), request);
if (request->sync_mode == RGA_BLIT_SYNC) {
ret = rga_request_wait(request);
@@ -730,7 +693,7 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job
{
struct rga_pending_request_manager *request_manager;
struct rga_request *request;
int finished_task_count;
int finished_count, failed_count;
unsigned long flags;
request_manager = rga_drvdata->pend_request_manager;
@@ -755,11 +718,19 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job
spin_lock_irqsave(&request->lock, flags);
finished_task_count = ++request->finished_task_count;
if (job->ret < 0) {
request->failed_task_count++;
request->ret = job->ret;
} else {
request->finished_task_count++;
}
failed_count = request->failed_task_count;
finished_count = request->finished_task_count;
spin_unlock_irqrestore(&request->lock, flags);
if (finished_task_count >= request->task_count) {
if ((failed_count + finished_count) >= request->task_count) {
rga_dma_fence_signal(request->release_fence);
wake_up(&request->finished_wq);
@@ -767,11 +738,16 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job
spin_lock_irqsave(&request->lock, flags);
request->is_running = false;
request->is_done = true;
rga_request_put_current_mm(request);
spin_unlock_irqrestore(&request->lock, flags);
if (DEBUGGER_EN(MSG))
pr_info("request[%d] finished %d failed %d\n",
request->id, finished_count, failed_count);
/* current submit request put */
mutex_lock(&request_manager->lock);
rga_request_put(request);
@@ -918,16 +894,18 @@ int rga_request_submit(struct rga_request *request)
return -EFAULT;
}
/* Reset */
request->finished_task_count = 0;
if (request->task_list == NULL) {
pr_err("can not find task list from id[%d]", request->id);
spin_unlock_irqrestore(&request->lock, flags);
return -EINVAL;
}
/* Reset */
request->is_running = true;
request->is_done = false;
request->finished_task_count = 0;
request->failed_task_count = 0;
rga_request_get_current_mm(request);
spin_unlock_irqrestore(&request->lock, flags);
@@ -991,16 +969,17 @@ int rga_request_mpi_submit(struct rga_req *req, struct rga_request *request)
return -EFAULT;
}
/* Reset */
request->finished_task_count = 0;
if (request->task_list == NULL) {
pr_err("can not find task list from id[%d]", request->id);
spin_unlock_irqrestore(&request->lock, flags);
return -EINVAL;
}
/* Reset */
request->is_running = true;
request->is_done = false;
request->finished_task_count = 0;
request->failed_task_count = 0;
spin_unlock_irqrestore(&request->lock, flags);
@@ -1069,7 +1048,7 @@ static void rga_request_kref_release(struct kref *ref)
rga_dma_fence_put(request->release_fence);
if (!request->is_running || request->finished_task_count >= request->task_count) {
if (!request->is_running || request->is_done) {
spin_unlock_irqrestore(&request->lock, flags);
goto free_request;
}
@@ -1103,10 +1082,9 @@ static void rga_request_kref_release(struct kref *ref)
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
if (need_reset) {
need_reset = false;
pr_info("reset core[%d] by user cancel", scheduler->core);
scheduler->ops->soft_reset(scheduler);
rga_job_finish_and_next(scheduler, job, 0);
}
}