Skip to contentSkip to conversation

arm: dma-mapping: fallback allocation for cma failure

RFC PATCH In review Gioh Kim 3 participants 12 messages May 20, 2014 – May 22, 2014

Subsystems (2)
lore
Share & tools
lore

Gioh Kim

author
#0 lore raw

RFC PATCH 1/1 arm: dma-mapping: fallback allocation for cma failure

Thanks for your advise, Michal Nazarewicz.

Having discuss with Joonsoo, I'm adding fallback allocation after __alloc_from_contiguous(). The fallback allocation works if CMA kernel options is turned on but CMA size is zero.

--------------------- 8< ------------------------

#1 lore raw
Quoted 5 lines · Gioh Kim

Thanks for your advise, Michal Nazarewicz.

Having discuss with Joonsoo, I'm adding fallback allocation after __alloc_from_contiguous(). The fallback allocation works if CMA kernel options is turned on but CMA size is zero.

Hello, Gioh.

I also mentioned the case where devices have their specific cma_area. It means that this device needs memory with some contraint. Although I'm not familiar with DMA infrastructure, I think that we should handle this case.

How about below patch?

------------>8----------------

arch/arm/mm/dma-mapping.c +19 -6
index 6b00be1..4023434 100644
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
 	unsigned long *bitmap;
 	struct page *page;
 	struct page **pages;
-	void *ptr;
+	void *ptr = NULL;
 	int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
 	bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -393,7 +393,8 @@ static int __init atomic_pool_init(void)
 	if (IS_ENABLED(CONFIG_DMA_CMA))
 		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
 					      atomic_pool_init);
-	else
+
+	if (!ptr)
 		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
 					   atomic_pool_init);
 	if (ptr) {
@@ -701,10 +702,22 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 		addr = __alloc_simple_buffer(dev, size, gfp, &page);
 	else if (!(gfp & __GFP_WAIT))
 		addr = __alloc_from_pool(size, &page);
-	else if (!IS_ENABLED(CONFIG_DMA_CMA))
-		addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
-	else
-		addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
+	else {
+		if (IS_ENABLED(CONFIG_DMA_CMA)) {
+			addr = __alloc_from_contiguous(dev, size, prot,
+							&page, caller);
+			/*
+			 * Device specific cma_area means that
+			 * this device needs memory with some contraint.
+			 * So, we can't fall through general remap allocation.
+			 */
+			if (!addr && dev && dev->cma_area)
+				return NULL;
+		}
+
+		addr = __alloc_remap_buffer(dev, size, gfp, prot,
+							&page, caller);
+	}
 
 	if (addr)
 		*handle = pfn_to_dma(dev, page_to_pfn(page));

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#2 lore raw

That case, device-specific coherent memory allocation, is handled at dma_alloc_coherent in arm_dma_alloc. __dma_alloc handles only general coherent memory allocation.

I'm sorry missing mention about it.

2014-05-20 i??i?? 3:52, Joonsoo Kim i?' e,?:

Quoted 58 lines · Gioh Kim
Quoted 5 lines

Thanks for your advise, Michal Nazarewicz.

Having discuss with Joonsoo, I'm adding fallback allocation after __alloc_from_contiguous(). The fallback allocation works if CMA kernel options is turned on but CMA size is zero.

Hello, Gioh.

I also mentioned the case where devices have their specific cma_area. It means that this device needs memory with some contraint. Although I'm not familiar with DMA infrastructure, I think that we should handle this case.

How about below patch?

------------>8----------------

arch/arm/mm/dma-mapping.c +12 -6
index 6b00be1..4023434 100644
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
  	unsigned long *bitmap;
  	struct page *page;
  	struct page **pages;
-	void *ptr;
+	void *ptr = NULL;
  	int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
  	bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -393,7 +393,8 @@ static int __init atomic_pool_init(void)
  	if (IS_ENABLED(CONFIG_DMA_CMA))
  		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
  					      atomic_pool_init);
