[PATCH v5 09/27] iommu/arm-smmu-v3: Allocate the CD table entry in advance
Michael Shavit
mshavit at google.com
Wed Mar 13 05:17:58 PDT 2024
On Tue, Mar 5, 2024 at 7:44 AM Jason Gunthorpe <jgg at nvidia.com> wrote:
>
> Avoid arm_smmu_attach_dev() having to undo the changes to the
> smmu_domain->devices list, acquire the cdptr earlier so we don't need to
> handle that error.
>
> Now there is a clear break in arm_smmu_attach_dev() where all the
> prep-work has been done non-disruptively and we commit to making the HW
> change, which cannot fail.
>
> This completes transforming arm_smmu_attach_dev() so that it does not
> disturb the HW if it fails.
>
> Tested-by: Nicolin Chen <nicolinc at nvidia.com>
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 +++++++--------------
> 1 file changed, 8 insertions(+), 16 deletions(-)
>
> 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 2dd6cb17112e98..39081d828a2132 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -2676,6 +2676,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> struct arm_smmu_device *smmu;
> struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> struct arm_smmu_master *master;
> + struct arm_smmu_cd *cdptr;
>
> if (!fwspec)
> return -ENOENT;
> @@ -2704,6 +2705,12 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> if (ret)
> return ret;
>
> + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
> + cdptr = arm_smmu_get_cd_ptr(master, IOMMU_NO_PASID);
> + if (!cdptr)
> + return -ENOMEM;
> + }
> +
> /*
> * Prevent arm_smmu_share_asid() from trying to change the ASID
> * of either the old or new domain while we are working on it.
> @@ -2723,13 +2730,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> switch (smmu_domain->stage) {
> case ARM_SMMU_DOMAIN_S1: {
> struct arm_smmu_cd target_cd;
> - struct arm_smmu_cd *cdptr;
> -
> - cdptr = arm_smmu_get_cd_ptr(master, IOMMU_NO_PASID);
> - if (!cdptr) {
> - ret = -ENOMEM;
> - goto out_list_del;
> - }
>
> arm_smmu_make_s1_cd(&target_cd, master, smmu_domain);
> arm_smmu_write_cd_entry(master, IOMMU_NO_PASID, cdptr,
> @@ -2746,16 +2746,8 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> }
>
> arm_smmu_enable_ats(master, smmu_domain);
> - goto out_unlock;
> -
> -out_list_del:
> - spin_lock_irqsave(&smmu_domain->devices_lock, flags);
> - list_del_init(&master->domain_head);
> - spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
> -
> -out_unlock:
> mutex_unlock(&arm_smmu_asid_lock);
> - return ret;
> + return 0;
> }
>
> static int arm_smmu_attach_dev_ste(struct device *dev,
> --
> 2.43.2
>
Reviewed-by: Michael Shavit <mshavit at google.com>
More information about the linux-arm-kernel
mailing list