.. | .. |
---|
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 */ |
---|