aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2014-02-25 13:01:09 +0100
committerMarek Szyprowski <m.szyprowski@samsung.com>2014-02-28 11:55:18 +0100
commit68efd7d2fb32c2606f1da318b6a851d933813f27 (patch)
tree2b86d6df14c10b8d288ad61624e485b429a1de18 /arch/arm/mm
parentarm: dma-mapping: Add support to extend DMA IOMMU mappings (diff)
downloadlinux-dev-68efd7d2fb32c2606f1da318b6a851d933813f27.tar.xz
linux-dev-68efd7d2fb32c2606f1da318b6a851d933813f27.zip
arm: dma-mapping: remove order parameter from arm_iommu_create_mapping()
The 'order' parameter for IOMMU-aware dma-mapping implementation was introduced mainly as a hack to reduce size of the bitmap used for tracking IO virtual address space. Since now it is possible to dynamically resize the bitmap, this hack is not needed and can be removed without any impact on the client devices. This way the parameters for arm_iommu_create_mapping() becomes much easier to understand. 'size' parameter now means the maximum supported IO address space size. The code will allocate (resize) bitmap in chunks, ensuring that a single chunk is not larger than a single memory page to avoid unreliable allocations of size larger than PAGE_SIZE in atomic context. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/dma-mapping.c43
1 files changed, 21 insertions, 22 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4d06295b8e3e..4fe42ce720d2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1084,11 +1084,8 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
if (order > CONFIG_ARM_DMA_IOMMU_ALIGNMENT)
order = CONFIG_ARM_DMA_IOMMU_ALIGNMENT;
- count = ((PAGE_ALIGN(size) >> PAGE_SHIFT) +
- (1 << mapping->order) - 1) >> mapping->order;
-
- if (order > mapping->order)
- align = (1 << (order - mapping->order)) - 1;
+ count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ align = (1 << order) - 1;
spin_lock_irqsave(&mapping->lock, flags);
for (i = 0; i < mapping->nr_bitmaps; i++) {
@@ -1126,7 +1123,7 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
spin_unlock_irqrestore(&mapping->lock, flags);
iova = mapping->base + (mapping->size * i);
- iova += start << (mapping->order + PAGE_SHIFT);
+ iova += start << PAGE_SHIFT;
return iova;
}
@@ -1147,7 +1144,7 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
bitmap_base = mapping->base + mapping->size * bitmap_index;
- start = (addr - bitmap_base) >> (mapping->order + PAGE_SHIFT);
+ start = (addr - bitmap_base) >> PAGE_SHIFT;
if (addr + size > bitmap_base + mapping->size) {
/*
@@ -1158,8 +1155,7 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
*/
BUG();
} else
- count = ((size >> PAGE_SHIFT) +
- (1 << mapping->order) - 1) >> mapping->order;
+ count = size >> PAGE_SHIFT;
spin_lock_irqsave(&mapping->lock, flags);
bitmap_clear(mapping->bitmaps[bitmap_index], start, count);
@@ -1927,8 +1923,7 @@ struct dma_map_ops iommu_coherent_ops = {
* arm_iommu_create_mapping
* @bus: pointer to the bus holding the client device (for IOMMU calls)
* @base: start address of the valid IO address space
- * @size: size of the valid IO address space
- * @order: accuracy of the IO addresses allocations
+ * @size: maximum size of the valid IO address space
*
* Creates a mapping structure which holds information about used/unused
* IO address ranges, which is required to perform memory allocation and
@@ -1938,37 +1933,41 @@ struct dma_map_ops iommu_coherent_ops = {
* arm_iommu_attach_device function.
*/
struct dma_iommu_mapping *
-arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
- int order)
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
{
- unsigned int count = size >> (PAGE_SHIFT + order);
+ unsigned int bits = size >> PAGE_SHIFT;
+ unsigned int bitmap_size = BITS_TO_LONGS(bits) * sizeof(long);
struct dma_iommu_mapping *mapping;
- int extensions = 0;
+ int extensions = 1;
int err = -ENOMEM;
- if (!count)
+ if (!bitmap_size)
return ERR_PTR(-EINVAL);
+ if (bitmap_size > PAGE_SIZE) {
+ extensions = bitmap_size / PAGE_SIZE;
+ bitmap_size = PAGE_SIZE;
+ }
+
mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL);
if (!mapping)
goto err;
- mapping->bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
- mapping->bitmaps = kzalloc((extensions + 1) * sizeof(unsigned long *),
+ mapping->bitmap_size = bitmap_size;
+ mapping->bitmaps = kzalloc(extensions * sizeof(unsigned long *),
GFP_KERNEL);
if (!mapping->bitmaps)
goto err2;
- mapping->bitmaps[0] = kzalloc(mapping->bitmap_size, GFP_KERNEL);
+ mapping->bitmaps[0] = kzalloc(bitmap_size, GFP_KERNEL);
if (!mapping->bitmaps[0])
goto err3;
mapping->nr_bitmaps = 1;
mapping->extensions = extensions;
mapping->base = base;
- mapping->size = size;
- mapping->order = order;
- mapping->bits = BITS_PER_BYTE * mapping->bitmap_size;
+ mapping->size = bitmap_size << PAGE_SHIFT;
+ mapping->bits = BITS_PER_BYTE * bitmap_size;
spin_lock_init(&mapping->lock);