-	else
+
+	if (!ptr)
  		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
  					   atomic_pool_init);
  	if (ptr) {
@@ -701,10 +702,22 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  		addr = __alloc_simple_buffer(dev, size, gfp, &page);
  	else if (!(gfp & __GFP_WAIT))
  		addr = __alloc_from_pool(size, &page);
-	else if (!IS_ENABLED(CONFIG_DMA_CMA))
-		addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
-	else
-		addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
+	else {
+		if (IS_ENABLED(CONFIG_DMA_CMA)) {
+			addr = __alloc_from_contiguous(dev, size, prot,
+							&page, caller);
+			/*
+			 * Device specific cma_area means that
+			 * this device needs memory with some contraint.
+			 * So, we can't fall through general remap allocation.
+			 */

arch/arm/mm/dma-mapping.c static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, · line 723

Quoted 10 lines
arch/arm/mm/dma-mapping.c +7 -0
+			if (!addr && dev && dev->cma_area)
+				return NULL;
+		}
+
+		addr = __alloc_remap_buffer(dev, size, gfp, prot,
+							&page, caller);
+	}
 
  	if (addr)
  		*handle = pfn_to_dma(dev, page_to_pfn(page));

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw
Quoted 5 lines · Gioh Kim

That case, device-specific coherent memory allocation, is handled at dma_alloc_coherent in arm_dma_alloc. __dma_alloc handles only general coherent memory allocation.

I'm sorry missing mention about it.

Hello,

AFAIK, *coherent* memory allocation is different with *contiguous* memory allocation(CMA). So we need to handle the case I mentioned.

Thanks.

author
#4 lore raw

2014-05-20 i??i?? 5:32, Joonsoo Kim i?' e,?:

Quoted 11 lines · Gioh Kim
Quoted 5 lines

That case, device-specific coherent memory allocation, is handled at dma_alloc_coherent in arm_dma_alloc. __dma_alloc handles only general coherent memory allocation.

I'm sorry missing mention about it.

Hello,

AFAIK, *coherent* memory allocation is different with *contiguous* memory allocation(CMA). So we need to handle the case I mentioned.

Yes, I confused the coherent memory aand contiguous memory. It's my mistake.

So I checked dma_alloc_from_contiguous and found dev_get_cma_area function.
The dev_get_cma_area returns device-specific cma if it exists or default global-cma.
I think __alloc_from_contiguous doesn't distinguish device-specific cma area and global cma.
The purpose of __alloc_from_contiguous is allocation of contiguous memory from any cma area, not device-specific area.

If my assumption is right, __alloc_from_contiguous can be replaced with __alloc_remap_buffer without checking device-specific cma area.

What do you think about it?

Quoted 3 lines

Thanks.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw
In reply to Joonsoo Kim
Quoted 54 lines · Joonsoo Kim
Quoted 5 lines · Gioh Kim

Thanks for your advise, Michal Nazarewicz.

Having discuss with Joonsoo, I'm adding fallback allocation after __alloc_from_contiguous(). The fallback allocation works if CMA kernel options is turned on but CMA size is zero.

Hello, Gioh.

I also mentioned the case where devices have their specific cma_area. It means that this device needs memory with some contraint. Although I'm not familiar with DMA infrastructure, I think that we should handle this case.

How about below patch?

------------>8----------------

arch/arm/mm/dma-mapping.c +9 -6
index 6b00be1..4023434 100644
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
 	unsigned long *bitmap;
 	struct page *page;
 	struct page **pages;
-	void *ptr;
+	void *ptr = NULL;
 	int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
 	bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -393,7 +393,8 @@ static int __init atomic_pool_init(void)
 	if (IS_ENABLED(CONFIG_DMA_CMA))
 		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
 					      atomic_pool_init);
