2015-06-03 17:16:37

by Lorenzo Nava

[permalink] [raw]
Subject: [RFC PATCH v2] arm DMA: Fix allocation from CMA for coherent DMA

This patch allows the use of CMA for DMA coherent memory allocation.
At the moment if the input parameter "is_coherent" is set to true
the allocation is not made using the CMA, which I think is not the
desired behaviour.

Signed-off-by: Lorenzo Nava <lorenx4@xxxxxxxx>
---
Changes in v2:
correct __arm_dma_free() according to __dma_alloc() allocation
---
arch/arm/mm/dma-mapping.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 7e7583d..15643b9 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -645,9 +645,9 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
size = PAGE_ALIGN(size);
want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs);

- if (is_coherent || nommu())
+ if (nommu())
addr = __alloc_simple_buffer(dev, size, gfp, &page);
- else if (!(gfp & __GFP_WAIT))
+ else if (!is_coherent && !(gfp & __GFP_WAIT))
addr = __alloc_from_pool(size, &page);
else if (!dev_get_cma_area(dev))
addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller, want_vaddr);
@@ -735,7 +735,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,

size = PAGE_ALIGN(size);

- if (is_coherent || nommu()) {
+ if (nommu()) {
__dma_free_buffer(page, size);
} else if (__free_from_pool(cpu_addr, size)) {
return;
--
1.7.10.4


2015-06-10 11:20:57

by Lorenzo Nava

[permalink] [raw]
Subject: Re: [RFC PATCH v2] arm DMA: Fix allocation from CMA for coherent DMA

ping!

On Wed, Jun 3, 2015 at 7:15 PM, Lorenzo Nava <[email protected]> wrote:
> This patch allows the use of CMA for DMA coherent memory allocation.
> At the moment if the input parameter "is_coherent" is set to true
> the allocation is not made using the CMA, which I think is not the
> desired behaviour.
>
> Signed-off-by: Lorenzo Nava <lorenx4@xxxxxxxx>
> ---
> Changes in v2:
> correct __arm_dma_free() according to __dma_alloc() allocation
> ---
> arch/arm/mm/dma-mapping.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index 7e7583d..15643b9 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -645,9 +645,9 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> size = PAGE_ALIGN(size);
> want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs);
>
> - if (is_coherent || nommu())
> + if (nommu())
> addr = __alloc_simple_buffer(dev, size, gfp, &page);
> - else if (!(gfp & __GFP_WAIT))
> + else if (!is_coherent && !(gfp & __GFP_WAIT))
> addr = __alloc_from_pool(size, &page);
> else if (!dev_get_cma_area(dev))
> addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller, want_vaddr);
> @@ -735,7 +735,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
>
> size = PAGE_ALIGN(size);
>
> - if (is_coherent || nommu()) {
> + if (nommu()) {
> __dma_free_buffer(page, size);
> } else if (__free_from_pool(cpu_addr, size)) {
> return;
> --
> 1.7.10.4
>

2015-06-10 16:28:31

by Catalin Marinas

[permalink] [raw]
Subject: Re: [RFC PATCH v2] arm DMA: Fix allocation from CMA for coherent DMA

On Wed, Jun 03, 2015 at 07:15:45PM +0200, Lorenzo Nava wrote:
> This patch allows the use of CMA for DMA coherent memory allocation.
> At the moment if the input parameter "is_coherent" is set to true
> the allocation is not made using the CMA, which I think is not the
> desired behaviour.
>
> Signed-off-by: Lorenzo Nava <lorenx4@xxxxxxxx>
> ---
> Changes in v2:
> correct __arm_dma_free() according to __dma_alloc() allocation
> ---
> arch/arm/mm/dma-mapping.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index 7e7583d..15643b9 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -645,9 +645,9 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> size = PAGE_ALIGN(size);
> want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs);
>
> - if (is_coherent || nommu())
> + if (nommu())
> addr = __alloc_simple_buffer(dev, size, gfp, &page);
> - else if (!(gfp & __GFP_WAIT))
> + else if (!is_coherent && !(gfp & __GFP_WAIT))
> addr = __alloc_from_pool(size, &page);
> else if (!dev_get_cma_area(dev))
> addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller, want_vaddr);

