mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
iommu/arm-smmu-v3: Do not bother impl_ops if IOMMU_VIOMMU_TYPE_ARM_SMMUV3
When viommu type is IOMMU_VIOMMU_TYPE_ARM_SMMUV3, always return or init the standard struct arm_vsmmu, instead of going through impl_ops that must have its own viommu type than the standard IOMMU_VIOMMU_TYPE_ARM_SMMUV3. Given that arm_vsmmu_init() is called after arm_smmu_get_viommu_size(), any unsupported viommu->type must be a corruption. And it must be a driver bug that its vsmmu_size and vsmmu_init ops aren't paired. Warn these two cases. Link: https://patch.msgid.link/r/20250724221002.1883034-2-nicolinc@nvidia.com Suggested-by: Will Deacon <will@kernel.org> Acked-by: Will Deacon <will@kernel.org> Reviewed-by: Pranjal Shrivastava <praan@google.com> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
ab6bc44159
commit
5a1c759093
|
|
@ -420,14 +420,13 @@ size_t arm_smmu_get_viommu_size(struct device *dev,
|
|||
!(smmu->features & ARM_SMMU_FEAT_S2FWB))
|
||||
return 0;
|
||||
|
||||
if (smmu->impl_ops && smmu->impl_ops->vsmmu_size &&
|
||||
viommu_type == smmu->impl_ops->vsmmu_type)
|
||||
return smmu->impl_ops->vsmmu_size;
|
||||
if (viommu_type == IOMMU_VIOMMU_TYPE_ARM_SMMUV3)
|
||||
return VIOMMU_STRUCT_SIZE(struct arm_vsmmu, core);
|
||||
|
||||
if (viommu_type != IOMMU_VIOMMU_TYPE_ARM_SMMUV3)
|
||||
if (!smmu->impl_ops || !smmu->impl_ops->vsmmu_size ||
|
||||
viommu_type != smmu->impl_ops->vsmmu_type)
|
||||
return 0;
|
||||
|
||||
return VIOMMU_STRUCT_SIZE(struct arm_vsmmu, core);
|
||||
return smmu->impl_ops->vsmmu_size;
|
||||
}
|
||||
|
||||
int arm_vsmmu_init(struct iommufd_viommu *viommu,
|
||||
|
|
@ -447,12 +446,18 @@ int arm_vsmmu_init(struct iommufd_viommu *viommu,
|
|||
/* FIXME Move VMID allocation from the S2 domain allocation to here */
|
||||
vsmmu->vmid = s2_parent->s2_cfg.vmid;
|
||||
|
||||
if (smmu->impl_ops && smmu->impl_ops->vsmmu_init &&
|
||||
viommu->type == smmu->impl_ops->vsmmu_type)
|
||||
return smmu->impl_ops->vsmmu_init(vsmmu, user_data);
|
||||
if (viommu->type == IOMMU_VIOMMU_TYPE_ARM_SMMUV3) {
|
||||
viommu->ops = &arm_vsmmu_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
viommu->ops = &arm_vsmmu_ops;
|
||||
return 0;
|
||||
/*
|
||||
* Unsupported type should be rejected by arm_smmu_get_viommu_size.
|
||||
* Seeing one here indicates a kernel bug or some data corruption.
|
||||
*/
|
||||
if (WARN_ON(viommu->type != smmu->impl_ops->vsmmu_type))
|
||||
return -EOPNOTSUPP;
|
||||
return smmu->impl_ops->vsmmu_init(vsmmu, user_data);
|
||||
}
|
||||
|
||||
int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster, u64 *evt)
|
||||
|
|
|
|||
|
|
@ -4703,6 +4703,7 @@ static void arm_smmu_impl_remove(void *data)
|
|||
static struct arm_smmu_device *arm_smmu_impl_probe(struct arm_smmu_device *smmu)
|
||||
{
|
||||
struct arm_smmu_device *new_smmu = ERR_PTR(-ENODEV);
|
||||
const struct arm_smmu_impl_ops *ops;
|
||||
int ret;
|
||||
|
||||
if (smmu->impl_dev && (smmu->options & ARM_SMMU_OPT_TEGRA241_CMDQV))
|
||||
|
|
@ -4713,11 +4714,24 @@ static struct arm_smmu_device *arm_smmu_impl_probe(struct arm_smmu_device *smmu)
|
|||
if (IS_ERR(new_smmu))
|
||||
return new_smmu;
|
||||
|
||||
ops = new_smmu->impl_ops;
|
||||
if (ops) {
|
||||
/* vsmmu_size and vsmmu_init ops must be paired */
|
||||
if (WARN_ON(!ops->vsmmu_size != !ops->vsmmu_init)) {
|
||||
ret = -EINVAL;
|
||||
goto err_remove;
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(new_smmu->dev, arm_smmu_impl_remove,
|
||||
new_smmu);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
return new_smmu;
|
||||
|
||||
err_remove:
|
||||
arm_smmu_impl_remove(new_smmu);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int arm_smmu_device_probe(struct platform_device *pdev)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user