-	else
+
+	if (!ptr)
 		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
 					   atomic_pool_init);
 	if (ptr) {
@@ -701,10 +702,22 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 		addr = __alloc_simple_buffer(dev, size, gfp, &page);
 	else if (!(gfp & __GFP_WAIT))
 		addr = __alloc_from_pool(size, &page);
-	else if (!IS_ENABLED(CONFIG_DMA_CMA))
-		addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
-	else
-		addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
+	else {
+		if (IS_ENABLED(CONFIG_DMA_CMA)) {
+			addr = __alloc_from_contiguous(dev, size, prot,
+							&page, caller);
+			/*
+			 * Device specific cma_area means that

arch/arm/mm/dma-mapping.c static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, · line 720

Quoted 10 lines
arch/arm/mm/dma-mapping.c +10 -0
+			 * this device needs memory with some contraint.
+			 * So, we can't fall through general remap allocation.
+			 */
+			if (!addr && dev && dev->cma_area)
+				return NULL;
+		}
+
+		addr = __alloc_remap_buffer(dev, size, gfp, prot,
+							&page, caller);
+	}

__arm_dma_free will have to be changed to handle the fallback as well. But perhaps Marek is right and there should be no fallback for regular allocations? Than again, non-CMA allocation should be performed at least in the case of cma=0.

Quoted 3 lines
arch/arm/mm/dma-mapping.c +0 -0
 	if (addr)
 		*handle = pfn_to_dma(dev, page_to_pfn(page));
Signature · 4 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Michał “mina86” Nazarewicz    (o o)
ooo +--<[email protected]>--<xmpp:[email protected]>--ooO--(_)--Ooo--
author
#6 lore raw

2014-05-21 i??i ? 3:22, Michal Nazarewicz i?' e,?:

Quoted 62 lines · Joonsoo Kim
Quoted 61 lines · Gioh Kim
Quoted 5 lines

Thanks for your advise, Michal Nazarewicz.

Having discuss with Joonsoo, I'm adding fallback allocation after __alloc_from_contiguous(). The fallback allocation works if CMA kernel options is turned on but CMA size is zero.

Hello, Gioh.

I also mentioned the case where devices have their specific cma_area. It means that this device needs memory with some contraint. Although I'm not familiar with DMA infrastructure, I think that we should handle this case.

How about below patch?

------------>8----------------

arch/arm/mm/dma-mapping.c +16 -6
index 6b00be1..4023434 100644
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
  	unsigned long *bitmap;
  	struct page *page;
  	struct page **pages;
-	void *ptr;
+	void *ptr = NULL;
  	int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
  	bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -393,7 +393,8 @@ static int __init atomic_pool_init(void)
  	if (IS_ENABLED(CONFIG_DMA_CMA))
  		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
  					      atomic_pool_init);
-	else
+
+	if (!ptr)
  		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
  					   atomic_pool_init);
  	if (ptr) {
@@ -701,10 +702,22 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  		addr = __alloc_simple_buffer(dev, size, gfp, &page);
  	else if (!(gfp & __GFP_WAIT))
  		addr = __alloc_from_pool(size, &page);
-	else if (!IS_ENABLED(CONFIG_DMA_CMA))
-		addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
-	else
-		addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
+	else {
+		if (IS_ENABLED(CONFIG_DMA_CMA)) {
+			addr = __alloc_from_contiguous(dev, size, prot,
+							&page, caller);
+			/*
+			 * Device specific cma_area means that
+			 * this device needs memory with some contraint.
+			 * So, we can't fall through general remap allocation.
+			 */
+			if (!addr && dev && dev->cma_area)
+				return NULL;
+		}
+
Quoted 8 lines

arch/arm/mm/dma-mapping.c static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, · line 720

Quoted 3 lines
arch/arm/mm/dma-mapping.c +3 -0
+		addr = __alloc_remap_buffer(dev, size, gfp, prot,
+							&page, caller);
+	}

__arm_dma_free will have to be changed to handle the fallback as well. But perhaps Marek is right and there should be no fallback for regular allocations? Than again, non-CMA allocation should be performed at least in the case of cma=0.

I think in the cases of cma=0, CONFIG_CMA_SIZE_SEL_MBYTES=0 and CONFIG_CMA_SIZE_SEL_PERCENTAGE=0 kernel should be act as like CMA is not turned on.
non-CMA allocation should be performed in the cases.

I will send a patch soon with __arm_dma_free changes.

Quoted 7 lines

arch/arm/mm/dma-mapping.c static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, · line 723

Quoted 4 lines
arch/arm/mm/dma-mapping.c +0 -0
  	if (addr)
  		*handle = pfn_to_dma(dev, page_to_pfn(page));

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#7 lore raw
In reply to Michal Nazarewicz

I change the name of patch into "[PATCH] arm: dma-mapping: add checking cma area initialized", because I remove fallback allocation and use dev_get_cma_area() to check cma area. If no cma area exists it goes to __alloc_remap_buffer().

I think this is the same with the fallback allocation but a little simple.

I am sorry but I am not familiar kernel mailing style.
Do I have to send the new patch in new email? Or is it OK to copy the new patch here?

------------------------------ 8< ------------------------------------------- From e50388f5904105cacea746cd6917c200704f0bf9 Mon Sep 17 00:00:00 2001
From: Gioh Kim <[email protected]>
Date: Tue, 20 May 2014 14:16:20 +0900
Subject: [PATCH] arm: dma-mapping: add checking cma area initialized

If CMA is turned on and CMA size is set to zero, kernel should behave as if CMA was not enabled at compile time. Every dma allocation should check existence of cma area before requesting memory.

---
 arch/arm/mm/dma-mapping.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/mm/dma-mapping.c +8 -4
index 18e98df..61f7b93 100644
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
        unsigned long *bitmap;
        struct page *page;
        struct page **pages;
-       void *ptr;
+       void *ptr = NULL;
        int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
        bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -390,12 +390,13 @@ static int __init atomic_pool_init(void)
        if (!pages)
                goto no_pages;
 
-       if (IS_ENABLED(CONFIG_DMA_CMA))
+       if (IS_ENABLED(CONFIG_DMA_CMA) && dma_contiguous_default_area)
                ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                              atomic_pool_init);
        else
                ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
                                           atomic_pool_init);
