diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-03 14:51:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-03 14:51:51 -0400 |
commit | ff806d034ef8e9a95ff0b0532104dd65332e446b (patch) | |
tree | 6170ccd68e32ac47666879c35e9a2af922bbf446 | |
parent | 312c76f1a3989b8d0c0c13fee765bb2c41f2d114 (diff) | |
parent | f70e3c4f8b6ab61f713e040822ec51f5de498146 (diff) |
Merge branch 'for-v3.16' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping into next
Pull CMA and DMA-mapping fixes from Marek Szyprowski:
"A few fixes for dma-mapping and CMA subsystems"
* 'for-v3.16' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping:
CMA: correct unlock target
drivers/base/dma-contiguous.c: erratum of dev_get_cma_area
arm: dma-mapping: add checking cma area initialized
arm: dma-iommu: Clean up redundant variable
cma: Remove potential deadlock situation
-rw-r--r-- | arch/arm/include/asm/dma-iommu.h | 1 | ||||
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 17 | ||||
-rw-r--r-- | drivers/base/dma-contiguous.c | 34 |
3 files changed, 35 insertions, 17 deletions
diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h index eec0a12c5c1d..8e3fcb924db6 100644 --- a/arch/arm/include/asm/dma-iommu.h +++ b/arch/arm/include/asm/dma-iommu.h | |||
@@ -18,7 +18,6 @@ struct dma_iommu_mapping { | |||
18 | unsigned int extensions; | 18 | unsigned int extensions; |
19 | size_t bitmap_size; /* size of a single bitmap */ | 19 | size_t bitmap_size; /* size of a single bitmap */ |
20 | size_t bits; /* per bitmap */ | 20 | size_t bits; /* per bitmap */ |
21 | unsigned int size; /* per bitmap */ | ||
22 | dma_addr_t base; | 21 | dma_addr_t base; |
23 | 22 | ||
24 | spinlock_t lock; | 23 | spinlock_t lock; |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 6b00be1f971e..5bef858568e6 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -390,7 +390,7 @@ static int __init atomic_pool_init(void) | |||
390 | if (!pages) | 390 | if (!pages) |
391 | goto no_pages; | 391 | goto no_pages; |
392 | 392 | ||
393 | if (IS_ENABLED(CONFIG_DMA_CMA)) | 393 | if (dev_get_cma_area(NULL)) |
394 | ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page, | 394 | ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page, |
395 | atomic_pool_init); | 395 | atomic_pool_init); |
396 | else | 396 | else |
@@ -701,7 +701,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, | |||
701 | addr = __alloc_simple_buffer(dev, size, gfp, &page); | 701 | addr = __alloc_simple_buffer(dev, size, gfp, &page); |
702 | else if (!(gfp & __GFP_WAIT)) | 702 | else if (!(gfp & __GFP_WAIT)) |
703 | addr = __alloc_from_pool(size, &page); | 703 | addr = __alloc_from_pool(size, &page); |
704 | else if (!IS_ENABLED(CONFIG_DMA_CMA)) | 704 | else if (!dev_get_cma_area(dev)) |
705 | addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller); | 705 | addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller); |
706 | else | 706 | else |
707 | addr = __alloc_from_contiguous(dev, size, prot, &page, caller); | 707 | addr = __alloc_from_contiguous(dev, size, prot, &page, caller); |
@@ -790,7 +790,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr, | |||
790 | __dma_free_buffer(page, size); | 790 | __dma_free_buffer(page, size); |
791 | } else if (__free_from_pool(cpu_addr, size)) { | 791 | } else if (__free_from_pool(cpu_addr, size)) { |
792 | return; | 792 | return; |
793 | } else if (!IS_ENABLED(CONFIG_DMA_CMA)) { | 793 | } else if (!dev_get_cma_area(dev)) { |
794 | __dma_free_remap(cpu_addr, size); | 794 | __dma_free_remap(cpu_addr, size); |
795 | __dma_free_buffer(page, size); | 795 | __dma_free_buffer(page, size); |
796 | } else { | 796 | } else { |
@@ -1074,6 +1074,7 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping, | |||
1074 | unsigned int order = get_order(size); | 1074 | unsigned int order = get_order(size); |
1075 | unsigned int align = 0; | 1075 | unsigned int align = 0; |
1076 | unsigned int count, start; | 1076 | unsigned int count, start; |
1077 | size_t mapping_size = mapping->bits << PAGE_SHIFT; | ||
1077 | unsigned long flags; | 1078 | unsigned long flags; |
1078 | dma_addr_t iova; | 1079 | dma_addr_t iova; |
1079 | int i; | 1080 | int i; |
@@ -1119,7 +1120,7 @@ static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping, | |||
1119 | } | 1120 | } |
1120 | spin_unlock_irqrestore(&mapping->lock, flags); | 1121 | spin_unlock_irqrestore(&mapping->lock, flags); |
1121 | 1122 | ||
1122 | iova = mapping->base + (mapping->size * i); | 1123 | iova = mapping->base + (mapping_size * i); |
1123 | iova += start << PAGE_SHIFT; | 1124 | iova += start << PAGE_SHIFT; |
1124 | 1125 | ||
1125 | return iova; | 1126 | return iova; |
@@ -1129,6 +1130,7 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping, | |||
1129 | dma_addr_t addr, size_t size) | 1130 | dma_addr_t addr, size_t size) |
1130 | { | 1131 | { |
1131 | unsigned int start, count; | 1132 | unsigned int start, count; |
1133 | size_t mapping_size = mapping->bits << PAGE_SHIFT; | ||
1132 | unsigned long flags; | 1134 | unsigned long flags; |
1133 | dma_addr_t bitmap_base; | 1135 | dma_addr_t bitmap_base; |
1134 | u32 bitmap_index; | 1136 | u32 bitmap_index; |
@@ -1136,14 +1138,14 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping, | |||
1136 | if (!size) | 1138 | if (!size) |
1137 | return; | 1139 | return; |
1138 | 1140 | ||
1139 | bitmap_index = (u32) (addr - mapping->base) / (u32) mapping->size; | 1141 | bitmap_index = (u32) (addr - mapping->base) / (u32) mapping_size; |
1140 | BUG_ON(addr < mapping->base || bitmap_index > mapping->extensions); | 1142 | BUG_ON(addr < mapping->base || bitmap_index > mapping->extensions); |
1141 | 1143 | ||
1142 | bitmap_base = mapping->base + mapping->size * bitmap_index; | 1144 | bitmap_base = mapping->base + mapping_size * bitmap_index; |
1143 | 1145 | ||
1144 | start = (addr - bitmap_base) >> PAGE_SHIFT; | 1146 | start = (addr - bitmap_base) >> PAGE_SHIFT; |
1145 | 1147 | ||
1146 | if (addr + size > bitmap_base + mapping->size) { | 1148 | if (addr + size > bitmap_base + mapping_size) { |
1147 | /* | 1149 | /* |
1148 | * The address range to be freed reaches into the iova | 1150 | * The address range to be freed reaches into the iova |
1149 | * range of the next bitmap. This should not happen as | 1151 | * range of the next bitmap. This should not happen as |
@@ -1964,7 +1966,6 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size) | |||
1964 | mapping->extensions = extensions; | 1966 | mapping->extensions = extensions; |
1965 | mapping->base = base; | 1967 | mapping->base = base; |
1966 | mapping->bits = BITS_PER_BYTE * bitmap_size; | 1968 | mapping->bits = BITS_PER_BYTE * bitmap_size; |
1967 | mapping->size = mapping->bits << PAGE_SHIFT; | ||
1968 | 1969 | ||
1969 | spin_lock_init(&mapping->lock); | 1970 | spin_lock_init(&mapping->lock); |
1970 | 1971 | ||
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 165c2c299e57..c34ec3364243 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c | |||
@@ -37,6 +37,7 @@ struct cma { | |||
37 | unsigned long base_pfn; | 37 | unsigned long base_pfn; |
38 | unsigned long count; | 38 | unsigned long count; |
39 | unsigned long *bitmap; | 39 | unsigned long *bitmap; |
40 | struct mutex lock; | ||
40 | }; | 41 | }; |
41 | 42 | ||
42 | struct cma *dma_contiguous_default_area; | 43 | struct cma *dma_contiguous_default_area; |
@@ -161,6 +162,7 @@ static int __init cma_activate_area(struct cma *cma) | |||
161 | init_cma_reserved_pageblock(pfn_to_page(base_pfn)); | 162 | init_cma_reserved_pageblock(pfn_to_page(base_pfn)); |
162 | } while (--i); | 163 | } while (--i); |
163 | 164 | ||
165 | mutex_init(&cma->lock); | ||
164 | return 0; | 166 | return 0; |
165 | } | 167 | } |
166 | 168 | ||
@@ -261,6 +263,13 @@ err: | |||
261 | return ret; | 263 | return ret; |
262 | } | 264 | } |
263 | 265 | ||
266 | static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count) | ||
267 | { | ||
268 | mutex_lock(&cma->lock); | ||
269 | bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count); | ||
270 | mutex_unlock(&cma->lock); | ||
271 | } | ||
272 | |||
264 | /** | 273 | /** |
265 | * dma_alloc_from_contiguous() - allocate pages from contiguous area | 274 | * dma_alloc_from_contiguous() - allocate pages from contiguous area |
266 | * @dev: Pointer to device for which the allocation is performed. | 275 | * @dev: Pointer to device for which the allocation is performed. |
@@ -269,7 +278,7 @@ err: | |||
269 | * | 278 | * |
270 | * This function allocates memory buffer for specified device. It uses | 279 | * This function allocates memory buffer for specified device. It uses |
271 | * device specific contiguous memory area if available or the default | 280 | * device specific contiguous memory area if available or the default |
272 | * global one. Requires architecture specific get_dev_cma_area() helper | 281 | * global one. Requires architecture specific dev_get_cma_area() helper |
273 | * function. | 282 | * function. |
274 | */ | 283 | */ |
275 | struct page *dma_alloc_from_contiguous(struct device *dev, int count, | 284 | struct page *dma_alloc_from_contiguous(struct device *dev, int count, |
@@ -294,30 +303,41 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count, | |||
294 | 303 | ||
295 | mask = (1 << align) - 1; | 304 | mask = (1 << align) - 1; |
296 | 305 | ||
297 | mutex_lock(&cma_mutex); | ||
298 | 306 | ||
299 | for (;;) { | 307 | for (;;) { |
308 | mutex_lock(&cma->lock); | ||
300 | pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count, | 309 | pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count, |
301 | start, count, mask); | 310 | start, count, mask); |
302 | if (pageno >= cma->count) | 311 | if (pageno >= cma->count) { |
312 | mutex_unlock(&cma->lock); | ||
303 | break; | 313 | break; |
314 | } | ||
315 | bitmap_set(cma->bitmap, pageno, count); | ||
316 | /* | ||
317 | * It's safe to drop the lock here. We've marked this region for | ||
318 | * our exclusive use. If the migration fails we will take the | ||
319 | * lock again and unmark it. | ||
320 | */ | ||
321 | mutex_unlock(&cma->lock); | ||
304 | 322 | ||
305 | pfn = cma->base_pfn + pageno; | 323 | pfn = cma->base_pfn + pageno; |
324 | mutex_lock(&cma_mutex); | ||
306 | ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA); | 325 | ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA); |
326 | mutex_unlock(&cma_mutex); | ||
307 | if (ret == 0) { | 327 | if (ret == 0) { |
308 | bitmap_set(cma->bitmap, pageno, count); | ||
309 | page = pfn_to_page(pfn); | 328 | page = pfn_to_page(pfn); |
310 | break; | 329 | break; |
311 | } else if (ret != -EBUSY) { | 330 | } else if (ret != -EBUSY) { |
331 | clear_cma_bitmap(cma, pfn, count); | ||
312 | break; | 332 | break; |
313 | } | 333 | } |
334 | clear_cma_bitmap(cma, pfn, count); | ||
314 | pr_debug("%s(): memory range at %p is busy, retrying\n", | 335 | pr_debug("%s(): memory range at %p is busy, retrying\n", |
315 | __func__, pfn_to_page(pfn)); | 336 | __func__, pfn_to_page(pfn)); |
316 | /* try again with a bit different memory target */ | 337 | /* try again with a bit different memory target */ |
317 | start = pageno + mask + 1; | 338 | start = pageno + mask + 1; |
318 | } | 339 | } |
319 | 340 | ||
320 | mutex_unlock(&cma_mutex); | ||
321 | pr_debug("%s(): returned %p\n", __func__, page); | 341 | pr_debug("%s(): returned %p\n", __func__, page); |
322 | return page; | 342 | return page; |
323 | } | 343 | } |
@@ -350,10 +370,8 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, | |||
350 | 370 | ||
351 | VM_BUG_ON(pfn + count > cma->base_pfn + cma->count); | 371 | VM_BUG_ON(pfn + count > cma->base_pfn + cma->count); |
352 | 372 | ||
353 | mutex_lock(&cma_mutex); | ||
354 | bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count); | ||
355 | free_contig_range(pfn, count); | 373 | free_contig_range(pfn, count); |
356 | mutex_unlock(&cma_mutex); | 374 | clear_cma_bitmap(cma, pfn, count); |
357 | 375 | ||
358 | return true; | 376 | return true; |
359 | } | 377 | } |