| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: John Stultz <john.stultz@linaro.org> |
| Date: Fri, 14 Aug 2020 22:42:09 +0000 |
| Subject: ANDROID: dma-heap: Rework allocation calls to return struct dma_buf |
| instead of fd |
| |
| While most uses will want to allocate a fd for a dmabuf, there |
| are some cases where it might be useful to have just a dma_buf structure. |
| |
| So refactor the heap allocaiton functions to return a struct dma_buf |
| and add a dma_heap_bufferfd_alloc() function to convert that return a fd. |
| |
| Signed-off-by: John Stultz <john.stultz@linaro.org> |
| Change-Id: Id6fd7e8471b9555a08bcdf8ca210feb589fa51c1 |
| Bug: 154341375 |
| --- |
| drivers/dma-buf/dma-heap.c | 44 +++++++++++++++++++++++------ |
| drivers/dma-buf/heaps/cma_heap.c | 21 +++++--------- |
| drivers/dma-buf/heaps/system_heap.c | 20 +++++-------- |
| include/linux/dma-heap.h | 6 ++-- |
| 4 files changed, 52 insertions(+), 39 deletions(-) |
| |
| diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c |
| --- a/drivers/dma-buf/dma-heap.c |
| +++ b/drivers/dma-buf/dma-heap.c |
| @@ -66,26 +66,52 @@ static struct dma_heap *dma_heap_find(const char *name) |
| return NULL; |
| } |
| |
| -static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, |
| - unsigned int fd_flags, |
| - unsigned int heap_flags) |
| +void dma_heap_buffer_free(struct dma_buf *dmabuf) |
| +{ |
| + dma_buf_put(dmabuf); |
| +} |
| + |
| +struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, |
| + unsigned int fd_flags, |
| + unsigned int heap_flags) |
| { |
| if (fd_flags & ~DMA_HEAP_VALID_FD_FLAGS) |
| - return -EINVAL; |
| + return ERR_PTR(-EINVAL); |
| |
| if (heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS) |
| - return -EINVAL; |
| + return ERR_PTR(-EINVAL); |
| /* |
| * Allocations from all heaps have to begin |
| * and end on page boundaries. |
| */ |
| len = PAGE_ALIGN(len); |
| if (!len) |
| - return -EINVAL; |
| + return ERR_PTR(-EINVAL); |
| |
| return heap->ops->allocate(heap, len, fd_flags, heap_flags); |
| } |
| |
| +int dma_heap_bufferfd_alloc(struct dma_heap *heap, size_t len, |
| + unsigned int fd_flags, |
| + unsigned int heap_flags) |
| +{ |
| + struct dma_buf *dmabuf; |
| + int fd; |
| + |
| + dmabuf = dma_heap_buffer_alloc(heap, len, fd_flags, heap_flags); |
| + |
| + if (IS_ERR(dmabuf)) |
| + return PTR_ERR(dmabuf); |
| + |
| + fd = dma_buf_fd(dmabuf, fd_flags); |
| + if (fd < 0) { |
| + dma_buf_put(dmabuf); |
| + /* just return, as put will call release and that will free */ |
| + } |
| + return fd; |
| + |
| +} |
| + |
| static int dma_heap_open(struct inode *inode, struct file *file) |
| { |
| struct dma_heap *heap; |
| @@ -112,9 +138,9 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data) |
| if (heap_allocation->fd) |
| return -EINVAL; |
| |
| - fd = dma_heap_buffer_alloc(heap, heap_allocation->len, |
| - heap_allocation->fd_flags, |
| - heap_allocation->heap_flags); |
| + fd = dma_heap_bufferfd_alloc(heap, heap_allocation->len, |
| + heap_allocation->fd_flags, |
| + heap_allocation->heap_flags); |
| if (fd < 0) |
| return fd; |
| |
| diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c |
| --- a/drivers/dma-buf/heaps/cma_heap.c |
| +++ b/drivers/dma-buf/heaps/cma_heap.c |
| @@ -268,10 +268,10 @@ static const struct dma_buf_ops cma_heap_buf_ops = { |
| .release = cma_heap_dma_buf_release, |
| }; |
| |
| -static int cma_heap_allocate(struct dma_heap *heap, |
| - unsigned long len, |
| - unsigned long fd_flags, |
| - unsigned long heap_flags) |
| +static struct dma_buf *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_drvdata(heap); |
| struct cma_heap_buffer *buffer; |
| @@ -286,7 +286,7 @@ static int cma_heap_allocate(struct dma_heap *heap, |
| |
| buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
| if (!buffer) |
| - return -ENOMEM; |
| + return ERR_PTR(-ENOMEM); |
| |
| INIT_LIST_HEAD(&buffer->attachments); |
| mutex_init(&buffer->lock); |
| @@ -346,14 +346,7 @@ static int cma_heap_allocate(struct dma_heap *heap, |
| goto free_pages; |
| } |
| |
| - 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; |
| + return dmabuf; |
| |
| free_pages: |
| kfree(buffer->pages); |
| @@ -362,7 +355,7 @@ static int cma_heap_allocate(struct dma_heap *heap, |
| free_buffer: |
| kfree(buffer); |
| |
| - return ret; |
| + return ERR_PTR(ret); |
| } |
| |
| static const struct dma_heap_ops cma_heap_ops = { |
| diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c |
| --- a/drivers/dma-buf/heaps/system_heap.c |
| +++ b/drivers/dma-buf/heaps/system_heap.c |
| @@ -331,10 +331,10 @@ static struct page *alloc_largest_available(unsigned long size, |
| return NULL; |
| } |
| |
| -static int system_heap_allocate(struct dma_heap *heap, |
| - unsigned long len, |
| - unsigned long fd_flags, |
| - unsigned long heap_flags) |
| +static struct dma_buf *system_heap_allocate(struct dma_heap *heap, |
| + unsigned long len, |
| + unsigned long fd_flags, |
| + unsigned long heap_flags) |
| { |
| struct system_heap_buffer *buffer; |
| DEFINE_DMA_BUF_EXPORT_INFO(exp_info); |
| @@ -349,7 +349,7 @@ static int system_heap_allocate(struct dma_heap *heap, |
| |
| buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
| if (!buffer) |
| - return -ENOMEM; |
| + return ERR_PTR(-ENOMEM); |
| |
| INIT_LIST_HEAD(&buffer->attachments); |
| mutex_init(&buffer->lock); |
| @@ -398,13 +398,7 @@ static int system_heap_allocate(struct dma_heap *heap, |
| goto free_pages; |
| } |
| |
| - 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; |
| + return dmabuf; |
| |
| free_pages: |
| for_each_sgtable_sg(table, sg, i) { |
| @@ -418,7 +412,7 @@ static int system_heap_allocate(struct dma_heap *heap, |
| __free_pages(page, compound_order(page)); |
| kfree(buffer); |
| |
| - return ret; |
| + return ERR_PTR(ret); |
| } |
| |
| static const struct dma_heap_ops system_heap_ops = { |
| diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h |
| --- a/include/linux/dma-heap.h |
| +++ b/include/linux/dma-heap.h |
| @@ -16,12 +16,12 @@ struct dma_heap; |
| |
| /** |
| * struct dma_heap_ops - ops to operate on a given heap |
| - * @allocate: allocate dmabuf and return fd |
| + * @allocate: allocate dmabuf and return struct dma_buf ptr |
| * |
| - * allocate returns dmabuf fd on success, -errno on error. |
| + * allocate returns dmabuf on success, ERR_PTR(-errno) on error. |
| */ |
| struct dma_heap_ops { |
| - int (*allocate)(struct dma_heap *heap, |
| + struct dma_buf *(*allocate)(struct dma_heap *heap, |
| unsigned long len, |
| unsigned long fd_flags, |
| unsigned long heap_flags); |