+
        if (ptr) {
                int i;
 
@@ -669,6 +670,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
        u64 mask = get_coherent_dma_mask(dev);
        struct page *page = NULL;
        void *addr;
+       struct cma *cma = dev_get_cma_area(dev);
 
 #ifdef CONFIG_DMA_API_DEBUG
        u64 limit = (mask + 1) & ~mask;
@@ -701,7 +703,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                addr = __alloc_simple_buffer(dev, size, gfp, &page);
        else if (!(gfp & __GFP_WAIT))
                addr = __alloc_from_pool(size, &page);
-       else if (!IS_ENABLED(CONFIG_DMA_CMA))
+       else if (!IS_ENABLED(CONFIG_DMA_CMA) || !cma)
                addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
        else
                addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -780,6 +782,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                           bool is_coherent)
 {
        struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
+       struct cma *cma = dev_get_cma_area(dev);
 
        if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
                return;
@@ -790,7 +793,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                __dma_free_buffer(page, size);
        } else if (__free_from_pool(cpu_addr, size)) {
                return;
-       } else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
+       } else if (!IS_ENABLED(CONFIG_DMA_CMA) || !cma) {
                __dma_free_remap(cpu_addr, size);
                __dma_free_buffer(page, size);
        } else {
@@ -798,6 +801,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                 * Non-atomic allocations cannot be freed with IRQs disabled
                 */
                WARN_ON(irqs_disabled());
+
                __free_from_contiguous(dev, page, cpu_addr, size);
        }
 }

--
1.7.9.5

2014-05-21 i??i ? 3:22, Michal Nazarewicz i?' e,?:

Quoted 62 lines · Joonsoo Kim
Quoted 61 lines · Gioh Kim
Quoted 5 lines

Thanks for your advise, Michal Nazarewicz.

Having discuss with Joonsoo, I'm adding fallback allocation after __alloc_from_contiguous(). The fallback allocation works if CMA kernel options is turned on but CMA size is zero.

Hello, Gioh.

I also mentioned the case where devices have their specific cma_area. It means that this device needs memory with some contraint. Although I'm not familiar with DMA infrastructure, I think that we should handle this case.

How about below patch?

------------>8----------------

arch/arm/mm/dma-mapping.c +16 -6
index 6b00be1..4023434 100644
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
  	unsigned long *bitmap;
  	struct page *page;
  	struct page **pages;
-	void *ptr;
+	void *ptr = NULL;
  	int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
  	bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -393,7 +393,8 @@ static int __init atomic_pool_init(void)
  	if (IS_ENABLED(CONFIG_DMA_CMA))
  		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
  					      atomic_pool_init);
