Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c262b511 authored by Mitchel Humpherys's avatar Mitchel Humpherys Committed by Patrick Daly
Browse files

arm64: dma-mapping: map sg lists into the SMMU as virtually contiguous



In arm_iommu_map_sg, currently we map each individual link in the given
scatterlist into the SMMU individually such that they may or may not be
virtually contiguous.  However, in most (all?) of our use cases we
actually want the entire sg list mapped into the SMMU as a single
contiguous range.  Use iommu_map_range to accomplish this.

Change-Id: Icf72ece50c3120a0091dbfab1523ff11da20f807
Signed-off-by: default avatarMitchel Humpherys <mitchelh@codeaurora.org>
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
parent 8de3a52b
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -1656,7 +1656,29 @@ int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
		int nents, enum dma_data_direction dir, unsigned long attrs)
{
	return __iommu_map_sg(dev, sg, nents, dir, attrs, false);
	struct scatterlist *s;
	int ret, i;
	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
	unsigned int iova, total_length = 0, current_offset = 0;
	int prot = __dma_direction_to_prot(dir);

	for_each_sg(sg, s, nents, i)
		total_length += s->length;

	iova = __alloc_iova(mapping, total_length);
	ret = iommu_map_sg(mapping->domain, iova, sg, nents, prot);
	if (ret != total_length) {
		__free_iova(mapping, iova, total_length);
		return 0;
	}

	for_each_sg(sg, s, nents, i) {
		s->dma_address = iova + current_offset;
		s->dma_length = total_length - current_offset;
		current_offset += s->length;
	}

	return nents;
}

static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
@@ -1706,7 +1728,15 @@ void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
			enum dma_data_direction dir, unsigned long attrs)
{
	__iommu_unmap_sg(dev, sg, nents, dir, attrs, false);
	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
	unsigned int total_length = sg_dma_len(sg);
	unsigned int iova = sg_dma_address(sg);

	total_length = PAGE_ALIGN((iova & ~PAGE_MASK) + total_length);
	iova &= PAGE_MASK;

	iommu_unmap(mapping->domain, iova, total_length);
	__free_iova(mapping, iova, total_length);
}

/**