From 8285fceb4371e9f0de224ffeeb2f39ead71e450a Mon Sep 17 00:00:00 2001 From: Herman Chen Date: Fri, 9 Apr 2021 10:25:19 +0800 Subject: [PATCH] video: rockchip: mpp: workaround patch for rv1126 iommu issue tips: rv1126/rv1109 use mmu-v1 which may trigger bug, and log shown below. [ 150.542230] rk_iommu ffb80480.iommu: Page fault at 0x02176000 of type write [ 150.542264] rk_iommu ffb80480.iommu: iova = 0x02176000: dte_index: 0x8 pte_index: 0x176 page_offset: 0x0 [ 150.542277] rk_iommu ffb80480.iommu: mmu_dte_addr: 0x3ebaf000 dte@0x3ebaf020: 0x375df001 valid: 1 pte@0x375df5d8: 0x10957007 valid: 1 page@0x10957000 flags: 0x6 [ 150.542288] mpp_rkvdec ffb80000.rkvdec: fault addr 0x02176000 status ab [ 150.542296] mpp_task_dump_mem_region:1546: --- dump mem region --- [ 150.542304] mpp_task_dump_mem_region:1552: reg[ 0]: 0x00000000, size 1000 [ 150.542311] mpp_task_dump_mem_region:1552: reg[ 4]: 0x0041e000, size 200000 [ 150.542319] mpp_task_dump_mem_region:1552: reg[ 6]: 0x00201000, size 1000 [ 150.542326] mpp_task_dump_mem_region:1552: reg[ 7]: 0x02176000, size 1f4000 [ 150.542333] mpp_task_dump_mem_region:1552: reg[ 10]: 0x011d6000, size 1f4000 [ 150.542340] mpp_task_dump_mem_region:1552: reg[ 11]: 0x013ca000, size 1f4000 [ 150.542347] mpp_task_dump_mem_region:1552: reg[ 12]: 0x01b9a000, size 1f4000 [ 150.542354] mpp_task_dump_mem_region:1552: reg[ 13]: 0x01b9a000, size 1f4000 [ 150.542361] mpp_task_dump_mem_region:1552: reg[ 14]: 0x01b9a000, size 1f4000 [ 150.542368] mpp_task_dump_mem_region:1552: reg[ 15]: 0x01b9a000, size 1f4000 [ 150.542375] mpp_task_dump_mem_region:1552: reg[ 16]: 0x01b9a000, size 1f4000 [ 150.542382] mpp_task_dump_mem_region:1552: reg[ 17]: 0x01b9a000, size 1f4000 method: Flush extra iommu tlb before running a task. Signed-off-by: Herman Chen Change-Id: Ic1a501bab6583e87c1c340c54e06dc7d021e99fc Signed-off-by: Ding Wei --- drivers/video/rockchip/mpp/mpp_iommu.c | 10 ++++++++ drivers/video/rockchip/mpp/mpp_iommu.h | 1 + drivers/video/rockchip/mpp/mpp_rkvdec.c | 31 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index dca7724a8afd..525aa110de75 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -604,3 +604,13 @@ int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev) return 0; } + +int mpp_iommu_flush_tlb(struct mpp_iommu_info *info) +{ + struct iommu_domain *domain = info->domain; + + if (domain && domain->ops && domain->ops->flush_iotlb_all) + domain->ops->flush_iotlb_all(domain); + + return 0; +} diff --git a/drivers/video/rockchip/mpp/mpp_iommu.h b/drivers/video/rockchip/mpp/mpp_iommu.h index 7a8b1b1279e2..0b111287f3b4 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.h +++ b/drivers/video/rockchip/mpp/mpp_iommu.h @@ -107,5 +107,6 @@ u32 mpp_iommu_get_dte_addr(struct mpp_rk_iommu *iommu); int mpp_iommu_enable(struct mpp_rk_iommu *iommu); int mpp_iommu_disable(struct mpp_rk_iommu *iommu); int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev); +int mpp_iommu_flush_tlb(struct mpp_iommu_info *info); #endif diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index bd49eaab7eb2..ebfb70054ebb 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -959,6 +959,16 @@ static int rkvdec_3328_run(struct mpp_dev *mpp, return 0; } +static int rkvdec_1126_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) +{ + struct rkvdec_task *task = to_rkvdec_task(mpp_task); + + if (task->link_mode == RKVDEC_MODE_ONEFRAME) + mpp_iommu_flush_tlb(mpp->iommu_info); + + return rkvdec_run(mpp, mpp_task); +} + static int rkvdec_irq(struct mpp_dev *mpp) { mpp->irq_status = mpp_read(mpp, RKVDEC_REG_INT_EN); @@ -1739,6 +1749,15 @@ static struct mpp_dev_ops rkvdec_3399_dev_ops = { .free_task = rkvdec_free_task, }; +static struct mpp_dev_ops rkvdec_1126_dev_ops = { + .alloc_task = rkvdec_alloc_task, + .run = rkvdec_1126_run, + .irq = rkvdec_irq, + .isr = rkvdec_isr, + .finish = rkvdec_finish, + .result = rkvdec_result, + .free_task = rkvdec_free_task, +}; static const struct mpp_dev_var rk_hevcdec_data = { .device_type = MPP_DEVICE_HEVC_DEC, .hw_info = &rk_hevcdec_hw_info, @@ -1787,6 +1806,14 @@ static const struct mpp_dev_var rkvdec_3328_data = { .dev_ops = &rkvdec_3328_dev_ops, }; +static const struct mpp_dev_var rkvdec_1126_data = { + .device_type = MPP_DEVICE_RKVDEC, + .hw_info = &rkvdec_v1_hw_info, + .trans_info = rkvdec_v1_trans, + .hw_ops = &rkvdec_v1_hw_ops, + .dev_ops = &rkvdec_1126_dev_ops, +}; + static const struct of_device_id mpp_rkvdec_dt_match[] = { { .compatible = "rockchip,hevc-decoder", @@ -1812,6 +1839,10 @@ static const struct of_device_id mpp_rkvdec_dt_match[] = { .compatible = "rockchip,rkv-decoder-rk3328", .data = &rkvdec_3328_data, }, + { + .compatible = "rockchip,rkv-decoder-rv1126", + .data = &rkvdec_1126_data, + }, {}, };