-	else
+
+	if (!ptr)
  		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
  					   atomic_pool_init);
  	if (ptr) {
@@ -701,10 +702,22 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
  		addr = __alloc_simple_buffer(dev, size, gfp, &page);
  	else if (!(gfp & __GFP_WAIT))
  		addr = __alloc_from_pool(size, &page);
-	else if (!IS_ENABLED(CONFIG_DMA_CMA))
-		addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
-	else
-		addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
+	else {
+		if (IS_ENABLED(CONFIG_DMA_CMA)) {
+			addr = __alloc_from_contiguous(dev, size, prot,
+							&page, caller);
+			/*
+			 * Device specific cma_area means that
+			 * this device needs memory with some contraint.
+			 * So, we can't fall through general remap allocation.
+			 */
+			if (!addr && dev && dev->cma_area)
+				return NULL;
+		}
+
Quoted 15 lines

arch/arm/mm/dma-mapping.c static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, · line 720

Quoted 3 lines
arch/arm/mm/dma-mapping.c +3 -0
+		addr = __alloc_remap_buffer(dev, size, gfp, prot,
+							&page, caller);
+	}

__arm_dma_free will have to be changed to handle the fallback as well. But perhaps Marek is right and there should be no fallback for regular allocations? Than again, non-CMA allocation should be performed at least in the case of cma=0.

Quoted 3 lines
arch/arm/mm/dma-mapping.c +0 -0
  	if (addr)
  		*handle = pfn_to_dma(dev, page_to_pfn(page));

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw
Quoted 10 lines · Gioh Kim

Date: Tue, 20 May 2014 14:16:20 +0900
Subject: [PATCH] arm: dma-mapping: add checking cma area initialized

If CMA is turned on and CMA size is set to zero, kernel should behave as if CMA was not enabled at compile time. Every dma allocation should check existence of cma area before requesting memory.

Some minor comments. Also, I'd love for someone more experienced with ARM to take a look at this as well.

Quoted 9 lines
---
  arch/arm/mm/dma-mapping.c |   12 ++++++++----
  1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/mm/dma-mapping.c +0 -0
index 18e98df..61f7b93 100644

arch/arm/mm/dma-mapping.c static int __init atomic_pool_init(void) · line 382

Quoted 5 lines
arch/arm/mm/dma-mapping.c +1 -1
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
         unsigned long *bitmap;
         struct page *page;
         struct page **pages;
-       void *ptr;
+       void *ptr = NULL;

This is unnecessary any more.

arch/arm/mm/dma-mapping.c static int __init atomic_pool_init(void) · line 393

Quoted 9 lines
arch/arm/mm/dma-mapping.c +1 -1
         int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
         bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -390,12 +390,13 @@ static int __init atomic_pool_init(void)
         if (!pages)
                 goto no_pages;
 
-       if (IS_ENABLED(CONFIG_DMA_CMA))
+       if (IS_ENABLED(CONFIG_DMA_CMA) && dma_contiguous_default_area)

+ if (dev_get_cma_area(NULL))

dev_get_cma_area returns NULL if !IS_ENABLED(CONFIG_DMA_CMA) so there's no need to check it explicitly. And with NULL argument, deg_get_cma_area returns the default area.

Quoted 18 lines
arch/arm/mm/dma-mapping.c +2 -0
                 ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                               atomic_pool_init);
         else
                 ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
                                            atomic_pool_init);
+
         if (ptr) {
                 int i;
 
@@ -669,6 +670,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
         u64 mask = get_coherent_dma_mask(dev);
         struct page *page = NULL;
         void *addr;
+       struct cma *cma = dev_get_cma_area(dev);
 
  #ifdef CONFIG_DMA_API_DEBUG
         u64 limit = (mask + 1) & ~mask;

arch/arm/mm/dma-mapping.c static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, · line 706

Quoted 5 lines
arch/arm/mm/dma-mapping.c +1 -1
@@ -701,7 +703,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                 addr = __alloc_simple_buffer(dev, size, gfp, &page);
         else if (!(gfp & __GFP_WAIT))
                 addr = __alloc_from_pool(size, &page);
-       else if (!IS_ENABLED(CONFIG_DMA_CMA))
+       else if (!IS_ENABLED(CONFIG_DMA_CMA) || !cma)

Like above, just do:

+ else if (!dev_get_cma_area(dev))

This will also allow to drop the “cma” variable above.

Quoted 12 lines
arch/arm/mm/dma-mapping.c +1 -0
                 addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
         else
                 addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -780,6 +782,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                            bool is_coherent)
  {
         struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
+       struct cma *cma = dev_get_cma_area(dev);
 
         if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
                 return;

arch/arm/mm/dma-mapping.c static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr, · line 796

Quoted 5 lines
arch/arm/mm/dma-mapping.c +1 -1
@@ -790,7 +793,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                 __dma_free_buffer(page, size);
         } else if (__free_from_pool(cpu_addr, size)) {
                 return;
-       } else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
+       } else if (!IS_ENABLED(CONFIG_DMA_CMA) || !cma) {

Ditto.

arch/arm/mm/dma-mapping.c static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr, · line 804

Quoted 8 lines
arch/arm/mm/dma-mapping.c +1 -0
                 __dma_free_remap(cpu_addr, size);
                 __dma_free_buffer(page, size);
         } else {
@@ -798,6 +801,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                  * Non-atomic allocations cannot be freed with IRQs disabled
                  */
                 WARN_ON(irqs_disabled());
+

Unrelated change.

Quoted 5 lines
arch/arm/mm/dma-mapping.c +0 -1
                 __free_from_contiguous(dev, page, cpu_addr, size);
         }
  }
