public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: sspatil@google.com
To: john.stultz@linaro.org, linux-kernel@vger.kernel.org,
	labbott@redhat.com, benjamin.gaignard@linaro.org,
	sumit.semwal@linaro.org, lmark@codeaurora.org,
	pratikp@codeaurora.org, Brian.Starkey@arm.com,
	Vincent.Donnefort@arm.com, Sudipto.Paul@arm.com, afd@ti.com,
	hch@infradead.org, fengc@google.com, astrachan@google.com,
	hridya@google.com, hdanton@sina.com, airlied@gmail.com,
	dri-devel@lists.freedesktop.org, sspatil+mutt@google.com
Cc: lkml <linux-kernel@vger.kernel.org>,
	Laura Abbott <labbott@redhat.com>,
	Benjamin Gaignard <benjamin.gaignard@linaro.org>,
	Sumit Semwal <sumit.semwal@linaro.org>,
	Liam Mark <lmark@codeaurora.org>,
	Pratik Patel <pratikp@codeaurora.org>,
	Brian Starkey <Brian.Starkey@arm.com>,
	Vincent Donnefort <Vincent.Donnefort@arm.com>,
	Sudipto Paul <Sudipto.Paul@arm.com>,
	"Andrew F . Davis" <afd@ti.com>,
	Christoph Hellwig <hch@infradead.org>,
	Chenbo Feng <fengc@google.com>,
	Alistair Strachan <astrachan@google.com>,
	Hridya Valsaraju <hridya@google.com>,
	Hillf Danton <hdanton@sina.com>, Dave Airlie <airlied@gmail.com>,
	dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v14 2/5] dma-buf: heaps: Add heap helpers
Date: Sun, 3 Nov 2019 08:13:48 -0800	[thread overview]
Message-ID: <20191103161348.GB13344@google.com> (raw)
In-Reply-To: <20191101214238.78015-3-john.stultz@linaro.org>

On Fri, Nov 01, 2019 at 09:42:35PM +0000, John Stultz wrote:
> Add generic helper dmabuf ops for dma heaps, so we can reduce
> the amount of duplicative code for the exported dmabufs.
> 
> 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: Laura Abbott <labbott@redhat.com>
> Tested-by: Ayan Kumar Halder <ayan.halder@arm.com>
> Signed-off-by: John Stultz <john.stultz@linaro.org>

I have one question and a naming suggestin below (sorry).

Acked-by: Sandeep Patil <sspatil@android.com>

