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

Commit 706381f2 authored by Chintan Pandya's avatar Chintan Pandya Committed by Charan Teja Reddy
Browse files

arm: 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 of our use cases we
actually want the entire sg list mapped into the SMMU as a single
contiguous range.

This was missing for arm 32bit, add it.

Change-Id: Ibf67f29a60b8d19e526c4719590f2f473ea9dca5
Signed-off-by: default avatarChintan Pandya <cpandya@codeaurora.org>
Signed-off-by: default avatarCharan Teja Reddy <charante@codeaurora.org>
parent 85247b2f
Loading
Loading
Loading
Loading
+34 −2
Original line number Diff line number Diff line
@@ -1843,7 +1843,31 @@ 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 i;
	size_t ret;
	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
	unsigned int total_length = 0, current_offset = 0;
	dma_addr_t iova;
	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,
@@ -1894,7 +1918,15 @@ 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);
	dma_addr_t iova = sg_dma_address(sg);

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

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

/**