ARM: dma-mapping: Add dma_alloc_*at*_coherent()
Hiroshi Doyu [Tue, 18 Jun 2013 05:49:09 +0000 (08:49 +0300)]
Add the version we can specify which IOVA to allocate.

Bug 1309498
Bug 1327616

Change-Id: I434171b09e40f888190b696b567d25777c69bb45
Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
Signed-off-by: Krishna Reddy <vdumpa@nvidia.com>
Reviewed-on: http://git-master/r/247938
(cherry picked from commit 063bf38038fa11b2ba0b7af64a2151b74dee8516)
Signed-off-by: Ajay Nandakumar <anandakumarm@nvidia.com>
Reviewed-on: http://git-master/r/250834
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Dan Willemsen <dwillemsen@nvidia.com>
Tested-by: Dan Willemsen <dwillemsen@nvidia.com>

arch/arm/include/asm/dma-mapping.h
arch/arm/mm/dma-mapping.c

index 4b9c37d..b11e86a 100644 (file)
@@ -133,8 +133,9 @@ extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                           gfp_t gfp, struct dma_attrs *attrs);
 
 #define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+#define dma_alloc_at_coherent(d, s, h, f) dma_alloc_at_attrs(d, s, h, f, NULL)
 
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+static inline void *dma_alloc_at_attrs(struct device *dev, size_t size,
                                       dma_addr_t *dma_handle, gfp_t flag,
                                       struct dma_attrs *attrs)
 {
@@ -147,6 +148,14 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size,
        return cpu_addr;
 }
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                      dma_addr_t *dma_handle, gfp_t flag,
+                                      struct dma_attrs *attrs)
+{
+       *dma_handle = DMA_ERROR_CODE;
+       return dma_alloc_at_attrs(dev, size, dma_handle, flag, attrs);
+}
+
 /**
  * arm_dma_free - free memory allocated by arm_dma_alloc
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
index 6d64422..d2e40f0 100644 (file)
@@ -1306,14 +1306,19 @@ err:
  * Create a mapping in device IO address space for specified pages
  */
 static dma_addr_t
-__iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
+____iommu_create_mapping(struct device *dev, dma_addr_t *req,
+                        struct page **pages, size_t size)
 {
        struct dma_iommu_mapping *mapping = dev->archdata.mapping;
        unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
        dma_addr_t dma_addr, iova;
        int i, ret = DMA_ERROR_CODE;
 
-       dma_addr = __alloc_iova(mapping, size);
+       if (req)
+               dma_addr = __alloc_iova_at(mapping, req, size);
+       else
+               dma_addr = __alloc_iova(mapping, size);
+
        if (dma_addr == DMA_ERROR_CODE)
                return dma_addr;
 
@@ -1341,6 +1346,12 @@ fail:
        return DMA_ERROR_CODE;
 }
 
+static dma_addr_t
+__iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
+{
+       return ____iommu_create_mapping(dev, NULL, pages, size);
+}
+
 static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t size)
 {
        struct dma_iommu_mapping *mapping = dev->archdata.mapping;
@@ -1426,7 +1437,6 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
         * platform--see CONFIG_HUGETLB_PAGE. */
        gfp &= ~(__GFP_COMP);
 
-       *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
        if (gfp & GFP_ATOMIC)
@@ -1436,7 +1446,11 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        if (!pages)
                return NULL;
 
-       *handle = __iommu_create_mapping(dev, pages, size);
+       if (*handle == DMA_ERROR_CODE)
+               *handle = __iommu_create_mapping(dev, pages, size);
+       else
+               *handle = ____iommu_create_mapping(dev, handle, pages, size);
+
        if (*handle == DMA_ERROR_CODE)
                goto err_buffer;