> ---
> v2:
> * Removed cache management performance hack that I had
>   accidentally folded in.
> * Removed stats code that was in helpers
> * Lots of checkpatch cleanups
> v3:
> * Uninline INIT_HEAP_HELPER_BUFFER (suggested by Christoph)
> * Switch to WARN on buffer destroy failure (suggested by Brian)
> * buffer->kmap_cnt decrementing cleanup (suggested by Christoph)
> * Extra buffer->vaddr checking in dma_heap_dma_buf_kmap
>   (suggested by Brian)
> * Switch to_helper_buffer from macro to inline function
>   (suggested by Benjamin)
> * Rename kmap->vmap (folded in from Andrew)
> * Use vmap for vmapping - not begin_cpu_access (folded in from
>   Andrew)
> * Drop kmap for now, as its optional (folded in from Andrew)
> * Fold dma_heap_map_user into the single caller (foled in from
>   Andrew)
> * Folded in patch from Andrew to track page list per heap not
>   sglist, which simplifies the tracking logic
> v4:
> * Moved dma-heap.h change out to previous patch
> v6:
> * Minor cleanups and typo fixes suggested by Brian
> v7:
> * Removed stray ;
> * Make init_heap_helper_buffer lowercase, as suggested by Christoph
> * Add dmabuf export helper to reduce boilerplate code
> v8:
> * Remove unused private_flags value
> * Condense dma_heap_buffer and heap_helper_buffer (suggested by
>   Christoph)
> * Fix indentation by using shorter argument names (suggested by
>   Christoph)
> * Add flush_kernel_vmap_range/invalidate_kernel_vmap_range calls
>   (suggested by Christoph)
> * Checkpatch whitespace fixups
> v9:
> * Minor cleanups suggested by Brian Starkey
> v10:
> * Fix missing vmalloc.h inclusion in heap helpers (found by
>   kbuild test robot <lkp@intel.com>)
> v12:
> * Add symbol exports for heaps as modules
> v13:
> * Re-remove symbol exports, per discussion with Brian, as I'll
>   resubmit the change for review independently.
> v14:
> * Fix missing argment to WARN() in dma_heap_buffer_destroy()
>   found and fixed by Dan Carpenter <dan.carpenter@oracle.com>
> * Add check in fault hanlder that pgoff isn't larger then
>   pagecount, reported by Dan Carpenter
> 
> ---
>  drivers/dma-buf/Makefile             |   1 +
>  drivers/dma-buf/heaps/Makefile       |   2 +
>  drivers/dma-buf/heaps/heap-helpers.c | 271 +++++++++++++++++++++++++++
>  drivers/dma-buf/heaps/heap-helpers.h |  55 ++++++
>  4 files changed, 329 insertions(+)
>  create mode 100644 drivers/dma-buf/heaps/Makefile
>  create mode 100644 drivers/dma-buf/heaps/heap-helpers.c
>  create mode 100644 drivers/dma-buf/heaps/heap-helpers.h
> 
> diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> index caee5eb3d351..9c190026bfab 100644
> --- a/drivers/dma-buf/Makefile
> +++ b/drivers/dma-buf/Makefile
> @@ -2,6 +2,7 @@
>  obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
>  	 dma-resv.o seqno-fence.o
>  obj-$(CONFIG_DMABUF_HEAPS)	+= dma-heap.o
> +obj-$(CONFIG_DMABUF_HEAPS)	+= heaps/
>  obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
>  obj-$(CONFIG_SW_SYNC)		+= sw_sync.o sync_debug.o
>  obj-$(CONFIG_UDMABUF)		+= udmabuf.o
> diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
> new file mode 100644
> index 000000000000..de49898112db
> --- /dev/null
> +++ b/drivers/dma-buf/heaps/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-y					+= heap-helpers.o
> diff --git a/drivers/dma-buf/heaps/heap-helpers.c b/drivers/dma-buf/heaps/heap-helpers.c
> new file mode 100644
> index 000000000000..9f964ca3f59c
> --- /dev/null
> +++ b/drivers/dma-buf/heaps/heap-helpers.c
> @@ -0,0 +1,271 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/device.h>
> +#include <linux/dma-buf.h>
> +#include <linux/err.h>
> +#include <linux/highmem.h>
> +#include <linux/idr.h>
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +#include <linux/vmalloc.h>
> +#include <uapi/linux/dma-heap.h>
> +
> +#include "heap-helpers.h"
> +
> +void init_heap_helper_buffer(struct heap_helper_buffer *buffer,
> +			     void (*free)(struct heap_helper_buffer *))
> +{
> +	buffer->priv_virt = NULL;
> +	mutex_init(&buffer->lock);
> +	buffer->vmap_cnt = 0;
> +	buffer->vaddr = NULL;
> +	buffer->pagecount = 0;
> +	buffer->pages = NULL;
> +	INIT_LIST_HEAD(&buffer->attachments);
> +	buffer->free = free;
> +}
> +
> +struct dma_buf *heap_helper_export_dmabuf(struct heap_helper_buffer *buffer,
> +					  int fd_flags)
> +{
> +	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> +
> +	exp_info.ops = &heap_helper_ops;
> +	exp_info.size = buffer->size;
> +	exp_info.flags = fd_flags;
> +	exp_info.priv = buffer;
> +
> +	return dma_buf_export(&exp_info);
> +}
> +
> +static void *dma_heap_map_kernel(struct heap_helper_buffer *buffer)
> +{
> +	void *vaddr;
> +
> +	vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, PAGE_KERNEL);
> +	if (!vaddr)
> +		return ERR_PTR(-ENOMEM);
> +
> +	return vaddr;
> +}
> +
> +static void dma_heap_buffer_destroy(struct heap_helper_buffer *buffer)
> +{
> +	if (buffer->vmap_cnt > 0) {
> +		WARN(1, "%s: buffer still mapped in the kernel\n", __func__);
> +		vunmap(buffer->vaddr);
> +	}
> +
> +	buffer->free(buffer);
> +}
> +
> +static void *dma_heap_buffer_vmap_get(struct heap_helper_buffer *buffer)
> +{
> +	void *vaddr;
> +
> +	if (buffer->vmap_cnt) {
> +		buffer->vmap_cnt++;
> +		return buffer->vaddr;
> +	}
> +	vaddr = dma_heap_map_kernel(buffer);
> +	if (IS_ERR(vaddr))
> +		return vaddr;
> +	buffer->vaddr = vaddr;
> +	buffer->vmap_cnt++;
> +	return vaddr;
> +}
> +
> +static void dma_heap_buffer_vmap_put(struct heap_helper_buffer *buffer)
> +{
> +	if (!--buffer->vmap_cnt) {

nit: just checking here cause I don't know the order in which vmap_get() and
vmap_put() is expected to be called from dmabuf, the manual refcounting
based map/unmap is ok?

I know ion had this for a while and it worked fine over the years, but I
don't know if anybody saw any issues with it.
> +		vunmap(buffer->vaddr);
> +		buffer->vaddr = NULL;
> +	}
> +}
> +
> +struct dma_heaps_attachment {
> +	struct device *dev;
> +	struct sg_table table;
> +	struct list_head list;
> +};
> +
> +static int dma_heap_attach(struct dma_buf *dmabuf,
> +			   struct dma_buf_attachment *attachment)
> +{
> +	struct dma_heaps_attachment *a;
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +	int ret;
> +
> +	a = kzalloc(sizeof(*a), GFP_KERNEL);
> +	if (!a)
> +		return -ENOMEM;
> +
> +	ret = sg_alloc_table_from_pages(&a->table, buffer->pages,
> +					buffer->pagecount, 0,
> +					buffer->pagecount << PAGE_SHIFT,
> +					GFP_KERNEL);
> +	if (ret) {
> +		kfree(a);
> +		return ret;
> +	}
> +
> +	a->dev = attachment->dev;
> +	INIT_LIST_HEAD(&a->list);
> +
> +	attachment->priv = a;
> +
> +	mutex_lock(&buffer->lock);
> +	list_add(&a->list, &buffer->attachments);
> +	mutex_unlock(&buffer->lock);
> +
> +	return 0;
> +}
> +
> +static void dma_heap_detach(struct dma_buf *dmabuf,
> +			    struct dma_buf_attachment *attachment)
> +{
> +	struct dma_heaps_attachment *a = attachment->priv;
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +
> +	mutex_lock(&buffer->lock);
> +	list_del(&a->list);
> +	mutex_unlock(&buffer->lock);
> +
> +	sg_free_table(&a->table);
> +	kfree(a);
> +}
> +
> +static
> +struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment,
> +				      enum dma_data_direction direction)
> +{
> +	struct dma_heaps_attachment *a = attachment->priv;
> +	struct sg_table *table;
> +
> +	table = &a->table;
> +
> +	if (!dma_map_sg(attachment->dev, table->sgl, table->nents,
> +			direction))
> +		table = ERR_PTR(-ENOMEM);
> +	return table;
> +}
> +
> +static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
> +				   struct sg_table *table,
> +				   enum dma_data_direction direction)
> +{
> +	dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction);
> +}
> +
> +static vm_fault_t dma_heap_vm_fault(struct vm_fault *vmf)
> +{
> +	struct vm_area_struct *vma = vmf->vma;
> +	struct heap_helper_buffer *buffer = vma->vm_private_data;
> +
> +	if (vmf->pgoff > buffer->pagecount)
> +		return VM_FAULT_SIGBUS;
> +
> +	vmf->page = buffer->pages[vmf->pgoff];
> +	get_page(vmf->page);
> +
> +	return 0;
> +}
> +
> +static const struct vm_operations_struct dma_heap_vm_ops = {
> +	.fault = dma_heap_vm_fault,
> +};
> +
> +static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
> +{
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +
> +	if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0)
> +		return -EINVAL;
> +
> +	vma->vm_ops = &dma_heap_vm_ops;
> +	vma->vm_private_data = buffer;
> +
> +	return 0;
> +}
> +
> +static void dma_heap_dma_buf_release(struct dma_buf *dmabuf)
> +{
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +
> +	dma_heap_buffer_destroy(buffer);
> +}
> +
> +static int dma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
> +					     enum dma_data_direction direction)
> +{
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +	struct dma_heaps_attachment *a;
> +	int ret = 0;
> +
> +	mutex_lock(&buffer->lock);
> +
> +	if (buffer->vmap_cnt)
> +		invalidate_kernel_vmap_range(buffer->vaddr, buffer->size);
> +
> +	list_for_each_entry(a, &buffer->attachments, list) {
> +		dma_sync_sg_for_cpu(a->dev, a->table.sgl, a->table.nents,
> +				    direction);
> +	}
> +	mutex_unlock(&buffer->lock);
> +
> +	return ret;
> +}
> +
> +static int dma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
> +					   enum dma_data_direction direction)
> +{
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +	struct dma_heaps_attachment *a;
> +
> +	mutex_lock(&buffer->lock);
> +
> +	if (buffer->vmap_cnt)
> +		flush_kernel_vmap_range(buffer->vaddr, buffer->size);
> +
> +	list_for_each_entry(a, &buffer->attachments, list) {
> +		dma_sync_sg_for_device(a->dev, a->table.sgl, a->table.nents,
> +				       direction);
> +	}
> +	mutex_unlock(&buffer->lock);
> +
> +	return 0;
> +}
> +
> +static void *dma_heap_dma_buf_vmap(struct dma_buf *dmabuf)
> +{
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +	void *vaddr;
> +
> +	mutex_lock(&buffer->lock);
> +	vaddr = dma_heap_buffer_vmap_get(buffer);
> +	mutex_unlock(&buffer->lock);
> +
> +	return vaddr;
> +}
> +
> +static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
> +{
> +	struct heap_helper_buffer *buffer = dmabuf->priv;
> +
> +	mutex_lock(&buffer->lock);
> +	dma_heap_buffer_vmap_put(buffer);
> +	mutex_unlock(&buffer->lock);
> +}
> +
> +const struct dma_buf_ops heap_helper_ops = {
> +	.map_dma_buf = dma_heap_map_dma_buf,
> +	.unmap_dma_buf = dma_heap_unmap_dma_buf,
> +	.mmap = dma_heap_mmap,
> +	.release = dma_heap_dma_buf_release,
> +	.attach = dma_heap_attach,
> +	.detach = dma_heap_detach,
> +	.begin_cpu_access = dma_heap_dma_buf_begin_cpu_access,
> +	.end_cpu_access = dma_heap_dma_buf_end_cpu_access,
> +	.vmap = dma_heap_dma_buf_vmap,
> +	.vunmap = dma_heap_dma_buf_vunmap,
> +};
> diff --git a/drivers/dma-buf/heaps/heap-helpers.h b/drivers/dma-buf/heaps/heap-helpers.h
> new file mode 100644
> index 000000000000..911c931f7f06
> --- /dev/null
> +++ b/drivers/dma-buf/heaps/heap-helpers.h
> @@ -0,0 +1,55 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * DMABUF Heaps helper code
> + *
> + * Copyright (C) 2011 Google, Inc.
> + * Copyright (C) 2019 Linaro Ltd.
> + */
> +
> +#ifndef _HEAP_HELPERS_H
> +#define _HEAP_HELPERS_H
> +
> +#include <linux/dma-heap.h>
> +#include <linux/list.h>
> +
> +/**
> + * struct heap_helper_buffer - helper buffer metadata
> + * @heap:		back pointer to the heap the buffer came from
> + * @dmabuf:		backing dma-buf for this buffer
> + * @size:		size of the buffer
> + * @flags:		buffer specific flags
nit: Are thee dmabuf flags, or dmabuf_heap specific / allocation related flags?
> + * @priv_virt		pointer to heap specific private value
nit: text looks misaligned (or is it my editor?)
> + * @lock		mutext to protect the data in this structure
> + * @vmap_cnt		count of vmap references on the buffer
> + * @vaddr		vmap'ed virtual address
> + * @pagecount		number of pages in the buffer
> + * @pages		list of page pointers
> + * @attachments		list of device attachments
ditto
> + *
> + * @free		heap callback to free the buffer
> + */
> +struct heap_helper_buffer {
/bikeshed/
s/heap_helper_buffer/dma_heap_buffer ?

The "heap helper buffer" doesn't really convey what it is.
> +	struct dma_heap *heap;
> +	struct dma_buf *dmabuf;
> +	size_t size;
> +	unsigned long flags;
> +
> +	void *priv_virt;
> +	struct mutex lock;
> +	int vmap_cnt;
> +	void *vaddr;
> +	pgoff_t pagecount;
> +	struct page **pages;
> +	struct list_head attachments;
> +
> +	void (*free)(struct heap_helper_buffer *buffer);
> +};
> +
> +void init_heap_helper_buffer(struct heap_helper_buffer *buffer,
> +			     void (*free)(struct heap_helper_buffer *));
> +
> +struct dma_buf *heap_helper_export_dmabuf(struct heap_helper_buffer *buffer,
> +					  int fd_flags);
> +
> +extern const struct dma_buf_ops heap_helper_ops;
> +#endif /* _HEAP_HELPERS_H */
> -- 
> 2.17.1
> 

  reply	other threads:[~2019-11-03 16:14 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-01 21:42 [PATCH v14 0/5] DMA-BUF Heaps (destaging ION) John Stultz
2019-11-01 21:42 ` [PATCH v14 1/5] dma-buf: Add dma-buf heaps framework John Stultz
2019-11-03 16:02   ` sspatil
2019-11-04 18:32     ` John Stultz
2019-11-04 10:24   ` Brian Starkey
2019-11-04 16:58     ` Dave Airlie
2019-11-04 17:43       ` Brian Starkey
2019-11-04 18:30         ` Daniel Vetter
2019-11-04 18:44     ` John Stultz
2019-11-01 21:42 ` [PATCH v14 2/5] dma-buf: heaps: Add heap helpers John Stultz
2019-11-03 16:13   ` sspatil [this message]
2019-11-04 19:34     ` John Stultz
2019-11-04 19:36       ` John Stultz
2019-11-01 21:42 ` [PATCH v14 3/5] dma-buf: heaps: Add system heap to dmabuf heaps John Stultz
2019-11-03 16:19   ` Sandeep Patil
2019-11-01 21:42 ` [PATCH v14 4/5] dma-buf: heaps: Add CMA " John Stultz
2019-11-03 16:22   ` Sandeep Patil
2019-11-01 21:42 ` [PATCH v14 5/5] kselftests: Add dma-heap test John Stultz
2019-11-03 16:25   ` Sandeep Patil
2019-11-04  8:18 ` [PATCH v14 0/5] DMA-BUF Heaps (destaging ION) Pekka Paalanen
2019-11-04 19:21   ` John Stultz
2019-11-05  8:19     ` Pekka Paalanen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191103161348.GB13344@google.com \
    --to=sspatil@google.com \
    --cc=Brian.Starkey@arm.com \
    --cc=Sudipto.Paul@arm.com \
    --cc=Vincent.Donnefort@arm.com \
    --cc=afd@ti.com \
    --cc=airlied@gmail.com \
    --cc=astrachan@google.com \
    --cc=benjamin.gaignard@linaro.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=fengc@google.com \
    --cc=hch@infradead.org \
    --cc=hdanton@sina.com \
    --cc=hridya@google.com \
    --cc=john.stultz@linaro.org \
    --cc=labbott@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lmark@codeaurora.org \
    --cc=pratikp@codeaurora.org \
    --cc=sspatil+mutt@google.com \
    --cc=sumit.semwal@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox