All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 0/2] CMA for arm64
@ 2013-12-10 21:43 Laura Abbott
  2013-12-10 21:43 ` [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask Laura Abbott
  2013-12-10 21:43 ` [PATCHv3 2/2] arm64: Enable CMA Laura Abbott
  0 siblings, 2 replies; 11+ messages in thread
From: Laura Abbott @ 2013-12-10 21:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This adds support for CMA in arm64

v3: Fix a missed line to actually set the dma_handle correctly

v2: Move the dma contiguous functions from swiotlb to arm64 directly

 arch/arm64/Kconfig                      |    1 +
 arch/arm64/include/asm/dma-contiguous.h |   29 +++++++++++++++++++++++++++++
 arch/arm64/mm/dma-mapping.c             |   27 ++++++++++++++++++++++++---
 arch/arm64/mm/init.c                    |    3 +++
 4 files changed, 57 insertions(+), 3 deletions(-)

Thanks,
Laura

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask
  2013-12-10 21:43 [PATCHv3 0/2] CMA for arm64 Laura Abbott
@ 2013-12-10 21:43 ` Laura Abbott
  2013-12-11 10:42   ` Will Deacon
  2013-12-10 21:43 ` [PATCHv3 2/2] arm64: Enable CMA Laura Abbott
  1 sibling, 1 reply; 11+ messages in thread
From: Laura Abbott @ 2013-12-10 21:43 UTC (permalink / raw)
  To: linux-arm-kernel

The device passed in to dma_alloc may be NULL. Check for this before
trying to get the coherent_dma_mask.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
 arch/arm64/mm/dma-mapping.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 4bd7579..4134212 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -33,7 +33,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
 					  dma_addr_t *dma_handle, gfp_t flags,
 					  struct dma_attrs *attrs)
 {
-	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
+	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
 	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
 		flags |= GFP_DMA32;
 	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCHv3 2/2] arm64: Enable CMA
  2013-12-10 21:43 [PATCHv3 0/2] CMA for arm64 Laura Abbott
  2013-12-10 21:43 ` [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask Laura Abbott
@ 2013-12-10 21:43 ` Laura Abbott
  2013-12-11 10:40   ` Will Deacon
  1 sibling, 1 reply; 11+ messages in thread
From: Laura Abbott @ 2013-12-10 21:43 UTC (permalink / raw)
  To: linux-arm-kernel

arm64 bit targets need the features CMA provides. Add the appropriate
hooks, header files, and Kconfig to allow this to happen.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
---
 arch/arm64/Kconfig                      |    1 +
 arch/arm64/include/asm/dma-contiguous.h |   29 +++++++++++++++++++++++++++++
 arch/arm64/mm/dma-mapping.c             |   25 +++++++++++++++++++++++--
 arch/arm64/mm/init.c                    |    3 +++
 4 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/dma-contiguous.h

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 9737e97..26e4bef 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -22,6 +22,7 @@ config ARM64
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
+	select HAVE_DMA_CONTIGUOUS
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
diff --git a/arch/arm64/include/asm/dma-contiguous.h b/arch/arm64/include/asm/dma-contiguous.h
new file mode 100644
index 0000000..bc32516
--- /dev/null
+++ b/arch/arm64/include/asm/dma-contiguous.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef ASMARM64_DMA_CONTIGUOUS_H
+#define ASMARM64_DMA_CONTIGUOUS_H
+
+#ifdef __KERNEL__
+#ifdef CONFIG_CMA
+
+#include <linux/types.h>
+#include <asm-generic/dma-contiguous.h>
+
+static inline void
+dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { }
+
+#endif
+#endif
+
+#endif
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 4134212..29d10b9 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -21,6 +21,7 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
 
@@ -36,14 +37,34 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
 	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
 	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
 		flags |= GFP_DMA32;
-	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+	if (IS_ENABLED(CONFIG_DMA_CMA)) {
+		struct page *page;
+
+		page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
+							get_order(size));
+		if (!page)
+			return NULL;
+
+		*dma_handle = phys_to_dma(dev, page_to_phys(page));
+		return page_address(page);
+	} else {
+		return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+	}
 }
 
 static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
 					void *vaddr, dma_addr_t dma_handle,
 					struct dma_attrs *attrs)
 {
-	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
+	if (IS_ENABLED(CONFIG_DMA_CMA)) {
+		phys_addr_t paddr = dma_to_phys(dev, dma_handle);
+
+		dma_release_from_contiguous(dev,
+					phys_to_page(paddr),
+					size >> PAGE_SHIFT);
+	} else {
+		swiotlb_free_coherent(dev, size, vaddr, dma_handle);
+	}
 }
 
 static struct dma_map_ops arm64_swiotlb_dma_ops = {
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 67e8d7c..74b7da1 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -30,6 +30,7 @@
 #include <linux/memblock.h>
 #include <linux/sort.h>
 #include <linux/of_fdt.h>
+#include <linux/dma-contiguous.h>
 
 #include <asm/prom.h>
 #include <asm/sections.h>
@@ -173,6 +174,8 @@ void __init arm64_memblock_init(void)
 		memblock_reserve(base, size);
 	}
 