So while you allow __alloc_from_contiguous() to be called when
is_coherent, the memory returned is still non-cacheable. The reason is
that the "prot" argument passed to __dma_alloc() in
arm_coherent_dma_alloc() is pgprot_dmacoherent(PAGE_KERNEL) which means
Normal NonCacheable memory. The mmap seems to create a cacheable mapping
as vma->vm_page_prot is not passed through __get_dma_pgprot().

I think you need something like below, completely untested:

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 1ced8a0f7a52..1ee3d8e8c313 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -573,11 +573,13 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
}

-static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
+static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
+ bool coherent)
{
- prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
- pgprot_writecombine(prot) :
- pgprot_dmacoherent(prot);
+ if (dma_get_attr(DMA_ATTR_WRITE_COMBINE))
+ prot = pgprot_writecombine(prot);
+ else if (!coherent)
+ prot = pgprot_dmacoherent(prot);
return prot;
}

@@ -587,7 +589,7 @@ static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)

#define nommu() 1

-#define __get_dma_pgprot(attrs, prot) __pgprot(0)
+#define __get_dma_pgprot(attrs, prot, coherent) __pgprot(0)
#define __alloc_remap_buffer(dev, size, gfp, prot, ret, c, wv) NULL
#define __alloc_from_pool(size, ret_page) NULL
#define __alloc_from_contiguous(dev, size, prot, ret, c, wv) NULL
@@ -670,7 +672,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
gfp_t gfp, struct dma_attrs *attrs)
{
- pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
+ pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, false);
void *memory;

if (dma_alloc_from_coherent(dev, size, handle, &memory))
@@ -683,7 +685,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
{
- pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
+ pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, true);
void *memory;

if (dma_alloc_from_coherent(dev, size, handle, &memory))
@@ -733,7 +735,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
struct dma_attrs *attrs)
{
#ifdef CONFIG_MMU
- vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
+ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, false);
#endif /* CONFIG_MMU */
return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
}
@@ -1362,7 +1364,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
{
- pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
+ pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, is_device_dma_coherent(dev));
struct page **pages;
void *addr = NULL;

@@ -1414,7 +1416,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
unsigned long usize = vma->vm_end - vma->vm_start;
struct page **pages = __iommu_get_pages(cpu_addr, attrs);

- vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
+ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, is_device_dma_coherent(dev));

if (!pages)
return -ENXIO;

2015-06-10 19:34:52

by Lorenzo Nava

[permalink] [raw]
Subject: Re: [RFC PATCH v2] arm DMA: Fix allocation from CMA for coherent DMA

