video: rockchip: mpp: rkvdec2: Trigger reset when iommu pagefault

1. When iommu pagefault, hardware will stop and wait to deal with it.
in order to respond quickly, such as NVR, reset the hardware directly.
2. The iommu handle should be for the current device, not the queue.
and, the mpp_task_dump_hw_reg function is used to dump hardware register
info, it no relation for task.
3. In the mode of link-mode and multi-core, it cannot accurately get task
via queue->running_task, thereforce, it is not suitable to dump task
register here.

Change-Id: Ifed2cbc484997a07ed65c38c16062abe9b9aff81
Signed-off-by: Ding Wei <leo.ding@rock-chips.com>
This commit is contained in:
Ding Wei
2022-03-02 17:06:55 +08:00
committed by Tao Huang
parent a8e9b2055a
commit 12f76c8580
7 changed files with 41 additions and 34 deletions

View File

@@ -1928,15 +1928,12 @@ int mpp_task_dump_reg(struct mpp_dev *mpp,
return 0;
}
int mpp_task_dump_hw_reg(struct mpp_dev *mpp, struct mpp_task *task)
int mpp_task_dump_hw_reg(struct mpp_dev *mpp)
{
if (!task)
return -EIO;
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) {
u32 i;
u32 s = task->hw_info->reg_start;
u32 e = task->hw_info->reg_end;
u32 s = mpp->var->hw_info->reg_start;
u32 e = mpp->var->hw_info->reg_end;
mpp_err("--- dump hardware register ---\n");
for (i = s; i <= e; i++) {
@@ -1955,22 +1952,10 @@ static int mpp_iommu_handle(struct iommu_domain *iommu,
unsigned long iova,
int status, void *arg)
{
struct mpp_taskqueue *queue = (struct mpp_taskqueue *)arg;
struct mpp_task *task = mpp_taskqueue_get_running_task(queue);
struct mpp_dev *mpp;
struct mpp_dev *mpp = (struct mpp_dev *)arg;
/*
* NOTE: In link mode, this task may not be the task of the current
* hardware processing error
*/
if (!task || !task->session)
return -EIO;
/* get mpp from cur task */
mpp = mpp_get_task_used_device(task, task->session);
dev_err(mpp->dev, "fault addr 0x%08lx status %x\n", iova, status);
mpp_task_dump_mem_region(mpp, task);
mpp_task_dump_hw_reg(mpp, task);
mpp_task_dump_hw_reg(mpp);
if (mpp->iommu_info->hdl)
mpp->iommu_info->hdl(iommu, iommu_dev, iova, status, arg);
@@ -2075,7 +2060,7 @@ int mpp_dev_probe(struct mpp_dev *mpp,
/* set iommu fault handler */
if (mpp->iommu_info)
iommu_set_fault_handler(mpp->iommu_info->domain,
mpp_iommu_handle, mpp->queue);
mpp_iommu_handle, mpp);
/* read hardware id */
if (hw_info->reg_id >= 0) {

View File

@@ -625,8 +625,7 @@ int mpp_task_dump_mem_region(struct mpp_dev *mpp,
struct mpp_task *task);
int mpp_task_dump_reg(struct mpp_dev *mpp,
struct mpp_task *task);
int mpp_task_dump_hw_reg(struct mpp_dev *mpp,
struct mpp_task *task);
int mpp_task_dump_hw_reg(struct mpp_dev *mpp);
void mpp_free_task(struct kref *ref);
int mpp_session_deinit(struct mpp_session *session);

View File

@@ -384,9 +384,8 @@ static int rkvdec2_isr(struct mpp_dev *mpp)
RKVDEC_TIMEOUT_STA | RKVDEC_ERROR_STA;
if (err_mask & task->irq_status) {
atomic_inc(&mpp->reset_request);
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n",
task->irq_status);
mpp_task_dump_hw_reg(mpp, mpp_task);
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", task->irq_status);
mpp_task_dump_hw_reg(mpp);
}
mpp_task_finish(mpp_task->session, mpp_task);
@@ -1111,6 +1110,7 @@ static int rkvdec2_core_probe(struct platform_device *pdev)
mpp->dev_ops->task_worker = rkvdec2_soft_ccu_worker;
kthread_init_work(&mpp->work, rkvdec2_soft_ccu_worker);
mpp->iommu_info->hdl = rkvdec2_ccu_iommu_fault_handle;
/* get irq request */
ret = devm_request_threaded_irq(dev, mpp->irq, rkvdec2_soft_ccu_irq, NULL,
IRQF_SHARED, dev_name(dev), mpp);

View File

@@ -1672,8 +1672,11 @@ static int rkvdec2_soft_ccu_dequeue(struct mpp_taskqueue *queue)
task->irq_status = irq_status;
mpp_debug(DEBUG_IRQ_CHECK, "irq_status=%08x, timeout=%u, abort=%u\n",
irq_status, timeout_flag, abort_flag);
if (mpp->dev_ops->finish)
if (irq_status && mpp->dev_ops->finish)
mpp->dev_ops->finish(mpp, mpp_task);
else
task->reg[RKVDEC_REG_INT_EN_INDEX] = RKVDEC_TIMEOUT_STA;
set_bit(TASK_STATE_FINISH, &mpp_task->state);
set_bit(TASK_STATE_DONE, &mpp_task->state);
@@ -1771,6 +1774,26 @@ void *rkvdec2_ccu_alloc_task(struct mpp_session *session,
return &task->mpp_task;
}
int rkvdec2_ccu_iommu_fault_handle(struct iommu_domain *iommu,
struct device *iommu_dev,
unsigned long iova, int status, void *arg)
{
u32 i = 0;
struct mpp_dev *mpp = (struct mpp_dev *)arg;
mpp_debug_enter();
atomic_inc(&mpp->queue->reset_request);
for (i = 0; i < mpp->queue->core_count; i++)
rk_iommu_mask_irq(mpp->queue->cores[i]->dev);
kthread_queue_work(&mpp->queue->worker, &mpp->work);
mpp_debug_leave();
return 0;
}
irqreturn_t rkvdec2_soft_ccu_irq(int irq, void *param)
{
struct mpp_dev *mpp = param;

View File

@@ -171,6 +171,9 @@ void rkvdec2_link_session_deinit(struct mpp_session *session);
int rkvdec2_attach_ccu(struct device *dev, struct rkvdec2_dev *dec);
int rkvdec2_ccu_link_init(struct platform_device *pdev, struct rkvdec2_dev *dec);
void *rkvdec2_ccu_alloc_task(struct mpp_session *session, struct mpp_task_msgs *msgs);
int rkvdec2_ccu_iommu_fault_handle(struct iommu_domain *iommu,
struct device *iommu_dev,
unsigned long iova, int status, void *arg);
irqreturn_t rkvdec2_soft_ccu_irq(int irq, void *param);
void rkvdec2_soft_ccu_worker(struct kthread_work *work_s);

View File

@@ -524,11 +524,8 @@ static int rkvenc_isr(struct mpp_dev *mpp)
if (task->irq_status & RKVENC_INT_ERROR_BITS) {
atomic_inc(&mpp->reset_request);
/* dump register */
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) {
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n",
task->irq_status);
mpp_task_dump_hw_reg(mpp, mpp_task);
}
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", task->irq_status);
mpp_task_dump_hw_reg(mpp);
}
/* unmap reserve buffer */

View File

@@ -857,8 +857,8 @@ static int rkvenc_isr(struct mpp_dev *mpp)
if (task->irq_status & enc->hw_info->err_mask) {
atomic_inc(&mpp->reset_request);
/* dump register */
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG))
mpp_task_dump_hw_reg(mpp, mpp_task);
mpp_task_dump_hw_reg(mpp);
}
mpp_task_finish(mpp_task->session, mpp_task);