[RFC][PATCH 4/5 v4] dma-buf: heaps: Add CMA heap to dmabuf heaps
This adds a CMA heap, which allows userspace to allocate a dma-buf of contiguous memory out of a CMA region. This code is an evolution of the Android ION implementation, so thanks to its original author and maintainters: Benjamin Gaignard, Laura Abbott, and others! Cc: Laura Abbott Cc: Benjamin Gaignard Cc: Sumit Semwal Cc: Liam Mark Cc: Pratik Patel Cc: Brian Starkey Cc: Vincent Donnefort Cc: Sudipto Paul Cc: Andrew F. Davis Cc: Xu YiPing Cc: "Chenfeng (puck)" Cc: butao Cc: "Xiaqing (A)" Cc: Yudongbin Cc: Christoph Hellwig Cc: Chenbo Feng Cc: Alistair Strachan Cc: dri-devel@lists.freedesktop.org Signed-off-by: John Stultz --- v2: * Switch allocate to return dmabuf fd * Simplify init code * Checkpatch fixups v3: * Switch to inline function for to_cma_heap() * Minor cleanups suggested by Brian * Fold in new registration style from Andrew * Folded in changes from Andrew to use simplified page list from the heap helpers * Use the fd_flags when creating dmabuf fd (Suggested by Benjamin) * Use precalculated pagecount (Suggested by Andrew) --- drivers/dma-buf/heaps/Kconfig| 8 ++ drivers/dma-buf/heaps/Makefile | 1 + drivers/dma-buf/heaps/cma_heap.c | 169 +++ 3 files changed, 178 insertions(+) create mode 100644 drivers/dma-buf/heaps/cma_heap.c diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig index 205052744169..a5eef06c4226 100644 --- a/drivers/dma-buf/heaps/Kconfig +++ b/drivers/dma-buf/heaps/Kconfig @@ -4,3 +4,11 @@ config DMABUF_HEAPS_SYSTEM help Choose this option to enable the system dmabuf heap. The system heap is backed by pages from the buddy allocator. If in doubt, say Y. + +config DMABUF_HEAPS_CMA + bool "DMA-BUF CMA Heap" + depends on DMABUF_HEAPS && DMA_CMA + help + Choose this option to enable dma-buf CMA heap. This heap is backed + by the Contiguous Memory Allocator (CMA). If your system has these + regions, you should say Y here. diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile index d1808eca2581..6e54cdec3da0 100644 --- a/drivers/dma-buf/heaps/Makefile +++ b/drivers/dma-buf/heaps/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += heap-helpers.o obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o +obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c new file mode 100644 index ..3d0ffbbd0a34 --- /dev/null +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DMABUF CMA heap exporter + * + * Copyright (C) 2012, 2019 Linaro Ltd. + * Author: for ST-Ericsson. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heap-helpers.h" + +struct cma_heap { + struct dma_heap *heap; + struct cma *cma; +}; + +static void cma_heap_free(struct heap_helper_buffer *buffer) +{ + struct cma_heap *cma_heap = dma_heap_get_data(buffer->heap_buffer.heap); + unsigned long nr_pages = buffer->pagecount; + struct page *pages = buffer->priv_virt; + + /* free page list */ + kfree(buffer->pages); + /* release memory */ + cma_release(cma_heap->cma, pages, nr_pages); + kfree(buffer); +} + +/* dmabuf heap CMA operations functions */ +static int cma_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + struct cma_heap *cma_heap = dma_heap_get_data(heap); + struct heap_helper_buffer *helper_buffer; + struct page *pages; + size_t size = PAGE_ALIGN(len); + unsigned long nr_pages = size >> PAGE_SHIFT; + unsigned long align = get_order(size); + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct dma_buf *dmabuf; + int ret = -ENOMEM; + pgoff_t pg; + + if (align > CONFIG_CMA_ALIGNMENT) + align = CONFIG_CMA_ALIGNMENT; + + helper_buffer = kzalloc(sizeof(*helper_buffer), GFP_KERNEL); + if (!helper_buffer) + return -ENOMEM; + + INIT_HEAP_HELPER_BUFFER(helper_buffer, cma_heap_free); + helper_buffer->heap_buffer.flags = heap_flags; + helper_buffer->heap_buffer.heap = heap; + helper_buffer->heap_buffer.size = len; + + pages = cma_alloc(cma_heap->cma, nr_pages, align, false); + if (!pages) + goto free_buf; + + if (PageHighMem(pages)) { + unsigned long nr_clear_pages = nr_pages; + struct page *page = pages; + + while (nr_clear_pages > 0) { + void *vaddr = kmap_atomic(page); + + memset(vaddr, 0, PAGE_SIZE); + kunmap_atomic(vaddr); +
Re: [RFC][PATCH 4/5 v4] dma-buf: heaps: Add CMA heap to dmabuf heaps
On 2019/5/14 2:37, John Stultz wrote: This adds a CMA heap, which allows userspace to allocate a dma-buf of contiguous memory out of a CMA region. This code is an evolution of the Android ION implementation, so thanks to its original author and maintainters: Benjamin Gaignard, Laura Abbott, and others! Cc: Laura Abbott Cc: Benjamin Gaignard Cc: Sumit Semwal Cc: Liam Mark Cc: Pratik Patel Cc: Brian Starkey Cc: Vincent Donnefort Cc: Sudipto Paul Cc: Andrew F. Davis Cc: Xu YiPing Cc: "Chenfeng (puck)" Cc: butao Cc: "Xiaqing (A)" Cc: Yudongbin Cc: Christoph Hellwig Cc: Chenbo Feng Cc: Alistair Strachan Cc: dri-devel@lists.freedesktop.org Signed-off-by: John Stultz --- v2: * Switch allocate to return dmabuf fd * Simplify init code * Checkpatch fixups v3: * Switch to inline function for to_cma_heap() * Minor cleanups suggested by Brian * Fold in new registration style from Andrew * Folded in changes from Andrew to use simplified page list from the heap helpers * Use the fd_flags when creating dmabuf fd (Suggested by Benjamin) * Use precalculated pagecount (Suggested by Andrew) --- drivers/dma-buf/heaps/Kconfig| 8 ++ drivers/dma-buf/heaps/Makefile | 1 + drivers/dma-buf/heaps/cma_heap.c | 169 +++ 3 files changed, 178 insertions(+) create mode 100644 drivers/dma-buf/heaps/cma_heap.c diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig index 205052744169..a5eef06c4226 100644 --- a/drivers/dma-buf/heaps/Kconfig +++ b/drivers/dma-buf/heaps/Kconfig @@ -4,3 +4,11 @@ config DMABUF_HEAPS_SYSTEM help Choose this option to enable the system dmabuf heap. The system heap is backed by pages from the buddy allocator. If in doubt, say Y. + +config DMABUF_HEAPS_CMA + bool "DMA-BUF CMA Heap" + depends on DMABUF_HEAPS && DMA_CMA + help + Choose this option to enable dma-buf CMA heap. This heap is backed + by the Contiguous Memory Allocator (CMA). If your system has these + regions, you should say Y here. diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile index d1808eca2581..6e54cdec3da0 100644 --- a/drivers/dma-buf/heaps/Makefile +++ b/drivers/dma-buf/heaps/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += heap-helpers.o obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o +obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c new file mode 100644 index ..3d0ffbbd0a34 --- /dev/null +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DMABUF CMA heap exporter + * + * Copyright (C) 2012, 2019 Linaro Ltd. + * Author: for ST-Ericsson. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heap-helpers.h" + +struct cma_heap { + struct dma_heap *heap; + struct cma *cma; +}; + +static void cma_heap_free(struct heap_helper_buffer *buffer) +{ + struct cma_heap *cma_heap = dma_heap_get_data(buffer->heap_buffer.heap); + unsigned long nr_pages = buffer->pagecount; + struct page *pages = buffer->priv_virt; + + /* free page list */ + kfree(buffer->pages); + /* release memory */ + cma_release(cma_heap->cma, pages, nr_pages); + kfree(buffer); +} + +/* dmabuf heap CMA operations functions */ +static int cma_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + struct cma_heap *cma_heap = dma_heap_get_data(heap); + struct heap_helper_buffer *helper_buffer; + struct page *pages; + size_t size = PAGE_ALIGN(len); + unsigned long nr_pages = size >> PAGE_SHIFT; + unsigned long align = get_order(size); + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct dma_buf *dmabuf; + int ret = -ENOMEM; + pgoff_t pg; + + if (align > CONFIG_CMA_ALIGNMENT) + align = CONFIG_CMA_ALIGNMENT; + + helper_buffer = kzalloc(sizeof(*helper_buffer), GFP_KERNEL); + if (!helper_buffer) + return -ENOMEM; + + INIT_HEAP_HELPER_BUFFER(helper_buffer, cma_heap_free); + helper_buffer->heap_buffer.flags = heap_flags; + helper_buffer->heap_buffer.heap = heap; + helper_buffer->heap_buffer.size = len; + + pages = cma_alloc(cma_heap->cma, nr_pages, align, false); + if (!pages) + goto free_buf; + + if (PageHighMem(pages)) { + unsigned long nr_clear_pages = nr_pages; + struct page *page = pages; + + while (nr_clear_pages > 0) { + void *vaddr = kmap_atomic(page); + + memset(vaddr, 0, PAGE_SI
Re: [RFC][PATCH 4/5 v4] dma-buf: heaps: Add CMA heap to dmabuf heaps
Le mar. 14 mai 2019 à 12:40, Xiaqing (A) a écrit : > > > > On 2019/5/14 2:37, John Stultz wrote: > > This adds a CMA heap, which allows userspace to allocate > > a dma-buf of contiguous memory out of a CMA region. > > > > This code is an evolution of the Android ION implementation, so > > thanks to its original author and maintainters: > >Benjamin Gaignard, Laura Abbott, and others! > > > > Cc: Laura Abbott > > Cc: Benjamin Gaignard > > Cc: Sumit Semwal > > Cc: Liam Mark > > Cc: Pratik Patel > > Cc: Brian Starkey > > Cc: Vincent Donnefort > > Cc: Sudipto Paul > > Cc: Andrew F. Davis > > Cc: Xu YiPing > > Cc: "Chenfeng (puck)" > > Cc: butao > > Cc: "Xiaqing (A)" > > Cc: Yudongbin > > Cc: Christoph Hellwig > > Cc: Chenbo Feng > > Cc: Alistair Strachan > > Cc: dri-devel@lists.freedesktop.org > > Signed-off-by: John Stultz > > --- > > v2: > > * Switch allocate to return dmabuf fd > > * Simplify init code > > * Checkpatch fixups > > v3: > > * Switch to inline function for to_cma_heap() > > * Minor cleanups suggested by Brian > > * Fold in new registration style from Andrew > > * Folded in changes from Andrew to use simplified page list > >from the heap helpers > > * Use the fd_flags when creating dmabuf fd (Suggested by > >Benjamin) > > * Use precalculated pagecount (Suggested by Andrew) > > --- > > drivers/dma-buf/heaps/Kconfig| 8 ++ > > drivers/dma-buf/heaps/Makefile | 1 + > > drivers/dma-buf/heaps/cma_heap.c | 169 +++ > > 3 files changed, 178 insertions(+) > > create mode 100644 drivers/dma-buf/heaps/cma_heap.c > > > > diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig > > index 205052744169..a5eef06c4226 100644 > > --- a/drivers/dma-buf/heaps/Kconfig > > +++ b/drivers/dma-buf/heaps/Kconfig > > @@ -4,3 +4,11 @@ config DMABUF_HEAPS_SYSTEM > > help > > Choose this option to enable the system dmabuf heap. The system heap > > is backed by pages from the buddy allocator. If in doubt, say Y. > > + > > +config DMABUF_HEAPS_CMA > > + bool "DMA-BUF CMA Heap" > > + depends on DMABUF_HEAPS && DMA_CMA > > + help > > + Choose this option to enable dma-buf CMA heap. This heap is backed > > + by the Contiguous Memory Allocator (CMA). If your system has these > > + regions, you should say Y here. > > diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile > > index d1808eca2581..6e54cdec3da0 100644 > > --- a/drivers/dma-buf/heaps/Makefile > > +++ b/drivers/dma-buf/heaps/Makefile > > @@ -1,3 +1,4 @@ > > # SPDX-License-Identifier: GPL-2.0 > > obj-y += heap-helpers.o > > obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o > > +obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o > > diff --git a/drivers/dma-buf/heaps/cma_heap.c > > b/drivers/dma-buf/heaps/cma_heap.c > > new file mode 100644 > > index ..3d0ffbbd0a34 > > --- /dev/null > > +++ b/drivers/dma-buf/heaps/cma_heap.c > > @@ -0,0 +1,169 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * DMABUF CMA heap exporter > > + * > > + * Copyright (C) 2012, 2019 Linaro Ltd. > > + * Author: for ST-Ericsson. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "heap-helpers.h" > > + > > +struct cma_heap { > > + struct dma_heap *heap; > > + struct cma *cma; > > +}; > > + > > +static void cma_heap_free(struct heap_helper_buffer *buffer) > > +{ > > + struct cma_heap *cma_heap = > > dma_heap_get_data(buffer->heap_buffer.heap); > > + unsigned long nr_pages = buffer->pagecount; > > + struct page *pages = buffer->priv_virt; > > + > > + /* free page list */ > > + kfree(buffer->pages); > > + /* release memory */ > > + cma_release(cma_heap->cma, pages, nr_pages); > > + kfree(buffer); > > +} > > + > > +/* dmabuf heap CMA operations functions */ > > +static int cma_heap_allocate(struct dma_heap *heap, > > + unsigned long len, > > + unsigned long fd_flags, > > + unsigned long heap_flags) > > +{ > > + struct cma_heap *cma_heap = dma_heap_get_data(heap); > > + struct heap_helper_buffer *helper_buffer; > > + struct page *pages; > > + size_t size = PAGE_ALIGN(len); > > + unsigned long nr_pages = size >> PAGE_SHIFT; > > + unsigned long align = get_order(size); > > + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); > > + struct dma_buf *dmabuf; > > + int ret = -ENOMEM; > > + pgoff_t pg; > > + > > + if (align > CONFIG_CMA_ALIGNMENT) > > + align = CONFIG_CMA_ALIGNMENT; > > + > > + helper_buffer = kzalloc(sizeof(*helper_buffer), GFP_KERNEL); > > + if (!helper_buffer) > > + return -ENOMEM; > > + > > + INIT_HEAP_HELPER_BUFFER(helper_buffer, cma_heap_free);
Re: [RFC][PATCH 4/5 v4] dma-buf: heaps: Add CMA heap to dmabuf heaps
On Tue, May 14, 2019 at 3:40 AM Xiaqing (A) wrote: > > > > On 2019/5/14 2:37, John Stultz wrote: > > This adds a CMA heap, which allows userspace to allocate > > a dma-buf of contiguous memory out of a CMA region. > > > > This code is an evolution of the Android ION implementation, so > > thanks to its original author and maintainters: > >Benjamin Gaignard, Laura Abbott, and others! > > > > Cc: Laura Abbott > > Cc: Benjamin Gaignard > > Cc: Sumit Semwal > > Cc: Liam Mark > > Cc: Pratik Patel > > Cc: Brian Starkey > > Cc: Vincent Donnefort > > Cc: Sudipto Paul > > Cc: Andrew F. Davis > > Cc: Xu YiPing > > Cc: "Chenfeng (puck)" > > Cc: butao > > Cc: "Xiaqing (A)" > > Cc: Yudongbin > > Cc: Christoph Hellwig > > Cc: Chenbo Feng > > Cc: Alistair Strachan > > Cc: dri-devel@lists.freedesktop.org > > Signed-off-by: John Stultz > > --- > > v2: > > * Switch allocate to return dmabuf fd > > * Simplify init code > > * Checkpatch fixups > > v3: > > * Switch to inline function for to_cma_heap() > > * Minor cleanups suggested by Brian > > * Fold in new registration style from Andrew > > * Folded in changes from Andrew to use simplified page list > >from the heap helpers > > * Use the fd_flags when creating dmabuf fd (Suggested by > >Benjamin) > > * Use precalculated pagecount (Suggested by Andrew) > > --- > > drivers/dma-buf/heaps/Kconfig| 8 ++ > > drivers/dma-buf/heaps/Makefile | 1 + > > drivers/dma-buf/heaps/cma_heap.c | 169 +++ > > 3 files changed, 178 insertions(+) > > create mode 100644 drivers/dma-buf/heaps/cma_heap.c > > > > diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig > > index 205052744169..a5eef06c4226 100644 > > --- a/drivers/dma-buf/heaps/Kconfig > > +++ b/drivers/dma-buf/heaps/Kconfig > > @@ -4,3 +4,11 @@ config DMABUF_HEAPS_SYSTEM > > help > > Choose this option to enable the system dmabuf heap. The system heap > > is backed by pages from the buddy allocator. If in doubt, say Y. > > + > > +config DMABUF_HEAPS_CMA > > + bool "DMA-BUF CMA Heap" > > + depends on DMABUF_HEAPS && DMA_CMA > > + help > > + Choose this option to enable dma-buf CMA heap. This heap is backed > > + by the Contiguous Memory Allocator (CMA). If your system has these > > + regions, you should say Y here. > > diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile > > index d1808eca2581..6e54cdec3da0 100644 > > --- a/drivers/dma-buf/heaps/Makefile > > +++ b/drivers/dma-buf/heaps/Makefile > > @@ -1,3 +1,4 @@ > > # SPDX-License-Identifier: GPL-2.0 > > obj-y += heap-helpers.o > > obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o > > +obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o > > diff --git a/drivers/dma-buf/heaps/cma_heap.c > > b/drivers/dma-buf/heaps/cma_heap.c > > new file mode 100644 > > index ..3d0ffbbd0a34 > > --- /dev/null > > +++ b/drivers/dma-buf/heaps/cma_heap.c > > @@ -0,0 +1,169 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * DMABUF CMA heap exporter > > + * > > + * Copyright (C) 2012, 2019 Linaro Ltd. > > + * Author: for ST-Ericsson. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "heap-helpers.h" > > + > > +struct cma_heap { > > + struct dma_heap *heap; > > + struct cma *cma; > > +}; > > + > > +static void cma_heap_free(struct heap_helper_buffer *buffer) > > +{ > > + struct cma_heap *cma_heap = > > dma_heap_get_data(buffer->heap_buffer.heap); > > + unsigned long nr_pages = buffer->pagecount; > > + struct page *pages = buffer->priv_virt; > > + > > + /* free page list */ > > + kfree(buffer->pages); > > + /* release memory */ > > + cma_release(cma_heap->cma, pages, nr_pages); > > + kfree(buffer); > > +} > > + > > +/* dmabuf heap CMA operations functions */ > > +static int cma_heap_allocate(struct dma_heap *heap, > > + unsigned long len, > > + unsigned long fd_flags, > > + unsigned long heap_flags) > > +{ > > + struct cma_heap *cma_heap = dma_heap_get_data(heap); > > + struct heap_helper_buffer *helper_buffer; > > + struct page *pages; > > + size_t size = PAGE_ALIGN(len); > > + unsigned long nr_pages = size >> PAGE_SHIFT; > > + unsigned long align = get_order(size); > > + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); > > + struct dma_buf *dmabuf; > > + int ret = -ENOMEM; > > + pgoff_t pg; > > + > > + if (align > CONFIG_CMA_ALIGNMENT) > > + align = CONFIG_CMA_ALIGNMENT; > > + > > + helper_buffer = kzalloc(sizeof(*helper_buffer), GFP_KERNEL); > > + if (!helper_buffer) > > + return -ENOMEM; > > + > > + INIT_HEAP_HELPER_BUFFER(helper_buffer, cma_heap_free);