In a 1-stage translation setup, a device is attached to a paging domain. In a 2-stage translation setup, a device is attached to a nested domain, which does not have the mappings for the MSI page but only an s2_parent paging domain pointer that holds the mappings. Add arm_smmu_get_msi_mapping_domain in arm_smmu_nested_ops to return the correct paging domain. Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 24836f3269b3..3962d5a55519 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3305,10 +3305,20 @@ static int arm_smmu_cache_invalidate_user(struct iommu_domain *domain, return ret; } +static struct iommu_domain * +arm_smmu_get_msi_mapping_domain(struct iommu_domain *domain) +{ + struct arm_smmu_nested_domain *nested_domain = + container_of(domain, struct arm_smmu_nested_domain, domain); + + return &nested_domain->s2_parent->domain; +} + static const struct iommu_domain_ops arm_smmu_nested_ops = { .attach_dev = arm_smmu_attach_dev_nested, .free = arm_smmu_domain_nested_free, .cache_invalidate_user = arm_smmu_cache_invalidate_user, + .get_msi_mapping_domain = arm_smmu_get_msi_mapping_domain, }; static struct iommu_domain * -- 2.43.0