diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index c63dad30a184..ac0c4db33898 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -3106,8 +3106,13 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, prot, &size); spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); - if (ret == -ENOMEM) { + /* unmap any partially mapped iova */ + if (size) { + arm_smmu_secure_domain_unlock(smmu_domain); + arm_smmu_unmap(domain, iova, size); + arm_smmu_secure_domain_lock(smmu_domain); + } arm_smmu_prealloc_memory(smmu_domain, batch_size, &nonsecure_pool); spin_lock_irqsave(&smmu_domain->cb_lock, flags); @@ -3122,8 +3127,8 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, &nonsecure_pool); } - /* Returns 0 on error */ - if (!ret) { + /* Returns -ve val on error */ + if (ret < 0) { size_to_unmap = iova + size - __saved_iova_start; goto out; } @@ -3131,6 +3136,7 @@ static size_t arm_smmu_map_sg(struct iommu_domain *domain, unsigned long iova, iova += batch_size; idx_start = idx_end; sg_start = sg_end; + size = 0; } out: diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 75b17a766e4c..e7d5450eea9a 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -634,7 +634,8 @@ static int arm_lpae_map_sg(struct io_pgtable_ops *ops, unsigned long iova, arm_lpae_iopte prot; struct scatterlist *s; size_t mapped = 0; - int i, ret; + int i; + int ret = -EINVAL; unsigned int min_pagesz; struct io_pgtable_cfg *cfg = &data->iop.cfg; struct map_state ms; @@ -705,7 +706,7 @@ static int arm_lpae_map_sg(struct io_pgtable_ops *ops, unsigned long iova, out_err: /* Return the size of the partial mapping so that they can be undone */ *size = mapped; - return 0; + return ret; } static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl, diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h index 294b9aea0b8b..9c4e18ae0388 100644 --- a/drivers/iommu/io-pgtable.h +++ b/drivers/iommu/io-pgtable.h @@ -156,8 +156,8 @@ struct io_pgtable_cfg { * * @map: Map a physically contiguous memory region. * @map_sg: Map a scatterlist. Returns the number of bytes mapped, - * or 0 on failure. The size parameter contains the size - * of the partial mapping in case of failure. + * or -ve val on failure. The size parameter contains the + * size of the partial mapping in case of failure. * @unmap: Unmap a physically contiguous memory region. * @iova_to_phys: Translate iova to physical address. * @is_iova_coherent: Checks coherency of given IOVA. Returns True if coherent