--

1.7.9.5

Signature · 10 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Michał “mina86” Nazarewicz    (o o)
ooo +--<[email protected]>--<xmpp:[email protected]>--ooO--(_)--Ooo--

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author
#9 lore raw

I appreciate your comments.
The previous patch was ugly. But now it's beautiful! Just 3 lines!

I'm not familiar with kernel patch process.
Can I have your name at Signed-off-by: line?
What tag do I have to write your name in?

--------------------------------- 8< ---------------------------------------------- From 135c986cfaa5a7291519308b3d47e58bf9f5af25 Mon Sep 17 00:00:00 2001
From: Gioh Kim <[email protected]>
Date: Tue, 20 May 2014 14:16:20 +0900
Subject: [PATCH] arm: dma-mapping: add checking cma area initialized

If CMA is turned on and CMA size is set to zero, kernel should behave as if CMA was not enabled at compile time. Every dma allocation should check existence of cma area before requesting memory.

---
 arch/arm/mm/dma-mapping.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
arch/arm/mm/dma-mapping.c +4 -3
index 18e98df..9173a13 100644
@@ -390,12 +390,13 @@ static int __init atomic_pool_init(void)
        if (!pages)
                goto no_pages;
 
-       if (IS_ENABLED(CONFIG_DMA_CMA))
+       if (dev_get_cma_area(NULL))
                ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                              atomic_pool_init);
        else
                ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
                                           atomic_pool_init);
+
        if (ptr) {
                int i;
 
@@ -701,7 +702,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                addr = __alloc_simple_buffer(dev, size, gfp, &page);
        else if (!(gfp & __GFP_WAIT))
                addr = __alloc_from_pool(size, &page);
-       else if (!IS_ENABLED(CONFIG_DMA_CMA))
+       else if (!dev_get_cma_area(dev))
                addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
        else
                addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -790,7 +791,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                __dma_free_buffer(page, size);
        } else if (__free_from_pool(cpu_addr, size)) {
                return;
-       } else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
+       } else if (!dev_get_cma_area(dev)) {
                __dma_free_remap(cpu_addr, size);
                __dma_free_buffer(page, size);
        } else {

--
1.7.9.5

2014-05-22 i??i ? 5:11, Michal Nazarewicz i?' e,?:

Quoted 98 lines · Gioh Kim
Quoted 10 lines

Date: Tue, 20 May 2014 14:16:20 +0900
Subject: [PATCH] arm: dma-mapping: add checking cma area initialized

If CMA is turned on and CMA size is set to zero, kernel should behave as if CMA was not enabled at compile time. Every dma allocation should check existence of cma area before requesting memory.

Some minor comments. Also, I'd love for someone more experienced with ARM to take a look at this as well.

Quoted 9 lines
---
   arch/arm/mm/dma-mapping.c |   12 ++++++++----
   1 file changed, 8 insertions(+), 4 deletions(-)
arch/arm/mm/dma-mapping.c +0 -0
index 18e98df..61f7b93 100644

arch/arm/mm/dma-mapping.c static int __init atomic_pool_init(void) · line 382

Quoted 5 lines
arch/arm/mm/dma-mapping.c +1 -1
@@ -379,7 +379,7 @@ static int __init atomic_pool_init(void)
          unsigned long *bitmap;
          struct page *page;
          struct page **pages;
-       void *ptr;
+       void *ptr = NULL;

This is unnecessary any more.

Quoted 9 lines
arch/arm/mm/dma-mapping.c +1 -1
          int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
          bitmap = kzalloc(bitmap_size, GFP_KERNEL);
@@ -390,12 +390,13 @@ static int __init atomic_pool_init(void)
          if (!pages)
                  goto no_pages;
 
-       if (IS_ENABLED(CONFIG_DMA_CMA))
+       if (IS_ENABLED(CONFIG_DMA_CMA) && dma_contiguous_default_area)
(quoted diff) +1 -0
+	if (dev_get_cma_area(NULL))

dev_get_cma_area returns NULL if !IS_ENABLED(CONFIG_DMA_CMA) so there's no need to check it explicitly. And with NULL argument, deg_get_cma_area returns the default area.

Quoted 18 lines
arch/arm/mm/dma-mapping.c +2 -0
                  ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                                atomic_pool_init);
          else
                  ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
                                             atomic_pool_init);