On Wed, Jun 10, 2015 at 6:28 PM, Catalin Marinas
<[email protected]> wrote:
>
> On Wed, Jun 03, 2015 at 07:15:45PM +0200, Lorenzo Nava wrote:
> > This patch allows the use of CMA for DMA coherent memory allocation.
> > At the moment if the input parameter "is_coherent" is set to true
> > the allocation is not made using the CMA, which I think is not the
> > desired behaviour.
> >
> > Signed-off-by: Lorenzo Nava <lorenx4@xxxxxxxx>
> > ---
> > Changes in v2:
> > correct __arm_dma_free() according to __dma_alloc() allocation
> > ---
> > arch/arm/mm/dma-mapping.c | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> > index 7e7583d..15643b9 100644
> > --- a/arch/arm/mm/dma-mapping.c
> > +++ b/arch/arm/mm/dma-mapping.c
> > @@ -645,9 +645,9 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> > size = PAGE_ALIGN(size);
> > want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs);
> >
> > - if (is_coherent || nommu())
> > + if (nommu())
> > addr = __alloc_simple_buffer(dev, size, gfp, &page);
> > - else if (!(gfp & __GFP_WAIT))
> > + else if (!is_coherent && !(gfp & __GFP_WAIT))
> > addr = __alloc_from_pool(size, &page);
> > else if (!dev_get_cma_area(dev))
> > addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller, want_vaddr);
>
> So while you allow __alloc_from_contiguous() to be called when
> is_coherent, the memory returned is still non-cacheable. The reason is
> that the "prot" argument passed to __dma_alloc() in
> arm_coherent_dma_alloc() is pgprot_dmacoherent(PAGE_KERNEL) which means
> Normal NonCacheable memory. The mmap seems to create a cacheable mapping
> as vma->vm_page_prot is not passed through __get_dma_pgprot().
>
> I think you need something like below, completely untested:
>
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index 1ced8a0f7a52..1ee3d8e8c313 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -573,11 +573,13 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
> dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
> }
>
> -static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
> +static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
> + bool coherent)
> {
> - prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
> - pgprot_writecombine(prot) :
> - pgprot_dmacoherent(prot);
> + if (dma_get_attr(DMA_ATTR_WRITE_COMBINE))
> + prot = pgprot_writecombine(prot);
> + else if (!coherent)
> + prot = pgprot_dmacoherent(prot);
> return prot;
> }
>
> @@ -587,7 +589,7 @@ static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
>
> #define nommu() 1
>
> -#define __get_dma_pgprot(attrs, prot) __pgprot(0)
> +#define __get_dma_pgprot(attrs, prot, coherent) __pgprot(0)
> #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c, wv) NULL
> #define __alloc_from_pool(size, ret_page) NULL
> #define __alloc_from_contiguous(dev, size, prot, ret, c, wv) NULL
> @@ -670,7 +672,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> gfp_t gfp, struct dma_attrs *attrs)
> {
> - pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
> + pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, false);
> void *memory;
>
> if (dma_alloc_from_coherent(dev, size, handle, &memory))
> @@ -683,7 +685,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
> static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
> dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
> {
> - pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
> + pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, true);
> void *memory;
>
> if (dma_alloc_from_coherent(dev, size, handle, &memory))
> @@ -733,7 +735,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
> struct dma_attrs *attrs)
> {
> #ifdef CONFIG_MMU
> - vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
> + vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, false);
> #endif /* CONFIG_MMU */
> return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
> }
> @@ -1362,7 +1364,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
> static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
> dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
> {
> - pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
> + pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, is_device_dma_coherent(dev));
> struct page **pages;
> void *addr = NULL;
>
> @@ -1414,7 +1416,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
> unsigned long usize = vma->vm_end - vma->vm_start;
> struct page **pages = __iommu_get_pages(cpu_addr, attrs);
>
> - vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
> + vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, is_device_dma_coherent(dev));
>
> if (!pages)
> return -ENXIO;


Thanks for the answer.
Well the final scope of this patch is just to fix what in my opinion
is an incorrect behaviour: the lack of use of CMA when the flag
"is_coherent" is set.

Of course it still exists the problem of modify the attribute to make
the memory cacheable, but it is something I would like to do in a
second step (the patch you posted is of course a good starting point).
I think that the current implementation maps memory keeping non
cacheable attributes enable, because the 'attrs' parameter passed to
arm_dma_mmap() has no WRITE_COMBINE attribute set (according to
dma_mmap_coherent() in include/asm-generic/dma-mapping-common.h).

I also notice this patch that is pending "[PATCH v3]
arm/mm/dma-mapping.c: Add arm_coherent_dma_mmap": it modifies the
mapping of memory for coherent DMA. I want to understand if the merge
of this patch requires any other modification to guarantee that
coherent memory is allocated with cacheable attributes.

Thanks.

2015-06-11 14:27:06

by Catalin Marinas

[permalink] [raw]
Subject: Re: [RFC PATCH v2] arm DMA: Fix allocation from CMA for coherent DMA

On Wed, Jun 10, 2015 at 09:34:43PM +0200, Lorenzo Nava wrote:
> On Wed, Jun 10, 2015 at 6:28 PM, Catalin Marinas
> <[email protected]> wrote:
> > On Wed, Jun 03, 2015 at 07:15:45PM +0200, Lorenzo Nava wrote:
> > > This patch allows the use of CMA for DMA coherent memory allocation.
> > > At the moment if the input parameter "is_coherent" is set to true
> > > the allocation is not made using the CMA, which I think is not the
> > > desired behaviour.
> > >
> > > Signed-off-by: Lorenzo Nava <lorenx4@xxxxxxxx>
[...]
> > So while you allow __alloc_from_contiguous() to be called when
> > is_coherent, the memory returned is still non-cacheable. The reason is
> > that the "prot" argument passed to __dma_alloc() in
> > arm_coherent_dma_alloc() is pgprot_dmacoherent(PAGE_KERNEL) which means
> > Normal NonCacheable memory. The mmap seems to create a cacheable mapping
> > as vma->vm_page_prot is not passed through __get_dma_pgprot().
[...]
> Well the final scope of this patch is just to fix what in my opinion
> is an incorrect behaviour: the lack of use of CMA when the flag
> "is_coherent" is set.

