| .. | .. |
|---|
| 22 | 22 | #include <linux/proc_fs.h> |
|---|
| 23 | 23 | #include <linux/nospec.h> |
|---|
| 24 | 24 | #include <soc/rockchip/pm_domains.h> |
|---|
| 25 | +#include <soc/rockchip/rockchip_iommu.h> |
|---|
| 25 | 26 | |
|---|
| 26 | 27 | #include "mpp_debug.h" |
|---|
| 27 | 28 | #include "mpp_common.h" |
|---|
| .. | .. |
|---|
| 882 | 883 | return 0; |
|---|
| 883 | 884 | } |
|---|
| 884 | 885 | |
|---|
| 886 | +static int vepu2_iommu_fault_handle(struct iommu_domain *iommu, struct device *iommu_dev, |
|---|
| 887 | + unsigned long iova, int status, void *arg) |
|---|
| 888 | +{ |
|---|
| 889 | + struct mpp_dev *mpp = (struct mpp_dev *)arg; |
|---|
| 890 | + struct mpp_task *mpp_task; |
|---|
| 891 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
|---|
| 892 | + struct vepu_ccu *ccu = enc->ccu; |
|---|
| 893 | + |
|---|
| 894 | + dev_err(iommu_dev, "fault addr 0x%08lx status %x arg %p\n", |
|---|
| 895 | + iova, status, arg); |
|---|
| 896 | + |
|---|
| 897 | + if (ccu) { |
|---|
| 898 | + int i; |
|---|
| 899 | + struct mpp_dev *core; |
|---|
| 900 | + |
|---|
| 901 | + for (i = 0; i < ccu->core_num; i++) { |
|---|
| 902 | + core = ccu->cores[i]; |
|---|
| 903 | + if (core->iommu_info && (&core->iommu_info->pdev->dev == iommu_dev)) { |
|---|
| 904 | + mpp = core; |
|---|
| 905 | + break; |
|---|
| 906 | + } |
|---|
| 907 | + } |
|---|
| 908 | + } |
|---|
| 909 | + |
|---|
| 910 | + if (!mpp) { |
|---|
| 911 | + dev_err(iommu_dev, "pagefault without device to handle\n"); |
|---|
| 912 | + return 0; |
|---|
| 913 | + } |
|---|
| 914 | + mpp_task = mpp->cur_task; |
|---|
| 915 | + if (mpp_task) |
|---|
| 916 | + mpp_task_dump_mem_region(mpp, mpp_task); |
|---|
| 917 | + |
|---|
| 918 | + mpp_task_dump_hw_reg(mpp); |
|---|
| 919 | + /* |
|---|
| 920 | + * Mask iommu irq, in order for iommu not repeatedly trigger pagefault. |
|---|
| 921 | + * Until the pagefault task finish by hw timeout. |
|---|
| 922 | + */ |
|---|
| 923 | + rockchip_iommu_mask_irq(mpp->dev); |
|---|
| 924 | + |
|---|
| 925 | + return 0; |
|---|
| 926 | +} |
|---|
| 927 | + |
|---|
| 885 | 928 | static struct mpp_hw_ops vepu_v2_hw_ops = { |
|---|
| 886 | 929 | .init = vepu_init, |
|---|
| 887 | 930 | .clk_on = vepu_clk_on, |
|---|
| .. | .. |
|---|
| 1100 | 1143 | return -EINVAL; |
|---|
| 1101 | 1144 | } |
|---|
| 1102 | 1145 | |
|---|
| 1146 | + mpp->fault_handler = vepu2_iommu_fault_handle; |
|---|
| 1103 | 1147 | mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS; |
|---|
| 1104 | 1148 | vepu_procfs_init(mpp); |
|---|
| 1105 | 1149 | vepu_procfs_ccu_init(mpp); |
|---|
| .. | .. |
|---|
| 1149 | 1193 | return -EINVAL; |
|---|
| 1150 | 1194 | } |
|---|
| 1151 | 1195 | |
|---|
| 1196 | + mpp->fault_handler = vepu2_iommu_fault_handle; |
|---|
| 1152 | 1197 | mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS; |
|---|
| 1153 | 1198 | vepu_procfs_init(mpp); |
|---|
| 1154 | 1199 | /* register current device to mpp service */ |
|---|