+
          if (ptr) {
                  int i;
 
@@ -669,6 +670,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
          u64 mask = get_coherent_dma_mask(dev);
          struct page *page = NULL;
          void *addr;
+       struct cma *cma = dev_get_cma_area(dev);
 
   #ifdef CONFIG_DMA_API_DEBUG
          u64 limit = (mask + 1) & ~mask;

arch/arm/mm/dma-mapping.c static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, · line 706

Quoted 5 lines
arch/arm/mm/dma-mapping.c +1 -1
@@ -701,7 +703,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                  addr = __alloc_simple_buffer(dev, size, gfp, &page);
          else if (!(gfp & __GFP_WAIT))
                  addr = __alloc_from_pool(size, &page);
-       else if (!IS_ENABLED(CONFIG_DMA_CMA))
+       else if (!IS_ENABLED(CONFIG_DMA_CMA) || !cma)

Like above, just do:

(quoted diff) +1 -0
+	else if (!dev_get_cma_area(dev))

This will also allow to drop the a??cmaa?? variable above.

Quoted 12 lines
arch/arm/mm/dma-mapping.c +1 -0
                  addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
          else
                  addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -780,6 +782,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                             bool is_coherent)
   {
          struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
+       struct cma *cma = dev_get_cma_area(dev);
 
          if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
                  return;

arch/arm/mm/dma-mapping.c static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr, · line 796

Quoted 5 lines
arch/arm/mm/dma-mapping.c +1 -1
@@ -790,7 +793,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                  __dma_free_buffer(page, size);
          } else if (__free_from_pool(cpu_addr, size)) {
                  return;
-       } else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
+       } else if (!IS_ENABLED(CONFIG_DMA_CMA) || !cma) {

Ditto.

Quoted 17 lines

arch/arm/mm/dma-mapping.c static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr, · line 804

Quoted 8 lines
arch/arm/mm/dma-mapping.c +1 -0
                  __dma_free_remap(cpu_addr, size);
                  __dma_free_buffer(page, size);
          } else {
@@ -798,6 +801,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                   * Non-atomic allocations cannot be freed with IRQs disabled
                   */
                  WARN_ON(irqs_disabled());
+

Unrelated change.

Quoted 5 lines
arch/arm/mm/dma-mapping.c +0 -1
                  __free_from_contiguous(dev, page, cpu_addr, size);
          }
   }
--

1.7.9.5

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw
Quoted 6 lines · Gioh Kim

I appreciate your comments.
The previous patch was ugly. But now it's beautiful! Just 3 lines!

I'm not familiar with kernel patch process.
Can I have your name at Signed-off-by: line?
What tag do I have to write your name in?

My Signed-off-by line does not apply in this case. Documentation/SubmittingPatches describes what Signed-off-by means.

I've added Acked-by below. You may want to resend this patch using “git-send-email”.

Quoted 6 lines

--------------------------------- 8< ----------------------------------------------
From 135c986cfaa5a7291519308b3d47e58bf9f5af25 Mon Sep 17 00:00:00 2001
From: Gioh Kim <[email protected]>
Date: Tue, 20 May 2014 14:16:20 +0900
Subject: [PATCH] arm: dma-mapping: add checking cma area initialized

Quoted 7 lines

If CMA is turned on and CMA size is set to zero, kernel should behave as if CMA was not enabled at compile time. Every dma allocation should check existence of cma area before requesting memory.

But like before, if someone with more ARM knowledge could take a look at it, it would be awesome.

Quoted 43 lines
---
  arch/arm/mm/dma-mapping.c |    7 ++++---
  1 file changed, 4 insertions(+), 3 deletions(-)