But you still have to fix it properly: "is_coherent" means cacheable
memory which you don't get with your patch.

> Of course it still exists the problem of modify the attribute to make
> the memory cacheable, but it is something I would like to do in a
> second step (the patch you posted is of course a good starting point).

So between the first and the second step, you basically break
dma_alloc_coherent() by moving the allocation from
__alloc_simple_buffer() (returning cacheable memory) to
__alloc_from_contiguous() which changes the memory attributes to
whatever __get_dma_pgprot() returned (currently Normal Non-cacheable).

> I think that the current implementation maps memory keeping non
> cacheable attributes enable, because the 'attrs' parameter passed to
> arm_dma_mmap() has no WRITE_COMBINE attribute set (according to
> dma_mmap_coherent() in include/asm-generic/dma-mapping-common.h).

At least on ARMv7, WRITE_COMBINE and Normal Non-cacheable are the same.

> I also notice this patch that is pending "[PATCH v3]
> arm/mm/dma-mapping.c: Add arm_coherent_dma_mmap": it modifies the
> mapping of memory for coherent DMA. I want to understand if the merge
> of this patch requires any other modification to guarantee that
> coherent memory is allocated with cacheable attributes.

I think this patch will go in, it is already in linux-next.

--
Catalin

2015-06-11 21:42:49

by Lorenzo Nava

[permalink] [raw]
Subject: Re: [RFC PATCH v2] arm DMA: Fix allocation from CMA for coherent DMA

On Thu, Jun 11, 2015 at 4:26 PM, Catalin Marinas
<[email protected]> wrote:
> On Wed, Jun 10, 2015 at 09:34:43PM +0200, Lorenzo Nava wrote:
>> On Wed, Jun 10, 2015 at 6:28 PM, Catalin Marinas
>> <[email protected]> wrote:
>> > On Wed, Jun 03, 2015 at 07:15:45PM +0200, Lorenzo Nava wrote:
>> > > This patch allows the use of CMA for DMA coherent memory allocation.
>> > > At the moment if the input parameter "is_coherent" is set to true
>> > > the allocation is not made using the CMA, which I think is not the
>> > > desired behaviour.
>> > >
>> > > Signed-off-by: Lorenzo Nava <lorenx4@xxxxxxxx>
> [...]
>> > So while you allow __alloc_from_contiguous() to be called when
>> > is_coherent, the memory returned is still non-cacheable. The reason is
>> > that the "prot" argument passed to __dma_alloc() in
>> > arm_coherent_dma_alloc() is pgprot_dmacoherent(PAGE_KERNEL) which means
>> > Normal NonCacheable memory. The mmap seems to create a cacheable mapping
>> > as vma->vm_page_prot is not passed through __get_dma_pgprot().
> [...]
>> Well the final scope of this patch is just to fix what in my opinion
>> is an incorrect behaviour: the lack of use of CMA when the flag
>> "is_coherent" is set.
>
> But you still have to fix it properly: "is_coherent" means cacheable
> memory which you don't get with your patch.
>
>> Of course it still exists the problem of modify the attribute to make
>> the memory cacheable, but it is something I would like to do in a
>> second step (the patch you posted is of course a good starting point).
>
> So between the first and the second step, you basically break
> dma_alloc_coherent() by moving the allocation from
> __alloc_simple_buffer() (returning cacheable memory) to
> __alloc_from_contiguous() which changes the memory attributes to
> whatever __get_dma_pgprot() returned (currently Normal Non-cacheable).
>