+	dma_contiguous_reserve(0);
+
 	memblock_allow_resize();
 	memblock_dump_all();
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCHv3 2/2] arm64: Enable CMA
  2013-12-10 21:43 ` [PATCHv3 2/2] arm64: Enable CMA Laura Abbott
@ 2013-12-11 10:40   ` Will Deacon
  2013-12-11 17:54     ` Laura Abbott
  0 siblings, 1 reply; 11+ messages in thread
From: Will Deacon @ 2013-12-11 10:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Laura,

Couple of really minor comments...

On Tue, Dec 10, 2013 at 09:43:36PM +0000, Laura Abbott wrote:
> arm64 bit targets need the features CMA provides. Add the appropriate
> hooks, header files, and Kconfig to allow this to happen.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
> ---
>  arch/arm64/Kconfig                      |    1 +
>  arch/arm64/include/asm/dma-contiguous.h |   29 +++++++++++++++++++++++++++++
>  arch/arm64/mm/dma-mapping.c             |   25 +++++++++++++++++++++++--
>  arch/arm64/mm/init.c                    |    3 +++
>  4 files changed, 56 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm64/include/asm/dma-contiguous.h
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 9737e97..26e4bef 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -22,6 +22,7 @@ config ARM64
>  	select HAVE_DEBUG_KMEMLEAK
>  	select HAVE_DMA_API_DEBUG
>  	select HAVE_DMA_ATTRS
> +	select HAVE_DMA_CONTIGUOUS
>  	select HAVE_GENERIC_DMA_COHERENT
>  	select HAVE_GENERIC_HARDIRQS
>  	select HAVE_HW_BREAKPOINT if PERF_EVENTS
> diff --git a/arch/arm64/include/asm/dma-contiguous.h b/arch/arm64/include/asm/dma-contiguous.h
> new file mode 100644
> index 0000000..bc32516
> --- /dev/null
> +++ b/arch/arm64/include/asm/dma-contiguous.h
> @@ -0,0 +1,29 @@
> +/*
> + * Copyright (c) 2013, The Linux Foundation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef ASMARM64_DMA_CONTIGUOUS_H
> +#define ASMARM64_DMA_CONTIGUOUS_H

We've tried to keep these guards consistent for the arm64 headers, so this
would be: __ASM_DMA_CONTIGUOUS_H.

> +
> +#ifdef __KERNEL__
> +#ifdef CONFIG_CMA

Why is this not CONFIG_DMA_CMA?

> +#include <linux/types.h>
> +#include <asm-generic/dma-contiguous.h>
> +
> +static inline void
> +dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { }
> +
> +#endif
> +#endif
> +
> +#endif
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index 4134212..29d10b9 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -21,6 +21,7 @@
>  #include <linux/export.h>
>  #include <linux/slab.h>
>  #include <linux/dma-mapping.h>
> +#include <linux/dma-contiguous.h>
>  #include <linux/vmalloc.h>
>  #include <linux/swiotlb.h>
>  
> @@ -36,14 +37,34 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
>  	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
>  	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
>  		flags |= GFP_DMA32;
> -	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
> +	if (IS_ENABLED(CONFIG_DMA_CMA)) {
> +		struct page *page;
> +
> +		page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
> +							get_order(size));
> +		if (!page)
> +			return NULL;

Seems a shame to fail the allocation if CMA can't manage it. Is there a good
reason not to fall back to swiotlb (other than complicating the freeing
paths)?

Will

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask
  2013-12-10 21:43 ` [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask Laura Abbott
@ 2013-12-11 10:42   ` Will Deacon
  2013-12-11 17:48     ` Laura Abbott
  0 siblings, 1 reply; 11+ messages in thread
From: Will Deacon @ 2013-12-11 10:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Dec 10, 2013 at 09:43:35PM +0000, Laura Abbott wrote:
> The device passed in to dma_alloc may be NULL. Check for this before
> trying to get the coherent_dma_mask.
> 
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
> ---
>  arch/arm64/mm/dma-mapping.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index 4bd7579..4134212 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -33,7 +33,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
>  					  dma_addr_t *dma_handle, gfp_t flags,
>  					  struct dma_attrs *attrs)
>  {
> -	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
> +	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
>  	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
>  		flags |= GFP_DMA32;
>  	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);