arch/arm/mm/dma-mapping.c +4 -4
index 18e98df..9173a13 100644
@@ -390,12 +390,13 @@ static int __init atomic_pool_init(void)
         if (!pages)
                 goto no_pages;
 
-       if (IS_ENABLED(CONFIG_DMA_CMA))
+       if (dev_get_cma_area(NULL))
                 ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                               atomic_pool_init);
         else
                 ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
                                            atomic_pool_init);
+
         if (ptr) {
                 int i;
 
@@ -701,7 +702,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                 addr = __alloc_simple_buffer(dev, size, gfp, &page);
         else if (!(gfp & __GFP_WAIT))
                 addr = __alloc_from_pool(size, &page);
-       else if (!IS_ENABLED(CONFIG_DMA_CMA))
+       else if (!dev_get_cma_area(dev))
                 addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
         else
                 addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -790,7 +791,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                 __dma_free_buffer(page, size);
         } else if (__free_from_pool(cpu_addr, size)) {
                 return;
-       } else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
+       } else if (!dev_get_cma_area(dev)) {
                 __dma_free_remap(cpu_addr, size);
                 __dma_free_buffer(page, size);
         } else {
--

1.7.9.5

Signature · 10 lines
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Michał “mina86” Nazarewicz    (o o)
ooo +--<[email protected]>--<xmpp:[email protected]>--ooO--(_)--Ooo--

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author
#11 lore raw

I'll resend the patch using git-send-email with your name. I also hope some ARM-guys took a look at it.

2014-05-22 i??i?? 12:22, Michal Nazarewicz i?' e,?:

Quoted 68 lines · Gioh Kim
Quoted 6 lines

I appreciate your comments.
The previous patch was ugly. But now it's beautiful! Just 3 lines!

I'm not familiar with kernel patch process.
Can I have your name at Signed-off-by: line?
What tag do I have to write your name in?

My Signed-off-by line does not apply in this case. Documentation/SubmittingPatches describes what Signed-off-by means.

I've added Acked-by below. You may want to resend this patch using a??git-send-emaila??.

Quoted 6 lines

--------------------------------- 8< ----------------------------------------------
From 135c986cfaa5a7291519308b3d47e58bf9f5af25 Mon Sep 17 00:00:00 2001
From: Gioh Kim <[email protected]>
Date: Tue, 20 May 2014 14:16:20 +0900
Subject: [PATCH] arm: dma-mapping: add checking cma area initialized

Quoted 7 lines

If CMA is turned on and CMA size is set to zero, kernel should behave as if CMA was not enabled at compile time. Every dma allocation should check existence of cma area before requesting memory.

But like before, if someone with more ARM knowledge could take a look at it, it would be awesome.

Quoted 35 lines
---
   arch/arm/mm/dma-mapping.c |    7 ++++---
   1 file changed, 4 insertions(+), 3 deletions(-)
arch/arm/mm/dma-mapping.c +3 -2
index 18e98df..9173a13 100644
@@ -390,12 +390,13 @@ static int __init atomic_pool_init(void)
          if (!pages)
                  goto no_pages;
 
-       if (IS_ENABLED(CONFIG_DMA_CMA))
+       if (dev_get_cma_area(NULL))
                  ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                                atomic_pool_init);
          else
                  ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
                                             atomic_pool_init);
+
          if (ptr) {
                  int i;
 
@@ -701,7 +702,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                  addr = __alloc_simple_buffer(dev, size, gfp, &page);
          else if (!(gfp & __GFP_WAIT))
                  addr = __alloc_from_pool(size, &page);
-       else if (!IS_ENABLED(CONFIG_DMA_CMA))
+       else if (!dev_get_cma_area(dev))
                  addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
          else
                  addr = __alloc_from_contiguous(dev, size, prot, &page, caller);
@@ -790,7 +791,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
                  __dma_free_buffer(page, size);
          } else if (__free_from_pool(cpu_addr, size)) {
Quoted 9 lines
Quoted 8 lines
arch/arm/mm/dma-mapping.c +1 -2
                  return;
-       } else if (!IS_ENABLED(CONFIG_DMA_CMA)) {
+       } else if (!dev_get_cma_area(dev)) {
                  __dma_free_remap(cpu_addr, size);
                  __dma_free_buffer(page, size);
          } else {
--

1.7.9.5

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>