arm: dma-mapping: remove order parameter from arm_iommu_create_mapping()
authorMarek Szyprowski <m.szyprowski@samsung.com>
Tue, 25 Feb 2014 12:01:09 +0000 (13:01 +0100)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Fri, 28 Feb 2014 10:55:18 +0000 (11:55 +0100)
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>
arch/arm/include/asm/dma-iommu.h
arch/arm/mm/dma-mapping.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_iommu.c
drivers/gpu/drm/exynos/exynos_drm_iommu.h
drivers/iommu/shmobile-iommu.c

index 686797cf5618776c717e7c14e691f010f35dce4b..eec0a12c5c1d8123e156436344fffddb949a8f37 100644 (file)
@@ -19,7 +19,6 @@ struct dma_iommu_mapping {
        size_t                  bitmap_size;    /* size of a single bitmap */
        size_t                  bits;           /* per bitmap */
        unsigned int            size;           /* per bitmap */
-       unsigned int            order;
        dma_addr_t              base;
 
        spinlock_t              lock;
@@ -27,8 +26,7 @@ struct dma_iommu_mapping {
 };
 
 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);
 
 void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping);
 
index 4d06295b8e3ef1ef3067f4faa0417e78bb688aff..4fe42ce720d2cd8066ab79319db431fdd65ba014 100644 (file)
@@ -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);
 
index 0eaf5a27e120e586129074446e816b902d7316f3..a8f9dba2a816075781aa1e420543f7a0df488197 100644 (file)
@@ -237,7 +237,6 @@ struct drm_exynos_file_private {
  *     otherwise default one.
  * @da_space_size: size of device address space.
  *     if 0 then default value is used for it.
- * @da_space_order: order to device address space.
  */
 struct exynos_drm_private {
        struct drm_fb_helper *fb_helper;
@@ -255,7 +254,6 @@ struct exynos_drm_private {
 
        unsigned long da_start;
        unsigned long da_space_size;
-       unsigned long da_space_order;
 };
 
 /*
index fb8db037827452c94783941f6e7daa70ff8788dd..b32b291f88ff0b80ba2919d919413dbe25d2c13b 100644 (file)
@@ -36,12 +36,10 @@ int drm_create_iommu_mapping(struct drm_device *drm_dev)
                priv->da_start = EXYNOS_DEV_ADDR_START;
        if (!priv->da_space_size)
                priv->da_space_size = EXYNOS_DEV_ADDR_SIZE;
-       if (!priv->da_space_order)
-               priv->da_space_order = EXYNOS_DEV_ADDR_ORDER;
 
        mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start,
-                                               priv->da_space_size,
-                                               priv->da_space_order);
+                                               priv->da_space_size);
+
        if (IS_ERR(mapping))
                return PTR_ERR(mapping);
 
index 598e60f57d4b41ff749e48fb222991914ab9f8c6..72376d41c5129c609be952f623be43b2e44d949c 100644 (file)
@@ -14,7 +14,6 @@
 
 #define EXYNOS_DEV_ADDR_START  0x20000000
 #define EXYNOS_DEV_ADDR_SIZE   0x40000000
-#define EXYNOS_DEV_ADDR_ORDER  0x0
 
 #ifdef CONFIG_DRM_EXYNOS_IOMMU
 
index 7a3b928fad1c81eadb788d45a281bacaca3f8949..464acda0bbc4bb3718a68c24f7568b4378261bb4 100644 (file)
@@ -343,7 +343,7 @@ static int shmobile_iommu_add_device(struct device *dev)
        mapping = archdata->iommu_mapping;
        if (!mapping) {
                mapping = arm_iommu_create_mapping(&platform_bus_type, 0,
-                                                  L1_LEN << 20, 0);
+                                                  L1_LEN << 20);
                if (IS_ERR(mapping))
                        return PTR_ERR(mapping);
                archdata->iommu_mapping = mapping;