aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2012-10-15 10:03:52 -0400
committerInki Dae <daeinki@gmail.com>2012-11-29 06:30:34 -0500
commit549a17e447d72bab648c783abbba98f3bd5b4dd5 (patch)
tree51d4664c81dc8540b8b8becb4f67299cc32eee33 /arch
parent4b9347dcbe3b426d19bda99b2061a2d1fe5a2dce (diff)
ARM: dma-mapping: add support for DMA_ATTR_FORCE_CONTIGUOUS attribute
This patch adds support for DMA_ATTR_FORCE_CONTIGUOUS attribute for dma_alloc_attrs() in IOMMU-aware implementation. For allocating physically contiguous buffers Contiguous Memory Allocator is used. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mm/dma-mapping.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 58bc3e4d3bd0..f076f209c7a4 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1036,7 +1036,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
1036 spin_unlock_irqrestore(&mapping->lock, flags); 1036 spin_unlock_irqrestore(&mapping->lock, flags);
1037} 1037}
1038 1038
1039static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp) 1039static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
1040 gfp_t gfp, struct dma_attrs *attrs)
1040{ 1041{
1041 struct page **pages; 1042 struct page **pages;
1042 int count = size >> PAGE_SHIFT; 1043 int count = size >> PAGE_SHIFT;
@@ -1050,6 +1051,23 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t
1050 if (!pages) 1051 if (!pages)
1051 return NULL; 1052 return NULL;
1052 1053
1054 if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs))
1055 {
1056 unsigned long order = get_order(size);
1057 struct page *page;
1058
1059 page = dma_alloc_from_contiguous(dev, count, order);
1060 if (!page)
1061 goto error;
1062
1063 __dma_clear_buffer(page, size);
1064
1065 for (i = 0; i < count; i++)
1066 pages[i] = page + i;
1067
1068 return pages;
1069 }
1070
1053 while (count) { 1071 while (count) {
1054 int j, order = __fls(count); 1072 int j, order = __fls(count);
1055 1073
@@ -1083,14 +1101,21 @@ error:
1083 return NULL; 1101 return NULL;
1084} 1102}
1085 1103
1086static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size) 1104static int __iommu_free_buffer(struct device *dev, struct page **pages,
1105 size_t size, struct dma_attrs *attrs)
1087{ 1106{
1088 int count = size >> PAGE_SHIFT; 1107 int count = size >> PAGE_SHIFT;
1089 int array_size = count * sizeof(struct page *); 1108 int array_size = count * sizeof(struct page *);
1090 int i; 1109 int i;
1091 for (i = 0; i < count; i++) 1110
1092 if (pages[i]) 1111 if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) {
1093 __free_pages(pages[i], 0); 1112 dma_release_from_contiguous(dev, pages[0], count);
1113 } else {
1114 for (i = 0; i < count; i++)
1115 if (pages[i])
1116 __free_pages(pages[i], 0);
1117 }
1118
1094 if (array_size <= PAGE_SIZE) 1119 if (array_size <= PAGE_SIZE)
1095 kfree(pages); 1120 kfree(pages);
1096 else 1121 else
@@ -1252,7 +1277,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
1252 if (gfp & GFP_ATOMIC) 1277 if (gfp & GFP_ATOMIC)
1253 return __iommu_alloc_atomic(dev, size, handle); 1278 return __iommu_alloc_atomic(dev, size, handle);
1254 1279
1255 pages = __iommu_alloc_buffer(dev, size, gfp); 1280 pages = __iommu_alloc_buffer(dev, size, gfp, attrs);
1256 if (!pages) 1281 if (!pages)
1257 return NULL; 1282 return NULL;
1258 1283
@@ -1273,7 +1298,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
1273err_mapping: 1298err_mapping:
1274 __iommu_remove_mapping(dev, *handle, size); 1299 __iommu_remove_mapping(dev, *handle, size);
1275err_buffer: 1300err_buffer:
1276 __iommu_free_buffer(dev, pages, size); 1301 __iommu_free_buffer(dev, pages, size, attrs);
1277 return NULL; 1302 return NULL;
1278} 1303}
1279 1304
@@ -1329,7 +1354,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
1329 } 1354 }
1330 1355
1331 __iommu_remove_mapping(dev, handle, size); 1356 __iommu_remove_mapping(dev, handle, size);
1332 __iommu_free_buffer(dev, pages, size); 1357 __iommu_free_buffer(dev, pages, size, attrs);
1333} 1358}
1334 1359
1335static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt, 1360static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,