-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dma-buf: heaps: Add system heap to dmabuf heaps
This patch adds system heap to the dma-buf heaps framework. This allows applications to get a page-allocator backed dma-buf for non-contiguous memory. This code is an evolution of the Android ION implementation, so thanks to its original authors and maintainters: Rebecca Schultz Zavin, Colin Cross, Laura Abbott, and others! Cc: Laura Abbott <labbott@redhat.com> Cc: Benjamin Gaignard <benjamin.gaignard@linaro.org> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: Liam Mark <lmark@codeaurora.org> Cc: Pratik Patel <pratikp@codeaurora.org> Cc: Brian Starkey <Brian.Starkey@arm.com> Cc: Vincent Donnefort <Vincent.Donnefort@arm.com> Cc: Sudipto Paul <Sudipto.Paul@arm.com> Cc: Andrew F. Davis <afd@ti.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Chenbo Feng <fengc@google.com> Cc: Alistair Strachan <astrachan@google.com> Cc: Hridya Valsaraju <hridya@google.com> Cc: Sandeep Patil <sspatil@google.com> Cc: Hillf Danton <hdanton@sina.com> Cc: Dave Airlie <airlied@gmail.com> Cc: dri-devel@lists.freedesktop.org Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Reviewed-by: Brian Starkey <brian.starkey@arm.com> Acked-by: Sandeep Patil <sspatil@android.com> Acked-by: Laura Abbott <labbott@redhat.com> Tested-by: Ayan Kumar Halder <ayan.halder@arm.com> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203172641.66642-4-john.stultz@linaro.org
- Loading branch information
John Stultz
authored and
Sumit Semwal
committed
Dec 11, 2019
1 parent
5248eb1
commit efa04fe
Showing
4 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
config DMABUF_HEAPS_SYSTEM | ||
bool "DMA-BUF System Heap" | ||
depends on DMABUF_HEAPS | ||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
# SPDX-License-Identifier: GPL-2.0 | ||
obj-y += heap-helpers.o | ||
obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* DMABUF System heap exporter | ||
* | ||
* Copyright (C) 2011 Google, Inc. | ||
* Copyright (C) 2019 Linaro Ltd. | ||
*/ | ||
|
||
#include <linux/dma-buf.h> | ||
#include <linux/dma-mapping.h> | ||
#include <linux/dma-heap.h> | ||
#include <linux/err.h> | ||
#include <linux/highmem.h> | ||
#include <linux/mm.h> | ||
#include <linux/module.h> | ||
#include <linux/scatterlist.h> | ||
#include <linux/slab.h> | ||
#include <linux/sched/signal.h> | ||
#include <asm/page.h> | ||
|
||
#include "heap-helpers.h" | ||
|
||
struct dma_heap *sys_heap; | ||
|
||
static void system_heap_free(struct heap_helper_buffer *buffer) | ||
{ | ||
pgoff_t pg; | ||
|
||
for (pg = 0; pg < buffer->pagecount; pg++) | ||
__free_page(buffer->pages[pg]); | ||
kfree(buffer->pages); | ||
kfree(buffer); | ||
} | ||
|
||
static int system_heap_allocate(struct dma_heap *heap, | ||
unsigned long len, | ||
unsigned long fd_flags, | ||
unsigned long heap_flags) | ||
{ | ||
struct heap_helper_buffer *helper_buffer; | ||
struct dma_buf *dmabuf; | ||
int ret = -ENOMEM; | ||
pgoff_t pg; | ||
|
||
helper_buffer = kzalloc(sizeof(*helper_buffer), GFP_KERNEL); | ||
if (!helper_buffer) | ||
return -ENOMEM; | ||
|
||
init_heap_helper_buffer(helper_buffer, system_heap_free); | ||
helper_buffer->heap = heap; | ||
helper_buffer->size = len; | ||
|
||
helper_buffer->pagecount = len / PAGE_SIZE; | ||
helper_buffer->pages = kmalloc_array(helper_buffer->pagecount, | ||
sizeof(*helper_buffer->pages), | ||
GFP_KERNEL); | ||
if (!helper_buffer->pages) { | ||
ret = -ENOMEM; | ||
goto err0; | ||
} | ||
|
||
for (pg = 0; pg < helper_buffer->pagecount; pg++) { | ||
/* | ||
* Avoid trying to allocate memory if the process | ||
* has been killed by by SIGKILL | ||
*/ | ||
if (fatal_signal_pending(current)) | ||
goto err1; | ||
|
||
helper_buffer->pages[pg] = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
if (!helper_buffer->pages[pg]) | ||
goto err1; | ||
} | ||
|
||
/* create the dmabuf */ | ||
dmabuf = heap_helper_export_dmabuf(helper_buffer, fd_flags); | ||
if (IS_ERR(dmabuf)) { | ||
ret = PTR_ERR(dmabuf); | ||
goto err1; | ||
} | ||
|
||
helper_buffer->dmabuf = dmabuf; | ||
|
||
ret = dma_buf_fd(dmabuf, fd_flags); | ||
if (ret < 0) { | ||
dma_buf_put(dmabuf); | ||
/* just return, as put will call release and that will free */ | ||
return ret; | ||
} | ||
|
||
return ret; | ||
|
||
err1: | ||
while (pg > 0) | ||
__free_page(helper_buffer->pages[--pg]); | ||
kfree(helper_buffer->pages); | ||
err0: | ||
kfree(helper_buffer); | ||
|
||
return ret; | ||
} | ||
|
||
static const struct dma_heap_ops system_heap_ops = { | ||
.allocate = system_heap_allocate, | ||
}; | ||
|
||
static int system_heap_create(void) | ||
{ | ||
struct dma_heap_export_info exp_info; | ||
int ret = 0; | ||
|
||
exp_info.name = "system_heap"; | ||
exp_info.ops = &system_heap_ops; | ||
exp_info.priv = NULL; | ||
|
||
sys_heap = dma_heap_add(&exp_info); | ||
if (IS_ERR(sys_heap)) | ||
ret = PTR_ERR(sys_heap); | ||
|
||
return ret; | ||
} | ||
module_init(system_heap_create); | ||
MODULE_LICENSE("GPL v2"); |