Maybe I'm losing something.
What I see is that dma_alloc_coherent() calls dma_alloc_attrs() with
attrs set to NULL.
Depending on DMA coherent settings the function
arm_coherent_dma_alloc() or arm_dma_alloc() is called. Functions has
similar behaviour and set prot according to __get_dma_pgprot() which
uses the pgprot_dmacoherent() attributes (in both cases), which
defines the memory bufferable and _non_ cacheable. So the memory has
the same attribute even if __alloc_simple_buffer() is used.
What I see is that only using the dma_alloc_writecombine() function
you can get cacheable memory attributes.

>> I think that the current implementation maps memory keeping non
>> cacheable attributes enable, because the 'attrs' parameter passed to
>> arm_dma_mmap() has no WRITE_COMBINE attribute set (according to
>> dma_mmap_coherent() in include/asm-generic/dma-mapping-common.h).
>
> At least on ARMv7, WRITE_COMBINE and Normal Non-cacheable are the same.

Yes, but the function __get_dma_pgprot() uses different flags
depending on attribute DMA_ATTR_WRITE_COMBINE: if defined the memory
is marked as cacheable.

>
>> I also notice this patch that is pending "[PATCH v3]
>> arm/mm/dma-mapping.c: Add arm_coherent_dma_mmap": it modifies the
>> mapping of memory for coherent DMA. I want to understand if the merge
>> of this patch requires any other modification to guarantee that
>> coherent memory is allocated with cacheable attributes.
>
> I think this patch will go in, it is already in linux-next.
>

Ok, thanks. Anyway I think it shouldn't affect the allocation stuffs.

Lorenzo

> --
> Catalin

2015-06-12 06:35:00

by Lorenzo Nava

[permalink] [raw]
Subject: Re: [RFC PATCH v2] arm DMA: Fix allocation from CMA for coherent DMA

On Thu, Jun 11, 2015 at 4:26 PM, Catalin Marinas
<[email protected]> wrote:
> On Wed, Jun 10, 2015 at 09:34:43PM +0200, Lorenzo Nava wrote:
>> On Wed, Jun 10, 2015 at 6:28 PM, Catalin Marinas
>> <[email protected]> wrote:
>> > On Wed, Jun 03, 2015 at 07:15:45PM +0200, Lorenzo Nava wrote:
>> > > This patch allows the use of CMA for DMA coherent memory allocation.
>> > > At the moment if the input parameter "is_coherent" is set to true
>> > > the allocation is not made using the CMA, which I think is not the
>> > > desired behaviour.
>> > >
>> > > Signed-off-by: Lorenzo Nava <lorenx4@xxxxxxxx>
> [...]
>> > So while you allow __alloc_from_contiguous() to be called when
>> > is_coherent, the memory returned is still non-cacheable. The reason is
>> > that the "prot" argument passed to __dma_alloc() in
>> > arm_coherent_dma_alloc() is pgprot_dmacoherent(PAGE_KERNEL) which means
>> > Normal NonCacheable memory. The mmap seems to create a cacheable mapping
>> > as vma->vm_page_prot is not passed through __get_dma_pgprot().
> [...]
>> Well the final scope of this patch is just to fix what in my opinion
>> is an incorrect behaviour: the lack of use of CMA when the flag
>> "is_coherent" is set.
>
> But you still have to fix it properly: "is_coherent" means cacheable
> memory which you don't get with your patch.
>
>> Of course it still exists the problem of modify the attribute to make
>> the memory cacheable, but it is something I would like to do in a
>> second step (the patch you posted is of course a good starting point).
>
> So between the first and the second step, you basically break
> dma_alloc_coherent() by moving the allocation from
> __alloc_simple_buffer() (returning cacheable memory) to
> __alloc_from_contiguous() which changes the memory attributes to
> whatever __get_dma_pgprot() returned (currently Normal Non-cacheable).
>

Ok, sorry, now I've understood: __alloc_simple_buffer just doesn't
consider the attributes set in arm_coherent_dma_alloc() or
arm_dma_alloc() functions.
So, as you already correctly pointed out, I have to keep cacheability
attributes coherent even using the CMA.
I will update my patch and submit a new version.

Thank you.

Lorenzo
> --
> Catalin