Unless I'm misreading the code, it looks like there are paths through
swiotlb_alloc_coherent that will dereference the dev parameter without a
NULL check. Are you sure we should allow for NULL devices here?

Will

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask
  2013-12-11 10:42   ` Will Deacon
@ 2013-12-11 17:48     ` Laura Abbott
  2013-12-11 17:51       ` Will Deacon
  0 siblings, 1 reply; 11+ messages in thread
From: Laura Abbott @ 2013-12-11 17:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/11/2013 2:42 AM, Will Deacon wrote:
> On Tue, Dec 10, 2013 at 09:43:35PM +0000, Laura Abbott wrote:
>> The device passed in to dma_alloc may be NULL. Check for this before
>> trying to get the coherent_dma_mask.
>>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
>> Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
>> ---
>>   arch/arm64/mm/dma-mapping.c |    2 +-
>>   1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
>> index 4bd7579..4134212 100644
>> --- a/arch/arm64/mm/dma-mapping.c
>> +++ b/arch/arm64/mm/dma-mapping.c
>> @@ -33,7 +33,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
>>   					  dma_addr_t *dma_handle, gfp_t flags,
>>   					  struct dma_attrs *attrs)
>>   {
>> -	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
>> +	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
>>   	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
>>   		flags |= GFP_DMA32;
>>   	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
>
> Unless I'm misreading the code, it looks like there are paths through
> swiotlb_alloc_coherent that will dereference the dev parameter without a
> NULL check. Are you sure we should allow for NULL devices here?
>

The current ARM code allows for NULL devices so that would be a 
difference in behavior between arm and arm64. We're also relying on this 
behavior in some code. Where exactly in swiotlb_alloc_coherent does this 
dereference happen? The only one I see is checked with 'if (hwdev && 
hwdev->coherent_dma_mask)'

> Will
>

Thanks,
Laura
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask
  2013-12-11 17:48     ` Laura Abbott
@ 2013-12-11 17:51       ` Will Deacon
  2013-12-11 18:10         ` Laura Abbott
  0 siblings, 1 reply; 11+ messages in thread
From: Will Deacon @ 2013-12-11 17:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Dec 11, 2013 at 05:48:10PM +0000, Laura Abbott wrote:
> On 12/11/2013 2:42 AM, Will Deacon wrote:
> > On Tue, Dec 10, 2013 at 09:43:35PM +0000, Laura Abbott wrote:
> >> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> >> index 4bd7579..4134212 100644
> >> --- a/arch/arm64/mm/dma-mapping.c
> >> +++ b/arch/arm64/mm/dma-mapping.c
> >> @@ -33,7 +33,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
> >>   					  dma_addr_t *dma_handle, gfp_t flags,
> >>   					  struct dma_attrs *attrs)
> >>   {
> >> -	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
> >> +	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
> >>   	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
> >>   		flags |= GFP_DMA32;
> >>   	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
> >
> > Unless I'm misreading the code, it looks like there are paths through
> > swiotlb_alloc_coherent that will dereference the dev parameter without a
> > NULL check. Are you sure we should allow for NULL devices here?
> >
> 
> The current ARM code allows for NULL devices so that would be a 
> difference in behavior between arm and arm64. We're also relying on this 
> behavior in some code. Where exactly in swiotlb_alloc_coherent does this 
> dereference happen? The only one I see is checked with 'if (hwdev && 
> hwdev->coherent_dma_mask)'

