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

Following commit implements mapping of sg virtually contiguously.

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

This has been left for ARM (32-bit). Implement the same for ARM.

Change-Id: Ibf67f29a60b8d19e526c4719590f2f473ea9dca5
Signed-off-by: Chintan Pandya <cpandya@codeaurora.org>
This commit is contained in:
Chintan Pandya 2015-05-26 17:59:11 +05:30 committed by David Keitel
parent cc077f64d2
commit 81e4499b1e

View file

@ -1689,7 +1689,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, struct dma_attrs *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,
@ -1739,7 +1763,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, struct dma_attrs *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);
}
/**