phys_to_dma could, but doesn't. The one I spotted was buried down in:

  map_single -> swiotlb_tbl_map_single -> dma_get_seg_boundary

Will

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 2/2] arm64: Enable CMA
  2013-12-11 10:40   ` Will Deacon
@ 2013-12-11 17:54     ` Laura Abbott
  0 siblings, 0 replies; 11+ messages in thread
From: Laura Abbott @ 2013-12-11 17:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/11/2013 2:40 AM, Will Deacon wrote:
> Hi Laura,
>
> Couple of really minor comments...
>
> On Tue, Dec 10, 2013 at 09:43:36PM +0000, Laura Abbott wrote:
>> arm64 bit targets need the features CMA provides. Add the appropriate
>> hooks, header files, and Kconfig to allow this to happen.
>>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
>> Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
>> ---
>>   arch/arm64/Kconfig                      |    1 +
>>   arch/arm64/include/asm/dma-contiguous.h |   29 +++++++++++++++++++++++++++++
>>   arch/arm64/mm/dma-mapping.c             |   25 +++++++++++++++++++++++--
>>   arch/arm64/mm/init.c                    |    3 +++
>>   4 files changed, 56 insertions(+), 2 deletions(-)
>>   create mode 100644 arch/arm64/include/asm/dma-contiguous.h
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 9737e97..26e4bef 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -22,6 +22,7 @@ config ARM64
>>   	select HAVE_DEBUG_KMEMLEAK
>>   	select HAVE_DMA_API_DEBUG
>>   	select HAVE_DMA_ATTRS
>> +	select HAVE_DMA_CONTIGUOUS
>>   	select HAVE_GENERIC_DMA_COHERENT
>>   	select HAVE_GENERIC_HARDIRQS
>>   	select HAVE_HW_BREAKPOINT if PERF_EVENTS
>> diff --git a/arch/arm64/include/asm/dma-contiguous.h b/arch/arm64/include/asm/dma-contiguous.h
>> new file mode 100644
>> index 0000000..bc32516
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/dma-contiguous.h
>> @@ -0,0 +1,29 @@
>> +/*
>> + * Copyright (c) 2013, The Linux Foundation. All rights reserved.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 and
>> + * only version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#ifndef ASMARM64_DMA_CONTIGUOUS_H
>> +#define ASMARM64_DMA_CONTIGUOUS_H
>
> We've tried to keep these guards consistent for the arm64 headers, so this
> would be: __ASM_DMA_CONTIGUOUS_H.
>

Fine.

>> +
>> +#ifdef __KERNEL__
>> +#ifdef CONFIG_CMA
>
> Why is this not CONFIG_DMA_CMA?
>

Whoops.

>> +#include <linux/types.h>
>> +#include <asm-generic/dma-contiguous.h>
>> +
>> +static inline void
>> +dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { }
>> +
>> +#endif
>> +#endif
>> +
>> +#endif
>> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
>> index 4134212..29d10b9 100644
>> --- a/arch/arm64/mm/dma-mapping.c
>> +++ b/arch/arm64/mm/dma-mapping.c
>> @@ -21,6 +21,7 @@
>>   #include <linux/export.h>
>>   #include <linux/slab.h>
>>   #include <linux/dma-mapping.h>
>> +#include <linux/dma-contiguous.h>
>>   #include <linux/vmalloc.h>
>>   #include <linux/swiotlb.h>
>>
>> @@ -36,14 +37,34 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
>>   	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
>>   	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
>>   		flags |= GFP_DMA32;
>> -	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
>> +	if (IS_ENABLED(CONFIG_DMA_CMA)) {
>> +		struct page *page;
>> +
>> +		page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
>> +							get_order(size));
>> +		if (!page)
>> +			return NULL;
>
> Seems a shame to fail the allocation if CMA can't manage it. Is there a good
> reason not to fall back to swiotlb (other than complicating the freeing
> paths)?
>

The current ARM code doesn't currently fall back but perhaps more 
importantly, the entire point of CMA is to be able to get allocations 
that are larger than the buddy allocator can handle. I'm not sure how 
likely it would be that if a CMA allocation failed the buddy allocator 
would be able to handle it successfully.

> Will
>

Thanks,
Laura

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask
  2013-12-11 17:51       ` Will Deacon
@ 2013-12-11 18:10         ` Laura Abbott
  2013-12-12 12:18           ` Will Deacon
  0 siblings, 1 reply; 11+ messages in thread
From: Laura Abbott @ 2013-12-11 18:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/11/2013 9:51 AM, Will Deacon wrote:
> On Wed, Dec 11, 2013 at 05:48:10PM +0000, Laura Abbott wrote:
>> On 12/11/2013 2:42 AM, Will Deacon wrote:
>>> On Tue, Dec 10, 2013 at 09:43:35PM +0000, Laura Abbott wrote:
>>>> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
>>>> index 4bd7579..4134212 100644
>>>> --- a/arch/arm64/mm/dma-mapping.c
>>>> +++ b/arch/arm64/mm/dma-mapping.c
>>>> @@ -33,7 +33,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
>>>>    					  dma_addr_t *dma_handle, gfp_t flags,
>>>>    					  struct dma_attrs *attrs)
>>>>    {
>>>> -	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
>>>> +	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
>>>>    	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
>>>>    		flags |= GFP_DMA32;
>>>>    	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
>>>
>>> Unless I'm misreading the code, it looks like there are paths through
>>> swiotlb_alloc_coherent that will dereference the dev parameter without a
>>> NULL check. Are you sure we should allow for NULL devices here?
>>>
>>
>> The current ARM code allows for NULL devices so that would be a
>> difference in behavior between arm and arm64. We're also relying on this
>> behavior in some code. Where exactly in swiotlb_alloc_coherent does this
>> dereference happen? The only one I see is checked with 'if (hwdev &&
>> hwdev->coherent_dma_mask)'
>
> phys_to_dma could, but doesn't. The one I spotted was buried down in:
>
>    map_single -> swiotlb_tbl_map_single -> dma_get_seg_boundary
>

Ah yes I see that now.

I guess the question still stands though, should we fixup the parts of 
the code to fully support the NULL devices or do we tell clients to fix 
their code and fail the allocation with a warning not to pass NULL?

> Will
>

Laura

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask
  2013-12-11 18:10         ` Laura Abbott
@ 2013-12-12 12:18           ` Will Deacon
  2013-12-12 19:00             ` Laura Abbott
  0 siblings, 1 reply; 11+ messages in thread
From: Will Deacon @ 2013-12-12 12:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Dec 11, 2013 at 06:10:59PM +0000, Laura Abbott wrote:
> On 12/11/2013 9:51 AM, Will Deacon wrote:
> > On Wed, Dec 11, 2013 at 05:48:10PM +0000, Laura Abbott wrote:
> >> On 12/11/2013 2:42 AM, Will Deacon wrote:
> >>> On Tue, Dec 10, 2013 at 09:43:35PM +0000, Laura Abbott wrote:
> >>>> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> >>>> index 4bd7579..4134212 100644
> >>>> --- a/arch/arm64/mm/dma-mapping.c
> >>>> +++ b/arch/arm64/mm/dma-mapping.c
> >>>> @@ -33,7 +33,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
> >>>>    					  dma_addr_t *dma_handle, gfp_t flags,
> >>>>    					  struct dma_attrs *attrs)
> >>>>    {
> >>>> -	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
> >>>> +	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
> >>>>    	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
> >>>>    		flags |= GFP_DMA32;
> >>>>    	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
> >>>
> >>> Unless I'm misreading the code, it looks like there are paths through
> >>> swiotlb_alloc_coherent that will dereference the dev parameter without a
> >>> NULL check. Are you sure we should allow for NULL devices here?
> >>>
> >>
> >> The current ARM code allows for NULL devices so that would be a
> >> difference in behavior between arm and arm64. We're also relying on this
> >> behavior in some code. Where exactly in swiotlb_alloc_coherent does this
> >> dereference happen? The only one I see is checked with 'if (hwdev &&
> >> hwdev->coherent_dma_mask)'
> >
> > phys_to_dma could, but doesn't. The one I spotted was buried down in:
> >
> >    map_single -> swiotlb_tbl_map_single -> dma_get_seg_boundary
> >
> 
> Ah yes I see that now.
> 
> I guess the question still stands though, should we fixup the parts of 
> the code to fully support the NULL devices or do we tell clients to fix 
> their code and fail the allocation with a warning not to pass NULL?

Assuming it's always possible to pass in a non-NULL device, I'd be tempted
to fix the callers. Can you think of a valid use-case where the caller
doesn't have a device handle to pass in?

Will

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask
  2013-12-12 12:18           ` Will Deacon
@ 2013-12-12 19:00             ` Laura Abbott
  0 siblings, 0 replies; 11+ messages in thread
From: Laura Abbott @ 2013-12-12 19:00 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/12/2013 4:18 AM, Will Deacon wrote:
> On Wed, Dec 11, 2013 at 06:10:59PM +0000, Laura Abbott wrote:
>> On 12/11/2013 9:51 AM, Will Deacon wrote:
>>> On Wed, Dec 11, 2013 at 05:48:10PM +0000, Laura Abbott wrote:
>>>> On 12/11/2013 2:42 AM, Will Deacon wrote:
>>>>> On Tue, Dec 10, 2013 at 09:43:35PM +0000, Laura Abbott wrote:
>>>>>> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
>>>>>> index 4bd7579..4134212 100644
>>>>>> --- a/arch/arm64/mm/dma-mapping.c
>>>>>> +++ b/arch/arm64/mm/dma-mapping.c
>>>>>> @@ -33,7 +33,7 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
>>>>>>     					  dma_addr_t *dma_handle, gfp_t flags,
>>>>>>     					  struct dma_attrs *attrs)
>>>>>>     {
>>>>>> -	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
>>>>>> +	if (dev && IS_ENABLED(CONFIG_ZONE_DMA32) &&
>>>>>>     	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
>>>>>>     		flags |= GFP_DMA32;
>>>>>>     	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
>>>>>
>>>>> Unless I'm misreading the code, it looks like there are paths through
>>>>> swiotlb_alloc_coherent that will dereference the dev parameter without a
>>>>> NULL check. Are you sure we should allow for NULL devices here?
>>>>>
>>>>
>>>> The current ARM code allows for NULL devices so that would be a
>>>> difference in behavior between arm and arm64. We're also relying on this
>>>> behavior in some code. Where exactly in swiotlb_alloc_coherent does this
>>>> dereference happen? The only one I see is checked with 'if (hwdev &&
>>>> hwdev->coherent_dma_mask)'
>>>
>>> phys_to_dma could, but doesn't. The one I spotted was buried down in:
>>>
>>>     map_single -> swiotlb_tbl_map_single -> dma_get_seg_boundary
>>>
>>
>> Ah yes I see that now.
>>
>> I guess the question still stands though, should we fixup the parts of
>> the code to fully support the NULL devices or do we tell clients to fix
>> their code and fail the allocation with a warning not to pass NULL?
>
> Assuming it's always possible to pass in a non-NULL device, I'd be tempted
> to fix the callers. Can you think of a valid use-case where the caller
> doesn't have a device handle to pass in?
>

Depends on your definition of 'valid' ;)

The only cases we've been able to come up with are places where we've 
been abusing the DMA APIs slightly to get chunks of contiguous memory 
through CMA for miscellaneous debugging/testing purposes. I only 
stumbled across this problem at all while writing a quick test case for 
CMA. I'd argue that if there is a real use case for non-device large 
contiguous allocations there should be a new dedicated API that doesn't 
break the dma abstraction.

I suggest for now we add a big WARN when a NULL device is passed in and 
see how many people complain.

Laura


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2013-12-12 19:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-10 21:43 [PATCHv3 0/2] CMA for arm64 Laura Abbott
2013-12-10 21:43 ` [PATCHv3 1/2] arm64: Check for NULL device before getting the coherent_dma_mask Laura Abbott
2013-12-11 10:42   ` Will Deacon
2013-12-11 17:48     ` Laura Abbott
2013-12-11 17:51       ` Will Deacon
2013-12-11 18:10         ` Laura Abbott
2013-12-12 12:18           ` Will Deacon
2013-12-12 19:00             ` Laura Abbott
2013-12-10 21:43 ` [PATCHv3 2/2] arm64: Enable CMA Laura Abbott
2013-12-11 10:40   ` Will Deacon
2013-12-11 17:54     ` Laura Abbott

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.